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