Example #1
0
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);
}
Example #2
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);
    }
}
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);
    }
}