X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=resource%2Fcsdk%2Fconnectivity%2Fsrc%2Fip_adapter%2Ftizen%2Fcaipnwmonitor.c;h=ef7291ec4b8db6686bf45f3333ef25210ff6526e;hb=3dbb160e2b03aa2056a714374232f17ab528fa98;hp=231975cf4029fdbb8dc392aa28090f9034534112;hpb=ed03b2f2d711027561c18956826580e1e81b84ec;p=platform%2Fupstream%2Fiotivity.git diff --git a/resource/csdk/connectivity/src/ip_adapter/tizen/caipnwmonitor.c b/resource/csdk/connectivity/src/ip_adapter/tizen/caipnwmonitor.c index 231975c..ef7291e 100644 --- a/resource/csdk/connectivity/src/ip_adapter/tizen/caipnwmonitor.c +++ b/resource/csdk/connectivity/src/ip_adapter/tizen/caipnwmonitor.c @@ -18,628 +18,402 @@ * ******************************************************************/ -#include "caipinterface.h" - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include +#include "caipinterface.h" +#include "caipnwmonitor.h" #include "caadapterutils.h" -#include "camutex.h" #include "logger.h" #include "oic_malloc.h" #include "oic_string.h" +#include + +#define TAG "OIC_CA_IP_MONITOR" -#define IP_MONITOR_TAG "IP_MONITOR" +#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; - } - - 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; - } + cbitem->callback(cbitem->adapter, status); } } - - 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; - } - - // Get wifi connected IP address - wifi_ap_h accessPoint = NULL; - if (WIFI_ERROR_NONE != (ret = wifi_get_connected_ap(&accessPoint))) - { - OIC_LOG_V(ERROR, IP_MONITOR_TAG, "Failed to get access point! error num [%d]", - ret); - - OICFree(*interfaceName); - *interfaceName = NULL; - return; + if (cbitem && adapter == cbitem->adapter && callback == cbitem->callback) + { + OIC_LOG(DEBUG, TAG, "this callback is already added"); + return CA_STATUS_OK; + } } - if (WIFI_ERROR_NONE != (ret = wifi_ap_get_ip_address(accessPoint, WIFI_ADDRESS_FAMILY_IPV4, - ipAddress))) + cbitem = (CAIPCBData_t *)OICCalloc(1, sizeof(*cbitem)); + if (!cbitem) { - OIC_LOG_V(ERROR, IP_MONITOR_TAG, "Failed to get interface address! 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_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; - } + cbitem->adapter = adapter; + cbitem->callback = callback; + LL_APPEND(g_adapterCallbackList, cbitem); - 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_NEWLINK) { - OIC_LOG(ERROR, IP_MONITOR_TAG, "Malloc failed"); - OICFree(interfaceName); - OICFree(ipAddress); - OICFree(subnetMask); - return; + continue; } + struct ifinfomsg *ifi = (struct ifinfomsg *)NLMSG_DATA(nh); - // set interface name - OICStrcpy(netInfo->interfaceName, sizeof(netInfo->interfaceName), interfaceName); + if ((!ifi || (ifi->ifi_flags & IFF_LOOPBACK) || !(ifi->ifi_flags & IFF_RUNNING))) + { + continue; + } - // set local ip address - OICStrcpy(netInfo->ipAddress, sizeof(netInfo->ipAddress), ipAddress); + int ifiIndex = ifi->ifi_index; - // set subnet mask - OICStrcpy(netInfo->subnetMask, sizeof(netInfo->subnetMask), subnetMask); + iflist = CAIPGetInterfaceInformation(ifiIndex); - bool ret = CACheckIsInterfaceInfoChanged(netInfo); - if (ret) + if (!iflist) { - OIC_LOG(DEBUG, IP_MONITOR_TAG, "CACheckIsInterfaceInfoChanged true"); + OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno)); + return NULL; } - - OICFree(interfaceName); - OICFree(ipAddress); - OICFree(subnetMask); - } - else - { - CARemoveInterfaceInfo(); } - - 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"); + OIC_LOG(DEBUG, TAG, "IN"); - if (WIFI_DEVICE_STATE_ACTIVATED == state) - { - OIC_LOG(DEBUG, IP_MONITOR_TAG, "Wifi is in Activated State"); - } - else + if (!g_adapterCallbackList) { - CAWIFIConnectionStateChangedCb(WIFI_CONNECTION_STATE_DISCONNECTED, NULL, NULL); - OIC_LOG(DEBUG, IP_MONITOR_TAG, "Wifi is in Deactivated State"); - } + // Initialize Wifi service. + if (WIFI_ERROR_NONE != wifi_initialize()) + { + OIC_LOG(ERROR, TAG, "wifi_initialize failed"); + } - 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; + return CAIPSetNetworkMonitorCallback(callback, adapter); } -static void CADestroyNetworkMonitorMutexes() +CAResult_t CAIPStopNetworkMonitor(CATransportAdapter_t adapter) { - ca_mutex_free(g_networkMonitorContextMutex); - g_networkMonitorContextMutex = NULL; -} + OIC_LOG(DEBUG, TAG, "IN"); -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) + CAIPUnSetNetworkMonitorCallback(adapter); + if (!g_adapterCallbackList) { - 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; - } + // Deinitialize Wifi service. + if (WIFI_ERROR_NONE != wifi_deinitialize()) + { + OIC_LOG(ERROR, TAG, "wifi_deinitialize failed"); + } - 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; - } + // 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"); 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; - ca_mutex_unlock(g_networkMonitorContextMutex); + return ifitem; +} - OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT"); +void CAIPConnectionStateChangedCb(connection_type_e type, void* userData) +{ + 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; + } }