#include "caipinterface.h"
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
#include <sys/types.h>
+#include <sys/select.h>
#include <ifaddrs.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
#include <net/if.h>
-#include <sys/socket.h>
#include <netdb.h>
-#include <string.h>
#include <errno.h>
-#include <unistd.h>
-#include "caadapterutils.h"
+#ifdef __linux__
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#endif
+
#include "camutex.h"
+#include "caadapterutils.h"
#include "logger.h"
#include "oic_malloc.h"
#include "oic_string.h"
-#define IP_MONITOR_TAG "IP_MONITOR"
+#define TAG "OIC_CA_IP_MONITOR"
/**
- * @var g_networkMonitorContextMutex
- * @brief Mutex for synchronizing access to cached interface and IP address information.
+ * Mutex for synchronizing access to cached interface and IP address information.
*/
static ca_mutex g_networkMonitorContextMutex = NULL;
/**
- * @var g_stopNetworkMonitor
- * @brief Used to stop the network monitor thread.
+ * Used to storing network interface.
*/
-static bool g_stopNetworkMonitor = false;
+static u_arraylist_t *g_netInterfaceList = NULL;
-/**
- * @var g_stopNetworkMonitorMutex
- * @brief Mutex for synchronizing access to g_stopNetworkMonitor flag.
- */
-static ca_mutex g_stopNetworkMonitorMutex = NULL;
+static CAIPConnectionStateChangeCallback g_networkChangeCallback = NULL;
-/**
- * @struct CAIPNwMonitorContext
- * @brief Used for storing network monitor context information.
- */
-typedef struct
-{
- u_arraylist_t *netInterfaceList;
- ca_thread_pool_t threadPool;
- CANetworkStatus_t nwConnectivityStatus;
- CAIPConnectionStateChangeCallback networkChangeCb;
-} CAIPNetworkMonitorContext;
+static CAResult_t CAIPInitializeNetworkMonitorList();
+static void CAIPDestroyNetworkMonitorList();
+static CAInterface_t *CANewInterfaceItem(int index, const char *name, int family,
+ uint32_t addr, int flags);
-/**
- * @var g_networkMonitorContext
- * @brief network monitor context.
- */
-static CAIPNetworkMonitorContext *g_networkMonitorContext = NULL;
-
-static void CAIPGetInterfaceInformation(u_arraylist_t **netInterfaceList)
+static CAResult_t CAIPInitializeNetworkMonitorList()
{
-
- VERIFY_NON_NULL_VOID(netInterfaceList, IP_MONITOR_TAG, "netInterfaceList is null");
-
- struct ifaddrs *ifp = NULL;
- if (-1 == getifaddrs(&ifp))
- {
- OIC_LOG_V(ERROR, IP_MONITOR_TAG, "Failed to get interface list!, Error code: %s",
- strerror(errno));
- return;
- }
-
- struct ifaddrs *ifa = NULL;
- for (ifa = ifp; ifa; ifa = ifa->ifa_next)
+ if (!g_networkMonitorContextMutex)
{
- char interfaceAddress[CA_IPADDR_SIZE] = {0};
- char interfaceSubnetMask[CA_IPADDR_SIZE] = {0};
- socklen_t len = sizeof(struct sockaddr_in);
-
- if (!ifa->ifa_addr)
- {
- continue;
- }
-
- int type = ifa->ifa_addr->sa_family;
- if (ifa->ifa_flags & IFF_LOOPBACK
- || !((ifa->ifa_flags & IFF_UP) && (ifa->ifa_flags & IFF_RUNNING)))
- {
- continue;
- }
-
- if (AF_INET != type)
- {
- continue;
- }
-
- // get the interface ip address
- if (0 != getnameinfo(ifa->ifa_addr, len, interfaceAddress,
- sizeof(interfaceAddress), NULL, 0, NI_NUMERICHOST))
- {
- OIC_LOG_V(ERROR, IP_MONITOR_TAG, "Failed to get IPAddress, Error code: %s",
- strerror(errno));
- continue;
- }
-
- // get the interface subnet mask
- if (0 != getnameinfo(ifa->ifa_netmask, len, interfaceSubnetMask,
- sizeof(interfaceSubnetMask), NULL, 0, NI_NUMERICHOST))
- {
- OIC_LOG_V(ERROR, IP_MONITOR_TAG, "Failed to get subnet mask, Error code: %s",
- strerror(errno));
- continue;
- }
-
- CANetInfo_t *netInfo = (CANetInfo_t *)OICCalloc(1, sizeof(CANetInfo_t));
- if (!netInfo)
+ g_networkMonitorContextMutex = ca_mutex_new();
+ if (!g_networkMonitorContextMutex)
{
- OIC_LOG(ERROR, IP_MONITOR_TAG, "Malloc failed");
- freeifaddrs(ifp);
- return;
+ OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
+ return CA_STATUS_FAILED;
}
- // set interface name
- strncpy(netInfo->interfaceName, ifa->ifa_name, sizeof(netInfo->interfaceName) - 1);
- netInfo->interfaceName[sizeof(netInfo->interfaceName)-1] = '\0';
-
- // set local ip address
- strncpy(netInfo->ipAddress, interfaceAddress, strlen(interfaceAddress));
-
- // set subnet mask
- strncpy(netInfo->subnetMask, interfaceSubnetMask, strlen(interfaceSubnetMask));
+ }
- CAResult_t result = u_arraylist_add(*netInterfaceList, (void *)netInfo);
- if (CA_STATUS_OK != result)
+ if (!g_netInterfaceList)
+ {
+ g_netInterfaceList = u_arraylist_create();
+ if (!g_netInterfaceList)
{
- OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_add failed!Thread exiting.");
- freeifaddrs(ifp);
- return;
+ OIC_LOG(ERROR, TAG, "u_arraylist_create has failed");
+ CAIPDestroyNetworkMonitorList();
+ return CA_STATUS_FAILED;
}
}
-
- freeifaddrs(ifp);
}
-static bool CACheckIsAnyInterfaceDown(const u_arraylist_t *netInterfaceList,
- const CANetInfo_t *info)
+static void CAIPDestroyNetworkMonitorList()
{
- VERIFY_NON_NULL_RET(netInterfaceList, IP_MONITOR_TAG, "netInterfaceList is null", false);
- VERIFY_NON_NULL_RET(info, IP_MONITOR_TAG, "info is null", false);
+ if (g_netInterfaceList)
+ {
+ u_arraylist_destroy(g_netInterfaceList);
+ g_netInterfaceList = NULL;
+ }
- uint32_t list_index = 0;
- uint32_t list_length = u_arraylist_length(netInterfaceList);
- for (list_index = 0; list_index < list_length; list_index++)
+ if (g_networkMonitorContextMutex)
{
- CANetInfo_t *netInfo = (CANetInfo_t *)u_arraylist_get(netInterfaceList,
- list_index);
- if (!netInfo)
- {
- continue;
- }
- if (strncmp(netInfo->interfaceName, info->interfaceName, strlen(info->interfaceName)) == 0)
- {
- return false;
- }
+ ca_mutex_free(g_networkMonitorContextMutex);
+ g_networkMonitorContextMutex = NULL;
}
- OIC_LOG(DEBUG, IP_MONITOR_TAG, "Interface is down");
- return true;
}
-static bool CACheckIsInterfaceInfoChanged(const CANetInfo_t *info)
+static bool CACmpNetworkList(uint32_t ifiindex)
{
- VERIFY_NON_NULL_RET(info, IP_MONITOR_TAG, "info is null", false);
+ if (!g_netInterfaceList)
+ {
+ OIC_LOG(ERROR, TAG, "g_netInterfaceList is NULL");
+ return 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++)
+
+ uint32_t list_length = u_arraylist_length(g_netInterfaceList);
+ for (uint32_t list_index = 0; list_index < list_length; list_index++)
{
- CANetInfo_t *netInfo = (CANetInfo_t *)u_arraylist_get(
- g_networkMonitorContext->netInterfaceList, list_index);
- if (!netInfo)
+ CAInterface_t *currItem = (CAInterface_t *) u_arraylist_get(g_netInterfaceList, list_index);
+ if (currItem->index == ifiindex)
{
- continue;
- }
- 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;
- }
+ ca_mutex_unlock(g_networkMonitorContextMutex);
+ return true;
}
}
+ ca_mutex_unlock(g_networkMonitorContextMutex);
+ return false;
+}
- 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;
- }
- memcpy(newNetInfo, info, sizeof(*newNetInfo));
-
- OIC_LOG(DEBUG, IP_MONITOR_TAG, "New Interface found");
+static CAResult_t CAAddNetworkMonitorList(CAInterface_t *ifitem)
+{
+ VERIFY_NON_NULL(g_netInterfaceList, TAG, "g_netInterfaceList is NULL");
+ VERIFY_NON_NULL(ifitem, TAG, "ifitem is NULL");
- CAResult_t result = u_arraylist_add(g_networkMonitorContext->netInterfaceList,
- (void *)newNetInfo);
- if (CA_STATUS_OK != result)
+ ca_mutex_lock(g_networkMonitorContextMutex);
+ bool result = u_arraylist_add(g_netInterfaceList, (void *) ifitem);
+ if (!result)
{
- OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_add failed!");
- OICFree(newNetInfo);
+ OIC_LOG(ERROR, TAG, "u_arraylist_add failed.");
ca_mutex_unlock(g_networkMonitorContextMutex);
- return false;
+ return CA_STATUS_FAILED;
}
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;
+ return CA_STATUS_OK;
}
-static void CANetworkMonitorThread(void *threadData)
+static void CARemoveNetworkMonitorList(int ifiindex)
{
- OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-
- while (!g_stopNetworkMonitor)
- {
- u_arraylist_t *netInterfaceList = u_arraylist_create();
-
- VERIFY_NON_NULL_VOID(netInterfaceList, IP_MONITOR_TAG, "netInterfaceList is null");
-
- CAIPGetInterfaceInformation(&netInterfaceList);
-
- ca_mutex_lock(g_networkMonitorContextMutex);
- if (!g_networkMonitorContext->netInterfaceList)
- {
- OIC_LOG(ERROR, IP_MONITOR_TAG,
- "u_arraylist_create failed. Network Monitor thread stopped");
- CAClearNetInterfaceInfoList(netInterfaceList);
- ca_mutex_unlock(g_networkMonitorContextMutex);
- return;
- }
-
- uint32_t listIndex = 0;
- uint32_t listLength = u_arraylist_length(g_networkMonitorContext->netInterfaceList);
- for (listIndex = 0; listIndex < listLength;)
- {
- CANetInfo_t *info = (CANetInfo_t *)u_arraylist_get(
- g_networkMonitorContext->netInterfaceList, listIndex);
- if (!info)
- {
- listIndex++;
- continue;
- }
+ VERIFY_NON_NULL_VOID(g_netInterfaceList, TAG, "g_netInterfaceList is NULL");
- bool ret = CACheckIsAnyInterfaceDown(netInterfaceList, info);
- if (ret)
- {
- OIC_LOG(DEBUG, IP_MONITOR_TAG, "Interface is down");
- if (u_arraylist_remove(g_networkMonitorContext->netInterfaceList, listIndex))
- {
- OIC_LOG(DEBUG, IP_MONITOR_TAG, "u_arraylist_remove success");
- if (g_networkMonitorContext->networkChangeCb)
- {
- g_networkMonitorContext->networkChangeCb(info->ipAddress,
- CA_INTERFACE_DOWN);
- }
- OICFree(info);
- listLength--;
- }
- else
- {
- OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_remove failed");
- break;
- }
- }
- else
- {
- listIndex++;
- }
- }
- ca_mutex_unlock(g_networkMonitorContextMutex);
+ ca_mutex_lock(g_networkMonitorContextMutex);
- listLength = u_arraylist_length(netInterfaceList);
- for (listIndex = 0; listIndex < listLength; listIndex++)
+ uint32_t list_length = u_arraylist_length(g_netInterfaceList);
+ for (uint32_t list_index = 0; list_index < list_length; list_index++)
+ {
+ CAInterface_t *removedifitem = (CAInterface_t *) u_arraylist_get(
+ g_netInterfaceList, list_index);
+ if (removedifitem && removedifitem->index == ifiindex)
{
- CANetInfo_t *info = (CANetInfo_t *)u_arraylist_get(netInterfaceList, listIndex);
- if (!info)
+ if (u_arraylist_remove(g_netInterfaceList, list_index))
{
- continue;
- }
- bool ret = CACheckIsInterfaceInfoChanged(info);
- if (ret)
- {
- OIC_LOG(DEBUG, IP_MONITOR_TAG, "CACheckIsInterfaceInfoChanged true");
+ OICFree(removedifitem);
+ ca_mutex_unlock(g_networkMonitorContextMutex);
+ return;
}
+ continue;
}
- CAClearNetInterfaceInfoList(netInterfaceList);
- sleep(2); // To avoid maximum cpu usage.
}
-
- OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
+ ca_mutex_unlock(g_networkMonitorContextMutex);
+ return;
}
-static CAResult_t CAInitializeNetworkMonitorMutexes()
+CAResult_t CAIPStartNetworkMonitor()
{
- if (!g_networkMonitorContextMutex)
- {
- g_networkMonitorContextMutex = ca_mutex_new();
- if (!g_networkMonitorContextMutex)
- {
- OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContextMutex Malloc failed");
- return CA_MEMORY_ALLOC_FAILED;
- }
- }
+ return CAIPInitializeNetworkMonitorList();
+}
- if (!g_stopNetworkMonitorMutex)
- {
- g_stopNetworkMonitorMutex = ca_mutex_new();
- if (!g_stopNetworkMonitorMutex)
- {
- OIC_LOG(ERROR, IP_MONITOR_TAG, "g_stopNetworkMonitorMutex Malloc failed");
- ca_mutex_free(g_networkMonitorContextMutex);
- return CA_MEMORY_ALLOC_FAILED;
- }
- }
+CAResult_t CAIPStopNetworkMonitor()
+{
+ CAIPDestroyNetworkMonitorList();
return CA_STATUS_OK;
}
-static void CADestroyNetworkMonitorMutexes()
-{
- ca_mutex_free(g_networkMonitorContextMutex);
- g_networkMonitorContextMutex = NULL;
- ca_mutex_free(g_stopNetworkMonitorMutex);
- g_stopNetworkMonitorMutex = NULL;
+int CAGetPollingInterval(int interval)
+{
+ return interval;
}
-CAResult_t CAIPInitializeNetworkMonitor(const ca_thread_pool_t threadPool)
+void CAIPSetNetworkMonitorCallback(CAIPConnectionStateChangeCallback callback)
{
- 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);
-
- g_networkMonitorContext = (CAIPNetworkMonitorContext *)OICCalloc(1,
- sizeof(*g_networkMonitorContext));
- if (!g_networkMonitorContext)
- {
- OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContext Malloc failed");
- ca_mutex_unlock(g_networkMonitorContextMutex);
- CADestroyNetworkMonitorMutexes();
- return CA_MEMORY_ALLOC_FAILED;
- }
- g_networkMonitorContext->threadPool = threadPool;
-
- 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;
- }
-
- CAIPGetInterfaceInformation(&g_networkMonitorContext->netInterfaceList);
-
+ g_networkChangeCallback = callback;
+}
- if (u_arraylist_length(g_networkMonitorContext->netInterfaceList))
- {
- g_networkMonitorContext->nwConnectivityStatus = CA_INTERFACE_UP;
- }
- else
+static CAInterface_t *CANewInterfaceItem(int index, const char *name, int family,
+ uint32_t addr, int flags)
+{
+ CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof (CAInterface_t));
+ if (!ifitem)
{
- g_networkMonitorContext->nwConnectivityStatus = CA_INTERFACE_DOWN;
+ OIC_LOG(ERROR, TAG, "Malloc failed");
+ return NULL;
}
- ca_mutex_unlock(g_networkMonitorContextMutex);
+ OICStrcpy(ifitem->name, sizeof (ifitem->name), name);
+ ifitem->index = index;
+ ifitem->family = family;
+ ifitem->ipv4addr = addr;
+ ifitem->flags = flags;
- OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
- return CA_STATUS_OK;
+ return ifitem;
}
-void CAIPTerminateNetworkMonitor()
+CAInterface_t *CAFindInterfaceChange()
{
- OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-
- ca_mutex_lock(g_networkMonitorContextMutex);
- g_networkMonitorContext->threadPool = NULL;
-
- CAClearNetInterfaceInfoList(g_networkMonitorContext->netInterfaceList);
-
- g_networkMonitorContext->netInterfaceList = NULL;
- g_networkMonitorContext->nwConnectivityStatus = CA_INTERFACE_DOWN;
- g_networkMonitorContext->networkChangeCb = NULL;
- g_networkMonitorContext->threadPool = NULL;
+ CAInterface_t *foundNewInterface = NULL;
+#ifdef __linux__
+ char buf[4096];
+ struct nlmsghdr *nh;
+ struct sockaddr_nl sa;
+ struct iovec iov = { buf, sizeof (buf) };
+ struct msghdr msg = { (void *)&sa, sizeof (sa), &iov, 1, NULL, 0, 0 };
- OICFree(g_networkMonitorContext);
- g_networkMonitorContext = NULL;
+ size_t len = recvmsg(caglobals.ip.netlinkFd, &msg, 0);
- ca_mutex_unlock(g_networkMonitorContextMutex);
-
- ca_mutex_lock(g_stopNetworkMonitorMutex);
- g_stopNetworkMonitor = true;
- ca_mutex_unlock(g_stopNetworkMonitorMutex);
+ for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len))
+ {
+ if (nh != NULL && nh->nlmsg_type != RTM_NEWLINK)
+ {
+ continue;
+ }
- CADestroyNetworkMonitorMutexes();
+ struct ifinfomsg *ifi = (struct ifinfomsg *)NLMSG_DATA(nh);
- OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
-}
+ int ifiIndex = ifi->ifi_index;
+ u_arraylist_t *iflist = CAIPGetInterfaceInformation(ifiIndex);
-CAResult_t CAIPStartNetworkMonitor()
-{
- OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-
- ca_mutex_lock(g_stopNetworkMonitorMutex);
-
- g_stopNetworkMonitor = false;
+ if ((!ifi || (ifi->ifi_flags & IFF_LOOPBACK) || !(ifi->ifi_flags & IFF_RUNNING)))
+ {
+ bool isFound = CACmpNetworkList(ifiIndex);
+ if (isFound)
+ {
+ CARemoveNetworkMonitorList(ifiIndex);
+ if (g_networkChangeCallback)
+ {
+ g_networkChangeCallback(CA_ADAPTER_IP ,CA_INTERFACE_DOWN);
+ }
+ }
+ continue;
+ }
- ca_mutex_unlock(g_stopNetworkMonitorMutex);
+ if (!iflist)
+ {
+ OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno));
+ return NULL;
+ }
- ca_mutex_lock(g_networkMonitorContextMutex);
+ uint32_t listLength = u_arraylist_length(iflist);
+ for (uint32_t i = 0; i < listLength; i++)
+ {
+ CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
+ if (!ifitem)
+ {
+ continue;
+ }
- if (!g_networkMonitorContext)
- {
- OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContext is null");
- ca_mutex_unlock(g_networkMonitorContextMutex);
- return CA_STATUS_FAILED;
- }
+ if ((int)ifitem->index != ifiIndex)
+ {
+ continue;
+ }
- if (CA_STATUS_OK != ca_thread_pool_add_task(g_networkMonitorContext->threadPool,
- CANetworkMonitorThread, NULL))
- {
- OIC_LOG(ERROR, IP_MONITOR_TAG, "[ThreadPool] thread_pool_add_task failed!");
- ca_mutex_unlock(g_networkMonitorContextMutex);
- return CA_STATUS_FAILED;
+ foundNewInterface = CANewInterfaceItem(ifitem->index, ifitem->name, ifitem->family,
+ ifitem->ipv4addr, ifitem->flags);
+ break; // we found the one we were looking for
+ }
+ u_arraylist_destroy(iflist);
}
- ca_mutex_unlock(g_networkMonitorContextMutex);
-
- OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
- return CA_STATUS_OK;
+#endif
+ return foundNewInterface;
}
-CAResult_t CAIPStopNetworkMonitor()
+u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex)
{
- OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-
- ca_mutex_lock(g_networkMonitorContextMutex);
- if (!g_networkMonitorContext)
+ if (desiredIndex < 0)
{
- OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContext is null");
- ca_mutex_unlock(g_networkMonitorContextMutex);
- return CA_STATUS_FAILED;
+ OIC_LOG_V(ERROR, TAG, "invalid index : %d", desiredIndex);
+ return NULL;
}
- ca_mutex_unlock(g_networkMonitorContextMutex);
-
- ca_mutex_lock(g_stopNetworkMonitorMutex);
- if (!g_stopNetworkMonitor)
+ u_arraylist_t *iflist = u_arraylist_create();
+ if (!iflist)
{
- g_stopNetworkMonitor = true;
+ OIC_LOG_V(ERROR, TAG, "Failed to create iflist: %s", strerror(errno));
+ return NULL;
}
- else
- {
- OIC_LOG(DEBUG, IP_MONITOR_TAG, "CAIPStopNetworkMonitor, already stopped!");
- }
- ca_mutex_unlock(g_stopNetworkMonitorMutex);
-
- OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
- return CA_STATUS_OK;
-}
-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)))
+ struct ifaddrs *ifp = NULL;
+ if (-1 == getifaddrs(&ifp))
{
- OIC_LOG(ERROR, IP_MONITOR_TAG, "Network not enabled");
- ca_mutex_unlock(g_networkMonitorContextMutex);
- return CA_ADAPTER_NOT_ENABLED;
+ OIC_LOG_V(ERROR, TAG, "Failed to get ifaddrs: %s", strerror(errno));
+ u_arraylist_destroy(iflist);
+ return NULL;
}
+ OIC_LOG(DEBUG, TAG, "Got ifaddrs");
- 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++)
+ struct ifaddrs *ifa = NULL;
+ for (ifa = ifp; ifa; ifa = ifa->ifa_next)
{
- CANetInfo_t *info = (CANetInfo_t *)u_arraylist_get(
- g_networkMonitorContext->netInterfaceList, list_index);
- if (!info)
+ if (!ifa->ifa_addr)
{
continue;
}
- OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "CAIPGetInterfaceInfo ip [%s]",
- info->ipAddress);
- CANetInfo_t *newNetinfo = (CANetInfo_t *) OICMalloc(sizeof(CANetInfo_t));
- if (!newNetinfo)
+ int family = ifa->ifa_addr->sa_family;
+ if ((ifa->ifa_flags & IFF_LOOPBACK) || (AF_INET != family && AF_INET6 != family))
{
- OIC_LOG(ERROR, IP_MONITOR_TAG, "Malloc failed!");
- ca_mutex_unlock(g_networkMonitorContextMutex);
- return CA_MEMORY_ALLOC_FAILED;
+ continue;
}
- memcpy(newNetinfo, info, sizeof(*info));
-
- CAResult_t result = u_arraylist_add(*netInterfaceList, (void *)newNetinfo);
- if (CA_STATUS_OK != result)
+ int ifindex = if_nametoindex(ifa->ifa_name);
+ if (desiredIndex && (ifindex != desiredIndex))
{
- OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_add failed!");
- ca_mutex_unlock(g_networkMonitorContextMutex);
- return CA_STATUS_FAILED;
+ continue;
}
- }
-
- ca_mutex_unlock(g_networkMonitorContextMutex);
-
- OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
- return CA_STATUS_OK;
-}
-
-CAResult_t CAIPGetInterfaceSubnetMask(const char *ipAddress, char **subnetMask)
-{
- 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
- || (0 == u_arraylist_length(g_networkMonitorContext->netInterfaceList)))
- {
- OIC_LOG(DEBUG, IP_MONITOR_TAG, "Network not enabled");
- ca_mutex_unlock(g_networkMonitorContextMutex);
- return CA_ADAPTER_NOT_ENABLED;
- }
+ int length = u_arraylist_length(iflist);
+ int already = false;
+ for (int i = length-1; i >= 0; i--)
+ {
+ CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
- 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++)
- {
- CANetInfo_t *info = (CANetInfo_t *)u_arraylist_get(
- g_networkMonitorContext->netInterfaceList, list_index);
- if (!info)
+ if (ifitem
+ && (int)ifitem->index == ifindex
+ && ifitem->family == (uint16_t)family)
+ {
+ already = true;
+ break;
+ }
+ }
+ if (already)
{
continue;
}
- if (strncmp(info->ipAddress, ipAddress, strlen(ipAddress)) == 0)
+ CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof(CAInterface_t));
+ if (!ifitem)
{
- OIC_LOG_V(DEBUG, IP_MONITOR_TAG,
- "CAIPGetInterfaceSubnetMask subnetmask is %s", info->subnetMask);
- *subnetMask = OICStrdup(info->subnetMask);
- break;
+ OIC_LOG(ERROR, TAG, "Malloc failed");
+ goto exit;
}
- }
- ca_mutex_unlock(g_networkMonitorContextMutex);
- OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
- return CA_STATUS_OK;
-}
-
-bool CAIPIsConnected()
-{
- OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
- if (!g_networkMonitorContextMutex || !g_networkMonitorContext)
- {
- OIC_LOG(ERROR, IP_MONITOR_TAG, "IP is not connected");
- return false;
- }
-
- ca_mutex_lock(g_networkMonitorContextMutex);
- if (0 == u_arraylist_length(g_networkMonitorContext->netInterfaceList))
- {
- OIC_LOG(ERROR, IP_MONITOR_TAG, "IP is not connected");
- ca_mutex_unlock(g_networkMonitorContextMutex);
- return false;
- }
- ca_mutex_unlock(g_networkMonitorContextMutex);
+ OICStrcpy(ifitem->name, INTERFACE_NAME_MAX, ifa->ifa_name);
+ ifitem->index = ifindex;
+ ifitem->family = family;
+ ifitem->ipv4addr = ((struct sockaddr_in *)(ifa->ifa_addr))->sin_addr.s_addr;
+ ifitem->flags = ifa->ifa_flags;
- OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
- return true;
-}
+ bool result = u_arraylist_add(iflist, ifitem);
+ if (!result)
+ {
+ OIC_LOG(ERROR, TAG, "u_arraylist_add failed.");
+ goto exit;
+ }
-void CAIPSetConnectionStateChangeCallback(CAIPConnectionStateChangeCallback callback)
-{
- OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
- if (!g_networkMonitorContextMutex || !g_networkMonitorContext)
- {
- OIC_LOG(ERROR, IP_MONITOR_TAG, "CAIPSetConnectionStateChangeCallback failed");
- return;
+ bool isFound = CACmpNetworkList(ifitem->index);
+ if (!isFound)
+ {
+ CAInterface_t *newifitem = CANewInterfaceItem(ifitem->index, ifitem->name, ifitem->family,
+ ifitem->ipv4addr, ifitem->flags);
+ CAResult_t ret = CAAddNetworkMonitorList(newifitem);
+ if (CA_STATUS_OK != ret)
+ {
+ OICFree(newifitem);
+ goto exit;
+ }
+ if (g_networkChangeCallback)
+ {
+ g_networkChangeCallback(CA_ADAPTER_IP, CA_INTERFACE_UP);
+ }
+ OIC_LOG_V(DEBUG, TAG, "Added interface: %s (%d)", ifitem->name, ifitem->family);
+ }
}
- ca_mutex_lock(g_networkMonitorContextMutex);
-
- g_networkMonitorContext->networkChangeCb = callback;
-
- ca_mutex_unlock(g_networkMonitorContextMutex);
+ freeifaddrs(ifp);
+ return iflist;
- OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
+exit:
+ freeifaddrs(ifp);
+ u_arraylist_destroy(iflist);
+ return NULL;
}
-