Add doxygen comments to connectivity module
[iotivity.git] / resource / csdk / connectivity / src / ip_adapter / webos / caipnwmonitor.c
1 /*******************************************************************
2  *
3  * Copyright (c) 2018 LG Electronics, Inc.
4  * Copyright 2014 Samsung Electronics All Rights Reserved.
5  *
6  *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      https://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21  */
22
23 #include "caipinterface.h"
24
25 #include <stdio.h>
26 #include <string.h>
27 #include <sys/types.h>
28 #include <sys/socket.h>
29 #include <sys/select.h>
30 #include <ifaddrs.h>
31 #include <unistd.h>
32 #include <fcntl.h>
33 #include <arpa/inet.h>
34 #include <netinet/in.h>
35 #include <net/if.h>
36 #include <netdb.h>
37 #include <errno.h>
38
39 #include <linux/netlink.h>
40 #include <linux/rtnetlink.h>
41
42 #include <luna-service2/lunaservice.h>
43 #include <pbnjson.h>
44 #include "caipnwmonitor.h"
45 #include "octhread.h"
46 #include "caadapterutils.h"
47 #include "experimental/logger.h"
48 #include "oic_malloc.h"
49 #include "oic_string.h"
50 #include <coap/utlist.h>
51
52 #define TAG "OIC_CA_IP_MONITOR"
53 #define LS_CONNECTIONMANAGER_GETSTATUS_URI "luna://com.webos.service.connectionmanager/getstatus"
54
55 typedef struct _CONNECTION_STATUS {
56     bool isConnectWired;
57     bool isConnectWiFi;
58 } CONNECTION_STATUS_T;
59
60 CONNECTION_STATUS_T gConnectionStates;
61
62 /*
63  * Enable or disable log for network changed event
64  */
65 #define NETWORK_INTERFACE_CHANGED_LOGGING 1
66
67 /**
68  * Mutex for synchronizing access to cached interface and IP address information.
69  */
70 static oc_mutex g_networkMonitorContextMutex = NULL;
71
72 /**
73  * Used to storing network interface.
74  */
75 static u_arraylist_t *g_netInterfaceList = NULL;
76
77 /**
78  * Used to storing adapter changes callback interface.
79  */
80 static struct CAIPCBData_t *g_adapterCallbackList = NULL;
81
82 /**
83  * Used to monitoring network changes over luna bus which webos uses for IPC
84  */
85 static ca_thread_pool_t g_ipMonitorThreadPool = NULL;
86
87 /**
88  * Initialize the network interface monitoring list.
89  */
90 static CAResult_t CAIPInitializeNetworkMonitorList();
91
92 /**
93  * Destroy the network interface monitoring list.
94  */
95 static void CAIPDestroyNetworkMonitorList();
96
97 /**
98  * Compare the interface with the already added interface in list.
99  */
100 static bool CACmpNetworkList(uint32_t ifiindex);
101
102 /**
103  * Add new network interface in list.
104  */
105 static CAResult_t CAAddNetworkMonitorList(CAInterface_t *ifitem);
106
107 /**
108  * Remove network interface from list.
109  */
110 static void CARemoveNetworkMonitorList(int ifiindex);
111
112 /**
113  * Pass the changed network status through the stored callback.
114  */
115 static void CAIPPassNetworkChangesToAdapter(CANetworkStatus_t status);
116
117 /**
118  * Create new interface item.
119  */
120 static CAInterface_t *CANewInterfaceItem(int index, const char *name, int family,
121                                          const char *addr, int flags);
122
123 /**
124  * Initialize network monitor list.
125  *
126  * @return OK if intialized success, otherwise FAIL.
127  */
128 static CAResult_t CAIPInitializeNetworkMonitorList()
129 {
130     if (!g_networkMonitorContextMutex)
131     {
132         g_networkMonitorContextMutex = oc_mutex_new();
133         if (!g_networkMonitorContextMutex)
134         {
135             OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
136             return CA_STATUS_FAILED;
137         }
138     }
139
140     if (!g_netInterfaceList)
141     {
142         g_netInterfaceList = u_arraylist_create();
143         if (!g_netInterfaceList)
144         {
145             OIC_LOG(ERROR, TAG, "u_arraylist_create has failed");
146             CAIPDestroyNetworkMonitorList();
147             return CA_STATUS_FAILED;
148         }
149     }
150     return CA_STATUS_OK;
151 }
152
153 /**
154  * Destroy network monitor list.
155  */
156 static void CAIPDestroyNetworkMonitorList()
157 {
158     if (g_netInterfaceList)
159     {
160         u_arraylist_destroy(g_netInterfaceList);
161         g_netInterfaceList = NULL;
162     }
163
164     if (g_networkMonitorContextMutex)
165     {
166         oc_mutex_free(g_networkMonitorContextMutex);
167         g_networkMonitorContextMutex = NULL;
168     }
169 }
170
171 /**
172  * Compare network list.
173  *
174  * @param ifiindex  interface index.
175  *
176  * @return true if index found, otherwise false.
177  */
178 static bool CACmpNetworkList(uint32_t ifiindex)
179 {
180 #if NETWORK_INTERFACE_CHANGED_LOGGING
181     OIC_LOG_V(DEBUG, TAG, "IN %s: ifiindex = %ul", __func__, ifiindex);
182 #endif
183     if (!g_netInterfaceList)
184     {
185         OIC_LOG(ERROR, TAG, "g_netInterfaceList is NULL");
186         return false;
187     }
188
189     oc_mutex_lock(g_networkMonitorContextMutex);
190
191     size_t list_length = u_arraylist_length(g_netInterfaceList);
192     for (size_t list_index = 0; list_index < list_length; list_index++)
193     {
194         CAInterface_t *currItem = (CAInterface_t *) u_arraylist_get(g_netInterfaceList,
195                                                                     list_index);
196         if (currItem->index == ifiindex)
197         {
198             oc_mutex_unlock(g_networkMonitorContextMutex);
199             return true;
200         }
201     }
202     oc_mutex_unlock(g_networkMonitorContextMutex);
203     OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
204     return false;
205 }
206
207 /**
208  * Add to network monitor list.
209  *
210  * @return OK if success, otherwise FAIL.
211  */
212 static CAResult_t CAAddNetworkMonitorList(CAInterface_t *ifitem)
213 {
214     OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
215     VERIFY_NON_NULL(g_netInterfaceList, TAG, "g_netInterfaceList is NULL");
216     VERIFY_NON_NULL(ifitem, TAG, "ifitem is NULL");
217
218     oc_mutex_lock(g_networkMonitorContextMutex);
219     bool result = u_arraylist_add(g_netInterfaceList, (void *) ifitem);
220     if (!result)
221     {
222         OIC_LOG(ERROR, TAG, "u_arraylist_add failed.");
223         oc_mutex_unlock(g_networkMonitorContextMutex);
224         return CA_STATUS_FAILED;
225     }
226     oc_mutex_unlock(g_networkMonitorContextMutex);
227     OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
228     return CA_STATUS_OK;
229 }
230
231 /**
232  * Remove from network monitor list.
233  *
234  * @param ifiindex  interface index.
235  */
236 static void CARemoveNetworkMonitorList(int ifiindex)
237 {
238     VERIFY_NON_NULL_VOID(g_netInterfaceList, TAG, "g_netInterfaceList is NULL");
239
240     oc_mutex_lock(g_networkMonitorContextMutex);
241
242     size_t list_length = u_arraylist_length(g_netInterfaceList);
243     for (size_t list_index = 0; list_index < list_length; list_index++)
244     {
245         CAInterface_t *removedifitem = (CAInterface_t *) u_arraylist_get(
246                 g_netInterfaceList, list_index);
247         if (removedifitem && ((int)removedifitem->index) == ifiindex)
248         {
249             if (u_arraylist_remove(g_netInterfaceList, list_index))
250             {
251                 OICFree(removedifitem);
252                 oc_mutex_unlock(g_networkMonitorContextMutex);
253                 return;
254             }
255             continue;
256         }
257     }
258     oc_mutex_unlock(g_networkMonitorContextMutex);
259     return;
260 }
261
262 /**
263  * Get connection status callback.
264  */
265 static bool get_connection_status_cb(LSHandle *sh, LSMessage *message, void *ctx)
266 {
267     OIC_LOG(DEBUG, TAG, "Callback for com.webos.service.connectionmanager/getstatus is invoked...");
268
269     jvalue_ref parsedObj = {0};
270     jschema_ref input_schema = jschema_parse(j_cstr_to_buffer("{}"), DOMOPT_NOOPT, NULL);
271
272     if (!input_schema)
273         return false;
274
275     JSchemaInfo schemaInfo;
276     jschema_info_init(&schemaInfo, input_schema, NULL, NULL);
277     parsedObj = jdom_parse(j_cstr_to_buffer(LSMessageGetPayload(message)), DOMOPT_NOOPT, &schemaInfo);
278     jschema_release(&input_schema);
279
280     if (jis_null(parsedObj))
281         return true;
282
283     const char *payload = jvalue_tostring(parsedObj, input_schema);
284
285     OIC_LOG_V(DEBUG, TAG, "Paylod: %s", payload);
286
287     jvalue_ref wiredObj={0}, wifiObj ={0}, wiredStateObj={0}, wifiStateObj={0};
288
289     if (jobject_get_exists(parsedObj, J_CSTR_TO_BUF("wired"), &wiredObj))
290     {
291         if (jobject_get_exists(wiredObj, J_CSTR_TO_BUF("state"), &wiredStateObj))
292         {
293             if (jstring_equal2(wiredStateObj, J_CSTR_TO_BUF("connected")) && !gConnectionStates.isConnectWired)
294             {
295                 gConnectionStates.isConnectWired = true;
296                 CAIPPassNetworkChangesToAdapter(CA_INTERFACE_UP);
297                 OIC_LOG(INFO, TAG, "Wired LAN is connected...");
298             }
299             else if (jstring_equal2(wiredStateObj, J_CSTR_TO_BUF("disconnected")) && gConnectionStates.isConnectWired)
300             {
301                 gConnectionStates.isConnectWired = false;
302                 CAIPPassNetworkChangesToAdapter(CA_INTERFACE_DOWN);
303                 OIC_LOG(INFO, TAG, "Wired LAN is disconnected...");
304             }
305         }
306     }
307
308     if (jobject_get_exists(parsedObj, J_CSTR_TO_BUF("wifi"), &wifiObj))
309     {
310         if (jobject_get_exists(wifiObj, J_CSTR_TO_BUF("state"), &wifiStateObj))
311         {
312             if (jstring_equal2(wifiStateObj, J_CSTR_TO_BUF("connected")) && !gConnectionStates.isConnectWiFi)
313             {
314                 gConnectionStates.isConnectWiFi = true;
315                 CAIPPassNetworkChangesToAdapter(CA_INTERFACE_UP);
316                 OIC_LOG(INFO, TAG, "Wi-Fi is connected...");
317             }
318             else if (jstring_equal2(wifiStateObj, J_CSTR_TO_BUF("disconnected")) && gConnectionStates.isConnectWiFi)
319             {
320                 gConnectionStates.isConnectWiFi = false;
321                 CAIPPassNetworkChangesToAdapter(CA_INTERFACE_DOWN);
322                 OIC_LOG(DEBUG, TAG, "Wi-Fi is disconnected...");
323             }
324         }
325     }
326
327     return true;
328 }
329
330 static void CANetworkMonitorHandler()
331 {
332     OIC_LOG(DEBUG, TAG, "CANetworkMonitorHandler");
333     LSError lserror;
334     LSErrorInit(&lserror);
335
336     if (!CAGetLSHandle())
337     {
338         OIC_LOG(ERROR, TAG, "Luna service handle is null");
339         exit(1);
340     }
341
342     if(!LSCall(CAGetLSHandle(), LS_CONNECTIONMANAGER_GETSTATUS_URI,
343                             "{\"subscribe\":true}",
344                             get_connection_status_cb, NULL, NULL, &lserror))
345     {
346         OIC_LOG(ERROR, TAG, "com.webos.service.connectionmanager/getstatus failed");
347         LSErrorPrint(&lserror, stderr);
348     }
349     else
350     {
351         OIC_LOG(INFO, TAG, "com.webos.service.connectionmanager/getstatus succeeds");
352     }
353 }
354
355 CAResult_t CAIPStartNetworkMonitor(CAIPAdapterStateChangeCallback callback,
356                                    CATransportAdapter_t adapter)
357 {
358     CAResult_t res = CA_STATUS_FAILED;
359
360     res = CAInitializeLS(g_ipMonitorThreadPool);
361     if (CA_STATUS_OK != res)
362     {
363         OIC_LOG(ERROR, TAG, "Failed to register LS in IP monitor");
364         return res;
365     }
366
367     CANetworkMonitorHandler();
368
369     res = CAIPInitializeNetworkMonitorList();
370     if (CA_STATUS_OK == res)
371     {
372         return CAIPSetNetworkMonitorCallback(callback, adapter);
373     }
374
375     return res;
376 }
377
378 CAResult_t CAIPStopNetworkMonitor(CATransportAdapter_t adapter)
379 {
380     gboolean ret = false;
381     LSError lserror;
382     LSErrorInit(&lserror);
383
384     CAIPDestroyNetworkMonitorList();
385
386     CATerminateLS();
387
388     return CAIPUnSetNetworkMonitorCallback(adapter);
389 }
390
391 int CAGetPollingInterval(int interval)
392 {
393     return interval;
394 }
395
396 static void CAIPPassNetworkChangesToAdapter(CANetworkStatus_t status)
397 {
398     OIC_LOG_V(DEBUG, TAG, "IN %s: status = %d", __func__, status);
399     CAIPCBData_t *cbitem = NULL;
400     LL_FOREACH(g_adapterCallbackList, cbitem)
401     {
402         if (cbitem && cbitem->adapter)
403         {
404             cbitem->callback(cbitem->adapter, status);
405             CALogAdapterStateInfo(cbitem->adapter, status);
406         }
407     }
408     OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
409 }
410
411 CAResult_t CAIPSetNetworkMonitorCallback(CAIPAdapterStateChangeCallback callback,
412                                          CATransportAdapter_t adapter)
413 {
414     if (!callback)
415     {
416         OIC_LOG(ERROR, TAG, "callback is null");
417         return CA_STATUS_INVALID_PARAM;
418     }
419
420     CAIPCBData_t *cbitem = NULL;
421     LL_FOREACH(g_adapterCallbackList, cbitem)
422     {
423         if (cbitem && adapter == cbitem->adapter && callback == cbitem->callback)
424         {
425             OIC_LOG(DEBUG, TAG, "this callback is already added");
426             return CA_STATUS_OK;
427         }
428     }
429
430     cbitem = (CAIPCBData_t *)OICCalloc(1, sizeof(*cbitem));
431     if (!cbitem)
432     {
433         OIC_LOG(ERROR, TAG, "Malloc failed");
434         return CA_STATUS_FAILED;
435     }
436
437     cbitem->adapter = adapter;
438     cbitem->callback = callback;
439     LL_APPEND(g_adapterCallbackList, cbitem);
440
441     return CA_STATUS_OK;
442 }
443
444 CAResult_t CAIPUnSetNetworkMonitorCallback(CATransportAdapter_t adapter)
445 {
446     CAIPCBData_t *cbitem = NULL;
447     CAIPCBData_t *tmpCbitem = NULL;
448     LL_FOREACH_SAFE(g_adapterCallbackList, cbitem, tmpCbitem)
449     {
450         if (cbitem && adapter == cbitem->adapter)
451         {
452             OIC_LOG(DEBUG, TAG, "remove specific callback");
453             LL_DELETE(g_adapterCallbackList, cbitem);
454             OICFree(cbitem);
455             return CA_STATUS_OK;
456         }
457     }
458     return CA_STATUS_OK;
459 }
460
461 static CAInterface_t *CANewInterfaceItem(int index, const char *name, int family,
462                                          const char *addr, int flags)
463 {
464     OIC_LOG_V(DEBUG, TAG, "IN %s:"
465               "index = %d, name = \"%s\", family = %d, addr = \"%s\", flags = %d",
466               __func__, index, name, family, addr, flags);
467     CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof (CAInterface_t));
468     if (!ifitem)
469     {
470         OIC_LOG(ERROR, TAG, "Malloc failed");
471         return NULL;
472     }
473
474     OICStrcpy(ifitem->name, sizeof (ifitem->name), name);
475     ifitem->index = index;
476     ifitem->family = family;
477     OICStrcpy(ifitem->addr, sizeof (ifitem->addr), addr);
478     ifitem->flags = flags;
479
480     OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
481     return ifitem;
482 }
483
484 u_arraylist_t *CAFindInterfaceChange()
485 {
486     u_arraylist_t *iflist = NULL;
487     char buf[4096] = { 0 };
488     struct nlmsghdr *nh = NULL;
489     struct sockaddr_nl sa = { .nl_family = 0 };
490     struct iovec iov = { .iov_base = buf,
491                          .iov_len = sizeof (buf) };
492     struct msghdr msg = { .msg_name = (void *)&sa,
493                           .msg_namelen = sizeof (sa),
494                           .msg_iov = &iov,
495                           .msg_iovlen = 1 };
496
497     ssize_t len = recvmsg(caglobals.ip.netlinkFd, &msg, 0);
498
499     for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len))
500     {
501         if (nh != NULL && (nh->nlmsg_type != RTM_DELADDR && nh->nlmsg_type != RTM_NEWADDR))
502         {
503             continue;
504         }
505
506         if (RTM_DELADDR == nh->nlmsg_type)
507         {
508             struct ifaddrmsg *ifa = (struct ifaddrmsg *)NLMSG_DATA (nh);
509             if (ifa)
510             {
511                 int ifiIndex = ifa->ifa_index;
512                 bool isFound = CACmpNetworkList(ifiIndex);
513                 if (isFound)
514                 {
515                     CARemoveNetworkMonitorList(ifiIndex);
516                 }
517             }
518             continue;
519         }
520
521         // Netlink message type is RTM_NEWADDR.
522         struct ifaddrmsg *ifa = (struct ifaddrmsg *)NLMSG_DATA (nh);
523         if (ifa)
524         {
525             int ifiIndex = ifa->ifa_index;
526             iflist = CAIPGetInterfaceInformation(ifiIndex);
527             if (!iflist)
528             {
529                 OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno));
530                 return NULL;
531             }
532         }
533     }
534     return iflist;
535 }
536
537 u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex)
538 {
539 #if NETWORK_INTERFACE_CHANGED_LOGGING
540     OIC_LOG_V(DEBUG, TAG, "IN %s: desiredIndex = %d", __func__, desiredIndex);
541 #endif
542     if (desiredIndex < 0)
543     {
544         OIC_LOG_V(ERROR, TAG, "invalid index : %d", desiredIndex);
545         return NULL;
546     }
547
548     u_arraylist_t *iflist = u_arraylist_create();
549     if (!iflist)
550     {
551         OIC_LOG_V(ERROR, TAG, "Failed to create iflist: %s", strerror(errno));
552         return NULL;
553     }
554
555     struct ifaddrs *ifp = NULL;
556     if (-1 == getifaddrs(&ifp))
557     {
558         OIC_LOG_V(ERROR, TAG, "Failed to get ifaddrs: %s", strerror(errno));
559         u_arraylist_destroy(iflist);
560         return NULL;
561     }
562
563     struct ifaddrs *ifa = NULL;
564 #if NETWORK_INTERFACE_CHANGED_LOGGING
565     OIC_LOG(DEBUG, TAG, "Iterating over interface addresses.");
566 #endif
567     for (ifa = ifp; ifa; ifa = ifa->ifa_next)
568     {
569         if (!ifa->ifa_addr)
570         {
571             continue;
572         }
573         int family = ifa->ifa_addr->sa_family;
574         if ((ifa->ifa_flags & IFF_LOOPBACK) || (AF_INET != family && AF_INET6 != family))
575         {
576             continue;
577         }
578
579         int ifindex = if_nametoindex(ifa->ifa_name);
580         if (desiredIndex && (ifindex != desiredIndex))
581         {
582             continue;
583         }
584
585         size_t length = u_arraylist_length(iflist);
586         int already = false;
587 #if NETWORK_INTERFACE_CHANGED_LOGGING
588         OIC_LOG_V(DEBUG, TAG, "Iterating over %" PRIuPTR " interfaces.", length);
589 #endif
590         for (size_t i = 0; i < length; i++)
591         {
592 #if NETWORK_INTERFACE_CHANGED_LOGGING
593             OIC_LOG_V(DEBUG, TAG, "Checking interface %" PRIuPTR ".", i);
594 #endif
595             CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
596
597             if (ifitem
598                 && (int)ifitem->index == ifindex
599                 && ifitem->family == (uint16_t)family)
600             {
601                 already = true;
602                 break;
603             }
604         }
605         if (already)
606         {
607             continue;
608         }
609
610         CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof(CAInterface_t));
611         if (!ifitem)
612         {
613             OIC_LOG(ERROR, TAG, "Malloc failed");
614             goto exit;
615         }
616
617         OICStrcpy(ifitem->name, INTERFACE_NAME_MAX, ifa->ifa_name);
618         ifitem->index = ifindex;
619         ifitem->family = family;
620         ifitem->flags = ifa->ifa_flags;
621
622         if (ifitem->family == AF_INET6)
623         {
624             struct sockaddr_in6 *in6 = (struct sockaddr_in6*) ifa->ifa_addr;
625             inet_ntop(ifitem->family, (void *)&(in6->sin6_addr), ifitem->addr,
626                       sizeof(ifitem->addr));
627         }
628         else if (ifitem->family == AF_INET)
629         {
630             struct sockaddr_in *in = (struct sockaddr_in*) ifa->ifa_addr;
631             inet_ntop(ifitem->family, (void *)&(in->sin_addr), ifitem->addr,
632                       sizeof(ifitem->addr));
633         }
634
635         bool result = u_arraylist_add(iflist, ifitem);
636         if (!result)
637         {
638             OIC_LOG(ERROR, TAG, "u_arraylist_add failed.");
639             goto exit;
640         }
641
642         bool isFound = CACmpNetworkList(ifitem->index);
643         if (!isFound)
644         {
645             CAInterface_t *newifitem = CANewInterfaceItem(ifitem->index, ifitem->name, ifitem->family,
646                                                           ifitem->addr, ifitem->flags);
647             CAResult_t ret = CAAddNetworkMonitorList(newifitem);
648             if (CA_STATUS_OK != ret)
649             {
650                 OICFree(newifitem);
651                 goto exit;
652             }
653             OIC_LOG_V(DEBUG, TAG, "Added interface: %s (%d)", ifitem->name, ifitem->family);
654         }
655     }
656     freeifaddrs(ifp);
657 #if NETWORK_INTERFACE_CHANGED_LOGGING
658     OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
659 #endif
660     return iflist;
661
662 exit:
663     freeifaddrs(ifp);
664     u_arraylist_destroy(iflist);
665 #if NETWORK_INTERFACE_CHANGED_LOGGING
666     OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
667 #endif
668     return NULL;
669 }
670
671 CAResult_t CAGetLinkLocalZoneIdInternal(uint32_t ifindex, char **zoneId)
672 {
673     if (!zoneId || (*zoneId != NULL))
674     {
675         return CA_STATUS_INVALID_PARAM;
676     }
677
678     *zoneId = (char *)OICCalloc(IF_NAMESIZE, sizeof(char));
679     if (!(*zoneId))
680     {
681         OIC_LOG(ERROR, TAG, "OICCalloc failed in CAGetLinkLocalZoneIdInternal");
682         return CA_MEMORY_ALLOC_FAILED;
683     }
684
685     if (!if_indextoname(ifindex, *zoneId))
686     {
687         OIC_LOG(ERROR, TAG, "if_indextoname failed in CAGetLinkLocalZoneIdInternal");
688         OICFree(*zoneId);
689         *zoneId = NULL;
690         return CA_STATUS_FAILED;
691     }
692
693     OIC_LOG_V(DEBUG, TAG, "Given ifindex is %d parsed zoneId is %s", ifindex, *zoneId);
694     return CA_STATUS_OK;
695 }
696
697 void CAIPSetMonitorThreadPoolHandle(ca_thread_pool_t handle)
698 {
699     g_ipMonitorThreadPool = handle;
700 }