Initial merge-commit of the OIC code. Should successfully do discovery for single...
[platform/upstream/iotivity.git] / csdk / ocsocket / src / ocsocket.c
1 //******************************************************************
2 //
3 // Copyright 2014 Intel Corporation All Rights Reserved.
4 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
5
6 #include <sys/types.h>
7 #include <sys/socket.h>
8 #include <sys/select.h>
9 #include <arpa/inet.h>
10 #include <netinet/in.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <stdlib.h>
14 #include <math.h>
15 #include <unistd.h>
16 #include <fcntl.h>
17 #include <net/if.h>
18 #include <errno.h>
19
20 #ifdef __ANDROID__
21 #include <sys/ioctl.h>
22 #else
23 #include <ifaddrs.h>
24 #include <linux/if_link.h>
25 #endif
26
27 #include <logger.h>
28 #include <ocsocket.h>
29
30 /// Module Name
31 #define MOD_NAME ("ocsocket")
32
33 /// Macro to verify the validity of input argument
34 #define VERIFY_NON_NULL(arg) { if (!arg) {OC_LOG(FATAL, MOD_NAME, #arg " is NULL"); return ERR_INVALID_INPUT;} }
35
36 /// Builds a socket interface address using IP address and port number
37 int32_t OCBuildIPv4Address(uint8_t a, uint8_t b, uint8_t c, uint8_t d, uint16_t port, OCDevAddr *ipAddr)
38 {
39     struct sockaddr_in *sa;
40     uint32_t ip = a;
41
42     VERIFY_NON_NULL(ipAddr);
43     memset(ipAddr, 0, sizeof(OCDevAddr));
44
45     ip <<= 8;
46     ip |= b;
47     ip <<= 8;
48     ip |= c;
49     ip <<= 8;
50     ip |= d;
51
52     ipAddr->size = sizeof(struct sockaddr_in);
53     sa = (struct sockaddr_in*)ipAddr->addr;
54     sa->sin_family = AF_INET;
55     sa->sin_addr.s_addr = htonl(ip);
56     sa->sin_port = htons(port);
57
58     return ERR_SUCCESS;
59 }
60
61 #ifdef __ANDROID__
62 /// Retrieves the IP address assigned to specified wireless interface
63 int32_t OCGetInterfaceAddress(uint8_t* ifName, uint32_t ifNameLen, uint16_t addrType,
64              uint8_t *addr,  uint32_t addrLen)
65 {
66     int32_t ret = ERR_UNKNOWN;
67     int32_t sfd = 0xFFFFFFFF;
68     struct ifreq ifr;
69
70     VERIFY_NON_NULL(addr);
71     VERIFY_NON_NULL(ifName);
72     if (ifNameLen > (IFNAMSIZ - 1) ) {
73         return ERR_INVALID_INPUT;
74     }
75     if (addrType != AF_INET) {
76         return ERR_INVALID_INPUT;
77     }
78
79     sfd = socket(addrType, SOCK_DGRAM, 0);
80     if (sfd < 0) {
81         OC_LOG_V(FATAL, MOD_NAME, "socket API ret val %d", sfd);
82         goto exit;
83     }
84
85     ifr.ifr_addr.sa_family = addrType;
86
87     strncpy(ifr.ifr_name, (const char*)ifName, ifNameLen);
88
89     if (ioctl(sfd, SIOCGIFADDR, &ifr) != 0) {
90         OC_LOG(FATAL, MOD_NAME, "ioctl call failed");
91         goto exit;
92     }
93
94     strncpy((char *)addr,
95             inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr),
96             addrLen);
97     ret = ERR_SUCCESS;
98
99 exit:
100     if (sfd >= 0) {
101         close(sfd);
102     }
103     return ret;
104 }
105
106 #else
107 /// Retrieves the IP address assigned to specified wireless interface
108 int32_t OCGetInterfaceAddress(uint8_t* ifName, uint32_t ifNameLen, uint16_t addrType,
109              uint8_t *addr,  uint32_t addrLen)
110 {
111     struct ifaddrs *myaddrs = NULL, *ifa = NULL;
112     int32_t ret = ERR_UNKNOWN;
113
114     VERIFY_NON_NULL(addr);
115
116     if (addrType != AF_INET) {
117         return ERR_INVALID_INPUT;
118     }
119
120     if(getifaddrs(&myaddrs) != 0) {
121         goto exit;
122     }
123
124     for (ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next) {
125         if (ifa->ifa_addr == NULL)
126             continue;
127         if (!(ifa->ifa_flags & IFF_UP))
128             continue;
129         if (!(ifa->ifa_flags & IFF_RUNNING))
130             continue;
131
132         if (ifName && ifa->ifa_name) {
133            if(strncmp((const char*)ifName, ifa->ifa_name, ifNameLen) != 0)
134             continue;
135         }
136
137         switch (ifa->ifa_addr->sa_family)
138         {
139             case AF_INET:
140                 {
141                     struct sockaddr_in *s4 = (struct sockaddr_in *)ifa->ifa_addr;
142                     if(inet_ntop(AF_INET, &(s4->sin_addr), (char *)addr, addrLen))
143                         ret = ERR_SUCCESS;
144                     goto exit;
145                 }
146
147             default:
148                 continue;
149         }
150     }
151
152 exit:
153     if (myaddrs) {
154         freeifaddrs(myaddrs);
155     }
156     return ret;
157 }
158 #endif //__ANDROID__
159
160 /// Creates a BSD socket and binds it specified port for UDP
161 int32_t OCInitUDP(OCDevAddr* ipAddr, int32_t *sockfd)
162 {
163     int32_t ret = ERR_UNKNOWN;
164     int32_t sfd = 0xFFFFFFFF;
165     int set_option_on = 1;
166
167     VERIFY_NON_NULL(ipAddr);
168     VERIFY_NON_NULL(sockfd);
169
170     OC_LOG_V(DEBUG, MOD_NAME, "%s Begin", __func__ );
171     //Create a datagram socket on which to recv/send.
172     sfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
173     if (sfd < 0) {
174         OC_LOG_V(FATAL, MOD_NAME, "socket API ret val %d", sfd);
175         goto exit;
176     }
177
178     if ((ret = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (char*) &set_option_on,
179                 sizeof(set_option_on))) < 0) {
180         OC_LOG(FATAL, MOD_NAME, "setsockopt API failed");
181         goto exit;
182     }
183
184     if (bind(sfd, (struct sockaddr*)ipAddr->addr, ipAddr->size) < 0) {
185         OC_LOG_V(FATAL, MOD_NAME, "bind API failed with errno %s", strerror(errno));
186         goto exit;
187     }
188
189     ret = ERR_SUCCESS;
190
191 exit:
192     if ((ret != ERR_SUCCESS) && (sfd >= 0)) {
193         close(sfd);
194     } else {
195         *sockfd = sfd;
196     }
197
198     OC_LOG_V(DEBUG, MOD_NAME, "%s End", __func__ );
199     return ret;
200 }
201
202
203
204 /// Creates a BSD socket and binds the specified port for UDP multicast.
205 int32_t OCInitUDPMulticast(OCDevAddr* ipmcastaddr, int32_t* sockfd)
206 {
207     int32_t ret = ERR_UNKNOWN;
208     int32_t sfd = 0xFFFFFFFF;
209     char loopch=1;
210     int set_option_on = 1;
211
212     VERIFY_NON_NULL(ipmcastaddr);
213     VERIFY_NON_NULL(sockfd);
214
215     OC_LOG_V(DEBUG, MOD_NAME, "%s Begin", __func__ );
216     //Create a datagram socket on which to recv/send.
217     sfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
218     if (sfd < 0) {
219         OC_LOG_V(FATAL, MOD_NAME, "socket API ret val %d", sfd);
220         goto exit;
221
222     }
223
224     if ((ret = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (char*) &set_option_on,
225                 sizeof(set_option_on))) < 0) {
226         OC_LOG_V(FATAL, MOD_NAME, "setsockopt API for SO_REUSEADDR failed with errno %s", strerror(errno));
227         goto exit;
228     }
229
230     // bind to multicast port
231     struct sockaddr_in sa;
232     struct sockaddr_in *sin;
233
234     sin = (struct sockaddr_in *)(ipmcastaddr->addr);
235     memset(&sa, 0, sizeof(sa));
236     sa.sin_family = AF_INET;
237     sa.sin_addr.s_addr = INADDR_ANY;
238     sa.sin_port = sin->sin_port;
239
240     if ((ret = bind(sfd, (struct sockaddr*)&sa, sizeof(sa))) < 0) {
241         OC_LOG_V(FATAL, MOD_NAME, "bind API failed with errno %s", strerror(errno));
242         goto exit;
243     }
244
245     // add membership to receiving socket
246     struct ip_mreq mreq;
247     memset(&mreq, 0, sizeof(struct ip_mreq));
248     mreq.imr_interface.s_addr = htonl(INADDR_ANY);
249     mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr;
250     if ((ret = setsockopt(sfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq, sizeof(mreq))) < 0) {
251         OC_LOG_V(FATAL, MOD_NAME, "setsockopt API for IP_ADD_MEMBERSHIP failed with errno %s", strerror(errno));
252         goto exit;
253     }
254
255     //Enable loopback so we can receive our own datagrams.
256     if ((ret = setsockopt(sfd, IPPROTO_IP, IP_MULTICAST_LOOP,
257                 (char *)&loopch, sizeof(loopch))) < 0) {
258         OC_LOG_V(FATAL, MOD_NAME, "setsockopt API for IP_MULTICAST_LOOP failed with errno %s", strerror(errno));
259         goto exit;
260     }
261
262     ret = ERR_SUCCESS;
263
264 exit:
265     if (ret == ERR_SUCCESS) {
266         *sockfd = sfd;
267     } else {
268         close(sfd);
269     }
270
271     OC_LOG_V(DEBUG, MOD_NAME, "%s End", __func__ );
272     return ret;
273 }
274
275
276
277 /// Send data to requested end-point using UDP socket
278 int32_t OCSendTo(int32_t sockfd, const uint8_t* buf, uint32_t bufLen, uint32_t flags,
279             OCDevAddr * ipAddr)
280 {
281     int32_t ret;
282
283     VERIFY_NON_NULL(buf);
284     VERIFY_NON_NULL(ipAddr);
285
286     OC_LOG_V(DEBUG, MOD_NAME, "%s Begin", __func__ );
287     ret = sendto(sockfd, buf, bufLen, flags,
288             (struct sockaddr*)ipAddr->addr, ipAddr->size);
289
290     OC_LOG_V(DEBUG, MOD_NAME, "%s End", __func__ );
291     return ret;
292 }
293
294
295 /// Retrieve any available data from UDP socket. This is a non-blocking call.
296 int32_t OCRecvFrom(int32_t sockfd, uint8_t* buf, uint32_t bufLen, uint32_t flags,
297             OCDevAddr * ipAddr)
298 {
299     int32_t ret = 0;
300
301     VERIFY_NON_NULL(buf);
302     VERIFY_NON_NULL(ipAddr);
303
304     struct timeval timeout;
305     timeout.tv_sec = 0;
306     timeout.tv_usec = 5000;
307     fd_set reads;
308
309     OC_LOG_V(DEBUG, MOD_NAME, "%s Begin", __func__ );
310
311     FD_ZERO(&reads);
312     FD_SET(sockfd, &reads);
313     ret = select(sockfd + 1, &reads, NULL, NULL, &timeout);
314     if( ret < 0) {
315         OC_LOG(FATAL, MOD_NAME, "select API failed");
316         return ret;
317     }
318     if (!FD_ISSET(sockfd, &reads)) {
319         OC_LOG(DEBUG, MOD_NAME, "No data to read");
320         return ERR_SUCCESS;
321     }
322
323     // Read available data.
324     ret = recvfrom(sockfd, buf, bufLen, flags,
325             (struct sockaddr*)ipAddr->addr, (socklen_t*)&(ipAddr->size));
326     if (ret < 1) {
327         OC_LOG(FATAL, MOD_NAME, "OCRecvFrom ERR");
328     }
329     OC_LOG_V(DEBUG, MOD_NAME, "%s End", __func__ );
330     return ret;
331 }
332
333
334 /// Close the socket and release all system resources.
335 int32_t OCClose(int32_t sockfd)
336 {
337     return (close(sockfd));
338 }
339
340
341 /// Retrieve the IPv4 address embedded inside OCDev address data structure
342 int32_t OCDevAddrToIPv4Addr(OCDevAddr *ipAddr, uint8_t *a, uint8_t *b,
343             uint8_t *c, uint8_t *d )
344 {
345     struct sockaddr_in *sa;
346     uint32_t ip;
347
348     if ( !ipAddr || !a || !b || !c || !d ) {
349         OC_LOG(FATAL, MOD_NAME, "Invalid argument");
350         return ERR_INVALID_INPUT;
351     }
352
353     sa = (struct sockaddr_in*)ipAddr->addr;
354     ip = ntohl(sa->sin_addr.s_addr);
355     *d = *((uint8_t*)&ip + 0);
356     *c = *((uint8_t*)&ip + 1);
357     *b = *((uint8_t*)&ip + 2);
358     *a = *((uint8_t*)&ip + 3);
359
360     return ERR_SUCCESS;
361 }
362
363
364 /// Retrieve the IPv4 address embedded inside OCDev address data structure
365 int32_t OCDevAddrToPort(OCDevAddr *ipAddr, uint16_t *port)
366 {
367     struct sockaddr_in *sa;
368     if ( !ipAddr || !port ) {
369         OC_LOG(FATAL, MOD_NAME, "Invalid argument");
370         return ERR_INVALID_INPUT;
371     }
372
373     sa = (struct sockaddr_in*)ipAddr->addr;
374     *port = ntohs(sa->sin_port);
375
376     return ERR_SUCCESS;
377 }