changed code to close the socket generated when initializing.
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / ip_adapter / caipserver.c
1 /*****************************************************************j
2  *
3  * Copyright 2014 Samsung Electronics All Rights Reserved.
4  *
5  *
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  ******************************************************************/
20
21 #ifndef __APPLE_USE_RFC_3542
22 #define __APPLE_USE_RFC_3542 // for PKTINFO
23 #endif
24 #ifndef _GNU_SOURCE
25 #define _GNU_SOURCE // for in6_pktinfo
26 #endif
27
28 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <stdio.h>
31 #include <unistd.h>
32 #include <sys/types.h>
33 #include <fcntl.h>
34 #include <sys/select.h>
35 #include <arpa/inet.h>
36 #include <netinet/in.h>
37 #include <net/if.h>
38 #include <errno.h>
39 #ifdef __linux__
40 #include <linux/netlink.h>
41 #include <linux/rtnetlink.h>
42 #endif
43
44 #include "pdu.h"
45 #include "caipinterface.h"
46 #include "caadapterutils.h"
47 #ifdef __WITH_DTLS__
48 #include "caadapternetdtls.h"
49 #endif
50 #include "camutex.h"
51 #include "oic_malloc.h"
52 #include "oic_string.h"
53
54 /*
55  * Logging tag for module name
56  */
57 #define TAG "OIC_CA_IP_SERVER"
58
59 #define SELECT_TIMEOUT 1     // select() seconds (and termination latency)
60
61 #define IPv4_MULTICAST     "224.0.1.187"
62 static struct in_addr IPv4MulticastAddress = { 0 };
63
64 #define IPv6_DOMAINS       16
65 #define IPv6_MULTICAST_INT "ff01::fd"
66 static struct in6_addr IPv6MulticastAddressInt;
67 #define IPv6_MULTICAST_LNK "ff02::fd"
68 static struct in6_addr IPv6MulticastAddressLnk;
69 #define IPv6_MULTICAST_RLM "ff03::fd"
70 static struct in6_addr IPv6MulticastAddressRlm;
71 #define IPv6_MULTICAST_ADM "ff04::fd"
72 static struct in6_addr IPv6MulticastAddressAdm;
73 #define IPv6_MULTICAST_SIT "ff05::fd"
74 static struct in6_addr IPv6MulticastAddressSit;
75 #define IPv6_MULTICAST_ORG "ff08::fd"
76 static struct in6_addr IPv6MulticastAddressOrg;
77 #define IPv6_MULTICAST_GLB "ff0e::fd"
78 static struct in6_addr IPv6MulticastAddressGlb;
79
80 static char *ipv6mcnames[IPv6_DOMAINS] = {
81     NULL,
82     IPv6_MULTICAST_INT,
83     IPv6_MULTICAST_LNK,
84     IPv6_MULTICAST_RLM,
85     IPv6_MULTICAST_ADM,
86     IPv6_MULTICAST_SIT,
87     NULL,
88     NULL,
89     IPv6_MULTICAST_ORG,
90     NULL,
91     NULL,
92     NULL,
93     NULL,
94     NULL,
95     IPv6_MULTICAST_GLB,
96     NULL
97 };
98
99 static CAIPExceptionCallback g_exceptionCallback;
100
101 static CAIPPacketReceivedCallback g_packetReceivedCallback;
102
103 static void CAHandleNetlink();
104 static void CAFindReadyMessage();
105 static void CASelectReturned(fd_set *readFds, int ret);
106 static void CAProcessNewInterface(CAInterface_t *ifchanged);
107 static CAResult_t CAReceiveMessage(int fd, CATransportFlags_t flags);
108
109 #define SET(TYPE, FDS) \
110     if (caglobals.ip.TYPE.fd != -1) \
111     { \
112         FD_SET(caglobals.ip.TYPE.fd, FDS); \
113     }
114
115 #define ISSET(TYPE, FDS, FLAGS) \
116     if (caglobals.ip.TYPE.fd != -1 && FD_ISSET(caglobals.ip.TYPE.fd, FDS)) \
117     { \
118         fd = caglobals.ip.TYPE.fd; \
119         flags = FLAGS; \
120     }
121
122 void CADeInitializeIPGlobals()
123 {
124     if (caglobals.ip.u6.fd != -1)
125     {
126         close(caglobals.ip.u6.fd);
127         caglobals.ip.u6.fd = -1;
128     }
129
130     if (caglobals.ip.u6s.fd != -1)
131     {
132         close(caglobals.ip.u6s.fd);
133         caglobals.ip.u6s.fd = -1;
134     }
135
136     if (caglobals.ip.u4.fd != -1)
137     {
138         close(caglobals.ip.u4.fd);
139         caglobals.ip.u4.fd = -1;
140     }
141
142     if (caglobals.ip.u4s.fd != -1)
143     {
144         close(caglobals.ip.u4s.fd);
145         caglobals.ip.u4s.fd = -1;
146     }
147
148     if (caglobals.ip.m6.fd != -1)
149     {
150         close(caglobals.ip.m6.fd);
151         caglobals.ip.m6.fd = -1;
152     }
153
154     if (caglobals.ip.m6s.fd != -1)
155     {
156         close(caglobals.ip.m6s.fd);
157         caglobals.ip.m6s.fd = -1;
158     }
159
160     if (caglobals.ip.m4.fd != -1)
161     {
162         close(caglobals.ip.m4.fd);
163         caglobals.ip.m4.fd = -1;
164     }
165
166     if (caglobals.ip.m4s.fd != -1)
167     {
168         close(caglobals.ip.m4s.fd);
169         caglobals.ip.m4s.fd = -1;
170     }
171 }
172
173 static void CAReceiveHandler(void *data)
174 {
175     (void)data;
176
177     while (!caglobals.ip.terminate)
178     {
179         CAFindReadyMessage();
180     }
181 }
182
183 static void CAFindReadyMessage()
184 {
185     fd_set readFds;
186     struct timeval timeout;
187
188     timeout.tv_sec = caglobals.ip.selectTimeout;
189     timeout.tv_usec = 0;
190     struct timeval *tv = caglobals.ip.selectTimeout == -1 ? NULL : &timeout;
191
192     FD_ZERO(&readFds);
193     SET(u6,  &readFds)
194     SET(u6s, &readFds)
195     SET(u4,  &readFds)
196     SET(u4s, &readFds)
197     SET(m6,  &readFds)
198     SET(m6s, &readFds)
199     SET(m4,  &readFds)
200     SET(m4s, &readFds)
201     if (caglobals.ip.shutdownFds[0] != -1)
202     {
203         FD_SET(caglobals.ip.shutdownFds[0], &readFds);
204     }
205     if (caglobals.ip.netlinkFd != -1)
206     {
207         FD_SET(caglobals.ip.netlinkFd, &readFds);
208     }
209
210     int ret = select(caglobals.ip.maxfd + 1, &readFds, NULL, NULL, tv);
211
212     if (caglobals.ip.terminate)
213     {
214         OIC_LOG_V(DEBUG, TAG, "Packet receiver Stop request received.");
215         return;
216     }
217     if (ret <= 0)
218     {
219         if (ret < 0)
220         {
221             OIC_LOG_V(FATAL, TAG, "select error %s", strerror(errno));
222         }
223         return;
224     }
225
226     CASelectReturned(&readFds, ret);
227 }
228
229 static void CASelectReturned(fd_set *readFds, int ret)
230 {
231     (void)ret;
232     int fd = -1;
233     CATransportFlags_t flags = CA_DEFAULT_FLAGS;
234
235     while (!caglobals.ip.terminate)
236     {
237         ISSET(u6,  readFds, CA_IPV6)
238         else ISSET(u6s, readFds, CA_IPV6 | CA_SECURE)
239         else ISSET(u4,  readFds, CA_IPV4)
240         else ISSET(u4s, readFds, CA_IPV4 | CA_SECURE)
241         else ISSET(m6,  readFds, CA_MULTICAST | CA_IPV6)
242         else ISSET(m6s, readFds, CA_MULTICAST | CA_IPV6 | CA_SECURE)
243         else ISSET(m4,  readFds, CA_MULTICAST | CA_IPV4)
244         else ISSET(m4s, readFds, CA_MULTICAST | CA_IPV4 | CA_SECURE)
245         else if (FD_ISSET(caglobals.ip.netlinkFd, readFds))
246         {
247             CAHandleNetlink();
248             break;
249         }
250         else if (FD_ISSET(caglobals.ip.shutdownFds[0], readFds))
251         {
252             char buf[10] = {0};
253             ssize_t len = read(caglobals.ip.shutdownFds[0], buf, sizeof (buf));
254             if (-1 == len)
255             {
256                 continue;
257             }
258
259             CAInterface_t *ifchanged = CAFindInterfaceChange();
260             if (ifchanged)
261             {
262                 CAProcessNewInterface(ifchanged);
263                 OICFree(ifchanged);
264             }
265             break;
266         }
267         else
268         {
269             break;
270         }
271
272         (void)CAReceiveMessage(fd, flags);
273         FD_CLR(fd, readFds);
274     }
275 }
276
277 static CAResult_t CAReceiveMessage(int fd, CATransportFlags_t flags)
278 {
279     char recvBuffer[COAP_MAX_PDU_SIZE];
280
281     size_t len;
282     int level, type, namelen;
283     struct sockaddr_storage srcAddr;
284     unsigned char *pktinfo = NULL;
285     struct cmsghdr *cmp = NULL;
286     struct iovec iov = { recvBuffer, sizeof (recvBuffer) };
287     union control
288     {
289         struct cmsghdr cmsg;
290         unsigned char data[CMSG_SPACE(sizeof (struct in6_pktinfo))];
291     } cmsg;
292
293     if (flags & CA_IPV6)
294     {
295         namelen = sizeof (struct sockaddr_in6);
296         level = IPPROTO_IPV6;
297         type = IPV6_PKTINFO;
298         len = sizeof (struct in6_pktinfo);
299     }
300     else
301     {
302         namelen = sizeof (struct sockaddr_in);
303         level = IPPROTO_IP;
304         type = IP_PKTINFO;
305         len = sizeof (struct in6_pktinfo);
306     }
307
308     struct msghdr msg = { .msg_name = &srcAddr,
309                           .msg_namelen = namelen,
310                           .msg_iov = &iov,
311                           .msg_iovlen = 1,
312                           .msg_control = &cmsg,
313                           .msg_controllen = CMSG_SPACE(len) };
314
315     ssize_t recvLen = recvmsg(fd, &msg, flags);
316     if (-1 == recvLen)
317     {
318         OIC_LOG_V(ERROR, TAG, "Recvfrom failed %s", strerror(errno));
319         return CA_STATUS_FAILED;
320     }
321
322     if (flags & CA_MULTICAST)
323     {
324         for (cmp = CMSG_FIRSTHDR(&msg); cmp != NULL; cmp = CMSG_NXTHDR(&msg, cmp))
325         {
326             if (cmp->cmsg_level == level && cmp->cmsg_type == type)
327             {
328                 pktinfo = CMSG_DATA(cmp);
329             }
330         }
331     }
332
333     CASecureEndpoint_t sep = {.endpoint = {.adapter = CA_ADAPTER_IP, .flags = flags}};
334
335     if (flags & CA_IPV6)
336     {
337         sep.endpoint.interface = ((struct sockaddr_in6 *)&srcAddr)->sin6_scope_id;
338         ((struct sockaddr_in6 *)&srcAddr)->sin6_scope_id = 0;
339
340         if ((flags & CA_MULTICAST) && pktinfo)
341         {
342             struct in6_addr *addr = &(((struct in6_pktinfo *)pktinfo)->ipi6_addr);
343             unsigned char topbits = ((unsigned char *)addr)[0];
344             if (topbits != 0xff)
345             {
346                 sep.endpoint.flags &= ~CA_MULTICAST;
347             }
348         }
349     }
350     else
351     {
352         if ((flags & CA_MULTICAST) && pktinfo)
353         {
354             struct in_addr *addr = &((struct in_pktinfo *)pktinfo)->ipi_addr;
355             uint32_t host = ntohl(addr->s_addr);
356             unsigned char topbits = ((unsigned char *)&host)[3];
357             if (topbits < 224 || topbits > 239)
358             {
359                 sep.endpoint.flags &= ~CA_MULTICAST;
360             }
361         }
362     }
363
364     CAConvertAddrToName(&srcAddr, msg.msg_namelen, sep.endpoint.addr, &sep.endpoint.port);
365
366     if (flags & CA_SECURE)
367     {
368 #ifdef __WITH_DTLS__
369         int ret = CAAdapterNetDtlsDecrypt(&sep, (uint8_t *)recvBuffer, recvLen);
370         OIC_LOG_V(DEBUG, TAG, "CAAdapterNetDtlsDecrypt returns [%d]", ret);
371 #else
372         OIC_LOG(ERROR, TAG, "Encrypted message but no DTLS");
373 #endif
374     }
375     else
376     {
377         if (g_packetReceivedCallback)
378         {
379             g_packetReceivedCallback(&sep, recvBuffer, recvLen);
380         }
381     }
382
383     return CA_STATUS_OK;
384 }
385
386 void CAIPPullData()
387 {
388     OIC_LOG(DEBUG, TAG, "IN");
389     OIC_LOG(DEBUG, TAG, "OUT");
390 }
391
392 static int CACreateSocket(int family, uint16_t *port)
393 {
394     int socktype = SOCK_DGRAM;
395 #ifdef SOCK_CLOEXEC
396     socktype |= SOCK_CLOEXEC;
397 #endif
398     int fd = socket(family, socktype, IPPROTO_UDP);
399     if (-1 == fd)
400     {
401         OIC_LOG_V(ERROR, TAG, "create socket failed: %s", strerror(errno));
402         return -1;
403     }
404
405 #ifndef SOCK_CLOEXEC
406     int fl = fcntl(fd, F_GETFD);
407     if (-1 == fl || -1 == fcntl(fd, F_SETFD, fl|FD_CLOEXEC))
408     {
409         OIC_LOG_V(ERROR, TAG, "set FD_CLOEXEC failed: %s", strerror(errno));
410         close(fd);
411         return -1;
412     }
413 #endif
414
415     struct sockaddr_storage sa = { .ss_family = family };
416     socklen_t socklen;
417
418     if (family == AF_INET6)
419     {
420         int on = 1;
421
422         if (-1 == setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on)))
423         {
424             OIC_LOG_V(ERROR, TAG, "IPV6_V6ONLY failed: %s", strerror(errno));
425         }
426
427         if (*port)      // only do this for multicast ports
428         {
429             if (-1 == setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof (on)))
430             {
431                 OIC_LOG_V(ERROR, TAG, "IPV6_RECVPKTINFO failed: %s", strerror(errno));
432             }
433         }
434
435         ((struct sockaddr_in6 *)&sa)->sin6_port = htons(*port);
436         socklen = sizeof (struct sockaddr_in6);
437     }
438     else
439     {
440         if (*port)      // only do this for multicast ports
441         {
442             int on = 1;
443             if (-1 == setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &on, sizeof (on)))
444             {
445                 OIC_LOG_V(ERROR, TAG, "IP_PKTINFO failed: %s", strerror(errno));
446             }
447         }
448
449         ((struct sockaddr_in *)&sa)->sin_port = htons(*port);
450         socklen = sizeof (struct sockaddr_in);
451     }
452
453     if (*port)  // use the given port
454     {
455         int on = 1;
456         if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)))
457         {
458             OIC_LOG_V(ERROR, TAG, "SO_REUSEADDR failed: %s", strerror(errno));
459             close(fd);
460             return -1;
461         }
462     }
463
464     if (-1 == bind(fd, (struct sockaddr *)&sa, socklen))
465     {
466         OIC_LOG_V(ERROR, TAG, "bind socket failed: %s", strerror(errno));
467         close(fd);
468         return -1;
469     }
470
471     if (!*port)  // return the assigned port
472     {
473         if (-1 == getsockname(fd, (struct sockaddr *)&sa, &socklen))
474         {
475             OIC_LOG_V(ERROR, TAG, "getsockname failed: %s", strerror(errno));
476             close(fd);
477             return -1;
478         }
479         *port = ntohs(family == AF_INET6 ?
480                       ((struct sockaddr_in6 *)&sa)->sin6_port :
481                       ((struct sockaddr_in *)&sa)->sin_port);
482     }
483
484     return fd;
485 }
486
487 #define CHECKFD(FD) \
488     if (FD > caglobals.ip.maxfd) \
489         caglobals.ip.maxfd = FD;
490 #define NEWSOCKET(FAMILY, NAME) \
491     caglobals.ip.NAME.fd = CACreateSocket(FAMILY, &caglobals.ip.NAME.port); \
492     CHECKFD(caglobals.ip.NAME.fd)
493
494 static void CAInitializeNetlink()
495 {
496 #ifdef __linux__
497     // create NETLINK fd for interface change notifications
498     struct sockaddr_nl sa = { AF_NETLINK, 0, 0, RTMGRP_LINK };
499
500     caglobals.ip.netlinkFd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, NETLINK_ROUTE);
501     if (caglobals.ip.netlinkFd == -1)
502     {
503         OIC_LOG_V(ERROR, TAG, "netlink socket failed: %s", strerror(errno));
504     }
505     else
506     {
507         int r = bind(caglobals.ip.netlinkFd, (struct sockaddr *)&sa, sizeof (sa));
508         if (r)
509         {
510             OIC_LOG_V(ERROR, TAG, "netlink bind failed: %s", strerror(errno));
511             close(caglobals.ip.netlinkFd);
512             caglobals.ip.netlinkFd = -1;
513         }
514         else
515         {
516             CHECKFD(caglobals.ip.netlinkFd);
517         }
518     }
519 #endif
520 }
521
522 static void CAInitializePipe()
523 {
524     caglobals.ip.selectTimeout = -1;
525 #ifdef HAVE_PIPE2
526     int ret = pipe2(caglobals.ip.shutdownFds, O_CLOEXEC);
527 #else
528     int ret = pipe(caglobals.ip.shutdownFds);
529     if (-1 != ret)
530     {
531         ret = fcntl(caglobals.ip.shutdownFds[0], F_GETFD);
532         if (-1 != ret)
533         {
534             ret = fcntl(caglobals.ip.shutdownFds[0], F_SETFD, ret|FD_CLOEXEC);
535         }
536         if (-1 != ret)
537         {
538             ret = fcntl(caglobals.ip.shutdownFds[1], F_GETFD);
539         }
540         if (-1 != ret)
541         {
542             ret = fcntl(caglobals.ip.shutdownFds[1], F_SETFD, ret|FD_CLOEXEC);
543         }
544         if (-1 == ret)
545         {
546             close(caglobals.ip.shutdownFds[1]);
547             close(caglobals.ip.shutdownFds[0]);
548             caglobals.ip.shutdownFds[0] = -1;
549             caglobals.ip.shutdownFds[1] = -1;
550         }
551     }
552 #endif
553     if (-1 == ret)
554     {
555         OIC_LOG_V(ERROR, TAG, "pipe failed: %s", strerror(errno));
556         caglobals.ip.selectTimeout = SELECT_TIMEOUT; //poll needed for shutdown
557     }
558 }
559
560 CAResult_t CAIPStartServer(const ca_thread_pool_t threadPool)
561 {
562     CAResult_t res = CA_STATUS_OK;
563
564     if (caglobals.ip.started)
565     {
566         return res;
567     }
568
569     if (!IPv4MulticastAddress.s_addr)
570     {
571         (void)inet_pton(AF_INET, IPv4_MULTICAST, &IPv4MulticastAddress);
572         (void)inet_pton(AF_INET6, IPv6_MULTICAST_INT, &IPv6MulticastAddressInt);
573         (void)inet_pton(AF_INET6, IPv6_MULTICAST_LNK, &IPv6MulticastAddressLnk);
574         (void)inet_pton(AF_INET6, IPv6_MULTICAST_RLM, &IPv6MulticastAddressRlm);
575         (void)inet_pton(AF_INET6, IPv6_MULTICAST_ADM, &IPv6MulticastAddressAdm);
576         (void)inet_pton(AF_INET6, IPv6_MULTICAST_SIT, &IPv6MulticastAddressSit);
577         (void)inet_pton(AF_INET6, IPv6_MULTICAST_ORG, &IPv6MulticastAddressOrg);
578         (void)inet_pton(AF_INET6, IPv6_MULTICAST_GLB, &IPv6MulticastAddressGlb);
579     }
580
581     if (!caglobals.ip.ipv6enabled && !caglobals.ip.ipv4enabled)
582     {
583         caglobals.ip.ipv4enabled = true;  // only needed to run CA tests
584     }
585
586     if (caglobals.ip.ipv6enabled)
587     {
588         NEWSOCKET(AF_INET6, u6)
589         NEWSOCKET(AF_INET6, u6s)
590         NEWSOCKET(AF_INET6, m6)
591         NEWSOCKET(AF_INET6, m6s)
592         OIC_LOG_V(INFO, TAG, "IPv6 unicast port: %u", caglobals.ip.u6.port);
593     }
594     if (caglobals.ip.ipv4enabled)
595     {
596         NEWSOCKET(AF_INET, u4)
597         NEWSOCKET(AF_INET, u4s)
598         NEWSOCKET(AF_INET, m4)
599         NEWSOCKET(AF_INET, m4s)
600         OIC_LOG_V(INFO, TAG, "IPv4 unicast port: %u", caglobals.ip.u4.port);
601     }
602
603     OIC_LOG_V(DEBUG, TAG,
604               "socket summary: u6=%d, u6s=%d, u4=%d, u4s=%d, m6=%d, m6s=%d, m4=%d, m4s=%d",
605               caglobals.ip.u6.fd, caglobals.ip.u6s.fd, caglobals.ip.u4.fd, caglobals.ip.u4s.fd,
606               caglobals.ip.m6.fd, caglobals.ip.m6s.fd, caglobals.ip.m4.fd, caglobals.ip.m4s.fd);
607
608     OIC_LOG_V(DEBUG, TAG,
609               "port summary: u6 port=%d, u6s port=%d, u4 port=%d, u4s port=%d, m6 port=%d,"
610               "m6s port=%d, m4 port=%d, m4s port=%d",
611               caglobals.ip.u6.port, caglobals.ip.u6s.port, caglobals.ip.u4.port,
612               caglobals.ip.u4s.port, caglobals.ip.m6.port, caglobals.ip.m6s.port,
613               caglobals.ip.m4.port, caglobals.ip.m4s.port);
614     // create pipe for fast shutdown
615     CAInitializePipe();
616     CHECKFD(caglobals.ip.shutdownFds[0]);
617     CHECKFD(caglobals.ip.shutdownFds[1]);
618
619     // create source of network interface change notifications
620     CAInitializeNetlink();
621
622     caglobals.ip.selectTimeout = CAGetPollingInterval(caglobals.ip.selectTimeout);
623
624     res = CAIPStartListenServer();
625     if (CA_STATUS_OK != res)
626     {
627         OIC_LOG_V(ERROR, TAG, "Failed to start listening server![%d]", res);
628         return res;
629     }
630
631     caglobals.ip.terminate = false;
632     res = ca_thread_pool_add_task(threadPool, CAReceiveHandler, NULL);
633     if (CA_STATUS_OK != res)
634     {
635         OIC_LOG(ERROR, TAG, "thread_pool_add_task failed");
636         return res;
637     }
638     OIC_LOG(DEBUG, TAG, "CAReceiveHandler thread started successfully.");
639
640     caglobals.ip.started = true;
641     return CA_STATUS_OK;
642 }
643
644 void CAIPStopServer()
645 {
646     caglobals.ip.started = false;
647     caglobals.ip.terminate = true;
648
649     if (caglobals.ip.shutdownFds[1] != -1)
650     {
651         close(caglobals.ip.shutdownFds[1]);
652         // receive thread will stop immediately
653     }
654     else
655     {
656         // receive thread will stop in SELECT_TIMEOUT seconds.
657     }
658 }
659
660 void CAWakeUpForChange()
661 {
662     if (caglobals.ip.shutdownFds[1] != -1)
663     {
664         ssize_t len = 0;
665         do
666         {
667             len = write(caglobals.ip.shutdownFds[1], "w", 1);
668         } while ((len == -1) && (errno == EINTR));
669         if ((len == -1) && (errno != EINTR) && (errno != EPIPE))
670         {
671             OIC_LOG_V(DEBUG, TAG, "write failed: %s", strerror(errno));
672         }
673     }
674 }
675
676 static void applyMulticastToInterface4(struct in_addr inaddr)
677 {
678     if (!caglobals.ip.ipv4enabled)
679     {
680         return;
681     }
682
683     struct ip_mreqn mreq = { .imr_multiaddr = IPv4MulticastAddress,
684                              .imr_address = inaddr,
685                              .imr_ifindex = 0 };
686     if (setsockopt(caglobals.ip.m4.fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof (mreq)))
687     {
688         if (EADDRINUSE != errno)
689         {
690             OIC_LOG_V(ERROR, TAG, "IPv4 IP_ADD_MEMBERSHIP failed: %s", strerror(errno));
691         }
692     }
693     if (setsockopt(caglobals.ip.m4s.fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof (mreq)))
694     {
695         if (EADDRINUSE != errno)
696         {
697             OIC_LOG_V(ERROR, TAG, "secure IPv4 IP_ADD_MEMBERSHIP failed: %s", strerror(errno));
698         }
699     }
700 }
701
702 static void applyMulticast6(int fd, struct in6_addr *addr, uint32_t interface)
703 {
704     struct ipv6_mreq mreq = {.ipv6mr_multiaddr = *addr, .ipv6mr_interface = interface};
705
706     if (setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof (mreq)))
707     {
708         if (EADDRINUSE != errno)
709         {
710             OIC_LOG_V(ERROR, TAG, "IPv6 IP_ADD_MEMBERSHIP failed: %s", strerror(errno));
711         }
712     }
713 }
714
715 static void applyMulticastToInterface6(uint32_t interface)
716 {
717     if (!caglobals.ip.ipv6enabled)
718     {
719         return;
720     }
721     //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressInt, interface);
722     applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressLnk, interface);
723     //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressRlm, interface);
724     //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressAdm, interface);
725     //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressSit, interface);
726     //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressOrg, interface);
727     //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressGlb, interface);
728
729     //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressInt, interface);
730     applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressLnk, interface);
731     //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressRlm, interface);
732     //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressAdm, interface);
733     //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressSit, interface);
734     //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressOrg, interface);
735     //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressGlb, interface);
736 }
737
738 CAResult_t CAIPStartListenServer()
739 {
740     u_arraylist_t *iflist = CAIPGetInterfaceInformation(0);
741     if (!iflist)
742     {
743         OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno));
744         return CA_STATUS_FAILED;
745     }
746
747     uint32_t len = u_arraylist_length(iflist);
748     OIC_LOG_V(DEBUG, TAG, "IP network interfaces found: %d", len);
749
750     for (uint32_t i = 0; i < len; i++)
751     {
752         CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
753
754         if (!ifitem)
755         {
756             continue;
757         }
758         if ((ifitem->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
759         {
760             continue;
761         }
762         if (ifitem->family == AF_INET)
763         {
764             struct in_addr inaddr;
765             inaddr.s_addr = ifitem->ipv4addr;
766             applyMulticastToInterface4(inaddr);
767             OIC_LOG_V(DEBUG, TAG, "IPv4 network interface: %s", ifitem->name);
768         }
769         if (ifitem->family == AF_INET6)
770         {
771             applyMulticastToInterface6(ifitem->index);
772             OIC_LOG_V(DEBUG, TAG, "IPv6 network interface: %s", ifitem->name);
773         }
774     }
775
776     u_arraylist_destroy(iflist);
777     return CA_STATUS_OK;
778 }
779
780 CAResult_t CAIPStopListenServer()
781 {
782     u_arraylist_t *iflist = CAIPGetInterfaceInformation(0);
783     if (!iflist)
784     {
785         OIC_LOG_V(ERROR, TAG, "Get interface info failed: %s", strerror(errno));
786         return CA_STATUS_FAILED;
787     }
788
789     uint32_t len = u_arraylist_length(iflist);
790     OIC_LOG_V(DEBUG, TAG, "IP network interfaces found: %d", len);
791
792     for (uint32_t i = 0; i < len; i++)
793     {
794         CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
795
796         if (!ifitem)
797         {
798             continue;
799         }
800
801         if ((ifitem->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
802         {
803             continue;
804         }
805         if (ifitem->family == AF_INET)
806         {
807             close(caglobals.ip.m4.fd);
808             close(caglobals.ip.m4s.fd);
809             caglobals.ip.m4.fd = -1;
810             caglobals.ip.m4s.fd = -1;
811             OIC_LOG_V(DEBUG, TAG, "IPv4 network interface: %s cloed", ifitem->name);
812         }
813         if (ifitem->family == AF_INET6)
814         {
815             close(caglobals.ip.m6.fd);
816             close(caglobals.ip.m6s.fd);
817             caglobals.ip.m6.fd = -1;
818             caglobals.ip.m6s.fd = -1;
819             OIC_LOG_V(DEBUG, TAG, "IPv6 network interface: %s", ifitem->name);
820         }
821     }
822     u_arraylist_destroy(iflist);
823     return CA_STATUS_OK;
824 }
825
826 static void CAProcessNewInterface(CAInterface_t *ifitem)
827 {
828     if (!ifitem)
829     {
830         OIC_LOG(DEBUG, TAG, "ifitem is null");
831         return;
832     }
833
834     applyMulticastToInterface6(ifitem->index);
835     struct in_addr inaddr = { .s_addr = ifitem->ipv4addr };
836     applyMulticastToInterface4(inaddr);
837 }
838 static void CAHandleNetlink()
839 {
840 #ifdef __linux__
841     char buf[4096];
842     struct nlmsghdr *nh;
843     struct sockaddr_nl sa;
844     struct iovec iov = { buf, sizeof (buf) };
845     struct msghdr msg = { (void *)&sa, sizeof (sa), &iov, 1, NULL, 0, 0 };
846
847     size_t len = recvmsg(caglobals.ip.netlinkFd, &msg, 0);
848
849     for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len))
850     {
851         if (nh != NULL && nh->nlmsg_type != RTM_NEWLINK)
852         {
853             continue;
854         }
855
856         struct ifinfomsg *ifi = (struct ifinfomsg *)NLMSG_DATA(nh);
857         if (!ifi || (ifi->ifi_flags & IFF_LOOPBACK) || !(ifi->ifi_flags & IFF_RUNNING))
858         {
859             continue;
860         }
861
862         int newIndex = ifi->ifi_index;
863
864         u_arraylist_t *iflist = CAIPGetInterfaceInformation(newIndex);
865         if (!iflist)
866         {
867             OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno));
868             return;
869         }
870
871         uint32_t listLength = u_arraylist_length(iflist);
872         for (uint32_t i = 0; i < listLength; i++)
873         {
874             CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
875             if (!ifitem)
876             {
877                 continue;
878             }
879
880             if ((int)ifitem->index != newIndex)
881             {
882                 continue;
883             }
884
885             CAProcessNewInterface(ifitem);
886             break; // we found the one we were looking for
887         }
888         u_arraylist_destroy(iflist);
889     }
890 #endif // __linux__
891 }
892
893 void CAIPSetPacketReceiveCallback(CAIPPacketReceivedCallback callback)
894 {
895     g_packetReceivedCallback = callback;
896 }
897
898 void CAIPSetExceptionCallback(CAIPExceptionCallback callback)
899 {
900     g_exceptionCallback = callback;
901 }
902
903 static void sendData(int fd, const CAEndpoint_t *endpoint,
904                      const void *data, uint32_t dlen,
905                      const char *cast, const char *fam)
906 {
907     OIC_LOG(DEBUG, TAG, "IN");
908
909     if (!endpoint)
910     {
911         OIC_LOG(DEBUG, TAG, "endpoint is null");
912         return;
913     }
914
915     char *secure = (endpoint->flags & CA_SECURE) ? "secure " : "";
916     (void)secure;   // eliminates release warning
917     struct sockaddr_storage sock;
918     CAConvertNameToAddr(endpoint->addr, endpoint->port, &sock);
919
920     socklen_t socklen;
921     if (sock.ss_family == AF_INET6)
922     {
923         struct sockaddr_in6 *sock6 = (struct sockaddr_in6 *)&sock;
924         if (!sock6->sin6_scope_id)
925         {
926             sock6->sin6_scope_id = endpoint->interface;
927         }
928         socklen = sizeof(struct sockaddr_in6);
929     }
930     else
931     {
932         socklen = sizeof(struct sockaddr_in);
933     }
934
935     ssize_t len = sendto(fd, data, dlen, 0, (struct sockaddr *)&sock, socklen);
936     if (-1 == len)
937     {
938          // If logging is not defined/enabled.
939         (void)cast;
940         (void)fam;
941         OIC_LOG_V(ERROR, TAG, "%s%s %s sendTo failed: %s", secure, cast, fam, strerror(errno));
942     }
943     else
944     {
945         OIC_LOG_V(INFO, TAG, "%s%s %s sendTo is successful: %zd bytes", secure, cast, fam, len);
946     }
947 }
948
949 static void sendMulticastData6(const u_arraylist_t *iflist,
950                                CAEndpoint_t *endpoint,
951                                const void *data, uint32_t datalen)
952 {
953     if (!endpoint)
954     {
955         OIC_LOG(DEBUG, TAG, "endpoint is null");
956         return;
957     }
958
959     int scope = endpoint->flags & CA_SCOPE_MASK;
960     char *ipv6mcname = ipv6mcnames[scope];
961     if (!ipv6mcname)
962     {
963         OIC_LOG_V(INFO, TAG, "IPv6 multicast scope invalid: %d", scope);
964         return;
965     }
966     OICStrcpy(endpoint->addr, sizeof(endpoint->addr), ipv6mcname);
967     int fd = caglobals.ip.u6.fd;
968
969     uint32_t len = u_arraylist_length(iflist);
970     for (uint32_t i = 0; i < len; i++)
971     {
972         CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
973         if (!ifitem)
974         {
975             continue;
976         }
977         if ((ifitem->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
978         {
979             continue;
980         }
981         if (ifitem->family != AF_INET6)
982         {
983             continue;
984         }
985
986         int index = ifitem->index;
987         if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &index, sizeof (index)))
988         {
989             OIC_LOG_V(ERROR, TAG, "setsockopt6 failed: %s", strerror(errno));
990             return;
991         }
992         sendData(fd, endpoint, data, datalen, "multicast", "ipv6");
993     }
994 }
995
996 static void sendMulticastData4(const u_arraylist_t *iflist,
997                                CAEndpoint_t *endpoint,
998                                const void *data, uint32_t datalen)
999 {
1000     VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL");
1001
1002     struct ip_mreqn mreq = { .imr_multiaddr = IPv4MulticastAddress,
1003                              .imr_ifindex = 0 };
1004     OICStrcpy(endpoint->addr, sizeof(endpoint->addr), IPv4_MULTICAST);
1005     int fd = caglobals.ip.u4.fd;
1006
1007     uint32_t len = u_arraylist_length(iflist);
1008     for (uint32_t i = 0; i < len; i++)
1009     {
1010         CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
1011         if (!ifitem)
1012         {
1013             continue;
1014         }
1015         if ((ifitem->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
1016         {
1017             continue;
1018         }
1019         if (ifitem->family != AF_INET)
1020         {
1021             continue;
1022         }
1023
1024         struct in_addr inaddr;
1025         inaddr.s_addr = ifitem->ipv4addr;
1026         mreq.imr_address = inaddr;
1027         if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, &mreq, sizeof (mreq)))
1028         {
1029             OIC_LOG_V(ERROR, TAG, "send IP_MULTICAST_IF failed: %s (using defualt)",
1030                     strerror(errno));
1031         }
1032         sendData(fd, endpoint, data, datalen, "multicast", "ipv4");
1033     }
1034 }
1035
1036 void CAIPSendData(CAEndpoint_t *endpoint, const void *data, uint32_t datalen,
1037                   bool isMulticast)
1038 {
1039     VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL");
1040     VERIFY_NON_NULL_VOID(data, TAG, "data is NULL");
1041
1042     bool isSecure = (endpoint->flags & CA_SECURE) != 0;
1043
1044     if (isMulticast)
1045     {
1046         endpoint->port = isSecure ? CA_SECURE_COAP : CA_COAP;
1047
1048         u_arraylist_t *iflist = CAIPGetInterfaceInformation(0);
1049         if (!iflist)
1050         {
1051             OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno));
1052             return;
1053         }
1054
1055         if ((endpoint->flags & CA_IPV6) && caglobals.ip.ipv6enabled)
1056         {
1057             sendMulticastData6(iflist, endpoint, data, datalen);
1058         }
1059         if ((endpoint->flags & CA_IPV4) && caglobals.ip.ipv4enabled)
1060         {
1061             sendMulticastData4(iflist, endpoint, data, datalen);
1062         }
1063
1064         u_arraylist_destroy(iflist);
1065     }
1066     else
1067     {
1068         if (!endpoint->port)    // unicast discovery
1069         {
1070             endpoint->port = isSecure ? CA_SECURE_COAP : CA_COAP;
1071         }
1072
1073         int fd;
1074         if (caglobals.ip.ipv6enabled && (endpoint->flags & CA_IPV6))
1075         {
1076             fd = isSecure ? caglobals.ip.u6s.fd : caglobals.ip.u6.fd;
1077 #ifndef __WITH_DTLS__
1078             fd = caglobals.ip.u6.fd;
1079 #endif
1080             sendData(fd, endpoint, data, datalen, "unicast", "ipv6");
1081         }
1082         if (caglobals.ip.ipv4enabled && (endpoint->flags & CA_IPV4))
1083         {
1084             fd = isSecure ? caglobals.ip.u4s.fd : caglobals.ip.u4.fd;
1085 #ifndef __WITH_DTLS__
1086             fd = caglobals.ip.u4.fd;
1087 #endif
1088             sendData(fd, endpoint, data, datalen, "unicast", "ipv4");
1089         }
1090     }
1091 }
1092
1093 CAResult_t CAGetIPInterfaceInformation(CAEndpoint_t **info, uint32_t *size)
1094 {
1095     VERIFY_NON_NULL(info, TAG, "info is NULL");
1096     VERIFY_NON_NULL(size, TAG, "size is NULL");
1097
1098     u_arraylist_t *iflist = CAIPGetInterfaceInformation(0);
1099     if (!iflist)
1100     {
1101         OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno));
1102         return CA_STATUS_FAILED;
1103     }
1104
1105     uint32_t len = u_arraylist_length(iflist);
1106     uint32_t length = len;
1107
1108 #ifdef __WITH_DTLS__
1109     //If DTLS is supported, each interface can support secure port as well
1110     length = len * 2;
1111 #endif
1112
1113     CAEndpoint_t *eps = (CAEndpoint_t *)OICCalloc(length, sizeof (CAEndpoint_t));
1114     if (!eps)
1115     {
1116         OIC_LOG(ERROR, TAG, "Malloc Failed");
1117         u_arraylist_destroy(iflist);
1118         return CA_MEMORY_ALLOC_FAILED;
1119     }
1120
1121     for (uint32_t i = 0, j = 0; i < len; i++)
1122     {
1123         CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
1124         if(!ifitem)
1125         {
1126             continue;
1127         }
1128
1129         eps[j].adapter = CA_ADAPTER_IP;
1130         eps[j].interface = 0;
1131
1132         if (ifitem->family == AF_INET6)
1133         {
1134             eps[j].flags = CA_IPV6;
1135             eps[j].port = caglobals.ip.u6.port;
1136         }
1137         else
1138         {
1139             eps[j].flags = CA_IPV4;
1140             eps[j].port = caglobals.ip.u4.port;
1141
1142             inet_ntop(AF_INET, &(ifitem->ipv4addr), eps[j].addr, MAX_ADDR_STR_SIZE_CA);
1143         }
1144
1145 #ifdef __WITH_DTLS__
1146         j++;
1147
1148         eps[j].adapter = CA_ADAPTER_IP;
1149         eps[j].interface = 0;
1150
1151         if (ifitem->family == AF_INET6)
1152         {
1153             eps[j].flags = CA_IPV6 | CA_SECURE;
1154             eps[j].port = caglobals.ip.u6s.port;
1155         }
1156         else
1157         {
1158             eps[j].flags = CA_IPV4 | CA_SECURE;
1159             eps[j].port = caglobals.ip.u4s.port;
1160             inet_ntop(AF_INET, &(ifitem->ipv4addr), eps[j].addr, MAX_ADDR_STR_SIZE_CA);
1161         }
1162 #endif
1163         j++;
1164     }
1165
1166     *info = eps;
1167     *size = len;
1168
1169     u_arraylist_destroy(iflist);
1170
1171     return CA_STATUS_OK;
1172 }