Imported Upstream version 0.9.1
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / ip_adapter / linux / caipnwmonitor.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 #include "caipinterface.h"
22
23 #include <sys/types.h>
24 #include <ifaddrs.h>
25 #include <net/if.h>
26 #include <sys/socket.h>
27 #include <netdb.h>
28 #include <string.h>
29 #include <errno.h>
30 #include <unistd.h>
31
32 #include "caadapterutils.h"
33 #include "camutex.h"
34 #include "logger.h"
35 #include "oic_malloc.h"
36 #include "oic_string.h"
37
38 #define IP_MONITOR_TAG "IP_MONITOR"
39
40 /**
41  * @var g_networkMonitorContextMutex
42  * @brief  Mutex for synchronizing access to cached interface and IP address information.
43  */
44 static ca_mutex g_networkMonitorContextMutex = NULL;
45
46 /**
47  * @var g_stopNetworkMonitor
48  * @brief  Used to stop the network monitor thread.
49  */
50 static bool g_stopNetworkMonitor = false;
51
52 /**
53  * @var g_stopNetworkMonitorMutex
54  * @brief  Mutex for synchronizing access to g_stopNetworkMonitor flag.
55  */
56 static ca_mutex g_stopNetworkMonitorMutex = NULL;
57
58 /**
59  * @struct CAIPNwMonitorContext
60  * @brief  Used for storing network monitor context information.
61  */
62 typedef struct
63 {
64     u_arraylist_t  *netInterfaceList;
65     ca_thread_pool_t threadPool;
66     CANetworkStatus_t nwConnectivityStatus;
67     CAIPConnectionStateChangeCallback networkChangeCb;
68 } CAIPNetworkMonitorContext;
69
70 /**
71  * @var g_networkMonitorContext
72  * @brief  network monitor context.
73  */
74 static CAIPNetworkMonitorContext *g_networkMonitorContext = NULL;
75
76 static void CAIPGetInterfaceInformation(u_arraylist_t **netInterfaceList)
77 {
78
79     VERIFY_NON_NULL_VOID(netInterfaceList, IP_MONITOR_TAG, "netInterfaceList is null");
80
81     struct ifaddrs *ifp = NULL;
82     if (-1 == getifaddrs(&ifp))
83     {
84         OIC_LOG_V(ERROR, IP_MONITOR_TAG, "Failed to get interface list!, Error code: %s",
85                   strerror(errno));
86         return;
87     }
88
89     struct ifaddrs *ifa = NULL;
90     for (ifa = ifp; ifa; ifa = ifa->ifa_next)
91     {
92         char interfaceAddress[CA_IPADDR_SIZE] = {0};
93         char interfaceSubnetMask[CA_IPADDR_SIZE] = {0};
94         socklen_t len = sizeof(struct sockaddr_in);
95
96         if (!ifa->ifa_addr)
97         {
98             continue;
99         }
100
101         int type = ifa->ifa_addr->sa_family;
102         if (ifa->ifa_flags & IFF_LOOPBACK
103             || !((ifa->ifa_flags & IFF_UP) && (ifa->ifa_flags & IFF_RUNNING)))
104         {
105             continue;
106         }
107
108         if (AF_INET != type)
109         {
110             continue;
111         }
112
113         // get the interface ip address
114         if (0 != getnameinfo(ifa->ifa_addr, len, interfaceAddress,
115                              sizeof(interfaceAddress), NULL, 0, NI_NUMERICHOST))
116         {
117             OIC_LOG_V(ERROR, IP_MONITOR_TAG, "Failed to get IPAddress, Error code: %s",
118                       strerror(errno));
119             continue;
120         }
121
122         // get the interface subnet mask
123         if (0 != getnameinfo(ifa->ifa_netmask, len, interfaceSubnetMask,
124                              sizeof(interfaceSubnetMask), NULL, 0, NI_NUMERICHOST))
125         {
126             OIC_LOG_V(ERROR, IP_MONITOR_TAG, "Failed to get subnet mask, Error code: %s",
127                       strerror(errno));
128             continue;
129         }
130
131         CANetInfo_t *netInfo = (CANetInfo_t *)OICCalloc(1, sizeof(CANetInfo_t));
132         if (!netInfo)
133         {
134             OIC_LOG(ERROR, IP_MONITOR_TAG, "Malloc failed");
135             freeifaddrs(ifp);
136             return;
137         }
138         // set interface name
139         strncpy(netInfo->interfaceName, ifa->ifa_name, sizeof(netInfo->interfaceName) - 1);
140         netInfo->interfaceName[sizeof(netInfo->interfaceName)-1] = '\0';
141
142         // set local ip address
143         strncpy(netInfo->ipAddress, interfaceAddress, strlen(interfaceAddress));
144
145         // set subnet mask
146         strncpy(netInfo->subnetMask, interfaceSubnetMask, strlen(interfaceSubnetMask));
147
148         CAResult_t result = u_arraylist_add(*netInterfaceList, (void *)netInfo);
149         if (CA_STATUS_OK != result)
150         {
151             OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_add failed!Thread exiting.");
152             freeifaddrs(ifp);
153             return;
154         }
155     }
156
157     freeifaddrs(ifp);
158 }
159
160 static bool CACheckIsAnyInterfaceDown(const u_arraylist_t *netInterfaceList,
161                                       const CANetInfo_t *info)
162 {
163     VERIFY_NON_NULL_RET(netInterfaceList, IP_MONITOR_TAG, "netInterfaceList is null", false);
164     VERIFY_NON_NULL_RET(info, IP_MONITOR_TAG, "info is null", false);
165
166     uint32_t list_index = 0;
167     uint32_t list_length = u_arraylist_length(netInterfaceList);
168     for (list_index = 0; list_index < list_length; list_index++)
169     {
170         CANetInfo_t *netInfo = (CANetInfo_t *)u_arraylist_get(netInterfaceList,
171                                list_index);
172         if (!netInfo)
173         {
174             continue;
175         }
176         if (strncmp(netInfo->interfaceName, info->interfaceName, strlen(info->interfaceName)) == 0)
177         {
178             return false;
179         }
180     }
181     OIC_LOG(DEBUG, IP_MONITOR_TAG, "Interface is down");
182     return true;
183 }
184
185 static bool CACheckIsInterfaceInfoChanged(const CANetInfo_t *info)
186 {
187     VERIFY_NON_NULL_RET(info, IP_MONITOR_TAG, "info is null", false);
188
189     ca_mutex_lock(g_networkMonitorContextMutex);
190     uint32_t list_index = 0;
191     uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList);
192     for (list_index = 0; list_index < list_length; list_index++)
193     {
194         CANetInfo_t *netInfo = (CANetInfo_t *)u_arraylist_get(
195                                g_networkMonitorContext->netInterfaceList, list_index);
196         if (!netInfo)
197         {
198             continue;
199         }
200         if (strncmp(netInfo->interfaceName, info->interfaceName, strlen(info->interfaceName)) == 0)
201         {
202             if (strncmp(netInfo->ipAddress, info->ipAddress, strlen(info->ipAddress)) == 0)
203             {
204                 ca_mutex_unlock(g_networkMonitorContextMutex);
205                 return false;
206             }
207             else
208             {
209                 OIC_LOG(DEBUG, IP_MONITOR_TAG, "Network interface info changed");
210                 if (u_arraylist_remove(g_networkMonitorContext->netInterfaceList, list_index))
211                 {
212                     if (g_networkMonitorContext->networkChangeCb)
213                     {
214                         g_networkMonitorContext->networkChangeCb(netInfo->ipAddress,
215                                                                  CA_INTERFACE_DOWN);
216                     }
217                     OICFree(netInfo);
218                 }
219                 else
220                 {
221                     OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_remove failed");
222                 }
223                 break;
224             }
225         }
226     }
227
228     CANetInfo_t *newNetInfo = (CANetInfo_t *)OICMalloc(sizeof(CANetInfo_t));
229     if (!newNetInfo)
230     {
231         OIC_LOG(ERROR, IP_MONITOR_TAG, "newNetInfo malloc failed");
232         ca_mutex_unlock(g_networkMonitorContextMutex);
233         return false;
234     }
235     memcpy(newNetInfo, info, sizeof(*newNetInfo));
236
237     OIC_LOG(DEBUG, IP_MONITOR_TAG, "New Interface found");
238
239     CAResult_t result = u_arraylist_add(g_networkMonitorContext->netInterfaceList,
240                                         (void *)newNetInfo);
241     if (CA_STATUS_OK != result)
242     {
243         OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_add failed!");
244         OICFree(newNetInfo);
245         ca_mutex_unlock(g_networkMonitorContextMutex);
246         return false;
247     }
248     ca_mutex_unlock(g_networkMonitorContextMutex);
249
250     /*Callback will be unset only at the time of termination. By that time, all the threads will be
251       stopped gracefully. This callback is properly protected*/
252     if (g_networkMonitorContext->networkChangeCb)
253     {
254         g_networkMonitorContext->networkChangeCb(newNetInfo->ipAddress, CA_INTERFACE_UP);
255     }
256
257     return true;
258 }
259
260 static void CANetworkMonitorThread(void *threadData)
261 {
262     OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
263
264     while (!g_stopNetworkMonitor)
265     {
266         u_arraylist_t  *netInterfaceList = u_arraylist_create();
267
268         VERIFY_NON_NULL_VOID(netInterfaceList, IP_MONITOR_TAG, "netInterfaceList is null");
269
270         CAIPGetInterfaceInformation(&netInterfaceList);
271
272         ca_mutex_lock(g_networkMonitorContextMutex);
273         if (!g_networkMonitorContext->netInterfaceList)
274         {
275             OIC_LOG(ERROR, IP_MONITOR_TAG,
276                     "u_arraylist_create failed. Network Monitor thread stopped");
277             CAClearNetInterfaceInfoList(netInterfaceList);
278             ca_mutex_unlock(g_networkMonitorContextMutex);
279             return;
280         }
281
282         uint32_t listIndex = 0;
283         uint32_t listLength = u_arraylist_length(g_networkMonitorContext->netInterfaceList);
284         for (listIndex = 0; listIndex < listLength;)
285         {
286             CANetInfo_t *info = (CANetInfo_t *)u_arraylist_get(
287                                     g_networkMonitorContext->netInterfaceList, listIndex);
288             if (!info)
289             {
290                 listIndex++;
291                 continue;
292             }
293
294             bool ret = CACheckIsAnyInterfaceDown(netInterfaceList, info);
295             if (ret)
296             {
297                 OIC_LOG(DEBUG, IP_MONITOR_TAG, "Interface is down");
298                 if (u_arraylist_remove(g_networkMonitorContext->netInterfaceList, listIndex))
299                 {
300                     OIC_LOG(DEBUG, IP_MONITOR_TAG, "u_arraylist_remove success");
301                     if (g_networkMonitorContext->networkChangeCb)
302                     {
303                         g_networkMonitorContext->networkChangeCb(info->ipAddress,
304                                                                  CA_INTERFACE_DOWN);
305                     }
306                     OICFree(info);
307                     listLength--;
308                 }
309                 else
310                 {
311                     OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_remove failed");
312                     break;
313                 }
314             }
315             else
316             {
317                 listIndex++;
318             }
319         }
320         ca_mutex_unlock(g_networkMonitorContextMutex);
321
322         listLength = u_arraylist_length(netInterfaceList);
323         for (listIndex = 0; listIndex < listLength; listIndex++)
324         {
325             CANetInfo_t *info = (CANetInfo_t *)u_arraylist_get(netInterfaceList, listIndex);
326             if (!info)
327             {
328                 continue;
329             }
330             bool ret = CACheckIsInterfaceInfoChanged(info);
331             if (ret)
332             {
333                 OIC_LOG(DEBUG, IP_MONITOR_TAG, "CACheckIsInterfaceInfoChanged true");
334             }
335         }
336         CAClearNetInterfaceInfoList(netInterfaceList);
337         sleep(2); // To avoid maximum cpu usage.
338     }
339
340     OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
341 }
342
343 static CAResult_t CAInitializeNetworkMonitorMutexes()
344 {
345     if (!g_networkMonitorContextMutex)
346     {
347         g_networkMonitorContextMutex = ca_mutex_new();
348         if (!g_networkMonitorContextMutex)
349         {
350             OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContextMutex Malloc  failed");
351             return CA_MEMORY_ALLOC_FAILED;
352         }
353     }
354
355     if (!g_stopNetworkMonitorMutex)
356     {
357         g_stopNetworkMonitorMutex = ca_mutex_new();
358         if (!g_stopNetworkMonitorMutex)
359         {
360             OIC_LOG(ERROR, IP_MONITOR_TAG, "g_stopNetworkMonitorMutex Malloc  failed");
361             ca_mutex_free(g_networkMonitorContextMutex);
362             return CA_MEMORY_ALLOC_FAILED;
363         }
364     }
365     return CA_STATUS_OK;
366 }
367 static void CADestroyNetworkMonitorMutexes()
368 {
369     ca_mutex_free(g_networkMonitorContextMutex);
370     g_networkMonitorContextMutex = NULL;
371
372     ca_mutex_free(g_stopNetworkMonitorMutex);
373     g_stopNetworkMonitorMutex = NULL;
374 }
375
376 CAResult_t CAIPInitializeNetworkMonitor(const ca_thread_pool_t threadPool)
377 {
378     OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
379
380     VERIFY_NON_NULL(threadPool, IP_MONITOR_TAG, "threadPool is null");
381
382     CAResult_t ret = CAInitializeNetworkMonitorMutexes();
383
384     if (CA_STATUS_OK != ret)
385     {
386         OIC_LOG(ERROR, IP_MONITOR_TAG, "CAInitializeNetworkMonitorMutexes failed");
387         return CA_STATUS_FAILED;
388     }
389
390     ca_mutex_lock(g_networkMonitorContextMutex);
391
392     g_networkMonitorContext = (CAIPNetworkMonitorContext *)OICCalloc(1,
393                               sizeof(*g_networkMonitorContext));
394     if (!g_networkMonitorContext)
395     {
396         OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContext Malloc  failed");
397         ca_mutex_unlock(g_networkMonitorContextMutex);
398         CADestroyNetworkMonitorMutexes();
399         return CA_MEMORY_ALLOC_FAILED;
400     }
401     g_networkMonitorContext->threadPool = threadPool;
402
403     g_networkMonitorContext->netInterfaceList = u_arraylist_create();
404     if (!g_networkMonitorContext->netInterfaceList)
405     {
406         OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_create failed");
407         OICFree(g_networkMonitorContext);
408         ca_mutex_unlock(g_networkMonitorContextMutex);
409         CADestroyNetworkMonitorMutexes();
410         return CA_MEMORY_ALLOC_FAILED;
411     }
412
413     CAIPGetInterfaceInformation(&g_networkMonitorContext->netInterfaceList);
414
415
416     if (u_arraylist_length(g_networkMonitorContext->netInterfaceList))
417     {
418         g_networkMonitorContext->nwConnectivityStatus = CA_INTERFACE_UP;
419     }
420     else
421     {
422         g_networkMonitorContext->nwConnectivityStatus = CA_INTERFACE_DOWN;
423     }
424
425     ca_mutex_unlock(g_networkMonitorContextMutex);
426
427     OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
428     return CA_STATUS_OK;
429 }
430
431 void CAIPTerminateNetworkMonitor()
432 {
433     OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
434
435     ca_mutex_lock(g_networkMonitorContextMutex);
436     g_networkMonitorContext->threadPool = NULL;
437
438     CAClearNetInterfaceInfoList(g_networkMonitorContext->netInterfaceList);
439
440     g_networkMonitorContext->netInterfaceList = NULL;
441     g_networkMonitorContext->nwConnectivityStatus = CA_INTERFACE_DOWN;
442     g_networkMonitorContext->networkChangeCb = NULL;
443     g_networkMonitorContext->threadPool = NULL;
444
445     OICFree(g_networkMonitorContext);
446     g_networkMonitorContext = NULL;
447
448     ca_mutex_unlock(g_networkMonitorContextMutex);
449
450     ca_mutex_lock(g_stopNetworkMonitorMutex);
451     g_stopNetworkMonitor = true;
452     ca_mutex_unlock(g_stopNetworkMonitorMutex);
453
454     CADestroyNetworkMonitorMutexes();
455
456     OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
457 }
458
459 CAResult_t CAIPStartNetworkMonitor()
460 {
461     OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
462
463     ca_mutex_lock(g_stopNetworkMonitorMutex);
464
465     g_stopNetworkMonitor = false;
466
467     ca_mutex_unlock(g_stopNetworkMonitorMutex);
468
469     ca_mutex_lock(g_networkMonitorContextMutex);
470
471     if (!g_networkMonitorContext)
472     {
473         OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContext is null");
474         ca_mutex_unlock(g_networkMonitorContextMutex);
475         return CA_STATUS_FAILED;
476     }
477
478     if (CA_STATUS_OK != ca_thread_pool_add_task(g_networkMonitorContext->threadPool,
479             CANetworkMonitorThread, NULL))
480     {
481         OIC_LOG(ERROR, IP_MONITOR_TAG, "[ThreadPool] thread_pool_add_task failed!");
482         ca_mutex_unlock(g_networkMonitorContextMutex);
483         return CA_STATUS_FAILED;
484     }
485     ca_mutex_unlock(g_networkMonitorContextMutex);
486
487     OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
488     return CA_STATUS_OK;
489 }
490
491 CAResult_t CAIPStopNetworkMonitor()
492 {
493     OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
494
495     ca_mutex_lock(g_networkMonitorContextMutex);
496     if (!g_networkMonitorContext)
497     {
498         OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContext is null");
499         ca_mutex_unlock(g_networkMonitorContextMutex);
500         return CA_STATUS_FAILED;
501     }
502
503     ca_mutex_unlock(g_networkMonitorContextMutex);
504
505     ca_mutex_lock(g_stopNetworkMonitorMutex);
506     if (!g_stopNetworkMonitor)
507     {
508         g_stopNetworkMonitor = true;
509     }
510     else
511     {
512         OIC_LOG(DEBUG, IP_MONITOR_TAG, "CAIPStopNetworkMonitor, already stopped!");
513     }
514     ca_mutex_unlock(g_stopNetworkMonitorMutex);
515
516     OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
517     return CA_STATUS_OK;
518 }
519
520 CAResult_t CAIPGetInterfaceInfo(u_arraylist_t **netInterfaceList)
521 {
522     OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
523
524     VERIFY_NON_NULL(netInterfaceList, IP_MONITOR_TAG, "u_array_list is null");
525     VERIFY_NON_NULL(g_networkMonitorContext, IP_MONITOR_TAG,
526                     "g_networkMonitorContext is null");
527     VERIFY_NON_NULL(g_networkMonitorContextMutex, IP_MONITOR_TAG,
528                     "g_networkMonitorContextMutex is null");
529
530     // Get the interface and ipaddress information from cache
531     ca_mutex_lock(g_networkMonitorContextMutex);
532     if (!g_networkMonitorContext->netInterfaceList
533         || !(u_arraylist_length(g_networkMonitorContext->netInterfaceList)))
534     {
535         OIC_LOG(ERROR, IP_MONITOR_TAG, "Network not enabled");
536         ca_mutex_unlock(g_networkMonitorContextMutex);
537         return CA_ADAPTER_NOT_ENABLED;
538     }
539
540     uint32_t list_index = 0;
541     uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList);
542     OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "CAIPGetInterfaceInfo list length [%d]",
543               list_length);
544     for (list_index = 0; list_index < list_length; list_index++)
545     {
546         CANetInfo_t *info = (CANetInfo_t *)u_arraylist_get(
547                             g_networkMonitorContext->netInterfaceList, list_index);
548         if (!info)
549         {
550             continue;
551         }
552         OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "CAIPGetInterfaceInfo ip [%s]",
553                   info->ipAddress);
554         CANetInfo_t *newNetinfo = (CANetInfo_t *) OICMalloc(sizeof(CANetInfo_t));
555         if (!newNetinfo)
556         {
557             OIC_LOG(ERROR, IP_MONITOR_TAG, "Malloc failed!");
558             ca_mutex_unlock(g_networkMonitorContextMutex);
559             return CA_MEMORY_ALLOC_FAILED;
560         }
561
562         memcpy(newNetinfo, info, sizeof(*info));
563
564         CAResult_t result = u_arraylist_add(*netInterfaceList, (void *)newNetinfo);
565         if (CA_STATUS_OK != result)
566         {
567             OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_add failed!");
568             ca_mutex_unlock(g_networkMonitorContextMutex);
569             return CA_STATUS_FAILED;
570         }
571     }
572
573     ca_mutex_unlock(g_networkMonitorContextMutex);
574
575     OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
576     return CA_STATUS_OK;
577 }
578
579 CAResult_t CAIPGetInterfaceSubnetMask(const char *ipAddress, char **subnetMask)
580 {
581     OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
582
583     VERIFY_NON_NULL(subnetMask, IP_MONITOR_TAG, "subnet mask");
584     VERIFY_NON_NULL(ipAddress, IP_MONITOR_TAG, "ipAddress is null");
585     VERIFY_NON_NULL(g_networkMonitorContext, IP_MONITOR_TAG,
586                     "g_networkMonitorContext is null");
587     VERIFY_NON_NULL(g_networkMonitorContextMutex, IP_MONITOR_TAG,
588                     "g_networkMonitorContextMutex is null");
589
590     // Get the interface and ipaddress information from cache
591     ca_mutex_lock(g_networkMonitorContextMutex);
592     if (!g_networkMonitorContext->netInterfaceList
593         || (0 == u_arraylist_length(g_networkMonitorContext->netInterfaceList)))
594     {
595         OIC_LOG(DEBUG, IP_MONITOR_TAG, "Network not enabled");
596         ca_mutex_unlock(g_networkMonitorContextMutex);
597         return CA_ADAPTER_NOT_ENABLED;
598     }
599
600     uint32_t list_index = 0;
601     uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList);
602     OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "list lenght [%d]", list_length);
603     for (list_index = 0; list_index < list_length; list_index++)
604     {
605         CANetInfo_t *info = (CANetInfo_t *)u_arraylist_get(
606                             g_networkMonitorContext->netInterfaceList, list_index);
607         if (!info)
608         {
609             continue;
610         }
611
612         if (strncmp(info->ipAddress, ipAddress, strlen(ipAddress)) == 0)
613         {
614             OIC_LOG_V(DEBUG, IP_MONITOR_TAG,
615                       "CAIPGetInterfaceSubnetMask subnetmask is %s", info->subnetMask);
616             *subnetMask = OICStrdup(info->subnetMask);
617             break;
618         }
619     }
620     ca_mutex_unlock(g_networkMonitorContextMutex);
621
622     OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
623     return CA_STATUS_OK;
624 }
625
626 bool CAIPIsConnected()
627 {
628     OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
629     if (!g_networkMonitorContextMutex || !g_networkMonitorContext)
630     {
631         OIC_LOG(ERROR, IP_MONITOR_TAG, "IP is not connected");
632         return false;
633     }
634
635     ca_mutex_lock(g_networkMonitorContextMutex);
636     if (0 == u_arraylist_length(g_networkMonitorContext->netInterfaceList))
637     {
638         OIC_LOG(ERROR, IP_MONITOR_TAG, "IP is not connected");
639         ca_mutex_unlock(g_networkMonitorContextMutex);
640         return false;
641     }
642     ca_mutex_unlock(g_networkMonitorContextMutex);
643
644     OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
645     return true;
646 }
647
648 void CAIPSetConnectionStateChangeCallback(CAIPConnectionStateChangeCallback callback)
649 {
650     OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
651     if (!g_networkMonitorContextMutex || !g_networkMonitorContext)
652     {
653         OIC_LOG(ERROR, IP_MONITOR_TAG, "CAIPSetConnectionStateChangeCallback failed");
654         return;
655     }
656     ca_mutex_lock(g_networkMonitorContextMutex);
657
658     g_networkMonitorContext->networkChangeCb = callback;
659
660     ca_mutex_unlock(g_networkMonitorContextMutex);
661
662     OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
663 }
664