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