CAResult_t CAGetIPInterfaceInformation(CAEndpoint_t **info, uint32_t *size)
{
    OIC_LOG(DEBUG, TAG, "IN");

    VERIFY_NON_NULL(info, TAG, "info is NULL");
    VERIFY_NON_NULL(size, TAG, "size is NULL");

    u_arraylist_t *iflist = CAIPGetInterfaceInformation(0);
    if (!iflist)
    {
        OIC_LOG(ERROR, TAG, "get interface info failed");
        return CA_STATUS_FAILED;
    }

    uint32_t len = u_arraylist_length(iflist);

    CAEndpoint_t *eps = (CAEndpoint_t *)OICCalloc(len, sizeof (CAEndpoint_t));
    if (!eps)
    {
        OIC_LOG(ERROR, TAG, "Malloc Failed");
        u_arraylist_destroy(iflist);
        return CA_MEMORY_ALLOC_FAILED;
    }

    for (uint32_t i = 0, j = 0; i < len; i++)
    {
        CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
        if(!ifitem)
        {
            continue;
        }
        unsigned char *addr=  (unsigned char *) &(ifitem->ipv4addr);
        snprintf(eps[j].addr, MAX_ADDR_STR_SIZE_CA, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);

        eps[j].flags = CA_IPV4;
        eps[j].adapter = CA_ADAPTER_IP;
        eps[j].interface = 0;
        eps[j].port = caglobals.ip.u4.port;
        j++;
    }

    *info = eps;
    *size = len;

    u_arraylist_destroy(iflist);

    OIC_LOG(DEBUG, TAG, "OUT");
    return CA_STATUS_OK;
}
예제 #2
0
CAResult_t CAGetIPInterfaceInformation(CAEndpoint_t **info, uint32_t *size)
{
    OIC_LOG(DEBUG, TAG, "IN");

    VERIFY_NON_NULL(info, TAG, "info is NULL");
    VERIFY_NON_NULL(size, TAG, "size is NULL");

    u_arraylist_t *iflist = CAIPGetInterfaceInformation(0);
    if (!iflist)
    {
        OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno));
        return CA_STATUS_FAILED;
    }

    uint32_t len = u_arraylist_length(iflist);

    CAEndpoint_t *eps = (CAEndpoint_t *)OICCalloc(len, sizeof (CAEndpoint_t));
    if (!eps)
    {
        OIC_LOG(ERROR, TAG, "Malloc Failed");
        u_arraylist_destroy(iflist);
        return CA_MEMORY_ALLOC_FAILED;
    }

    for (uint32_t i = 0, j = 0; i < len; i++)
    {
        CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
        if(!ifitem)
        {
            continue;
        }

        OICStrcpy(eps[j].addr, CA_INTERFACE_NAME_SIZE, ifitem->name);
        eps[j].flags = ifitem->family == AF_INET6 ? CA_IPV6 : CA_IPV4;
        eps[j].adapter = CA_ADAPTER_IP;
        eps[j].interface = 0;
        eps[j].port = 0;
        j++;
    }

    *info = eps;
    *size = len;

    u_arraylist_destroy(iflist);

    OIC_LOG(DEBUG, TAG, "OUT");
    return CA_STATUS_OK;
}
예제 #3
0
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;
        }
        u_arraylist_destroy(iflist);
    }

    OIC_LOG(DEBUG, TAG, "OUT");
}
예제 #4
0
OCStackResult TerminateKeepAlive(OCMode mode)
{
    OIC_LOG(DEBUG, TAG, "TerminateKeepAlive IN");
    if (!g_isKeepAliveInitialized)
    {
        OIC_LOG(ERROR, TAG, "KeepAlive not initialized");
        return OC_STACK_ERROR;
    }

    if (OC_CLIENT != mode)
    {
        // Delete the KeepAlive Resource[/oic/ping].
        OCStackResult result = DeleteKeepAliveResource();
        if (OC_STACK_OK != result)
        {
            OIC_LOG_V(ERROR, TAG, "DeleteKeepAliveResource failed[%d]", result);
            return result;
        }
    }

    if (NULL != g_keepAliveConnectionTable)
    {
        u_arraylist_destroy(g_keepAliveConnectionTable);
        g_keepAliveConnectionTable = NULL;
    }

    g_isKeepAliveInitialized = false;

    OIC_LOG(DEBUG, TAG, "TerminateKeepAlive OUT");
    return OC_STACK_OK;
}
예제 #5
0
void CAIPSendData(CAEndpoint_t *endpoint, const void *data, uint32_t datalen,
                                                            bool isMulticast)
{
    VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL");
    VERIFY_NON_NULL_VOID(data, TAG, "data is NULL");

    bool isSecure = (endpoint->flags & CA_SECURE) != 0;

    if (isMulticast)
    {
        endpoint->port = isSecure ? CA_SECURE_COAP : CA_COAP;

        u_arraylist_t *iflist = CAIPGetInterfaceInformation(0);
        if (!iflist)
        {
            OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno));
            return;
        }

        if ((endpoint->flags & CA_IPV6) && caglobals.ip.ipv6enabled)
        {
            sendMulticastData6(iflist, endpoint, data, datalen);
        }
        if ((endpoint->flags & CA_IPV4) && caglobals.ip.ipv4enabled)
        {
            sendMulticastData4(iflist, endpoint, data, datalen);
        }

        u_arraylist_destroy(iflist);
    }
    else
    {
        if (!endpoint->port)    // unicast discovery
        {
            endpoint->port = isSecure ? CA_SECURE_COAP : CA_COAP;
        }

        int fd;
        if (caglobals.ip.ipv6enabled && (endpoint->flags & CA_IPV6))
        {
            fd = isSecure ? caglobals.ip.u6s.fd : caglobals.ip.u6.fd;
            #ifndef __WITH_DTLS__
            fd = caglobals.ip.u6.fd;
            #endif
            sendData(fd, endpoint, data, datalen, "unicast", "ipv6");
        }
        if (caglobals.ip.ipv4enabled && (endpoint->flags & CA_IPV4))
        {
            fd = isSecure ? caglobals.ip.u4s.fd : caglobals.ip.u4.fd;
            #ifndef __WITH_DTLS__
            fd = caglobals.ip.u4.fd;
            #endif
            sendData(fd, endpoint, data, datalen, "unicast", "ipv4");
        }
    }
}
예제 #6
0
static void CAHandleNetlink()
{
#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->nlmsg_type != RTM_NEWLINK)
        {
            continue;
        }

        struct ifinfomsg *ifi = (struct ifinfomsg *)NLMSG_DATA(nh);
        if (!ifi || (ifi->ifi_flags & IFF_LOOPBACK) || !(ifi->ifi_flags & IFF_RUNNING))
        {
            continue;
        }

        int newIndex = ifi->ifi_index;

        u_arraylist_t *iflist = CAIPGetInterfaceInformation(newIndex);
        if (!iflist)
        {
            OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno));
            return;
        }

        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 != newIndex)
            {
                continue;
            }

            CAProcessNewInterface(ifitem);
            break; // we found the one we were looking for
        }
        u_arraylist_destroy(iflist);
    }
#endif // __linux__
}
static void CAIPDestroyNetworkMonitorList()
{
    if (g_netInterfaceList)
    {
        u_arraylist_destroy(g_netInterfaceList);
        g_netInterfaceList = NULL;
    }

    if (g_networkMonitorContextMutex)
    {
        ca_mutex_free(g_networkMonitorContextMutex);
        g_networkMonitorContextMutex = NULL;
    }
}
예제 #8
0
u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex)
{
    bool result = true;

    u_arraylist_t *iflist = u_arraylist_create();
    if (!iflist)
    {
        OIC_LOG(ERROR, TAG, "Failed to create iflist");
        return NULL;
    }

    CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof(CAInterface_t));
    if (!ifitem)
    {
        OIC_LOG(ERROR, TAG, "Malloc failed");
        goto exit;
    }

    // Since Arduino currently only supports one interface, the next 4 lines are sufficient.
    OICStrcpy(ifitem->name, INTERFACE_NAME_MAX, "WIFI");
    ifitem->index = 1;
    ifitem->family = AF_INET;
    ifitem->flags = 0;
    CAArduinoGetInterfaceAddress(ifitem->addr, sizeof(ifitem->addr));

    result = u_arraylist_add(iflist, ifitem);
    if (!result)
    {
        OIC_LOG(ERROR, TAG, "u_arraylist_add failed.");
        goto exit;
    }

    OIC_LOG_V(DEBUG, TAG, "Added interface: %s (%d)", ifitem->name, ifitem->family);

    return iflist;

exit:
    u_arraylist_destroy(iflist);
    return NULL;
}
예제 #9
0
static void CAApplyInterfaces()
{
    u_arraylist_t *iflist = CAIPGetInterfaceInformation(0);
    if (!iflist)
    {
        OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno));
        return;
    }

    uint32_t len = u_arraylist_length(iflist);
    OIC_LOG_V(DEBUG, TAG, "IP network interfaces found: %d", len);

    for (uint32_t i = 0; i < len; i++)
    {
        CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);

        if (!ifitem)
        {
            continue;
        }
        if ((ifitem->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
        {
            continue;
        }
        if (ifitem->family == AF_INET)
        {
            struct in_addr inaddr;
            inaddr.s_addr = ifitem->ipv4addr;
            applyMulticastToInterface4(inaddr);
            OIC_LOG_V(DEBUG, TAG, "IPv4 network interface: %s", ifitem->name);
        }
        if (ifitem->family == AF_INET6)
        {
            applyMulticastToInterface6(ifitem->index);
            OIC_LOG_V(DEBUG, TAG, "IPv6 network interface: %s", ifitem->name);
        }
    }

    u_arraylist_destroy(iflist);
}
예제 #10
0
static void CATCPDisconnectAll()
{
    OIC_LOG(DEBUG, TAG, "IN");

    ca_mutex_lock(g_mutexObjectList);
    uint32_t length = u_arraylist_length(caglobals.tcp.svrlist);

    CATCPServerInfo_t *svritem = NULL;
    for (size_t i = 0; i < length; i++)
    {
        svritem = (CATCPServerInfo_t *) u_arraylist_get(caglobals.tcp.svrlist, i);
        if (svritem && svritem->u4tcp.fd >= 0)
        {
            shutdown(svritem->u4tcp.fd, SHUT_RDWR);
            close(svritem->u4tcp.fd);
        }
    }
    u_arraylist_destroy(caglobals.tcp.svrlist);
    caglobals.tcp.svrlist = NULL;
    ca_mutex_unlock(g_mutexObjectList);

    OIC_LOG(DEBUG, TAG, "OUT");
}
예제 #11
0
static void applyMulticastToInterface4(struct in_addr inaddr)
{
    if (!caglobals.ip.ipv4enabled)
    {
        return;
    }

    struct ip_mreqn mreq = { .imr_multiaddr = IPv4MulticastAddress,
                             .imr_address = inaddr,
                             .imr_ifindex = 0 };
    if (setsockopt(caglobals.ip.m4.fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof (mreq)))
    {
        if (EADDRINUSE != errno)
        {
            OIC_LOG_V(ERROR, TAG, "IPv4 IP_ADD_MEMBERSHIP failed: %s", strerror(errno));
        }
    }
    if (setsockopt(caglobals.ip.m4s.fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof (mreq)))
    {
        if (EADDRINUSE != errno)
        {
            OIC_LOG_V(ERROR, TAG, "secure IPv4 IP_ADD_MEMBERSHIP failed: %s", strerror(errno));
        }
    }
}

static void applyMulticast6(int fd, struct in6_addr *addr, uint32_t interface)
{
    struct ipv6_mreq mreq = {.ipv6mr_multiaddr = *addr, .ipv6mr_interface = interface};

    if (setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof (mreq)))
    {
        if (EADDRINUSE != errno)
        {
            OIC_LOG_V(ERROR, TAG, "IPv6 IP_ADD_MEMBERSHIP failed: %s", strerror(errno));
        }
    }
}

static void applyMulticastToInterface6(uint32_t interface)
{
    if (!caglobals.ip.ipv6enabled)
    {
        return;
    }
    //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressInt, interface);
    applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressLnk, interface);
    //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressRlm, interface);
    //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressAdm, interface);
    //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressSit, interface);
    //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressOrg, interface);
    //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressGlb, interface);

    //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressInt, interface);
    applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressLnk, interface);
    //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressRlm, interface);
    //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressAdm, interface);
    //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressSit, interface);
    //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressOrg, interface);
    //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressGlb, interface);
}

CAResult_t CAIPStartListenServer()
{
    u_arraylist_t *iflist = CAIPGetInterfaceInformation(0);
    if (!iflist)
    {
        OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno));
        return CA_STATUS_FAILED;
    }

    uint32_t len = u_arraylist_length(iflist);
    OIC_LOG_V(DEBUG, TAG, "IP network interfaces found: %d", len);

    for (uint32_t i = 0; i < len; i++)
    {
        CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);

        if (!ifitem)
        {
            continue;
        }
        if ((ifitem->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
        {
            continue;
        }
        if (ifitem->family == AF_INET)
        {
            struct in_addr inaddr;
            inaddr.s_addr = ifitem->ipv4addr;
            applyMulticastToInterface4(inaddr);
            OIC_LOG_V(DEBUG, TAG, "IPv4 network interface: %s", ifitem->name);
        }
        if (ifitem->family == AF_INET6)
        {
            applyMulticastToInterface6(ifitem->index);
            OIC_LOG_V(DEBUG, TAG, "IPv6 network interface: %s", ifitem->name);
        }
    }

    u_arraylist_destroy(iflist);
    return CA_STATUS_OK;
}

CAResult_t CAIPStopListenServer()
{
    u_arraylist_t *iflist = CAIPGetInterfaceInformation(0);
    if (!iflist)
    {
        OIC_LOG_V(ERROR, TAG, "Get interface info failed: %s", strerror(errno));
        return CA_STATUS_FAILED;
    }

    uint32_t len = u_arraylist_length(iflist);
    OIC_LOG_V(DEBUG, TAG, "IP network interfaces found: %d", len);

    for (uint32_t i = 0; i < len; i++)
    {
        CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);

        if (!ifitem)
        {
            continue;
        }

        if ((ifitem->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
        {
            continue;
        }
        if (ifitem->family == AF_INET)
        {
            close(caglobals.ip.m4.fd);
            close(caglobals.ip.m4s.fd);
            caglobals.ip.m4.fd = -1;
            caglobals.ip.m4s.fd = -1;
            OIC_LOG_V(DEBUG, TAG, "IPv4 network interface: %s cloed", ifitem->name);
        }
        if (ifitem->family == AF_INET6)
        {
            close(caglobals.ip.m6.fd);
            close(caglobals.ip.m6s.fd);
            caglobals.ip.m6.fd = -1;
            caglobals.ip.m6s.fd = -1;
            OIC_LOG_V(DEBUG, TAG, "IPv6 network interface: %s", ifitem->name);
        }
    }
    u_arraylist_destroy(iflist);
    return CA_STATUS_OK;
}

static void CAProcessNewInterface(CAInterface_t *ifitem)
{
    if (!ifitem)
    {
        OIC_LOG(DEBUG, TAG, "ifitem is null");
        return;
    }

    applyMulticastToInterface6(ifitem->index);
    struct in_addr inaddr = { .s_addr = ifitem->ipv4addr };
    applyMulticastToInterface4(inaddr);
}
static void CAHandleNetlink()
{
#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->nlmsg_type != RTM_NEWLINK)
        {
            continue;
        }

        struct ifinfomsg *ifi = (struct ifinfomsg *)NLMSG_DATA(nh);
        if (!ifi || (ifi->ifi_flags & IFF_LOOPBACK) || !(ifi->ifi_flags & IFF_RUNNING))
        {
            continue;
        }

        int newIndex = ifi->ifi_index;

        u_arraylist_t *iflist = CAIPGetInterfaceInformation(newIndex);
        if (!iflist)
        {
            OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno));
            return;
        }

        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 != newIndex)
            {
                continue;
            }

            CAProcessNewInterface(ifitem);
            break; // we found the one we were looking for
        }
        u_arraylist_destroy(iflist);
    }
#endif // __linux__
}

void CAIPSetPacketReceiveCallback(CAIPPacketReceivedCallback callback)
{
    g_packetReceivedCallback = callback;
}

void CAIPSetExceptionCallback(CAIPExceptionCallback callback)
{
    g_exceptionCallback = callback;
}

static void sendData(int fd, const CAEndpoint_t *endpoint,
                     const void *data, uint32_t dlen,
                     const char *cast, const char *fam)
{
    OIC_LOG(DEBUG, TAG, "IN");

    if (!endpoint)
    {
        OIC_LOG(DEBUG, TAG, "endpoint is null");
        return;
    }

    char *secure = (endpoint->flags & CA_SECURE) ? "secure " : "";
    (void)secure;   // eliminates release warning
    struct sockaddr_storage sock;
    CAConvertNameToAddr(endpoint->addr, endpoint->port, &sock);

    socklen_t socklen;
    if (sock.ss_family == AF_INET6)
    {
        struct sockaddr_in6 *sock6 = (struct sockaddr_in6 *)&sock;
        if (!sock6->sin6_scope_id)
        {
            sock6->sin6_scope_id = endpoint->interface;
        }
        socklen = sizeof(struct sockaddr_in6);
    }
    else
    {
        socklen = sizeof(struct sockaddr_in);
    }

    ssize_t len = sendto(fd, data, dlen, 0, (struct sockaddr *)&sock, socklen);
    if (-1 == len)
    {
         // If logging is not defined/enabled.
        (void)cast;
        (void)fam;
        OIC_LOG_V(ERROR, TAG, "%s%s %s sendTo failed: %s", secure, cast, fam, strerror(errno));
    }
    else
    {
        OIC_LOG_V(INFO, TAG, "%s%s %s sendTo is successful: %zd bytes", secure, cast, fam, len);
    }
}
예제 #12
0
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;
    }

    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));
        u_arraylist_destroy(iflist);
        return NULL;
    }

    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)
    {
        CAIfItem_t *items = (CAIfItem_t *)OICRealloc(caglobals.ip.nm.ifItems, ifreqsize);
        if (!items)
        {
            OIC_LOG(ERROR, TAG, "OICRealloc failed");
            goto exit;
        }
        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)
        {
            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;
        caglobals.ip.nm.numIfItems++;

        if (desiredIndex && (ifindex != desiredIndex))
        {
            continue;
        }

        // Add IPv4 interface
        result = CAAddInterfaceItem(iflist, ifindex, name, AF_INET, ipv4addr, flags);
        if (CA_STATUS_OK != result)
        {
            goto exit;
        }

        // Add IPv6 interface
        result = CAAddInterfaceItem(iflist, ifindex, name, AF_INET6, ipv4addr, flags);
        if (CA_STATUS_OK != result)
        {
            goto exit;
        }
    }
    return iflist;

exit:
    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;
}
예제 #14
0
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;
        }

        OIC_LOG_V(DEBUG, TAG, "Added interface: %s (%d)", ifitem->name, family);
    }

    freeifaddrs(ifp);
    return iflist;

exit:
    freeifaddrs(ifp);
    u_arraylist_destroy(iflist);
    return NULL;
}
예제 #15
0
CAResult_t CAGetIPInterfaceInformation(CAEndpoint_t **info, uint32_t *size)
{
    VERIFY_NON_NULL(info, TAG, "info is NULL");
    VERIFY_NON_NULL(size, TAG, "size is NULL");

    u_arraylist_t *iflist = CAIPGetInterfaceInformation(0);
    if (!iflist)
    {
        OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno));
        return CA_STATUS_FAILED;
    }

    uint32_t len = u_arraylist_length(iflist);
    uint32_t length = len;

#ifdef __WITH_DTLS__
    //If DTLS is supported, each interface can support secure port as well
    length = len * 2;
#endif

    CAEndpoint_t *eps = (CAEndpoint_t *)OICCalloc(length, sizeof (CAEndpoint_t));
    if (!eps)
    {
        OIC_LOG(ERROR, TAG, "Malloc Failed");
        u_arraylist_destroy(iflist);
        return CA_MEMORY_ALLOC_FAILED;
    }

    for (uint32_t i = 0, j = 0; i < len; i++)
    {
        CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
        if(!ifitem)
        {
            continue;
        }

        eps[j].adapter = CA_ADAPTER_IP;
        eps[j].interface = 0;

        if (ifitem->family == AF_INET6)
        {
            eps[j].flags = CA_IPV6;
            eps[j].port = caglobals.ip.u6.port;
        }
        else
        {
            eps[j].flags = CA_IPV4;
            eps[j].port = caglobals.ip.u4.port;

            inet_ntop(AF_INET, &(ifitem->ipv4addr), eps[j].addr, MAX_ADDR_STR_SIZE_CA);
        }

#ifdef __WITH_DTLS__
        j++;

        eps[j].adapter = CA_ADAPTER_IP;
        eps[j].interface = 0;

        if (ifitem->family == AF_INET6)
        {
            eps[j].flags = CA_IPV6 | CA_SECURE;
            eps[j].port = caglobals.ip.u6s.port;
        }
        else
        {
            eps[j].flags = CA_IPV4 | CA_SECURE;
            eps[j].port = caglobals.ip.u4s.port;
            inet_ntop(AF_INET, &(ifitem->ipv4addr), eps[j].addr, MAX_ADDR_STR_SIZE_CA);
        }
#endif
        j++;
    }

    *info = eps;
    *size = len;

    u_arraylist_destroy(iflist);

    return CA_STATUS_OK;
}
예제 #16
0
static void sendMulticastData4(const u_arraylist_t *iflist,
                               CAEndpoint_t *endpoint,
                               const void *data, uint32_t datalen)
{
    VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL");

    struct ip_mreqn mreq = { .imr_multiaddr = IPv4MulticastAddress,
                             .imr_ifindex = 0 };
    OICStrcpy(endpoint->addr, sizeof(endpoint->addr), IPv4_MULTICAST);
    int fd = caglobals.ip.u4.fd;

    uint32_t len = u_arraylist_length(iflist);
    for (uint32_t i = 0; i < len; i++)
    {
        CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
        if (!ifitem)
        {
            continue;
        }
        if ((ifitem->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
        {
            continue;
        }
        if (ifitem->family != AF_INET)
        {
            continue;
        }

        struct in_addr inaddr;
        inaddr.s_addr = ifitem->ipv4addr;
        mreq.imr_address = inaddr;
        if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, &mreq, sizeof (mreq)))
        {
            OIC_LOG_V(ERROR, TAG, "send IP_MULTICAST_IF failed: %s (using defualt)",
                    strerror(errno));
        }
        sendData(fd, endpoint, data, datalen, "multicast", "ipv4");
    }
}

void CAIPSendData(CAEndpoint_t *endpoint, const void *data, uint32_t datalen,
                  bool isMulticast)
{
    VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL");
    VERIFY_NON_NULL_VOID(data, TAG, "data is NULL");

    bool isSecure = (endpoint->flags & CA_SECURE) != 0;

    if (isMulticast)
    {
        endpoint->port = isSecure ? CA_SECURE_COAP : CA_COAP;

        u_arraylist_t *iflist = CAIPGetInterfaceInformation(0);
        if (!iflist)
        {
            OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno));
            return;
        }

        if ((endpoint->flags & CA_IPV6) && caglobals.ip.ipv6enabled)
        {
            sendMulticastData6(iflist, endpoint, data, datalen);
        }
        if ((endpoint->flags & CA_IPV4) && caglobals.ip.ipv4enabled)
        {
            sendMulticastData4(iflist, endpoint, data, datalen);
        }

        u_arraylist_destroy(iflist);
    }
    else
    {
        if (!endpoint->port)    // unicast discovery
        {
            endpoint->port = isSecure ? CA_SECURE_COAP : CA_COAP;
        }

        int fd;
        if (caglobals.ip.ipv6enabled && (endpoint->flags & CA_IPV6))
        {
            fd = isSecure ? caglobals.ip.u6s.fd : caglobals.ip.u6.fd;
#ifndef __WITH_DTLS__
            fd = caglobals.ip.u6.fd;
#endif
            sendData(fd, endpoint, data, datalen, "unicast", "ipv6");
        }
        if (caglobals.ip.ipv4enabled && (endpoint->flags & CA_IPV4))
        {
            fd = isSecure ? caglobals.ip.u4s.fd : caglobals.ip.u4.fd;
#ifndef __WITH_DTLS__
            fd = caglobals.ip.u4.fd;
#endif
            sendData(fd, endpoint, data, datalen, "unicast", "ipv4");
        }
    }
}
예제 #17
0
static void applyMulticastToInterface4(struct in_addr inaddr)
{
    if (!caglobals.ip.ipv4enabled)
    {
        return;
    }

    struct ip_mreqn mreq = { .imr_multiaddr = IPv4MulticastAddress,
                             .imr_address = inaddr,
                             .imr_ifindex = 0 };
    if (setsockopt(caglobals.ip.m4.fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof (mreq)))
    {
        if (EADDRINUSE != errno)
        {
            OIC_LOG_V(ERROR, TAG, "IPv4 IP_ADD_MEMBERSHIP failed: %s", strerror(errno));
        }
    }
    if (setsockopt(caglobals.ip.m4s.fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof (mreq)))
    {
        if (EADDRINUSE != errno)
        {
            OIC_LOG_V(ERROR, TAG, "secure IPv4 IP_ADD_MEMBERSHIP failed: %s", strerror(errno));
        }
    }
}

static void applyMulticast6(int fd, struct in6_addr *addr, uint32_t interface)
{
    struct ipv6_mreq mreq = {.ipv6mr_multiaddr = *addr, .ipv6mr_interface = interface};

    if (setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof (mreq)))
    {
        if (EADDRINUSE != errno)
        {
            OIC_LOG_V(ERROR, TAG, "IPv6 IP_ADD_MEMBERSHIP failed: %s", strerror(errno));
        }
    }
}

static void applyMulticastToInterface6(uint32_t interface)
{
    if (!caglobals.ip.ipv6enabled)
    {
        return;
    }
    //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressInt, interface);
    applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressLnk, interface);
    //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressRlm, interface);
    //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressAdm, interface);
    //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressSit, interface);
    //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressOrg, interface);
    //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressGlb, interface);

    //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressInt, interface);
    applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressLnk, interface);
    //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressRlm, interface);
    //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressAdm, interface);
    //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressSit, interface);
    //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressOrg, interface);
    //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressGlb, interface);
}

CAResult_t CAIPStartListenServer()
{
    u_arraylist_t *iflist = CAIPGetInterfaceInformation(0);
    if (!iflist)
    {
        OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno));
        return CA_STATUS_FAILED;
    }

    uint32_t len = u_arraylist_length(iflist);
    OIC_LOG_V(DEBUG, TAG, "IP network interfaces found: %d", len);

    for (uint32_t i = 0; i < len; i++)
    {
        CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);

        if (!ifitem)
        {
            continue;
        }
        if ((ifitem->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
        {
            continue;
        }
        if (ifitem->family == AF_INET)
        {
            struct in_addr inaddr;
            inaddr.s_addr = ifitem->ipv4addr;
            applyMulticastToInterface4(inaddr);
            OIC_LOG_V(DEBUG, TAG, "IPv4 network interface: %s", ifitem->name);
        }
        if (ifitem->family == AF_INET6)
        {
            applyMulticastToInterface6(ifitem->index);
            OIC_LOG_V(DEBUG, TAG, "IPv6 network interface: %s", ifitem->name);
        }
    }

    u_arraylist_destroy(iflist);
    return CA_STATUS_OK;
}

CAResult_t CAIPStopListenServer()
{
    u_arraylist_t *iflist = CAIPGetInterfaceInformation(0);
    if (!iflist)
    {
        OIC_LOG_V(ERROR, TAG, "Get interface info failed: %s", strerror(errno));
        return CA_STATUS_FAILED;
    }

    uint32_t len = u_arraylist_length(iflist);
    OIC_LOG_V(DEBUG, TAG, "IP network interfaces found: %d", len);

    for (uint32_t i = 0; i < len; i++)
    {
        CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);

        if (!ifitem)
        {
            continue;
        }

        if ((ifitem->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
        {
            continue;
        }
        if (ifitem->family == AF_INET)
        {
            close(caglobals.ip.m4.fd);
            close(caglobals.ip.m4s.fd);
            caglobals.ip.m4.fd = -1;
            caglobals.ip.m4s.fd = -1;
            OIC_LOG_V(DEBUG, TAG, "IPv4 network interface: %s cloed", ifitem->name);
        }
        if (ifitem->family == AF_INET6)
        {
            close(caglobals.ip.m6.fd);
            close(caglobals.ip.m6s.fd);
            caglobals.ip.m6.fd = -1;
            caglobals.ip.m6s.fd = -1;
            OIC_LOG_V(DEBUG, TAG, "IPv6 network interface: %s", ifitem->name);
        }
    }
    u_arraylist_destroy(iflist);
    return CA_STATUS_OK;
}

static void CAProcessNewInterface(CAInterface_t *ifitem)
{
    if (!ifitem)
    {
        OIC_LOG(DEBUG, TAG, "ifitem is null");
        return;
    }
    if (ifitem->family == AF_INET6)
    {
        applyMulticastToInterface6(ifitem->index);
    }
    if (ifitem->family == AF_INET)
    {
        struct in_addr inaddr = { .s_addr = ifitem->ipv4addr };
        applyMulticastToInterface4(inaddr);
    }
}

void CAIPSetPacketReceiveCallback(CAIPPacketReceivedCallback callback)
{
    g_packetReceivedCallback = callback;
}

void CAIPSetConnectionStateChangeCallback(CAIPConnectionStateChangeCallback callback)
{
    CAIPSetNetworkMonitorCallback(callback);
}

static void sendData(int fd, const CAEndpoint_t *endpoint,
                     const void *data, uint32_t dlen,
                     const char *cast, const char *fam)
{
    OIC_LOG(DEBUG, TAG, "IN");

    if (!endpoint)
    {
        OIC_LOG(DEBUG, TAG, "endpoint is null");
        if (g_ipErrorHandler)
        {
            g_ipErrorHandler(endpoint, data, dlen, CA_STATUS_INVALID_PARAM);
        }
        return;
    }

    char *secure = (endpoint->flags & CA_SECURE) ? "secure " : "";
    (void)secure;   // eliminates release warning
    struct sockaddr_storage sock;
    CAConvertNameToAddr(endpoint->addr, endpoint->port, &sock);

    socklen_t socklen;
    if (sock.ss_family == AF_INET6)
    {
        struct sockaddr_in6 *sock6 = (struct sockaddr_in6 *)&sock;
        if (!sock6->sin6_scope_id)
        {
            sock6->sin6_scope_id = endpoint->interface;
        }
        socklen = sizeof(struct sockaddr_in6);
    }
    else
    {
        socklen = sizeof(struct sockaddr_in);
    }

    ssize_t len = sendto(fd, data, dlen, 0, (struct sockaddr *)&sock, socklen);
    if (-1 == len)
    {
         // If logging is not defined/enabled.
        (void)cast;
        (void)fam;
        if (g_ipErrorHandler)
        {
            g_ipErrorHandler(endpoint, data, dlen, CA_SEND_FAILED);
        }
        OIC_LOG_V(ERROR, TAG, "%s%s %s sendTo failed: %s", secure, cast, fam, strerror(errno));
    }
    else
    {
        OIC_LOG_V(INFO, TAG, "%s%s %s sendTo is successful: %zd bytes", secure, cast, fam, len);
    }
}