예제 #1
0
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;
}
예제 #2
0
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;
}