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