[IOT-1361]Change "CAFindInterfaceChange()" to support IPv4/6
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / ip_adapter / caipserver.c
1 /* ****************************************************************
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 "iotivity_config.h"
29 #include <sys/types.h>
30 #ifdef HAVE_SYS_SOCKET_H
31 #include <sys/socket.h>
32 #endif
33 #include <assert.h>
34 #ifdef HAVE_WINSOCK2_H
35 #include <winsock2.h>
36 #endif
37 #ifdef HAVE_WS2TCPIP_H
38 #include <ws2tcpip.h>
39 #endif
40 #include <stdio.h>
41 #ifdef HAVE_UNISTD_H
42 #include <unistd.h>
43 #endif
44 #include <fcntl.h>
45 #ifdef HAVE_SYS_SELECT_H
46 #include <sys/select.h>
47 #endif
48 #ifdef HAVE_ARPA_INET_H
49 #include <arpa/inet.h>
50 #endif
51 #ifdef HAVE_NETINET_IN_H
52 #include <netinet/in.h>
53 #endif
54 #ifdef HAVE_NET_IF_H
55 #include <net/if.h>
56 #endif
57 #include <errno.h>
58 #ifdef __linux__
59 #include <linux/netlink.h>
60 #include <linux/rtnetlink.h>
61 #endif
62
63 #include <coap/pdu.h>
64 #include "caipinterface.h"
65 #include "caipnwmonitor.h"
66 #include "caadapterutils.h"
67 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
68 #include "ca_adapter_net_ssl.h"
69 #endif
70 #include "octhread.h"
71 #include "oic_malloc.h"
72 #include "oic_string.h"
73
74 #define USE_IP_MREQN
75 #if defined(_WIN32)
76 #undef USE_IP_MREQN
77 #endif
78
79 /*
80  * Logging tag for module name
81  */
82 #define TAG "OIC_CA_IP_SERVER"
83
84 #define SELECT_TIMEOUT 1     // select() seconds (and termination latency)
85
86 #define IPv4_MULTICAST     "224.0.1.187"
87 static struct in_addr IPv4MulticastAddress = { 0 };
88
89 #define IPv6_DOMAINS       16
90 #define IPv6_MULTICAST_INT "ff01::158"
91 static struct in6_addr IPv6MulticastAddressInt;
92 #define IPv6_MULTICAST_LNK "ff02::158"
93 static struct in6_addr IPv6MulticastAddressLnk;
94 #define IPv6_MULTICAST_RLM "ff03::158"
95 static struct in6_addr IPv6MulticastAddressRlm;
96 #define IPv6_MULTICAST_ADM "ff04::158"
97 static struct in6_addr IPv6MulticastAddressAdm;
98 #define IPv6_MULTICAST_SIT "ff05::158"
99 static struct in6_addr IPv6MulticastAddressSit;
100 #define IPv6_MULTICAST_ORG "ff08::158"
101 static struct in6_addr IPv6MulticastAddressOrg;
102 #define IPv6_MULTICAST_GLB "ff0e::158"
103 static struct in6_addr IPv6MulticastAddressGlb;
104
105 static char *ipv6mcnames[IPv6_DOMAINS] = {
106     NULL,
107     IPv6_MULTICAST_INT,
108     IPv6_MULTICAST_LNK,
109     IPv6_MULTICAST_RLM,
110     IPv6_MULTICAST_ADM,
111     IPv6_MULTICAST_SIT,
112     NULL,
113     NULL,
114     IPv6_MULTICAST_ORG,
115     NULL,
116     NULL,
117     NULL,
118     NULL,
119     NULL,
120     IPv6_MULTICAST_GLB,
121     NULL
122 };
123
124 #if defined (_WIN32)
125 #define IFF_UP_RUNNING_FLAGS  (IFF_UP)
126
127     char* caips_get_error(){
128         static char buffer[32];
129         snprintf(buffer, 32, "%i", WSAGetLastError());
130         return buffer;
131     }
132 #define CAIPS_GET_ERROR \
133     caips_get_error()
134 #else
135 #define IFF_UP_RUNNING_FLAGS  (IFF_UP|IFF_RUNNING)
136
137 #define CAIPS_GET_ERROR \
138     strerror(errno)
139 #endif
140 static CAIPErrorHandleCallback g_ipErrorHandler = NULL;
141
142 static CAIPPacketReceivedCallback g_packetReceivedCallback = NULL;
143
144 static void CAFindReadyMessage();
145 #if !defined(WSA_WAIT_EVENT_0)
146 static void CASelectReturned(fd_set *readFds, int ret);
147 #else
148 static void CAEventReturned(CASocketFd_t socket);
149 #endif
150 static void CAProcessNewInterface(CAInterface_t *ifchanged);
151 static CAResult_t CAReceiveMessage(CASocketFd_t fd, CATransportFlags_t flags);
152
153 static void CAReceiveHandler(void *data)
154 {
155     (void)data;
156
157     while (!caglobals.ip.terminate)
158     {
159         CAFindReadyMessage();
160     }
161 }
162
163 #if !defined(WSA_WAIT_EVENT_0)
164
165 #define CLOSE_SOCKET(TYPE) \
166     if (caglobals.ip.TYPE.fd != OC_INVALID_SOCKET) \
167     { \
168         close(caglobals.ip.TYPE.fd); \
169         caglobals.ip.TYPE.fd = OC_INVALID_SOCKET; \
170     }
171
172 #define SET(TYPE, FDS) \
173     if (caglobals.ip.TYPE.fd != OC_INVALID_SOCKET) \
174     { \
175         FD_SET(caglobals.ip.TYPE.fd, FDS); \
176     }
177
178 #define ISSET(TYPE, FDS, FLAGS) \
179     if (caglobals.ip.TYPE.fd != OC_INVALID_SOCKET && FD_ISSET(caglobals.ip.TYPE.fd, FDS)) \
180     { \
181         fd = caglobals.ip.TYPE.fd; \
182         flags = FLAGS; \
183     }
184
185
186 static void CAFindReadyMessage()
187 {
188     fd_set readFds;
189     struct timeval timeout;
190
191     timeout.tv_sec = caglobals.ip.selectTimeout;
192     timeout.tv_usec = 0;
193     struct timeval *tv = caglobals.ip.selectTimeout == -1 ? NULL : &timeout;
194
195     FD_ZERO(&readFds);
196     SET(u6,  &readFds)
197     SET(u6s, &readFds)
198     SET(u4,  &readFds)
199     SET(u4s, &readFds)
200     SET(m6,  &readFds)
201     SET(m6s, &readFds)
202     SET(m4,  &readFds)
203     SET(m4s, &readFds)
204
205     if (caglobals.ip.shutdownFds[0] != -1)
206     {
207         FD_SET(caglobals.ip.shutdownFds[0], &readFds);
208     }
209     if (caglobals.ip.netlinkFd != OC_INVALID_SOCKET)
210     {
211         FD_SET(caglobals.ip.netlinkFd, &readFds);
212     }
213
214     int ret = select(caglobals.ip.maxfd + 1, &readFds, NULL, NULL, tv);
215
216     if (caglobals.ip.terminate)
217     {
218         OIC_LOG_V(DEBUG, TAG, "Packet receiver Stop request received.");
219         return;
220     }
221
222     if (ret <= 0)
223     {
224         if (ret < 0)
225         {
226             OIC_LOG_V(FATAL, TAG, "select error %s", CAIPS_GET_ERROR);
227         }
228         return;
229     }
230
231     CASelectReturned(&readFds, ret);
232 }
233
234 static void CASelectReturned(fd_set *readFds, int ret)
235 {
236     (void)ret;
237     CASocketFd_t fd = OC_INVALID_SOCKET;
238     CATransportFlags_t flags = CA_DEFAULT_FLAGS;
239
240     while (!caglobals.ip.terminate)
241     {
242         ISSET(u6,  readFds, CA_IPV6)
243         else ISSET(u6s, readFds, CA_IPV6 | CA_SECURE)
244         else ISSET(u4,  readFds, CA_IPV4)
245         else ISSET(u4s, readFds, CA_IPV4 | CA_SECURE)
246         else ISSET(m6,  readFds, CA_MULTICAST | CA_IPV6)
247         else ISSET(m6s, readFds, CA_MULTICAST | CA_IPV6 | CA_SECURE)
248         else ISSET(m4,  readFds, CA_MULTICAST | CA_IPV4)
249         else ISSET(m4s, readFds, CA_MULTICAST | CA_IPV4 | CA_SECURE)
250         else if ((caglobals.ip.netlinkFd != OC_INVALID_SOCKET) && FD_ISSET(caglobals.ip.netlinkFd, readFds))
251         {
252             u_arraylist_t *iflist = CAFindInterfaceChange();
253             if (iflist)
254             {
255                 uint32_t listLength = u_arraylist_length(iflist);
256                 for (uint32_t i = 0; i < listLength; i++)
257                 {
258                     CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
259                     if (ifitem)
260                     {
261                         CAProcessNewInterface(ifitem);
262                     }
263                 }
264                 u_arraylist_destroy(iflist);
265             }
266             break;
267         }
268         else if (FD_ISSET(caglobals.ip.shutdownFds[0], readFds))
269         {
270             char buf[10] = {0};
271             ssize_t len = read(caglobals.ip.shutdownFds[0], buf, sizeof (buf));
272             if (-1 == len)
273             {
274                 continue;
275             }
276             break;
277         }
278         else
279         {
280             break;
281         }
282         (void)CAReceiveMessage(fd, flags);
283         FD_CLR(fd, readFds);
284     }
285 }
286
287 #else // if defined(WSA_WAIT_EVENT_0)
288
289 #define CLOSE_SOCKET(TYPE) \
290     if (caglobals.ip.TYPE.fd != OC_INVALID_SOCKET) \
291     { \
292         closesocket(caglobals.ip.TYPE.fd); \
293         caglobals.ip.TYPE.fd = OC_INVALID_SOCKET; \
294     }
295
296 #define PUSH_HANDLE(HANDLE, ARRAY, INDEX) \
297 { \
298     ARRAY[INDEX] = HANDLE; \
299     INDEX++; \
300 }
301
302 // Turn handle into WSAEvent and push to ARRAY
303 #define PUSH_SOCKET(SOCKET, ARRAY, INDEX) \
304     if (SOCKET != OC_INVALID_SOCKET) \
305     { \
306         WSAEVENT NewEvent; \
307         NewEvent = WSACreateEvent(); \
308         if (WSA_INVALID_EVENT != NewEvent) \
309         { \
310             if (0 != WSAEventSelect(SOCKET, NewEvent, FD_READ)) \
311             { \
312                 OIC_LOG_V(ERROR, TAG, "WSAEventSelect failed 0x%08x ", WSAGetLastError()); \
313                 if (!WSACloseEvent(NewEvent)) \
314                 { \
315                     OIC_LOG_V(ERROR, TAG, "WSACloseEvent(NewEvent) failed 0x%08x", WSAGetLastError()); \
316                 } \
317             } \
318             else \
319             { \
320                 PUSH_HANDLE(NewEvent, ARRAY, INDEX); \
321             } \
322         } \
323         else \
324         { \
325             OIC_LOG_V(ERROR, TAG, "WSACreateEvent(NewEvent) failed 0x%08x", WSAGetLastError()); \
326         }\
327     }
328
329 #define INSERT_SOCKET(FD, ARRAY, INDEX) \
330     { \
331         if (OC_INVALID_SOCKET != FD) \
332         { \
333             ARRAY[INDEX] = FD; \
334         } \
335     }
336
337
338 // Inserts the socket into the SOCKET_ARRAY and pushes the socket event into EVENT_ARRAY
339 #define PUSH_IP_SOCKET(TYPE, EVENT_ARRAY, SOCKET_ARRAY, INDEX) \
340     { \
341         if (OC_INVALID_SOCKET != caglobals.ip.TYPE.fd) \
342         { \
343             INSERT_SOCKET(caglobals.ip.TYPE.fd, SOCKET_ARRAY, INDEX); \
344             PUSH_SOCKET(caglobals.ip.TYPE.fd, EVENT_ARRAY, INDEX); \
345         } \
346     }
347
348 #define IS_MATCHING_IP_SOCKET(TYPE, SOCKET, FLAGS) \
349     if ((caglobals.ip.TYPE.fd != OC_INVALID_SOCKET) && (caglobals.ip.TYPE.fd == SOCKET)) \
350     { \
351         fd = caglobals.ip.TYPE.fd; \
352         flags = FLAGS; \
353     }
354
355 #define EVENT_ARRAY_SIZE  10
356
357 static void CAFindReadyMessage()
358 {
359     CASocketFd_t socketArray[EVENT_ARRAY_SIZE];
360     HANDLE eventArray[EVENT_ARRAY_SIZE];
361     int arraySize = 0;
362     int eventIndex;
363
364     // socketArray and eventArray should have same number of elements
365     OC_STATIC_ASSERT(_countof(socketArray) == _countof(eventArray), "Arrays should have same number of elements");
366
367     PUSH_IP_SOCKET(u6,  eventArray, socketArray, arraySize);
368     PUSH_IP_SOCKET(u6s, eventArray, socketArray, arraySize);
369     PUSH_IP_SOCKET(u4,  eventArray, socketArray, arraySize);
370     PUSH_IP_SOCKET(u4s, eventArray, socketArray, arraySize);
371     PUSH_IP_SOCKET(m6,  eventArray, socketArray, arraySize);
372     PUSH_IP_SOCKET(m6s, eventArray, socketArray, arraySize);
373     PUSH_IP_SOCKET(m4,  eventArray, socketArray, arraySize);
374     PUSH_IP_SOCKET(m4s, eventArray, socketArray, arraySize);
375
376     if (WSA_INVALID_EVENT != caglobals.ip.shutdownEvent)
377     {
378         INSERT_SOCKET(OC_INVALID_SOCKET, socketArray, arraySize);
379         PUSH_HANDLE(caglobals.ip.shutdownEvent, eventArray, arraySize);
380     }
381
382     if (WSA_INVALID_EVENT != caglobals.ip.addressChangeEvent)
383     {
384         INSERT_SOCKET(OC_INVALID_SOCKET, socketArray, arraySize);
385         PUSH_HANDLE(caglobals.ip.addressChangeEvent, eventArray, arraySize);
386     }
387
388     // Should not have overflowed buffer
389     assert(arraySize <= (_countof(socketArray)));
390
391     // Timeout is unnecessary on Windows
392     assert(-1 == caglobals.ip.selectTimeout);
393
394     while (!caglobals.ip.terminate)
395     {
396         int ret = WSAWaitForMultipleEvents(arraySize, eventArray, FALSE, WSA_INFINITE, FALSE);
397
398         switch (ret)
399         {
400             case WSA_WAIT_FAILED:
401                 OIC_LOG_V(ERROR, TAG, "WSAWaitForMultipleEvents returned WSA_WAIT_FAILED 0x%08x", WSAGetLastError());
402                 break;
403             case WSA_WAIT_IO_COMPLETION:
404                 OIC_LOG_V(ERROR, TAG, "WSAWaitForMultipleEvents returned WSA_WAIT_IO_COMPLETION 0x%08x", WSAGetLastError());
405                 break;
406             case WSA_WAIT_TIMEOUT:
407                 OIC_LOG_V(ERROR, TAG, "WSAWaitForMultipleEvents returned WSA_WAIT_TIMEOUT 0x%08x", WSAGetLastError());
408                 break;
409             default:
410                 eventIndex = ret - WSA_WAIT_EVENT_0;
411                 if ((eventIndex >= 0) && (eventIndex < arraySize))
412                 {
413                     if (false == WSAResetEvent(eventArray[eventIndex]))
414                     {
415                         OIC_LOG_V(ERROR, TAG, "WSAResetEvent failed 0x%08x", WSAGetLastError());
416                     }
417
418                     // Handle address changes if addressChangeEvent is triggered.
419                     if ((caglobals.ip.addressChangeEvent != WSA_INVALID_EVENT) &&
420                         (caglobals.ip.addressChangeEvent == eventArray[eventIndex]))
421                     {
422                         u_arraylist_t *iflist = CAFindInterfaceChange();
423                         if (iflist)
424                         {
425                             uint32_t listLength = u_arraylist_length(iflist);
426                             for (uint32_t i = 0; i < listLength; i++)
427                             {
428                                 CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
429                                 if (ifitem)
430                                 {
431                                     CAProcessNewInterface(ifitem);
432                                 }
433                             }
434                             u_arraylist_destroy(iflist);
435                         }
436                         break;
437                     }
438
439                     // Break out if shutdownEvent is triggered.
440                     if ((caglobals.ip.shutdownEvent != WSA_INVALID_EVENT) &&
441                         (caglobals.ip.shutdownEvent == eventArray[eventIndex]))
442                     {
443                         break;
444                     }
445                     CAEventReturned(socketArray[eventIndex]);
446                 }
447                 else
448                 {
449                     OIC_LOG_V(ERROR, TAG, "WSAWaitForMultipleEvents failed 0x%08x", WSAGetLastError());
450                 }
451                 break;
452         }
453
454     }
455
456     while (arraySize > 0)
457     {
458         arraySize--;
459         if (!WSACloseEvent(eventArray[arraySize]))
460         {
461             OIC_LOG_V(ERROR, TAG, "WSACloseEvent (Index %i) failed 0x%08x", arraySize, WSAGetLastError());
462         }
463     }
464
465     if (caglobals.ip.terminate)
466     {
467         caglobals.ip.shutdownEvent = WSA_INVALID_EVENT;
468         WSACleanup();
469     }
470 }
471
472 static void CAEventReturned(CASocketFd_t socket)
473 {
474     CASocketFd_t fd = OC_INVALID_SOCKET;
475     CATransportFlags_t flags = CA_DEFAULT_FLAGS;
476
477     while (!caglobals.ip.terminate)
478     {
479         IS_MATCHING_IP_SOCKET(u6,  socket, CA_IPV6)
480         else IS_MATCHING_IP_SOCKET(u6s, socket, CA_IPV6 | CA_SECURE)
481         else IS_MATCHING_IP_SOCKET(u4,  socket, CA_IPV4)
482         else IS_MATCHING_IP_SOCKET(u4s, socket, CA_IPV4 | CA_SECURE)
483         else IS_MATCHING_IP_SOCKET(m6,  socket, CA_MULTICAST | CA_IPV6)
484         else IS_MATCHING_IP_SOCKET(m6s, socket, CA_MULTICAST | CA_IPV6 | CA_SECURE)
485         else IS_MATCHING_IP_SOCKET(m4,  socket, CA_MULTICAST | CA_IPV4)
486         else IS_MATCHING_IP_SOCKET(m4s, socket, CA_MULTICAST | CA_IPV4 | CA_SECURE)
487         else
488         {
489             break;
490         }
491         (void)CAReceiveMessage(socket, flags);
492         // We will never get more than one match per socket, so always break.
493         break;
494     }
495 }
496
497 #endif
498
499 void CAUnregisterForAddressChanges()
500 {
501 #ifdef _WIN32
502     if (caglobals.ip.addressChangeEvent != WSA_INVALID_EVENT)
503     {
504         WSACloseEvent(caglobals.ip.addressChangeEvent);
505         caglobals.ip.addressChangeEvent = WSA_INVALID_EVENT;
506     }
507 #else
508     if (caglobals.ip.netlinkFd != OC_INVALID_SOCKET)
509     {
510         close(caglobals.ip.netlinkFd);
511         caglobals.ip.netlinkFd = OC_INVALID_SOCKET;
512     }
513 #endif
514 }
515
516 void CADeInitializeIPGlobals()
517 {
518     CLOSE_SOCKET(u6);
519     CLOSE_SOCKET(u6s);
520     CLOSE_SOCKET(u4);
521     CLOSE_SOCKET(u4s);
522     CLOSE_SOCKET(m6);
523     CLOSE_SOCKET(m6s);
524     CLOSE_SOCKET(m4);
525     CLOSE_SOCKET(m4s);
526
527     CAUnregisterForAddressChanges();
528 }
529
530 static CAResult_t CAReceiveMessage(CASocketFd_t fd, CATransportFlags_t flags)
531 {
532     char recvBuffer[COAP_MAX_PDU_SIZE] = {0};
533
534     size_t len = 0;
535     int level = 0;
536     int type = 0;
537     int namelen = 0;
538     struct sockaddr_storage srcAddr = { .ss_family = 0 };
539     unsigned char *pktinfo = NULL;
540 #if !defined(WSA_CMSG_DATA)
541     struct cmsghdr *cmp = NULL;
542     struct iovec iov = { .iov_base = recvBuffer, .iov_len = sizeof (recvBuffer) };
543     union control
544     {
545         struct cmsghdr cmsg;
546         unsigned char data[CMSG_SPACE(sizeof (struct in6_pktinfo))];
547     } cmsg;
548
549     if (flags & CA_IPV6)
550     {
551         namelen = sizeof (struct sockaddr_in6);
552         level = IPPROTO_IPV6;
553         type = IPV6_PKTINFO;
554         len = sizeof (struct in6_pktinfo);
555     }
556     else
557     {
558         namelen = sizeof (struct sockaddr_in);
559         level = IPPROTO_IP;
560         type = IP_PKTINFO;
561         len = sizeof (struct in6_pktinfo);
562     }
563
564     struct msghdr msg = { .msg_name = &srcAddr,
565                           .msg_namelen = namelen,
566                           .msg_iov = &iov,
567                           .msg_iovlen = 1,
568                           .msg_control = &cmsg,
569                           .msg_controllen = CMSG_SPACE(len) };
570
571     ssize_t recvLen = recvmsg(fd, &msg, flags);
572     if (OC_SOCKET_ERROR == recvLen)
573     {
574         OIC_LOG_V(ERROR, TAG, "Recvfrom failed %s", strerror(errno));
575         return CA_STATUS_FAILED;
576     }
577
578     for (cmp = CMSG_FIRSTHDR(&msg); cmp != NULL; cmp = CMSG_NXTHDR(&msg, cmp))
579     {
580         if (cmp->cmsg_level == level && cmp->cmsg_type == type)
581         {
582             pktinfo = CMSG_DATA(cmp);
583         }
584     }
585 #else // if defined(WSA_CMSG_DATA)
586     union control
587     {
588         WSACMSGHDR cmsg;
589         uint8_t data[WSA_CMSG_SPACE(sizeof (IN6_PKTINFO))];
590     } cmsg;
591     memset(&cmsg, 0, sizeof(cmsg));
592
593     if (flags & CA_IPV6)
594     {
595         namelen  = sizeof (struct sockaddr_in6);
596         level = IPPROTO_IPV6;
597         type = IPV6_PKTINFO;
598     }
599     else
600     {
601         namelen = sizeof (struct sockaddr_in);
602         level = IPPROTO_IP;
603         type = IP_PKTINFO;
604     }
605
606     WSABUF iov = {.len = sizeof (recvBuffer), .buf = recvBuffer};
607     WSAMSG msg = {.name = (PSOCKADDR)&srcAddr,
608                   .namelen = namelen,
609                   .lpBuffers = &iov,
610                   .dwBufferCount = 1,
611                   .Control = {.buf = cmsg.data, .len = sizeof (cmsg)}
612                  };
613
614     uint32_t recvLen = 0;
615     uint32_t ret = caglobals.ip.wsaRecvMsg(fd, &msg, &recvLen, 0,0);
616     OIC_LOG_V(DEBUG, TAG, "WSARecvMsg recvd %u bytes", recvLen);
617     if (OC_SOCKET_ERROR == ret)
618     {
619         OIC_LOG_V(ERROR, TAG, "WSARecvMsg failed %i", WSAGetLastError());
620     }
621
622     for (WSACMSGHDR *cmp = WSA_CMSG_FIRSTHDR(&msg); cmp != NULL;
623          cmp = WSA_CMSG_NXTHDR(&msg, cmp))
624     {
625         if (cmp->cmsg_level == level && cmp->cmsg_type == type)
626         {
627             pktinfo = WSA_CMSG_DATA(cmp);
628         }
629     }
630 #endif // !defined(WSA_CMSG_DATA)
631     CASecureEndpoint_t sep = {.endpoint = {.adapter = CA_ADAPTER_IP, .flags = flags}};
632
633     if (flags & CA_IPV6)
634     {
635         sep.endpoint.ifindex = ((struct in6_pktinfo *)pktinfo)->ipi6_ifindex;
636
637         if (flags & CA_MULTICAST)
638         {
639             struct in6_addr *addr = &(((struct in6_pktinfo *)pktinfo)->ipi6_addr);
640             unsigned char topbits = ((unsigned char *)addr)[0];
641             if (topbits != 0xff)
642             {
643                 sep.endpoint.flags &= ~CA_MULTICAST;
644             }
645         }
646     }
647     else
648     {
649         sep.endpoint.ifindex = ((struct in_pktinfo *)pktinfo)->ipi_ifindex;
650
651         if (flags & CA_MULTICAST)
652         {
653             struct in_addr *addr = &((struct in_pktinfo *)pktinfo)->ipi_addr;
654             uint32_t host = ntohl(addr->s_addr);
655             unsigned char topbits = ((unsigned char *)&host)[3];
656             if (topbits < 224 || topbits > 239)
657             {
658                 sep.endpoint.flags &= ~CA_MULTICAST;
659             }
660         }
661     }
662
663     CAConvertAddrToName(&srcAddr, namelen, sep.endpoint.addr, &sep.endpoint.port);
664
665     if (flags & CA_SECURE)
666     {
667 #ifdef __WITH_DTLS__
668         int ret = CAdecryptSsl(&sep, (uint8_t *)recvBuffer, recvLen);
669         OIC_LOG_V(DEBUG, TAG, "CAdecryptSsl returns [%d]", ret);
670 #else
671         OIC_LOG(ERROR, TAG, "Encrypted message but no DTLS");
672 #endif
673     }
674     else
675     {
676         if (g_packetReceivedCallback)
677         {
678             g_packetReceivedCallback(&sep, recvBuffer, recvLen);
679         }
680     }
681
682     return CA_STATUS_OK;
683 }
684
685 void CAIPPullData()
686 {
687     OIC_LOG(DEBUG, TAG, "IN");
688     OIC_LOG(DEBUG, TAG, "OUT");
689 }
690
691 static CASocketFd_t CACreateSocket(int family, uint16_t *port, bool isMulticast)
692 {
693     int socktype = SOCK_DGRAM;
694 #ifdef SOCK_CLOEXEC
695     socktype |= SOCK_CLOEXEC;
696 #endif
697     CASocketFd_t fd = socket(family, socktype, IPPROTO_UDP);
698     if (OC_INVALID_SOCKET == fd)
699     {
700         OIC_LOG_V(ERROR, TAG, "create socket failed: %s", CAIPS_GET_ERROR);
701         return OC_INVALID_SOCKET;
702     }
703
704 #if !defined(SOCK_CLOEXEC) && defined(FD_CLOEXEC)
705     int fl = fcntl(fd, F_GETFD);
706     if (-1 == fl || -1 == fcntl(fd, F_SETFD, fl|FD_CLOEXEC))
707     {
708         OIC_LOG_V(ERROR, TAG, "set FD_CLOEXEC failed: %s", strerror(errno));
709         close(fd);
710         return OC_INVALID_SOCKET;
711     }
712 #endif
713     struct sockaddr_storage sa = { .ss_family = family };
714     socklen_t socklen = 0;
715
716     if (family == AF_INET6)
717     {
718         int on = 1;
719
720         if (OC_SOCKET_ERROR == setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, OPTVAL_T(&on), sizeof (on)))
721         {
722             OIC_LOG_V(ERROR, TAG, "IPV6_V6ONLY failed: %s", CAIPS_GET_ERROR);
723         }
724
725 #if defined(IPV6_RECVPKTINFO)
726         if (OC_SOCKET_ERROR == setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof (on)))
727 #else
728         if (OC_SOCKET_ERROR == setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, OPTVAL_T(&on), sizeof (on)))
729 #endif
730         {
731             OIC_LOG_V(ERROR, TAG, "IPV6_RECVPKTINFO failed: %s",CAIPS_GET_ERROR);
732         }
733
734         ((struct sockaddr_in6 *)&sa)->sin6_port = htons(*port);
735         socklen = sizeof (struct sockaddr_in6);
736     }
737     else
738     {
739         int on = 1;
740         if (OC_SOCKET_ERROR == setsockopt(fd, IPPROTO_IP, IP_PKTINFO, OPTVAL_T(&on), sizeof (on)))
741         {
742             OIC_LOG_V(ERROR, TAG, "IP_PKTINFO failed: %s", CAIPS_GET_ERROR);
743         }
744
745         ((struct sockaddr_in *)&sa)->sin_port = htons(*port);
746         socklen = sizeof (struct sockaddr_in);
747     }
748
749     if (isMulticast && *port) // use the given port
750     {
751         int on = 1;
752         if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on), sizeof (on)))
753         {
754             OIC_LOG_V(ERROR, TAG, "SO_REUSEADDR failed: %s", CAIPS_GET_ERROR);
755 #ifdef _WIN32
756             closesocket(fd);
757 #else
758             close(fd);
759 #endif
760             return OC_INVALID_SOCKET;
761         }
762     }
763
764     if (OC_SOCKET_ERROR == bind(fd, (struct sockaddr *)&sa, socklen))
765     {
766         OIC_LOG_V(ERROR, TAG, "bind socket failed: %s", CAIPS_GET_ERROR);
767 #ifdef _WIN32
768         closesocket(fd);
769 #else
770         close(fd);
771 #endif
772         return OC_INVALID_SOCKET;
773     }
774
775     if (!*port) // return the assigned port
776     {
777         if (OC_SOCKET_ERROR == getsockname(fd, (struct sockaddr *)&sa, &socklen))
778         {
779             OIC_LOG_V(ERROR, TAG, "getsockname failed: %s", CAIPS_GET_ERROR);
780 #ifdef _WIN32
781             closesocket(fd);
782 #else
783             close(fd);
784 #endif
785             return OC_INVALID_SOCKET;
786         }
787         *port = ntohs(family == AF_INET6 ?
788                       ((struct sockaddr_in6 *)&sa)->sin6_port :
789                       ((struct sockaddr_in *)&sa)->sin_port);
790     }
791
792     return fd;
793 }
794
795 #define CHECKFD(FD) \
796     if (FD > caglobals.ip.maxfd) \
797         caglobals.ip.maxfd = FD;
798 #define NEWSOCKET(FAMILY, NAME, MULTICAST) \
799     caglobals.ip.NAME.fd = CACreateSocket(FAMILY, &caglobals.ip.NAME.port, MULTICAST); \
800     if (caglobals.ip.NAME.fd == OC_INVALID_SOCKET) \
801     {   \
802         caglobals.ip.NAME.port = 0; \
803         caglobals.ip.NAME.fd = CACreateSocket(FAMILY, &caglobals.ip.NAME.port, MULTICAST); \
804     }   \
805     CHECKFD(caglobals.ip.NAME.fd)
806
807 static void CARegisterForAddressChanges()
808 {
809 #ifdef _WIN32
810     caglobals.ip.addressChangeEvent = WSACreateEvent();
811     if (WSA_INVALID_EVENT != caglobals.ip.addressChangeEvent)
812     {
813         OIC_LOG(ERROR, TAG, "WSACreateEvent failed");
814     }
815 #else
816     caglobals.ip.netlinkFd = OC_INVALID_SOCKET;
817 #ifdef __linux__
818     // create NETLINK fd for interface change notifications
819     struct sockaddr_nl sa = { AF_NETLINK, 0, 0, RTMGRP_LINK };
820
821     caglobals.ip.netlinkFd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, NETLINK_ROUTE);
822     if (caglobals.ip.netlinkFd == OC_INVALID_SOCKET)
823     {
824         OIC_LOG_V(ERROR, TAG, "netlink socket failed: %s", strerror(errno));
825     }
826     else
827     {
828         int r = bind(caglobals.ip.netlinkFd, (struct sockaddr *)&sa, sizeof (sa));
829         if (r)
830         {
831             OIC_LOG_V(ERROR, TAG, "netlink bind failed: %s", strerror(errno));
832             close(caglobals.ip.netlinkFd);
833             caglobals.ip.netlinkFd = OC_INVALID_SOCKET;
834         }
835         else
836         {
837             CHECKFD(caglobals.ip.netlinkFd);
838         }
839     }
840 #endif
841 #endif
842 }
843
844 static void CAInitializeFastShutdownMechanism()
845 {
846     caglobals.ip.selectTimeout = -1; // don't poll for shutdown
847     int ret = -1;
848 #if defined(WSA_WAIT_EVENT_0)
849     caglobals.ip.shutdownEvent = WSACreateEvent();
850     if (WSA_INVALID_EVENT != caglobals.ip.shutdownEvent)
851     {
852         ret = 0;
853     }
854 #elif defined(HAVE_PIPE2)
855     ret = pipe2(caglobals.ip.shutdownFds, O_CLOEXEC);
856     CHECKFD(caglobals.ip.shutdownFds[0]);
857     CHECKFD(caglobals.ip.shutdownFds[1]);
858 #else
859     ret = pipe(caglobals.ip.shutdownFds);
860     if (-1 != ret)
861     {
862         ret = fcntl(caglobals.ip.shutdownFds[0], F_GETFD);
863         if (-1 != ret)
864         {
865             ret = fcntl(caglobals.ip.shutdownFds[0], F_SETFD, ret|FD_CLOEXEC);
866         }
867         if (-1 != ret)
868         {
869             ret = fcntl(caglobals.ip.shutdownFds[1], F_GETFD);
870         }
871         if (-1 != ret)
872         {
873             ret = fcntl(caglobals.ip.shutdownFds[1], F_SETFD, ret|FD_CLOEXEC);
874         }
875         if (-1 == ret)
876         {
877             close(caglobals.ip.shutdownFds[1]);
878             close(caglobals.ip.shutdownFds[0]);
879             caglobals.ip.shutdownFds[0] = -1;
880             caglobals.ip.shutdownFds[1] = -1;
881         }
882     }
883     CHECKFD(caglobals.ip.shutdownFds[0]);
884     CHECKFD(caglobals.ip.shutdownFds[1]);
885 #endif
886     if (-1 == ret)
887     {
888         OIC_LOG_V(ERROR, TAG, "fast shutdown mechanism init failed: %s", CAIPS_GET_ERROR);
889         caglobals.ip.selectTimeout = SELECT_TIMEOUT; //poll needed for shutdown
890     }
891 }
892
893 CAResult_t CAIPStartServer(const ca_thread_pool_t threadPool)
894 {
895     CAResult_t res = CA_STATUS_OK;
896
897     if (caglobals.ip.started)
898     {
899         return res;
900     }
901 #if defined (_WIN32)
902     WORD wVersionRequested = MAKEWORD(2, 2);
903     WSADATA wsaData ={.wVersion = 0};
904     int err = WSAStartup(wVersionRequested, &wsaData);
905     if (err != 0)
906     {
907         OIC_LOG_V(ERROR, TAG, "WSAStartup failed: %i", err);
908         return CA_STATUS_FAILED;
909     }
910     OIC_LOG(DEBUG, TAG, "WSAStartup Succeeded");
911 #endif
912     if (!IPv4MulticastAddress.s_addr)
913     {
914         (void)inet_pton(AF_INET, IPv4_MULTICAST, &IPv4MulticastAddress);
915         (void)inet_pton(AF_INET6, IPv6_MULTICAST_INT, &IPv6MulticastAddressInt);
916         (void)inet_pton(AF_INET6, IPv6_MULTICAST_LNK, &IPv6MulticastAddressLnk);
917         (void)inet_pton(AF_INET6, IPv6_MULTICAST_RLM, &IPv6MulticastAddressRlm);
918         (void)inet_pton(AF_INET6, IPv6_MULTICAST_ADM, &IPv6MulticastAddressAdm);
919         (void)inet_pton(AF_INET6, IPv6_MULTICAST_SIT, &IPv6MulticastAddressSit);
920         (void)inet_pton(AF_INET6, IPv6_MULTICAST_ORG, &IPv6MulticastAddressOrg);
921         (void)inet_pton(AF_INET6, IPv6_MULTICAST_GLB, &IPv6MulticastAddressGlb);
922     }
923
924     if (!caglobals.ip.ipv6enabled && !caglobals.ip.ipv4enabled)
925     {
926         caglobals.ip.ipv4enabled = true;  // only needed to run CA tests
927     }
928
929     if (caglobals.ip.ipv6enabled)
930     {
931         NEWSOCKET(AF_INET6, u6, false)
932         NEWSOCKET(AF_INET6, u6s, false)
933         NEWSOCKET(AF_INET6, m6, true)
934         NEWSOCKET(AF_INET6, m6s, true)
935         OIC_LOG_V(INFO, TAG, "IPv6 unicast port: %u", caglobals.ip.u6.port);
936     }
937     if (caglobals.ip.ipv4enabled)
938     {
939         NEWSOCKET(AF_INET, u4, false)
940         NEWSOCKET(AF_INET, u4s, false)
941         NEWSOCKET(AF_INET, m4, true)
942         NEWSOCKET(AF_INET, m4s, true)
943         OIC_LOG_V(INFO, TAG, "IPv4 unicast port: %u", caglobals.ip.u4.port);
944     }
945
946     OIC_LOG_V(DEBUG, TAG,
947               "socket summary: u6=%d, u6s=%d, u4=%d, u4s=%d, m6=%d, m6s=%d, m4=%d, m4s=%d",
948               caglobals.ip.u6.fd, caglobals.ip.u6s.fd, caglobals.ip.u4.fd, caglobals.ip.u4s.fd,
949               caglobals.ip.m6.fd, caglobals.ip.m6s.fd, caglobals.ip.m4.fd, caglobals.ip.m4s.fd);
950
951     OIC_LOG_V(DEBUG, TAG,
952               "port summary: u6 port=%d, u6s port=%d, u4 port=%d, u4s port=%d, m6 port=%d,"
953               "m6s port=%d, m4 port=%d, m4s port=%d",
954               caglobals.ip.u6.port, caglobals.ip.u6s.port, caglobals.ip.u4.port,
955               caglobals.ip.u4s.port, caglobals.ip.m6.port, caglobals.ip.m6s.port,
956               caglobals.ip.m4.port, caglobals.ip.m4s.port);
957 #if defined (SIO_GET_EXTENSION_FUNCTION_POINTER)
958     caglobals.ip.wsaRecvMsg = NULL;
959     GUID GuidWSARecvMsg = WSAID_WSARECVMSG;
960     DWORD copied = 0;
961     err = WSAIoctl(caglobals.ip.u4.fd, SIO_GET_EXTENSION_FUNCTION_POINTER, &GuidWSARecvMsg, sizeof(GuidWSARecvMsg), &(caglobals.ip.wsaRecvMsg), sizeof(caglobals.ip.wsaRecvMsg), &copied, 0, 0);
962     if (0 != err)
963     {
964         OIC_LOG_V(ERROR, TAG, "WSAIoctl failed %i", WSAGetLastError());
965         return CA_STATUS_FAILED;
966     }
967 #endif
968     // set up appropriate FD mechanism for fast shutdown
969     CAInitializeFastShutdownMechanism();
970
971     // create source of network address change notifications
972     CARegisterForAddressChanges();
973
974     caglobals.ip.selectTimeout = CAGetPollingInterval(caglobals.ip.selectTimeout);
975
976     res = CAIPStartListenServer();
977     if (CA_STATUS_OK != res)
978     {
979         OIC_LOG_V(ERROR, TAG, "Failed to start listening server![%d]", res);
980         return res;
981     }
982
983     caglobals.ip.terminate = false;
984     res = ca_thread_pool_add_task(threadPool, CAReceiveHandler, NULL);
985     if (CA_STATUS_OK != res)
986     {
987         OIC_LOG(ERROR, TAG, "thread_pool_add_task failed");
988         return res;
989     }
990     OIC_LOG(DEBUG, TAG, "CAReceiveHandler thread started successfully.");
991
992     caglobals.ip.started = true;
993     return CA_STATUS_OK;
994 }
995
996 void CAIPStopServer()
997 {
998     caglobals.ip.started = false;
999     caglobals.ip.terminate = true;
1000
1001 #if !defined(WSA_WAIT_EVENT_0)
1002     if (caglobals.ip.shutdownFds[1] != -1)
1003     {
1004         close(caglobals.ip.shutdownFds[1]);
1005         // receive thread will stop immediately
1006     }
1007     else
1008     {
1009         // receive thread will stop in SELECT_TIMEOUT seconds.
1010     }
1011 #else
1012     // receive thread will stop immediately.
1013     if (!WSASetEvent(caglobals.ip.shutdownEvent))
1014     {
1015         OIC_LOG_V(DEBUG, TAG, "set shutdown event failed: %#08X", GetLastError());
1016     }
1017 #endif
1018 }
1019
1020 void CAWakeUpForChange()
1021 {
1022 #if !defined(WSA_WAIT_EVENT_0)
1023     if (caglobals.ip.shutdownFds[1] != -1)
1024     {
1025         ssize_t len = 0;
1026         do
1027         {
1028             len = write(caglobals.ip.shutdownFds[1], "w", 1);
1029         } while ((len == -1) && (errno == EINTR));
1030         if ((len == -1) && (errno != EINTR) && (errno != EPIPE))
1031         {
1032             OIC_LOG_V(DEBUG, TAG, "write failed: %s", strerror(errno));
1033         }
1034     }
1035 #else
1036     if (!WSASetEvent(caglobals.ip.shutdownEvent))
1037     {
1038         OIC_LOG_V(DEBUG, TAG, "set shutdown event failed: %#08X", GetLastError());
1039     }
1040 #endif
1041 }
1042
1043 static void applyMulticastToInterface4(uint32_t ifindex)
1044 {
1045     if (!caglobals.ip.ipv4enabled)
1046     {
1047         return;
1048     }
1049
1050 #if defined(USE_IP_MREQN)
1051     struct ip_mreqn mreq = { .imr_multiaddr = IPv4MulticastAddress,
1052                              .imr_address.s_addr = htonl(INADDR_ANY),
1053                              .imr_ifindex = ifindex };
1054 #else
1055     struct ip_mreq mreq  = { .imr_multiaddr.s_addr = IPv4MulticastAddress.s_addr,
1056                              .imr_interface.s_addr = htonl(ifindex) };
1057 #endif
1058
1059     int ret = setsockopt(caglobals.ip.m4.fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, OPTVAL_T(&mreq), sizeof (mreq));
1060     if (OC_SOCKET_ERROR == ret)
1061     {
1062 #if !defined(WSAEINVAL)
1063         if (EADDRINUSE != errno)
1064 #else
1065         if (WSAEINVAL != WSAGetLastError()) // Joining multicast group more than once (IPv4 Flavor)
1066 #endif
1067         {
1068             OIC_LOG_V(ERROR, TAG, "       IPv4 IP_ADD_MEMBERSHIP failed: %s", CAIPS_GET_ERROR);
1069         }
1070     }
1071     ret = setsockopt(caglobals.ip.m4s.fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, OPTVAL_T(&mreq), sizeof (mreq));
1072     if (OC_SOCKET_ERROR == ret)
1073     {
1074 #if !defined(WSAEINVAL)
1075         if (EADDRINUSE != errno)
1076 #else
1077         if (WSAEINVAL == WSAGetLastError())
1078         {
1079             // We're trying to join the multicast group again.
1080             // If the interface has gone down and come back up, the socket might be in
1081             // an inconsistent state where it still thinks we're joined when the interface
1082             // doesn't think we're joined.  So try to leave and rejoin the group just in case.
1083             setsockopt(caglobals.ip.m4s.fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, OPTVAL_T(&mreq),
1084                              sizeof(mreq));
1085             ret = setsockopt(caglobals.ip.m4s.fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, OPTVAL_T(&mreq),
1086                              sizeof(mreq));
1087         }
1088         if (OC_SOCKET_ERROR == ret)
1089 #endif
1090         {
1091             OIC_LOG_V(ERROR, TAG, "SECURE IPv4 IP_ADD_MEMBERSHIP failed: %s", CAIPS_GET_ERROR);
1092         }
1093     }
1094 }
1095
1096 static void applyMulticast6(int fd, struct in6_addr *addr, uint32_t ifindex)
1097 {
1098     struct ipv6_mreq mreq = {.ipv6mr_multiaddr = {0},
1099                              .ipv6mr_interface = ifindex };
1100
1101     // VS2013 has problems with struct copies inside struct initializers, so copy separately.
1102     mreq.ipv6mr_multiaddr = *addr;
1103
1104     int ret = setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, OPTVAL_T(&mreq), sizeof (mreq));
1105     if (OC_SOCKET_ERROR == ret)
1106     {
1107 #if !defined(_WIN32)
1108         if (EADDRINUSE != errno)
1109 #else
1110         if (WSAEINVAL == WSAGetLastError())
1111         {
1112             // We're trying to join the multicast group again.
1113             // If the interface has gone down and come back up, the socket might be in
1114             // an inconsistent state where it still thinks we're joined when the interface
1115             // doesn't think we're joined.  So try to leave and rejoin the group just in case.
1116             setsockopt(fd, IPPROTO_IPV6, IPV6_LEAVE_GROUP, OPTVAL_T(&mreq), sizeof(mreq));
1117             ret = setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, OPTVAL_T(&mreq), sizeof(mreq));
1118         }
1119         if (OC_SOCKET_ERROR == ret)
1120 #endif
1121         {
1122             OIC_LOG_V(ERROR, TAG, "IPv6 IPV6_JOIN_GROUP failed: %s", CAIPS_GET_ERROR);
1123         }
1124     }
1125 }
1126
1127 static void applyMulticastToInterface6(uint32_t ifindex)
1128 {
1129     if (!caglobals.ip.ipv6enabled)
1130     {
1131         return;
1132     }
1133     //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressInt, ifindex);
1134     applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressLnk, ifindex);
1135     //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressRlm, ifindex);
1136     //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressAdm, ifindex);
1137     //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressSit, ifindex);
1138     //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressOrg, ifindex);
1139     //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressGlb, ifindex);
1140
1141     //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressInt, ifindex);
1142     applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressLnk, ifindex);
1143     //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressRlm, ifindex);
1144     //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressAdm, ifindex);
1145     //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressSit, ifindex);
1146     //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressOrg, ifindex);
1147     //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressGlb, ifindex);
1148 }
1149
1150 CAResult_t CAIPStartListenServer()
1151 {
1152     u_arraylist_t *iflist = CAIPGetInterfaceInformation(0);
1153     if (!iflist)
1154     {
1155         OIC_LOG_V(ERROR, TAG, "CAIPGetInterfaceInformation() failed: %s", strerror(errno));
1156         return CA_STATUS_FAILED;
1157     }
1158
1159     uint32_t len = u_arraylist_length(iflist);
1160     OIC_LOG_V(DEBUG, TAG, "IP network interfaces found: %d", len);
1161
1162     for (uint32_t i = 0; i < len; i++)
1163     {
1164         CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
1165
1166         if (!ifitem)
1167         {
1168             continue;
1169         }
1170         if ((ifitem->flags & IFF_UP_RUNNING_FLAGS) != IFF_UP_RUNNING_FLAGS)
1171         {
1172             continue;
1173         }
1174         if (ifitem->family == AF_INET)
1175         {
1176             OIC_LOG_V(DEBUG, TAG, "Adding IPv4 interface %i to multicast group", ifitem->index);
1177             applyMulticastToInterface4(ifitem->index);
1178         }
1179         if (ifitem->family == AF_INET6)
1180         {
1181             OIC_LOG_V(DEBUG, TAG, "Adding IPv6 interface %i to multicast group", ifitem->index);
1182             applyMulticastToInterface6(ifitem->index);
1183         }
1184     }
1185
1186     u_arraylist_destroy(iflist);
1187     return CA_STATUS_OK;
1188 }
1189
1190 CAResult_t CAIPStopListenServer()
1191 {
1192     u_arraylist_t *iflist = CAIPGetInterfaceInformation(0);
1193     if (!iflist)
1194     {
1195         OIC_LOG_V(ERROR, TAG, "Get interface info failed: %s", strerror(errno));
1196         return CA_STATUS_FAILED;
1197     }
1198
1199     uint32_t len = u_arraylist_length(iflist);
1200     OIC_LOG_V(DEBUG, TAG, "IP network interfaces found: %d", len);
1201
1202     for (uint32_t i = 0; i < len; i++)
1203     {
1204         CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
1205
1206         if (!ifitem)
1207         {
1208             continue;
1209         }
1210         if ((ifitem->flags & IFF_UP_RUNNING_FLAGS) != IFF_UP_RUNNING_FLAGS)
1211         {
1212             continue;
1213         }
1214         if (ifitem->family == AF_INET)
1215         {
1216             CLOSE_SOCKET(m4);
1217             CLOSE_SOCKET(m4s);
1218             OIC_LOG_V(DEBUG, TAG, "IPv4 network interface: %s cloed", ifitem->name);
1219         }
1220         if (ifitem->family == AF_INET6)
1221         {
1222             CLOSE_SOCKET(m6);
1223             CLOSE_SOCKET(m6s);
1224             OIC_LOG_V(DEBUG, TAG, "IPv6 network interface: %s", ifitem->name);
1225         }
1226     }
1227     u_arraylist_destroy(iflist);
1228     return CA_STATUS_OK;
1229 }
1230
1231 static void CAProcessNewInterface(CAInterface_t *ifitem)
1232 {
1233     if (!ifitem)
1234     {
1235         OIC_LOG(DEBUG, TAG, "ifitem is null");
1236         return;
1237     }
1238
1239     if (ifitem->family == AF_INET6)
1240     {
1241         applyMulticastToInterface6(ifitem->index);
1242     }
1243     if (ifitem->family == AF_INET)
1244     {
1245         applyMulticastToInterface4(ifitem->index);
1246     }
1247 }
1248
1249 void CAIPSetPacketReceiveCallback(CAIPPacketReceivedCallback callback)
1250 {
1251     g_packetReceivedCallback = callback;
1252 }
1253
1254 static void sendData(int fd, const CAEndpoint_t *endpoint,
1255                      const void *data, uint32_t dlen,
1256                      const char *cast, const char *fam)
1257 {
1258     OIC_LOG(DEBUG, TAG, "IN");
1259
1260     if (!endpoint)
1261     {
1262         OIC_LOG(DEBUG, TAG, "endpoint is null");
1263         if (g_ipErrorHandler)
1264         {
1265             g_ipErrorHandler(endpoint, data, dlen, CA_STATUS_INVALID_PARAM);
1266         }
1267         return;
1268     }
1269
1270     (void)cast;  // eliminates release warning
1271     (void)fam;
1272
1273     struct sockaddr_storage sock = { .ss_family = 0 };
1274     CAConvertNameToAddr(endpoint->addr, endpoint->port, &sock);
1275
1276     socklen_t socklen = 0;
1277     if (sock.ss_family == AF_INET6)
1278     {
1279         socklen = sizeof(struct sockaddr_in6);
1280     }
1281     else
1282     {
1283         socklen = sizeof(struct sockaddr_in);
1284     }
1285
1286 #ifdef TB_LOG
1287     const char *secure = (endpoint->flags & CA_SECURE) ? "secure " : "";
1288 #endif
1289 #if !defined(_WIN32)
1290     ssize_t len = sendto(fd, data, dlen, 0, (struct sockaddr *)&sock, socklen);
1291     if (OC_SOCKET_ERROR == len)
1292     {
1293          // If logging is not defined/enabled.
1294         if (g_ipErrorHandler)
1295         {
1296             g_ipErrorHandler(endpoint, data, dlen, CA_SEND_FAILED);
1297         }
1298         OIC_LOG_V(ERROR, TAG, "%s%s %s sendTo failed: %s", secure, cast, fam, strerror(errno));
1299     }
1300     else
1301     {
1302         OIC_LOG_V(INFO, TAG, "%s%s %s sendTo is successful: %zd bytes", secure, cast, fam, len);
1303     }
1304 #else
1305     int err = 0;
1306     int len = 0;
1307     int sent = 0;
1308     do {
1309         len = sendto(fd, ((char*)data) + sent, dlen - sent, 0, (struct sockaddr *)&sock, socklen);
1310         if (OC_SOCKET_ERROR == len)
1311         {
1312             err = WSAGetLastError();
1313             if ((WSAEWOULDBLOCK != err) && (WSAENOBUFS != err))
1314             {
1315                  // If logging is not defined/enabled.
1316                 if (g_ipErrorHandler)
1317                 {
1318                     g_ipErrorHandler(endpoint, data, dlen, CA_SEND_FAILED);
1319                 }
1320
1321                 OIC_LOG_V(ERROR, TAG, "%s%s %s sendTo failed: %i", secure, cast, fam, err);
1322             }
1323         }
1324         else
1325         {
1326             sent += len;
1327             if (sent != len)
1328             {
1329                 OIC_LOG_V(DEBUG, TAG, "%s%s %s sendTo (Partial Send) is successful: "
1330                                       "currently sent: %ld bytes, "
1331                                       "total sent: %ld bytes, "
1332                                       "remaining: %ld bytes",
1333                                       secure, cast, fam, len, sent, dlen-sent);
1334             }
1335             else
1336             {
1337                 OIC_LOG_V(INFO, TAG, "%s%s %s sendTo is successful: %ld bytes",
1338                                      secure, cast, fam, len);
1339             }
1340         }
1341     } while ((OC_SOCKET_ERROR == len) && ((WSAEWOULDBLOCK == err) || (WSAENOBUFS == err)) || (sent < dlen));
1342 #endif
1343 }
1344
1345 static void sendMulticastData6(const u_arraylist_t *iflist,
1346                                CAEndpoint_t *endpoint,
1347                                const void *data, uint32_t datalen)
1348 {
1349     if (!endpoint)
1350     {
1351         OIC_LOG(DEBUG, TAG, "endpoint is null");
1352         return;
1353     }
1354
1355     int scope = endpoint->flags & CA_SCOPE_MASK;
1356     char *ipv6mcname = ipv6mcnames[scope];
1357     if (!ipv6mcname)
1358     {
1359         OIC_LOG_V(INFO, TAG, "IPv6 multicast scope invalid: %d", scope);
1360         return;
1361     }
1362     OICStrcpy(endpoint->addr, sizeof(endpoint->addr), ipv6mcname);
1363     int fd = caglobals.ip.u6.fd;
1364
1365     uint32_t len = u_arraylist_length(iflist);
1366     for (uint32_t i = 0; i < len; i++)
1367     {
1368         CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
1369         if (!ifitem)
1370         {
1371             continue;
1372         }
1373         if ((ifitem->flags & IFF_UP_RUNNING_FLAGS) != IFF_UP_RUNNING_FLAGS)
1374         {
1375             continue;
1376         }
1377         if (ifitem->family != AF_INET6)
1378         {
1379             continue;
1380         }
1381
1382         int index = ifitem->index;
1383         if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, OPTVAL_T(&index), sizeof (index)))
1384         {
1385             OIC_LOG_V(ERROR, TAG, "setsockopt6 failed: %s", CAIPS_GET_ERROR);
1386             return;
1387         }
1388         sendData(fd, endpoint, data, datalen, "multicast", "ipv6");
1389     }
1390 }
1391
1392 static void sendMulticastData4(const u_arraylist_t *iflist,
1393                                CAEndpoint_t *endpoint,
1394                                const void *data, uint32_t datalen)
1395 {
1396     VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL");
1397
1398 #if defined(USE_IP_MREQN)
1399     struct ip_mreqn mreq = { .imr_multiaddr = IPv4MulticastAddress,
1400                              .imr_address.s_addr = htonl(INADDR_ANY),
1401                              .imr_ifindex = 0};
1402 #else
1403     struct ip_mreq mreq  = { .imr_multiaddr.s_addr = IPv4MulticastAddress.s_addr,
1404                              .imr_interface = {0}};
1405 #endif
1406
1407     OICStrcpy(endpoint->addr, sizeof(endpoint->addr), IPv4_MULTICAST);
1408     int fd = caglobals.ip.u4.fd;
1409
1410     uint32_t len = u_arraylist_length(iflist);
1411     for (uint32_t i = 0; i < len; i++)
1412     {
1413         CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
1414         if (!ifitem)
1415         {
1416             continue;
1417         }
1418         if ((ifitem->flags & IFF_UP_RUNNING_FLAGS) != IFF_UP_RUNNING_FLAGS)
1419         {
1420             continue;
1421         }
1422         if (ifitem->family != AF_INET)
1423         {
1424             continue;
1425         }
1426 #if defined(USE_IP_MREQN)
1427         mreq.imr_ifindex = ifitem->index;
1428 #else
1429         mreq.imr_interface.s_addr = htonl(ifitem->index);
1430 #endif
1431         if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, OPTVAL_T(&mreq), sizeof (mreq)))
1432         {
1433             OIC_LOG_V(ERROR, TAG, "send IP_MULTICAST_IF failed: %s (using defualt)",
1434                     CAIPS_GET_ERROR);
1435         }
1436         sendData(fd, endpoint, data, datalen, "multicast", "ipv4");
1437     }
1438 }
1439
1440 void CAIPSendData(CAEndpoint_t *endpoint, const void *data, uint32_t datalen,
1441                   bool isMulticast)
1442 {
1443     VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL");
1444     VERIFY_NON_NULL_VOID(data, TAG, "data is NULL");
1445
1446     bool isSecure = (endpoint->flags & CA_SECURE) != 0;
1447
1448     if (isMulticast)
1449     {
1450         endpoint->port = isSecure ? CA_SECURE_COAP : CA_COAP;
1451
1452         u_arraylist_t *iflist = CAIPGetInterfaceInformation(0);
1453         if (!iflist)
1454         {
1455             OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno));
1456             return;
1457         }
1458
1459         if ((endpoint->flags & CA_IPV6) && caglobals.ip.ipv6enabled)
1460         {
1461             sendMulticastData6(iflist, endpoint, data, datalen);
1462         }
1463         if ((endpoint->flags & CA_IPV4) && caglobals.ip.ipv4enabled)
1464         {
1465             sendMulticastData4(iflist, endpoint, data, datalen);
1466         }
1467
1468         u_arraylist_destroy(iflist);
1469     }
1470     else
1471     {
1472         if (!endpoint->port)    // unicast discovery
1473         {
1474             endpoint->port = isSecure ? CA_SECURE_COAP : CA_COAP;
1475         }
1476
1477         CASocketFd_t fd;
1478         if (caglobals.ip.ipv6enabled && (endpoint->flags & CA_IPV6))
1479         {
1480             fd = isSecure ? caglobals.ip.u6s.fd : caglobals.ip.u6.fd;
1481 #ifndef __WITH_DTLS__
1482             fd = caglobals.ip.u6.fd;
1483 #endif
1484             sendData(fd, endpoint, data, datalen, "unicast", "ipv6");
1485         }
1486         if (caglobals.ip.ipv4enabled && (endpoint->flags & CA_IPV4))
1487         {
1488             fd = isSecure ? caglobals.ip.u4s.fd : caglobals.ip.u4.fd;
1489 #ifndef __WITH_DTLS__
1490             fd = caglobals.ip.u4.fd;
1491 #endif
1492             sendData(fd, endpoint, data, datalen, "unicast", "ipv4");
1493         }
1494     }
1495 }
1496
1497 CAResult_t CAGetIPInterfaceInformation(CAEndpoint_t **info, uint32_t *size)
1498 {
1499     VERIFY_NON_NULL(info, TAG, "info is NULL");
1500     VERIFY_NON_NULL(size, TAG, "size is NULL");
1501
1502     u_arraylist_t *iflist = CAIPGetInterfaceInformation(0);
1503     if (!iflist)
1504     {
1505         OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno));
1506         return CA_STATUS_FAILED;
1507     }
1508
1509     uint32_t len = u_arraylist_length(iflist);
1510     uint32_t length = len;
1511
1512 #ifdef __WITH_DTLS__
1513     //If DTLS is supported, each interface can support secure port as well
1514     length = len * 2;
1515 #endif
1516
1517     CAEndpoint_t *eps = (CAEndpoint_t *)OICCalloc(length, sizeof (CAEndpoint_t));
1518     if (!eps)
1519     {
1520         OIC_LOG(ERROR, TAG, "Malloc Failed");
1521         u_arraylist_destroy(iflist);
1522         return CA_MEMORY_ALLOC_FAILED;
1523     }
1524
1525     for (uint32_t i = 0, j = 0; i < len; i++)
1526     {
1527         CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
1528         if(!ifitem)
1529         {
1530             continue;
1531         }
1532
1533         eps[j].adapter = CA_ADAPTER_IP;
1534         eps[j].ifindex = 0;
1535
1536         if (ifitem->family == AF_INET6)
1537         {
1538             eps[j].flags = CA_IPV6;
1539             eps[j].port = caglobals.ip.u6.port;
1540         }
1541         else
1542         {
1543             eps[j].flags = CA_IPV4;
1544             eps[j].port = caglobals.ip.u4.port;
1545         }
1546         OICStrcpy(eps[j].addr, sizeof(eps[j].addr), ifitem->addr);
1547
1548 #ifdef __WITH_DTLS__
1549         j++;
1550
1551         eps[j].adapter = CA_ADAPTER_IP;
1552         eps[j].ifindex = 0;
1553
1554         if (ifitem->family == AF_INET6)
1555         {
1556             eps[j].flags = CA_IPV6 | CA_SECURE;
1557             eps[j].port = caglobals.ip.u6s.port;
1558         }
1559         else
1560         {
1561             eps[j].flags = CA_IPV4 | CA_SECURE;
1562             eps[j].port = caglobals.ip.u4s.port;
1563         }
1564         OICStrcpy(eps[j].addr, sizeof(eps[j].addr), ifitem->addr);
1565 #endif
1566         j++;
1567     }
1568
1569     *info = eps;
1570     *size = length;
1571
1572     u_arraylist_destroy(iflist);
1573
1574     return CA_STATUS_OK;
1575 }
1576
1577 void CAIPSetErrorHandler(CAIPErrorHandleCallback errorHandleCallback)
1578 {
1579     g_ipErrorHandler = errorHandleCallback;
1580 }