Update snapshot(2017-12-06)
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / ip_adapter / tizen / caipnwmonitor.c
index 729968e..079ecd5 100644 (file)
 *
 ******************************************************************/
 
-#include "caipinterface.h"
-
-#include <wifi.h>
+#include <sys/types.h>
+#include <ifaddrs.h>
+#include <net/if.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <net_connection.h>
 
+#include "caipinterface.h"
+#include "caipnwmonitor.h"
 #include "caadapterutils.h"
-#include "camutex.h"
 #include "logger.h"
 #include "oic_malloc.h"
 #include "oic_string.h"
+#include <coap/utlist.h>
 
-#define IP_MONITOR_TAG "IP_MONITOR"
+#define TAG "OIC_CA_IP_MONITOR"
+#define MAX_INTERFACE_INFO_LENGTH (1024)
+#define NETLINK_MESSAGE_LENGTH  (4096)
+#define IFC_LABEL_LOOP          "lo"
+#define IFC_ADDR_LOOP_IPV4      "127.0.0.1"
+#define IFC_ADDR_LOOP_IPV6      "::1"
 
 /**
- * @var g_networkMonitorContextMutex
- * @brief  Mutex for synchronizing access to cached interface and IP address information.
+ * Used to storing a connection handle for managing data connections.
  */
-static ca_mutex g_networkMonitorContextMutex = NULL;
+static connection_h connection = NULL;
 
 /**
- * @struct CAIPNwMonitorContext
- * @brief  Used for storing network monitor context information.
+ * Used to storing adapter changes callback interface.
  */
-typedef struct
-{
-    u_arraylist_t  *netInterfaceList;
-    ca_thread_pool_t threadPool;
-    CANetworkStatus_t nwConnectivityStatus;
-    CAIPConnectionStateChangeCallback networkChangeCb;
-} CAIPNetworkMonitorContext;
+static struct CAIPCBData_t *g_adapterCallbackList = NULL;
 
 /**
- * @var g_networkMonitorContext
- * @brief  network monitor context.
+ * Create new interface item.
  */
-static CAIPNetworkMonitorContext *g_networkMonitorContext = NULL;
-
-static void CARemoveInterfaceInfo()
-{
-    ca_mutex_lock(g_networkMonitorContextMutex);
-    if (!g_networkMonitorContext->netInterfaceList)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG,
-                "netInterfaceList is empty");
-        ca_mutex_unlock(g_networkMonitorContextMutex);
-        return;
-    }
-
-    uint32_t list_index = 0;
-    uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList);
-    for (list_index = 0; list_index < list_length; list_index++)
-    {
-        CANetInfo_t *netInfo = (CANetInfo_t *)u_arraylist_get(
-                               g_networkMonitorContext->netInterfaceList, list_index);
-        if (!netInfo)
-        {
-            continue;
-        }
+static CAInterface_t *CANewInterfaceItem(int index, char *name, int family,
+                                         const char *addr, int flags);
 
-        if (u_arraylist_remove(g_networkMonitorContext->netInterfaceList, list_index))
-        {
-            if (g_networkMonitorContext->networkChangeCb)
-            {
-                g_networkMonitorContext->networkChangeCb(netInfo->ipAddress,
-                                                         CA_INTERFACE_DOWN);
-            }
-        }
-        else
-        {
-            OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_remove failed");
-        }
+/**
+ * Add new network interface in list.
+ */
+static CAResult_t CAAddInterfaceItem(u_arraylist_t *iflist, int index,
+                                     char *name, int family, const char *addr, int flags);
 
-        OICFree(netInfo);
-    }
+/**
+ * Pass the changed network status through the stored callback.
+ */
+static void CAIPPassNetworkChangesToAdapter(CANetworkStatus_t status);
 
-    u_arraylist_free(&g_networkMonitorContext->netInterfaceList);
+/**
+ * Callback function to received connection state changes.
+ */
+static void CAIPConnectionStateChangedCb(connection_type_e type, void* userData);
 
-    ca_mutex_unlock(g_networkMonitorContextMutex);
+int CAGetPollingInterval(int interval)
+{
+    return interval;
 }
 
-static bool CACheckIsInterfaceInfoChanged(const CANetInfo_t *info)
+static void CAIPPassNetworkChangesToAdapter(CANetworkStatus_t status)
 {
-    VERIFY_NON_NULL_RET(info, IP_MONITOR_TAG, "info is null", false);
-
-    ca_mutex_lock(g_networkMonitorContextMutex);
-    uint32_t list_index = 0;
-    uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList);
-    for (list_index = 0; list_index < list_length; list_index++)
+    CAIPCBData_t *cbitem = NULL;
+    LL_FOREACH(g_adapterCallbackList, cbitem)
     {
-        CANetInfo_t *netInfo = (CANetInfo_t *)u_arraylist_get(
-                               g_networkMonitorContext->netInterfaceList, list_index);
-        if (!netInfo)
+        if (cbitem && cbitem->adapter)
         {
-            continue;
+            cbitem->callback(cbitem->adapter, status);
         }
-
-        if (strncmp(netInfo->interfaceName, info->interfaceName, strlen(info->interfaceName)) == 0)
-        {
-            if (strncmp(netInfo->ipAddress, info->ipAddress, strlen(info->ipAddress)) == 0)
-            {
-                ca_mutex_unlock(g_networkMonitorContextMutex);
-                return false;
-            }
-            else
-            {
-                OIC_LOG(DEBUG, IP_MONITOR_TAG, "Network interface info changed");
-                if (u_arraylist_remove(g_networkMonitorContext->netInterfaceList, list_index))
-                {
-                    if (g_networkMonitorContext->networkChangeCb)
-                    {
-                        g_networkMonitorContext->networkChangeCb(netInfo->ipAddress,
-                                                                 CA_INTERFACE_DOWN);
-                    }
-                    OICFree(netInfo);
-                }
-                else
-                {
-                    OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_remove failed");
-                }
-                break;
-            }
-        }
-    }
-
-    CANetInfo_t *newNetInfo = (CANetInfo_t *)OICMalloc(sizeof(CANetInfo_t));
-    if (!newNetInfo)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "newNetInfo malloc failed");
-        ca_mutex_unlock(g_networkMonitorContextMutex);
-        return false;
     }
-    *newNetInfo = *info;
-
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "New Interface found");
-
-    CAResult_t result = u_arraylist_add(g_networkMonitorContext->netInterfaceList,
-                                        (void *)newNetInfo);
-    if (CA_STATUS_OK != result)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_add failed!");
-        OICFree(newNetInfo);
-        ca_mutex_unlock(g_networkMonitorContextMutex);
-        return false;
-    }
-    ca_mutex_unlock(g_networkMonitorContextMutex);
-
-    /*Callback will be unset only at the time of termination. By that time, all the threads will be
-      stopped gracefully. This callback is properly protected*/
-    if (g_networkMonitorContext->networkChangeCb)
-    {
-        g_networkMonitorContext->networkChangeCb(newNetInfo->ipAddress, CA_INTERFACE_UP);
-    }
-
-    return true;
 }
 
-void CAWiFiGetInterfaceInformation(char **interfaceName, char **ipAddress, char **subnetMask)
+CAResult_t CAIPSetNetworkMonitorCallback(CAIPAdapterStateChangeCallback callback,
+                                         CATransportAdapter_t adapter)
 {
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-
-    int ret = WIFI_ERROR_NONE;
-
-    if (!interfaceName || !ipAddress || !subnetMask)
+    if (!callback)
     {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "Invalid input: interface/ipaddress holder is NULL!");
-        return;
+        OIC_LOG(ERROR, TAG, "callback is null");
+        return CA_STATUS_INVALID_PARAM;
     }
 
-    // Get wifi interface name
-    if (WIFI_ERROR_NONE != (ret = wifi_get_network_interface_name(interfaceName)))
+    CAIPCBData_t *cbitem = NULL;
+    LL_FOREACH(g_adapterCallbackList, cbitem)
     {
-        OIC_LOG_V(ERROR, IP_MONITOR_TAG, "Failed to get interface name! error num [%d]", ret);
-        return;
+        if (cbitem && adapter == cbitem->adapter && callback == cbitem->callback)
+        {
+            OIC_LOG(DEBUG, TAG, "this callback is already added");
+            return CA_STATUS_OK;
+        }
     }
 
-    // Get wifi connected IP address
-    wifi_ap_h accessPoint = NULL;
-    if (WIFI_ERROR_NONE != (ret = wifi_get_connected_ap(&accessPoint)))
+    cbitem = (CAIPCBData_t *)OICCalloc(1, sizeof(*cbitem));
+    if (!cbitem)
     {
-        OIC_LOG_V(ERROR, IP_MONITOR_TAG, "Failed to get access point! error num [%d]",
-                  ret);
-
-        OICFree(*interfaceName);
-        *interfaceName = NULL;
-        return;
+        OIC_LOG(ERROR, TAG, "Malloc failed");
+        return CA_STATUS_FAILED;
     }
 
-    if (WIFI_ERROR_NONE != (ret = wifi_ap_get_ip_address(accessPoint, WIFI_ADDRESS_FAMILY_IPV4,
-                                  ipAddress)))
-    {
-        OIC_LOG_V(ERROR, IP_MONITOR_TAG, "Failed to get interface address! error num [%d]",
-                  ret);
-        OICFree(*interfaceName);
-        *interfaceName = NULL;
-        return;
-    }
+    cbitem->adapter = adapter;
+    cbitem->callback = callback;
+    LL_APPEND(g_adapterCallbackList, cbitem);
 
-    if (WIFI_ERROR_NONE != (ret = wifi_ap_get_subnet_mask(accessPoint, WIFI_ADDRESS_FAMILY_IPV4,
-                                  subnetMask)))
-    {
-        OIC_LOG_V(ERROR, IP_MONITOR_TAG, "Failed to get interface address! error num [%d]",
-                  ret);
-        OICFree(*ipAddress);
-        OICFree(*interfaceName);
-        *ipAddress = NULL;
-        *interfaceName = NULL;
-        return;
-    }
-
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
+    return CA_STATUS_OK;
 }
 
-static void CAIPGetInterfaceInformation(u_arraylist_t **netInterfaceList)
+CAResult_t CAIPUnSetNetworkMonitorCallback(CATransportAdapter_t adapter)
 {
-    VERIFY_NON_NULL_VOID(netInterfaceList, IP_MONITOR_TAG, "netInterfaceList is null");
-
-    // Get wifi network information
-    char *interfaceName = NULL;
-    char *ipAddress = NULL;
-    char *subnetMask = NULL;
-    ///TODO: currently we are filling single interface. Once found the proper tizen apis for
-    // getting multiple interfaces, then this function will be updated.
-    CAWiFiGetInterfaceInformation(&interfaceName, &ipAddress, &subnetMask);
-
-    if (!interfaceName || !ipAddress || !subnetMask)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "interface/ipaddress/subnetmask is NULL!");
-        return;
-    }
-
-    CANetInfo_t *netInfo = (CANetInfo_t *)OICCalloc(1, sizeof(CANetInfo_t));
-    if (!netInfo)
+    CAIPCBData_t *cbitem = NULL;
+    CAIPCBData_t *tmpCbitem = NULL;
+    LL_FOREACH_SAFE(g_adapterCallbackList, cbitem, tmpCbitem)
     {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "Malloc failed");
-        OICFree(interfaceName);
-        OICFree(ipAddress);
-        OICFree(subnetMask);
-        return;
-    }
-
-    // set interface name
-    OICStrcpy(netInfo->interfaceName, sizeof(netInfo->interfaceName), interfaceName);
-
-    // set local ip address
-    OICStrcpy(netInfo->ipAddress, sizeof(netInfo->ipAddress), ipAddress);
-
-    // set subnet mask
-    OICStrcpy(netInfo->subnetMask, sizeof(netInfo->subnetMask), subnetMask);
-
-    CAResult_t result = u_arraylist_add(*netInterfaceList, (void *)netInfo);
-    if (CA_STATUS_OK != result)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_add failed!");
+        if (cbitem && adapter == cbitem->adapter)
+        {
+            OIC_LOG(DEBUG, TAG, "remove specific callback");
+            LL_DELETE(g_adapterCallbackList, cbitem);
+            OICFree(cbitem);
+            return CA_STATUS_OK;
+        }
     }
-    OICFree(interfaceName);
-    OICFree(ipAddress);
-    OICFree(subnetMask);
+    return CA_STATUS_OK;
 }
 
-
-void CAWIFIConnectionStateChangedCb(wifi_connection_state_e state, wifi_ap_h ap,
-                                    void *userData)
+u_arraylist_t *CAFindInterfaceChange()
 {
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
+    u_arraylist_t *iflist = NULL;
+    char buf[NETLINK_MESSAGE_LENGTH] = { 0 };
+    struct sockaddr_nl sa = { 0 };
+    struct iovec iov = { .iov_base = buf,
+                         .iov_len = sizeof (buf) };
+    struct msghdr msg = { .msg_name = (void *)&sa,
+                          .msg_namelen = sizeof (sa),
+                          .msg_iov = &iov,
+                          .msg_iovlen = 1 };
 
-    if (WIFI_CONNECTION_STATE_ASSOCIATION == state
-        || WIFI_CONNECTION_STATE_CONFIGURATION == state)
-    {
-        OIC_LOG(DEBUG, IP_MONITOR_TAG, "Connection is in Association State");
-        return;
-    }
+    ssize_t len = recvmsg(caglobals.ip.netlinkFd, &msg, 0);
 
-    // If Wifi is connected, then get the latest IP from the WIFI Interface
-    if (WIFI_CONNECTION_STATE_CONNECTED == state)
+    for (struct nlmsghdr *nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len))
     {
-        // Get network information
-        char *interfaceName = NULL;
-        char *ipAddress = NULL;
-        char *subnetMask = NULL;
-        CAWiFiGetInterfaceInformation(&interfaceName, &ipAddress, &subnetMask);
-
-        CANetInfo_t *netInfo = (CANetInfo_t *)OICCalloc(1, sizeof(CANetInfo_t));
-        if (!netInfo)
+        if (nh != NULL && (nh->nlmsg_type != RTM_DELADDR && nh->nlmsg_type != RTM_NEWADDR))
         {
-            OIC_LOG(ERROR, IP_MONITOR_TAG, "Malloc failed");
-            OICFree(interfaceName);
-            OICFree(ipAddress);
-            OICFree(subnetMask);
-            return;
+            continue;
         }
 
-        // set interface name
-        OICStrcpy(netInfo->interfaceName, sizeof(netInfo->interfaceName), interfaceName);
-
-        // set local ip address
-        OICStrcpy(netInfo->ipAddress, sizeof(netInfo->ipAddress), ipAddress);
-
-        // set subnet mask
-        OICStrcpy(netInfo->subnetMask, sizeof(netInfo->subnetMask), subnetMask);
+        struct ifinfomsg *ifi = (struct ifinfomsg *)NLMSG_DATA(nh);
+        if (!ifi)
+        {
+            continue;
+        }
 
-        bool ret = CACheckIsInterfaceInfoChanged(netInfo);
-        if (ret)
+        if (RTM_DELADDR == nh->nlmsg_type)
         {
-            OIC_LOG(DEBUG, IP_MONITOR_TAG, "CACheckIsInterfaceInfoChanged true");
+            CloseMulticastSocket();
         }
-        OICFree(netInfo);
 
-        OICFree(interfaceName);
-        OICFree(ipAddress);
-        OICFree(subnetMask);
-    }
-    else
-    {
-        CARemoveInterfaceInfo();
+        int ifiIndex = ifi->ifi_index;
+        iflist = CAIPGetInterfaceInformation(ifiIndex);
+        if (!iflist)
+        {
+            OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno));
+            return NULL;
+        }
+        CreateMulticastSocket();
     }
-
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
+    return iflist;
 }
 
-void CAWIFIDeviceStateChangedCb(wifi_device_state_e state, void *userData)
+CAResult_t CAIPStartNetworkMonitor(CAIPAdapterStateChangeCallback callback,
+                                   CATransportAdapter_t adapter)
 {
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-
-    if (WIFI_DEVICE_STATE_ACTIVATED == state)
+    if (!g_adapterCallbackList)
     {
-        OIC_LOG(DEBUG, IP_MONITOR_TAG, "Wifi is in Activated State");
-    }
-    else
-    {
-        CAWIFIConnectionStateChangedCb(WIFI_CONNECTION_STATE_DISCONNECTED, NULL, NULL);
-        OIC_LOG(DEBUG, IP_MONITOR_TAG, "Wifi is in Deactivated State");
-    }
-
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
-}
+        // Initialize Connections.
+        connection_error_e ret = connection_create(&connection);
+        if (CONNECTION_ERROR_NONE != ret)
+        {
+            OIC_LOG(ERROR, TAG, "connection_create failed");
+            return CA_STATUS_FAILED;
+        }
 
-static CAResult_t CAInitializeNetworkMonitorMutexes()
-{
-    if (!g_networkMonitorContextMutex)
-    {
-        g_networkMonitorContextMutex = ca_mutex_new();
-        if (!g_networkMonitorContextMutex)
+        // Set callback for receiving state changes.
+        ret = connection_set_type_changed_cb(connection, CAIPConnectionStateChangedCb, NULL);
+        if (CONNECTION_ERROR_NONE != ret)
         {
-            OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContextMutex Malloc  failed");
-            return CA_MEMORY_ALLOC_FAILED;
+            OIC_LOG(ERROR, TAG, "connection_set_type_changed_cb failed");
+            return CA_STATUS_FAILED;
         }
     }
 
-    return CA_STATUS_OK;
+    OIC_LOG(DEBUG, TAG, "Initialize network monitoring successfully");
+    return CAIPSetNetworkMonitorCallback(callback, adapter);
 }
 
-static void CADestroyNetworkMonitorMutexes()
+CAResult_t CAIPStopNetworkMonitor(CATransportAdapter_t adapter)
 {
-    ca_mutex_free(g_networkMonitorContextMutex);
-    g_networkMonitorContextMutex = NULL;
-}
-
-CAResult_t CAIPInitializeNetworkMonitor(const ca_thread_pool_t threadPool)
-{
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-
-    VERIFY_NON_NULL(threadPool, IP_MONITOR_TAG, "threadPool is null");
-
-    CAResult_t ret = CAInitializeNetworkMonitorMutexes();
-
-    if (CA_STATUS_OK != ret)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "CAInitializeNetworkMonitorMutexes failed");
-        return CA_STATUS_FAILED;
-    }
-    ca_mutex_lock(g_networkMonitorContextMutex);
-
-     // Initialize Wifi service
-    wifi_error_e retValue = wifi_initialize();
-    if (WIFI_ERROR_NONE != retValue)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "wifi_initialize failed");
-        return CA_STATUS_FAILED;
-    }
+    OIC_LOG(DEBUG, TAG, "IN");
 
-    g_networkMonitorContext = (CAIPNetworkMonitorContext *)OICCalloc(1,
-                              sizeof(*g_networkMonitorContext));
-    if (!g_networkMonitorContext)
+    CAIPUnSetNetworkMonitorCallback(adapter);
+    if (!g_adapterCallbackList)
     {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContext Malloc  failed");
-        ca_mutex_unlock(g_networkMonitorContextMutex);
-        CADestroyNetworkMonitorMutexes();
-        return CA_MEMORY_ALLOC_FAILED;
-    }
+        // Reset callback for receiving state changes.
+        if (connection)
+        {
+            connection_error_e ret = connection_unset_type_changed_cb(connection);
+            if (CONNECTION_ERROR_NONE != ret)
+            {
+                OIC_LOG(ERROR, TAG, "connection_unset_type_changed_cb failed");
+            }
 
-    g_networkMonitorContext->netInterfaceList = u_arraylist_create();
-    if (!g_networkMonitorContext->netInterfaceList)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_create failed");
-        OICFree(g_networkMonitorContext);
-        ca_mutex_unlock(g_networkMonitorContextMutex);
-        CADestroyNetworkMonitorMutexes();
-        return CA_MEMORY_ALLOC_FAILED;
+            // Deinitialize Wifi service.
+            ret = connection_destroy(connection);
+            if (CONNECTION_ERROR_NONE != ret)
+            {
+                OIC_LOG(ERROR, TAG, "connection_destroy failed");
+            }
+            connection = NULL;
+        }
     }
 
-    CAIPGetInterfaceInformation(&g_networkMonitorContext->netInterfaceList);
-
-    ca_mutex_unlock(g_networkMonitorContextMutex);
-
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
+    OIC_LOG(DEBUG, TAG, "Network monitoring terminated successfully");
     return CA_STATUS_OK;
 }
 
-void CAIPTerminateNetworkMonitor()
-{
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-
-    ca_mutex_lock(g_networkMonitorContextMutex);
-
-     // Deinitialize Wifi service
-    wifi_error_e ret = wifi_deinitialize();
-    if (WIFI_ERROR_NONE != ret)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "wifi_deinitialize failed");
-    }
-
-    CAClearNetInterfaceInfoList(g_networkMonitorContext->netInterfaceList);
-
-    g_networkMonitorContext->netInterfaceList = NULL;
-    g_networkMonitorContext->nwConnectivityStatus = CA_INTERFACE_DOWN;
-    g_networkMonitorContext->networkChangeCb = NULL;
-
-    OICFree(g_networkMonitorContext);
-    g_networkMonitorContext = NULL;
-
-    ca_mutex_unlock(g_networkMonitorContextMutex);
-
-    CADestroyNetworkMonitorMutexes();
-
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
-}
-
-CAResult_t CAIPStartNetworkMonitor()
+/**
+ * Used to send netlink query to kernel and recv response from kernel.
+ *
+ * @param[in]   idx       desired network interface index, 0 means all interfaces.
+ * @param[out]  iflist    linked list.
+ *
+ */
+static bool CAIPGetAddrInfo(int idx, u_arraylist_t *iflist)
 {
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-
-     // Set callback for receiving state changes
-    wifi_error_e ret = wifi_set_device_state_changed_cb(CAWIFIDeviceStateChangedCb, NULL);
-    if (WIFI_ERROR_NONE != ret)
+    if ((idx < 0) || (iflist == NULL))
     {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "wifi_set_device_state_changed_cb failed");
-        return CA_STATUS_FAILED;
-    }
-
-    // Set callback for receiving connection state changes
-    ret = wifi_set_connection_state_changed_cb(CAWIFIConnectionStateChangedCb, NULL);
-    if (WIFI_ERROR_NONE != ret)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "wifi_set_connection_state_changed_cb failed");
-        return CA_STATUS_FAILED;
+        return false;
     }
 
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
-    return CA_STATUS_OK;
-}
-
-CAResult_t CAIPStopNetworkMonitor()
-{
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-
-     // Reset callback for receiving state changes
-    wifi_error_e ret = wifi_unset_device_state_changed_cb();
-    if (WIFI_ERROR_NONE != ret)
+    struct ifaddrs *ifp = NULL;
+    if (-1 == getifaddrs(&ifp))
     {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "wifi_unset_device_state_changed_cb failed");
+        OIC_LOG_V(ERROR, TAG, "Failed to get ifaddrs: %s", strerror(errno));
+        return false;
     }
 
-    // Reset callback for receiving connection state changes
-    ret = wifi_unset_connection_state_changed_cb();
-    if (WIFI_ERROR_NONE != ret)
+    struct ifaddrs *ifa = NULL;
+    for (ifa = ifp; ifa; ifa = ifa->ifa_next)
     {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "wifi_unset_connection_state_changed_cb failed");
-    }
-
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
-    return CA_STATUS_OK;
-}
+        if (!ifa->ifa_addr)
+        {
+            continue;
+        }
 
-CAResult_t CAIPGetInterfaceInfo(u_arraylist_t **netInterfaceList)
-{
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-
-    VERIFY_NON_NULL(netInterfaceList, IP_MONITOR_TAG, "u_array_list is null");
-    VERIFY_NON_NULL(g_networkMonitorContext, IP_MONITOR_TAG,
-                    "g_networkMonitorContext is null");
-    VERIFY_NON_NULL(g_networkMonitorContextMutex, IP_MONITOR_TAG,
-                    "g_networkMonitorContextMutex is null");
-
-    // Get the interface and ipaddress information from cache
-    ca_mutex_lock(g_networkMonitorContextMutex);
-    if (!g_networkMonitorContext->netInterfaceList
-        || !(u_arraylist_length(g_networkMonitorContext->netInterfaceList)))
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "Network not enabled");
-        ca_mutex_unlock(g_networkMonitorContextMutex);
-        return CA_ADAPTER_NOT_ENABLED;
-    }
+        int family = ifa->ifa_addr->sa_family;
+        if ((ifa->ifa_flags & IFF_LOOPBACK) || (AF_INET != family && AF_INET6 != family))
+        {
+            continue;
+        }
 
-    uint32_t list_index = 0;
-    uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList);
-    OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "CAIPGetInterfaceInfo list length [%d]",
-              list_length);
-    for (list_index = 0; list_index < list_length; list_index++)
-    {
-        CANetInfo_t *info = (CANetInfo_t *)u_arraylist_get(
-                            g_networkMonitorContext->netInterfaceList, list_index);
-        if (!info)
+        int ifindex = if_nametoindex(ifa->ifa_name);
+        if (idx && (ifindex != idx))
         {
             continue;
         }
-        OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "CAIPGetInterfaceInfo ip [%s]",
-                  info->ipAddress);
-        CANetInfo_t *newNetinfo = (CANetInfo_t *) OICMalloc(sizeof(CANetInfo_t));
-        if (!newNetinfo)
+
+        char ipaddr[MAX_ADDR_STR_SIZE_CA] = {0};
+        if (family == AF_INET6)
+        {
+            struct sockaddr_in6 *in6 = (struct sockaddr_in6*) ifa->ifa_addr;
+            inet_ntop(family, (void *)&(in6->sin6_addr), ipaddr, sizeof(ipaddr));
+        }
+        else if (family == AF_INET)
         {
-            OIC_LOG(ERROR, IP_MONITOR_TAG, "Malloc failed!");
-            ca_mutex_unlock(g_networkMonitorContextMutex);
-            return CA_MEMORY_ALLOC_FAILED;
+            struct sockaddr_in *in = (struct sockaddr_in*) ifa->ifa_addr;
+            inet_ntop(family, (void *)&(in->sin_addr), ipaddr, sizeof(ipaddr));
         }
 
-        *newNetinfo = *info;
+        if ((strcmp(ipaddr, IFC_ADDR_LOOP_IPV4) == 0) ||
+            (strcmp(ipaddr, IFC_ADDR_LOOP_IPV6) == 0) ||
+            (strcmp(ifa->ifa_name, IFC_LABEL_LOOP) == 0))
+        {
+            OIC_LOG(DEBUG, TAG, "LOOPBACK continue!!!");
+            continue;
+        }
 
-        CAResult_t result = u_arraylist_add(*netInterfaceList, (void *)newNetinfo);
+        CAResult_t result = CAAddInterfaceItem(iflist, ifindex,
+                                               ifa->ifa_name, family,
+                                               ipaddr, ifa->ifa_flags);
         if (CA_STATUS_OK != result)
         {
-            OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_add failed!");
-            ca_mutex_unlock(g_networkMonitorContextMutex);
-            return CA_STATUS_FAILED;
+            OIC_LOG(ERROR, TAG, "CAAddInterfaceItem fail");
+            goto exit;
         }
     }
+    freeifaddrs(ifp);
+    return true;
 
-    ca_mutex_unlock(g_networkMonitorContextMutex);
-
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
-    return CA_STATUS_OK;
+exit:
+    freeifaddrs(ifp);
+    return false;
 }
 
-CAResult_t CAIPGetInterfaceSubnetMask(const char *ipAddress, char **subnetMask)
+u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex)
 {
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-
-    VERIFY_NON_NULL(subnetMask, IP_MONITOR_TAG, "subnet mask");
-    VERIFY_NON_NULL(ipAddress, IP_MONITOR_TAG, "ipAddress is null");
-    VERIFY_NON_NULL(g_networkMonitorContext, IP_MONITOR_TAG,
-                    "g_networkMonitorContext is null");
-    VERIFY_NON_NULL(g_networkMonitorContextMutex, IP_MONITOR_TAG,
-                    "g_networkMonitorContextMutex is null");
-
-    // Get the interface and ipaddress information from cache
-    ca_mutex_lock(g_networkMonitorContextMutex);
-    if (!g_networkMonitorContext->netInterfaceList
-        || !(u_arraylist_length(g_networkMonitorContext->netInterfaceList)))
+    u_arraylist_t *iflist = u_arraylist_create();
+    if (!iflist)
     {
-        OIC_LOG(DEBUG, IP_MONITOR_TAG, "Network not enabled");
-        ca_mutex_unlock(g_networkMonitorContextMutex);
-        return CA_ADAPTER_NOT_ENABLED;
+        OIC_LOG_V(ERROR, TAG, "Failed to create iflist: %s", strerror(errno));
+        return NULL;
     }
 
-    uint32_t list_index = 0;
-    uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList);
-    OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "list lenght [%d]", list_length);
-    for (list_index = 0; list_index < list_length; list_index++)
+    if (!CAIPGetAddrInfo(desiredIndex, iflist))
     {
-        CANetInfo_t *info = (CANetInfo_t *)u_arraylist_get(
-                            g_networkMonitorContext->netInterfaceList, list_index);
-        if (!info)
-        {
-            continue;
-        }
-
-        if (strncmp(info->ipAddress, ipAddress, strlen(ipAddress)) == 0)
-        {
-            OIC_LOG_V(DEBUG, IP_MONITOR_TAG,
-                      "CAIPGetInterfaceSubnetMask subnetmask is %s", info->subnetMask);
-            *subnetMask = OICStrdup(info->subnetMask);
-            break;
-        }
+        goto exit;
     }
-    ca_mutex_unlock(g_networkMonitorContextMutex);
 
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
-    return CA_STATUS_OK;
+    return iflist;
+
+exit:
+    u_arraylist_destroy(iflist);
+    return NULL;
 }
 
-bool CAIPIsConnected()
+static CAResult_t CAAddInterfaceItem(u_arraylist_t *iflist, int index,
+                                     char *name, int family, const char *addr, int flags)
 {
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-
-    wifi_connection_state_e connection_state;
-    wifi_error_e ret = wifi_get_connection_state(&connection_state);
-    if (WIFI_ERROR_NONE != ret)
+    CAInterface_t *ifitem = CANewInterfaceItem(index, name, family, addr, flags);
+    if (!ifitem)
     {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "Failed to get the Connection State");
-        return false;
+        return CA_STATUS_FAILED;
     }
-
-    if (WIFI_CONNECTION_STATE_DISCONNECTED == connection_state)
+    bool result = u_arraylist_add(iflist, ifitem);
+    if (!result)
     {
-        OIC_LOG(DEBUG, IP_MONITOR_TAG, "WIFI is not Connected");
-        return false;
+        OIC_LOG(ERROR, TAG, "u_arraylist_add failed.");
+        OICFree(ifitem);
+        return CA_STATUS_FAILED;
     }
 
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
-    return true;
+    return CA_STATUS_OK;
 }
 
-void CAIPSetConnectionStateChangeCallback(CAIPConnectionStateChangeCallback callback)
+static CAInterface_t *CANewInterfaceItem(int index, char *name, int family,
+                                         const char *addr, int flags)
 {
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-    if (!g_networkMonitorContextMutex || !g_networkMonitorContext)
+    CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof (CAInterface_t));
+    if (!ifitem)
     {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "CAIPSetConnectionStateChangeCallback failed");
-        return;
+        OIC_LOG(ERROR, TAG, "Malloc failed");
+        return NULL;
     }
-    ca_mutex_lock(g_networkMonitorContextMutex);
 
-    g_networkMonitorContext->networkChangeCb = callback;
+    OICStrcpy(ifitem->name, INTERFACE_NAME_MAX, name);
+    ifitem->index = index;
+    ifitem->family = family;
+    OICStrcpy(ifitem->addr, sizeof(ifitem->addr), addr);
+    ifitem->flags = flags;
+
+    return ifitem;
+}
 
-    ca_mutex_unlock(g_networkMonitorContextMutex);
+void CAIPConnectionStateChangedCb(connection_type_e type, void* userData)
+{
+    (void)userData;
 
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
+    switch (type)
+    {
+        case CONNECTION_TYPE_DISCONNECTED:
+            OIC_LOG(DEBUG, TAG, "Connection is in CONNECTION_TYPE_DISCONNECTED");
+            CAIPPassNetworkChangesToAdapter(CA_INTERFACE_DOWN);
+            break;
+        case CONNECTION_TYPE_ETHERNET:
+            OIC_LOG(DEBUG, TAG, "Connection is in CONNECTION_TYPE_ETHERNET");
+            CAIPPassNetworkChangesToAdapter(CA_INTERFACE_UP);
+            break;
+        case CONNECTION_TYPE_WIFI:
+            OIC_LOG(DEBUG, TAG, "Connection is in CONNECTION_TYPE_WIFI");
+            CAIPPassNetworkChangesToAdapter(CA_INTERFACE_UP);
+            break;
+        case CONNECTION_TYPE_CELLULAR:
+            OIC_LOG(DEBUG, TAG, "Connection is in CONNECTION_TYPE_CELLULAR");
+            CAIPPassNetworkChangesToAdapter(CA_INTERFACE_UP);
+            break;
+        default:
+            break;
+    }
 }