X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=resource%2Fcsdk%2Fconnectivity%2Fsrc%2Fip_adapter%2Flinux%2Fcaipnwmonitor.c;h=a2f2e4f8260fecfc292860ef9f8950be257d9c84;hb=1cee1631595cac6a6394ac2e0b365c6dd5a42c68;hp=c077580c1998a628fa3ce4032b0f55d8afd64bb9;hpb=935fdb9b67b6c10d007e652e9e2e028fd6ccfe09;p=platform%2Fupstream%2Fiotivity.git diff --git a/resource/csdk/connectivity/src/ip_adapter/linux/caipnwmonitor.c b/resource/csdk/connectivity/src/ip_adapter/linux/caipnwmonitor.c index c077580..a2f2e4f 100644 --- a/resource/csdk/connectivity/src/ip_adapter/linux/caipnwmonitor.c +++ b/resource/csdk/connectivity/src/ip_adapter/linux/caipnwmonitor.c @@ -20,645 +20,372 @@ #include "caipinterface.h" +#include +#include +#include +#include #include +#include #include +#include +#include +#include +#include #include -#include #include -#include #include -#include -#include "caadapterutils.h" +#ifdef __linux__ +#include +#include +#include +#include +#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; } -