static CAResult_t CAAddInterfaceItem(u_arraylist_t *iflist, int index, const char *name, int family, uint32_t addr, int flags) { CAInterface_t *ifitem = CANewInterfaceItem(index, name, family, addr, flags); if (!ifitem) { return CA_STATUS_FAILED; } bool result = u_arraylist_add(iflist, ifitem); if (!result) { OIC_LOG(ERROR, TAG, "u_arraylist_add failed."); OICFree(ifitem); return CA_STATUS_FAILED; } return CA_STATUS_OK; }
CAInterface_t *CAFindInterfaceChange() { 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) { OIC_LOG_V(ERROR, TAG, "SIOCGIFCONF failed: %s", strerror(errno)); return NULL; } 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) { OIC_LOG(ERROR, TAG, "OICMalloc failed"); return NULL; } memcpy(previous, caglobals.ip.nm.ifItems, ifreqsize); size_t numprevious = caglobals.ip.nm.numIfItems; if (ifreqsize > caglobals.ip.nm.sizeIfItems) { CAIfItem_t *items = (CAIfItem_t *)OICRealloc(caglobals.ip.nm.ifItems, ifreqsize); if (!items) { OIC_LOG(ERROR, TAG, "OICRealloc failed"); OICFree(previous); return NULL; } caglobals.ip.nm.ifItems = items; caglobals.ip.nm.sizeIfItems = ifreqsize; } caglobals.ip.nm.numIfItems = 0; for (size_t i = 0; i < interfaces; i++) { 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) { OIC_LOG_V(ERROR, TAG, "SIOCGIFFLAGS failed: %s", strerror(errno)); continue; } int16_t flags = item->ifr_flags; if ((flags & IFF_LOOPBACK) || !(flags & IFF_RUNNING)) { continue; } if (ioctl(s, SIOCGIFINDEX, item) < 0) { 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) { continue; // continue updating interface list } // 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) { OIC_LOG_V(INFO, TAG, "Interface found: %s", name); continue; } foundNewInterface = CANewInterfaceItem(ifIndex, name, AF_INET, ipv4addr, flags); } OICFree(previous); return foundNewInterface; }
u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex) { if (desiredIndex < 0) { OIC_LOG_V(ERROR, TAG, "invalid index : %d", desiredIndex); return NULL; } u_arraylist_t *iflist = u_arraylist_create(); if (!iflist) { OIC_LOG_V(ERROR, TAG, "Failed to create iflist: %s", strerror(errno)); return NULL; } struct ifaddrs *ifp = NULL; if (-1 == getifaddrs(&ifp)) { OIC_LOG_V(ERROR, TAG, "Failed to get ifaddrs: %s", strerror(errno)); u_arraylist_destroy(iflist); return NULL; } OIC_LOG(DEBUG, TAG, "Got ifaddrs"); struct ifaddrs *ifa = NULL; for (ifa = ifp; ifa; ifa = ifa->ifa_next) { if (!ifa->ifa_addr) { continue; } int family = ifa->ifa_addr->sa_family; if ((ifa->ifa_flags & IFF_LOOPBACK) || (AF_INET != family && AF_INET6 != family)) { continue; } int ifindex = if_nametoindex(ifa->ifa_name); if (desiredIndex && (ifindex != desiredIndex)) { continue; } 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); if (ifitem && (int)ifitem->index == ifindex && ifitem->family == (uint16_t)family) { already = true; break; } } if (already) { continue; } CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof(CAInterface_t)); if (!ifitem) { OIC_LOG(ERROR, TAG, "Malloc failed"); goto exit; } 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; bool result = u_arraylist_add(iflist, ifitem); if (!result) { OIC_LOG(ERROR, TAG, "u_arraylist_add failed."); goto exit; } 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); } } freeifaddrs(ifp); return iflist; exit: freeifaddrs(ifp); u_arraylist_destroy(iflist); return NULL; }
CAInterface_t *CAFindInterfaceChange() { 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 }; size_t len = recvmsg(caglobals.ip.netlinkFd, &msg, 0); for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len)) { if (nh != NULL && nh->nlmsg_type != RTM_NEWLINK) { continue; } struct ifinfomsg *ifi = (struct ifinfomsg *)NLMSG_DATA(nh); int ifiIndex = ifi->ifi_index; u_arraylist_t *iflist = CAIPGetInterfaceInformation(ifiIndex); 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; } if (!iflist) { OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno)); return NULL; } 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 ((int)ifitem->index != ifiIndex) { continue; } 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); } #endif return foundNewInterface; }