X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=resource%2Fcsdk%2Fconnectivity%2Fsrc%2Fip_adapter%2Ftizen%2Fcaipnwmonitor.c;h=079ecd53daf165ed2ef306e6adad95b09b14caa8;hb=d2d11fd812a38648d4c797eb7e5c872ba5961d41;hp=47e11b47a237e098a667c225d726ed86ce59714d;hpb=b79dc9e23777bca1995ae5fbb63d1b7071a0f079;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 47e11b4..079ecd5 100644 --- a/resource/csdk/connectivity/src/ip_adapter/tizen/caipnwmonitor.c +++ b/resource/csdk/connectivity/src/ip_adapter/tizen/caipnwmonitor.c @@ -18,8 +18,6 @@ * ******************************************************************/ -#include "caipinterface.h" - #include #include #include @@ -29,276 +27,318 @@ #include #include #include -#include +#include +#include +#include +#include +#include +#include "caipinterface.h" +#include "caipnwmonitor.h" #include "caadapterutils.h" #include "logger.h" #include "oic_malloc.h" #include "oic_string.h" +#include -#define 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" + +/** + * Used to storing a connection handle for managing data connections. + */ +static connection_h connection = NULL; + +/** + * Used to storing adapter changes callback interface. + */ +static struct CAIPCBData_t *g_adapterCallbackList = NULL; + +/** + * Create new interface item. + */ static CAInterface_t *CANewInterfaceItem(int index, char *name, int family, - uint32_t addr, int flags); + const char *addr, int flags); +/** + * Add new network interface in list. + */ static CAResult_t CAAddInterfaceItem(u_arraylist_t *iflist, int index, - char *name, int family, uint32_t addr, int flags); - -static void CAWIFIConnectionStateChangedCb(wifi_connection_state_e state, wifi_ap_h ap, - void *userData); + char *name, int family, const char *addr, int flags); -static void CAWIFIDeviceStateChangedCb(wifi_device_state_e state, void *userData); +/** + * Pass the changed network status through the stored callback. + */ +static void CAIPPassNetworkChangesToAdapter(CANetworkStatus_t status); +/** + * Callback function to received connection state changes. + */ +static void CAIPConnectionStateChangedCb(connection_type_e type, void* userData); int CAGetPollingInterval(int interval) { return interval; } -CAInterface_t *CAFindInterfaceChange() +static void CAIPPassNetworkChangesToAdapter(CANetworkStatus_t status) { - char buf[MAX_INTERFACE_INFO_LENGTH] = { 0 }; - struct ifconf ifc = { .ifc_len = MAX_INTERFACE_INFO_LENGTH, .ifc_buf = buf }; - - int s = caglobals.ip.u6.fd != -1 ? caglobals.ip.u6.fd : caglobals.ip.u4.fd; - if (ioctl(s, SIOCGIFCONF, &ifc) < 0) + CAIPCBData_t *cbitem = NULL; + LL_FOREACH(g_adapterCallbackList, cbitem) { - OIC_LOG_V(ERROR, TAG, "SIOCGIFCONF failed: %s", strerror(errno)); - return NULL; + if (cbitem && cbitem->adapter) + { + cbitem->callback(cbitem->adapter, status); + } } +} - CAInterface_t *foundNewInterface = NULL; - - struct ifreq* ifr = ifc.ifc_req; - size_t interfaces = ifc.ifc_len / sizeof (ifc.ifc_req[0]); - size_t ifreqsize = ifc.ifc_len; - - CAIfItem_t *previous = (CAIfItem_t *)OICMalloc(ifreqsize); - if (!previous) +CAResult_t CAIPSetNetworkMonitorCallback(CAIPAdapterStateChangeCallback callback, + CATransportAdapter_t adapter) +{ + if (!callback) { - OIC_LOG(ERROR, TAG, "OICMalloc failed"); - return NULL; + OIC_LOG(ERROR, TAG, "callback is null"); + return CA_STATUS_INVALID_PARAM; } - memcpy(previous, caglobals.ip.nm.ifItems, ifreqsize); - size_t numprevious = caglobals.ip.nm.numIfItems; - - if (ifreqsize > caglobals.ip.nm.sizeIfItems) + CAIPCBData_t *cbitem = NULL; + LL_FOREACH(g_adapterCallbackList, cbitem) { - - CAIfItem_t *items = (CAIfItem_t *)OICRealloc(caglobals.ip.nm.ifItems, ifreqsize); - if (!items) + if (cbitem && adapter == cbitem->adapter && callback == cbitem->callback) { - OIC_LOG(ERROR, TAG, "OICRealloc failed"); - OICFree(previous); - return NULL; + OIC_LOG(DEBUG, TAG, "this callback is already added"); + return CA_STATUS_OK; } - caglobals.ip.nm.ifItems = items; - caglobals.ip.nm.sizeIfItems = ifreqsize; } - caglobals.ip.nm.numIfItems = 0; - for (size_t i = 0; i < interfaces; i++) + cbitem = (CAIPCBData_t *)OICCalloc(1, sizeof(*cbitem)); + if (!cbitem) { - struct ifreq* item = &ifr[i]; - char *name = item->ifr_name; - struct sockaddr_in *sa4 = (struct sockaddr_in *)&item->ifr_addr; - uint32_t ipv4addr = sa4->sin_addr.s_addr; + OIC_LOG(ERROR, TAG, "Malloc failed"); + return CA_STATUS_FAILED; + } + + cbitem->adapter = adapter; + cbitem->callback = callback; + LL_APPEND(g_adapterCallbackList, cbitem); - if (ioctl(s, SIOCGIFFLAGS, item) < 0) + return CA_STATUS_OK; +} + +CAResult_t CAIPUnSetNetworkMonitorCallback(CATransportAdapter_t adapter) +{ + CAIPCBData_t *cbitem = NULL; + CAIPCBData_t *tmpCbitem = NULL; + LL_FOREACH_SAFE(g_adapterCallbackList, cbitem, tmpCbitem) + { + if (cbitem && adapter == cbitem->adapter) { - OIC_LOG_V(ERROR, TAG, "SIOCGIFFLAGS failed: %s", strerror(errno)); - continue; + OIC_LOG(DEBUG, TAG, "remove specific callback"); + LL_DELETE(g_adapterCallbackList, cbitem); + OICFree(cbitem); + return CA_STATUS_OK; } - int16_t flags = item->ifr_flags; - if ((flags & IFF_LOOPBACK) || !(flags & IFF_RUNNING)) + } + return CA_STATUS_OK; +} + +u_arraylist_t *CAFindInterfaceChange() +{ + 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 }; + + ssize_t len = recvmsg(caglobals.ip.netlinkFd, &msg, 0); + + for (struct nlmsghdr *nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len)) + { + if (nh != NULL && (nh->nlmsg_type != RTM_DELADDR && nh->nlmsg_type != RTM_NEWADDR)) { continue; } - if (ioctl(s, SIOCGIFINDEX, item) < 0) + + struct ifinfomsg *ifi = (struct ifinfomsg *)NLMSG_DATA(nh); + if (!ifi) { - OIC_LOG_V(ERROR, TAG, "SIOCGIFINDEX failed: %s", strerror(errno)); continue; } - int ifIndex = item->ifr_ifindex; - caglobals.ip.nm.ifItems[i].ifIndex = ifIndex; // refill interface list - caglobals.ip.nm.numIfItems++; - - if (foundNewInterface) + if (RTM_DELADDR == nh->nlmsg_type) { - continue; // continue updating interface list + CloseMulticastSocket(); } - // see if this interface didn't previously exist - bool found = false; - for (size_t j = 0; j < numprevious; j++) - { - if (ifIndex == previous[j].ifIndex) - { - found = true; - break; - } - } - if (found) + int ifiIndex = ifi->ifi_index; + iflist = CAIPGetInterfaceInformation(ifiIndex); + if (!iflist) { - OIC_LOG_V(INFO, TAG, "Interface found: %s", name); - continue; + OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno)); + return NULL; } - - foundNewInterface = CANewInterfaceItem(ifIndex, name, AF_INET, ipv4addr, flags); + CreateMulticastSocket(); } - - OICFree(previous); - return foundNewInterface; + return iflist; } -CAResult_t CAIPStartNetworkMonitor() +CAResult_t CAIPStartNetworkMonitor(CAIPAdapterStateChangeCallback callback, + CATransportAdapter_t adapter) { - OIC_LOG(DEBUG, TAG, "IN"); - - // Initialize Wifi service - wifi_error_e ret = wifi_initialize(); - if (WIFI_ERROR_NONE != ret) - { - OIC_LOG(ERROR, TAG, "wifi_initialize failed"); - return CA_STATUS_FAILED; - } - - // Set callback for receiving state changes - ret = wifi_set_device_state_changed_cb(CAWIFIDeviceStateChangedCb, NULL); - if (WIFI_ERROR_NONE != ret) + if (!g_adapterCallbackList) { - OIC_LOG(ERROR, TAG, "wifi_set_device_state_changed_cb failed"); - return CA_STATUS_FAILED; - } + // 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; + } - // Set callback for receiving connection state changes - ret = wifi_set_connection_state_changed_cb(CAWIFIConnectionStateChangedCb, NULL); - if (WIFI_ERROR_NONE != ret) - { - OIC_LOG(ERROR, TAG, "wifi_set_connection_state_changed_cb failed"); - return CA_STATUS_FAILED; + // Set callback for receiving state changes. + ret = connection_set_type_changed_cb(connection, CAIPConnectionStateChangedCb, NULL); + if (CONNECTION_ERROR_NONE != ret) + { + OIC_LOG(ERROR, TAG, "connection_set_type_changed_cb failed"); + return CA_STATUS_FAILED; + } } - OIC_LOG(DEBUG, TAG, "OUT"); - return CA_STATUS_OK; + OIC_LOG(DEBUG, TAG, "Initialize network monitoring successfully"); + return CAIPSetNetworkMonitorCallback(callback, adapter); } -CAResult_t CAIPStopNetworkMonitor() +CAResult_t CAIPStopNetworkMonitor(CATransportAdapter_t adapter) { OIC_LOG(DEBUG, TAG, "IN"); - // Reset callback for receiving state changes - wifi_error_e ret = wifi_unset_device_state_changed_cb(); - if (WIFI_ERROR_NONE != ret) - { - OIC_LOG(ERROR, TAG, "wifi_unset_device_state_changed_cb failed"); - } - - // Reset callback for receiving connection state changes - ret = wifi_unset_connection_state_changed_cb(); - if (WIFI_ERROR_NONE != ret) + CAIPUnSetNetworkMonitorCallback(adapter); + if (!g_adapterCallbackList) { - OIC_LOG(ERROR, TAG, "wifi_unset_connection_state_changed_cb 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"); + } - // Deinitialize Wifi service - ret = wifi_deinitialize(); - if (WIFI_ERROR_NONE != ret) - { - OIC_LOG(ERROR, TAG, "wifi_deinitialize failed"); + // Deinitialize Wifi service. + ret = connection_destroy(connection); + if (CONNECTION_ERROR_NONE != ret) + { + OIC_LOG(ERROR, TAG, "connection_destroy failed"); + } + connection = NULL; + } } - OIC_LOG(DEBUG, TAG, "OUT"); + OIC_LOG(DEBUG, TAG, "Network monitoring terminated successfully"); return CA_STATUS_OK; } -u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex) +/** + * 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) { - u_arraylist_t *iflist = u_arraylist_create(); - if (!iflist) + if ((idx < 0) || (iflist == NULL)) { - OIC_LOG_V(ERROR, TAG, "Failed to create iflist: %s", strerror(errno)); - return NULL; + return false; } - char buf[MAX_INTERFACE_INFO_LENGTH] = { 0 }; - struct ifconf ifc = { .ifc_len = MAX_INTERFACE_INFO_LENGTH, .ifc_buf = buf }; - - int s = caglobals.ip.u6.fd != -1 ? caglobals.ip.u6.fd : caglobals.ip.u4.fd; - if (ioctl(s, SIOCGIFCONF, &ifc) < 0) + struct ifaddrs *ifp = NULL; + if (-1 == getifaddrs(&ifp)) { - OIC_LOG_V(ERROR, TAG, "SIOCGIFCONF failed: %s", strerror(errno)); - u_arraylist_destroy(iflist); - return NULL; + OIC_LOG_V(ERROR, TAG, "Failed to get ifaddrs: %s", strerror(errno)); + return false; } - struct ifreq* ifr = ifc.ifc_req; - size_t interfaces = ifc.ifc_len / sizeof (ifc.ifc_req[0]); - size_t ifreqsize = ifc.ifc_len; - - if (ifreqsize > caglobals.ip.nm.sizeIfItems) + struct ifaddrs *ifa = NULL; + for (ifa = ifp; ifa; ifa = ifa->ifa_next) { - CAIfItem_t *items = (CAIfItem_t *)OICRealloc(caglobals.ip.nm.ifItems, ifreqsize); - if (!items) + if (!ifa->ifa_addr) { - OIC_LOG(ERROR, TAG, "OICRealloc failed"); - goto exit; + continue; } - caglobals.ip.nm.ifItems = items; - caglobals.ip.nm.sizeIfItems = ifreqsize; - } - - caglobals.ip.nm.numIfItems = 0; - for (size_t i = 0; i < interfaces; i++) - { - CAResult_t result = CA_STATUS_OK; - struct ifreq* item = &ifr[i]; - char *name = item->ifr_name; - struct sockaddr_in *sa4 = (struct sockaddr_in *)&item->ifr_addr; - uint32_t ipv4addr = sa4->sin_addr.s_addr; - if (ioctl(s, SIOCGIFFLAGS, item) < 0) + int family = ifa->ifa_addr->sa_family; + if ((ifa->ifa_flags & IFF_LOOPBACK) || (AF_INET != family && AF_INET6 != family)) { - OIC_LOG_V(ERROR, TAG, "SIOCGIFFLAGS failed: %s", strerror(errno)); continue; } - int16_t flags = item->ifr_flags; - if ((flags & IFF_LOOPBACK) || !(flags & IFF_RUNNING)) + + int ifindex = if_nametoindex(ifa->ifa_name); + if (idx && (ifindex != idx)) { continue; } - if (ioctl(s, SIOCGIFINDEX, item) < 0) + + char ipaddr[MAX_ADDR_STR_SIZE_CA] = {0}; + if (family == AF_INET6) { - OIC_LOG_V(ERROR, TAG, "SIOCGIFINDEX failed: %s", strerror(errno)); - continue; + struct sockaddr_in6 *in6 = (struct sockaddr_in6*) ifa->ifa_addr; + inet_ntop(family, (void *)&(in6->sin6_addr), ipaddr, sizeof(ipaddr)); } - - int ifindex = item->ifr_ifindex; - caglobals.ip.nm.ifItems[i].ifIndex = ifindex; - caglobals.ip.nm.numIfItems++; - - if (desiredIndex && (ifindex != desiredIndex)) + else if (family == AF_INET) { - continue; + struct sockaddr_in *in = (struct sockaddr_in*) ifa->ifa_addr; + inet_ntop(family, (void *)&(in->sin_addr), ipaddr, sizeof(ipaddr)); } - // Add IPv4 interface - result = CAAddInterfaceItem(iflist, ifindex, name, AF_INET, ipv4addr, flags); - if (CA_STATUS_OK != result) + if ((strcmp(ipaddr, IFC_ADDR_LOOP_IPV4) == 0) || + (strcmp(ipaddr, IFC_ADDR_LOOP_IPV6) == 0) || + (strcmp(ifa->ifa_name, IFC_LABEL_LOOP) == 0)) { - goto exit; + OIC_LOG(DEBUG, TAG, "LOOPBACK continue!!!"); + continue; } - // Add IPv6 interface - result = CAAddInterfaceItem(iflist, ifindex, name, AF_INET6, ipv4addr, flags); + CAResult_t result = CAAddInterfaceItem(iflist, ifindex, + ifa->ifa_name, family, + ipaddr, ifa->ifa_flags); if (CA_STATUS_OK != result) { + OIC_LOG(ERROR, TAG, "CAAddInterfaceItem fail"); goto exit; } } + freeifaddrs(ifp); + return true; + +exit: + freeifaddrs(ifp); + return false; +} + +u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex) +{ + u_arraylist_t *iflist = u_arraylist_create(); + if (!iflist) + { + OIC_LOG_V(ERROR, TAG, "Failed to create iflist: %s", strerror(errno)); + return NULL; + } + + if (!CAIPGetAddrInfo(desiredIndex, iflist)) + { + goto exit; + } + return iflist; exit: @@ -307,7 +347,7 @@ exit: } static CAResult_t CAAddInterfaceItem(u_arraylist_t *iflist, int index, - char *name, int family, uint32_t addr, int flags) + char *name, int family, const char *addr, int flags) { CAInterface_t *ifitem = CANewInterfaceItem(index, name, family, addr, flags); if (!ifitem) @@ -326,7 +366,7 @@ static CAResult_t CAAddInterfaceItem(u_arraylist_t *iflist, int index, } static CAInterface_t *CANewInterfaceItem(int index, char *name, int family, - uint32_t addr, int flags) + const char *addr, int flags) { CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof (CAInterface_t)); if (!ifitem) @@ -338,54 +378,35 @@ static CAInterface_t *CANewInterfaceItem(int index, char *name, int family, OICStrcpy(ifitem->name, INTERFACE_NAME_MAX, name); ifitem->index = index; ifitem->family = family; - ifitem->ipv4addr = addr; + OICStrcpy(ifitem->addr, sizeof(ifitem->addr), addr); ifitem->flags = flags; return ifitem; } -void CAWIFIConnectionStateChangedCb(wifi_connection_state_e state, wifi_ap_h ap, - void *userData) -{ - OIC_LOG(DEBUG, TAG, "IN"); - - if (WIFI_CONNECTION_STATE_ASSOCIATION == state - || WIFI_CONNECTION_STATE_CONFIGURATION == state) - { - OIC_LOG(DEBUG, TAG, "Connection is in Association State"); - return; - } - - if (WIFI_CONNECTION_STATE_CONNECTED == state) - { - CAWakeUpForChange(); - } - else - { - u_arraylist_t *iflist = CAIPGetInterfaceInformation(0); - if (!iflist) - { - OIC_LOG_V(ERROR, TAG, "get interface info failed"); - return; - } - } - - OIC_LOG(DEBUG, TAG, "OUT"); -} - -void CAWIFIDeviceStateChangedCb(wifi_device_state_e state, void *userData) +void CAIPConnectionStateChangedCb(connection_type_e type, void* userData) { - OIC_LOG(DEBUG, TAG, "IN"); + (void)userData; - if (WIFI_DEVICE_STATE_ACTIVATED == state) - { - OIC_LOG(DEBUG, TAG, "Wifi is in Activated State"); - } - else + switch (type) { - CAWIFIConnectionStateChangedCb(WIFI_CONNECTION_STATE_DISCONNECTED, NULL, NULL); - OIC_LOG(DEBUG, TAG, "Wifi is in Deactivated State"); + 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; } - - OIC_LOG(DEBUG, TAG, "OUT"); }