static CAResult_t CAReceiveMessage(int fd, CATransportFlags_t flags)
{
    char recvBuffer[COAP_MAX_PDU_SIZE];

    struct sockaddr_storage srcAddr;
    socklen_t srcAddrLen = sizeof (srcAddr);

    ssize_t recvLen = recvfrom(fd,
                               recvBuffer,
                               sizeof (recvBuffer),
                               0,
                               (struct sockaddr *)&srcAddr,
                               &srcAddrLen);
    if (-1 == recvLen)
    {
        OIC_LOG_V(ERROR, TAG, "Recvfrom failed %s", strerror(errno));
        return CA_STATUS_FAILED;
    }

    CASecureEndpoint_t sep =
    {.endpoint = {.adapter = CA_ADAPTER_IP, .flags = flags}};

    if (flags & CA_IPV6)
    {
        sep.endpoint.interface = ((struct sockaddr_in6 *)&srcAddr)->sin6_scope_id;
        ((struct sockaddr_in6 *)&srcAddr)->sin6_scope_id = 0;
    }
    CAConvertAddrToName(&srcAddr, sep.endpoint.addr, &sep.endpoint.port);

    if (flags & CA_SECURE)
    {
#ifdef __WITH_DTLS__
        int ret = CAAdapterNetDtlsDecrypt(&sep, (uint8_t *)recvBuffer, recvLen);
        OIC_LOG_V(DEBUG, TAG, "CAAdapterNetDtlsDecrypt returns [%d]", ret);
#else
        OIC_LOG(ERROR, TAG, "Encrypted message but no DTLS");
#endif
    }
    else
    {
        if (g_packetReceivedCallback)
        {
            g_packetReceivedCallback(&sep, recvBuffer, recvLen);
        }
    }

    return CA_STATUS_OK;
}
Exemple #2
0
static CAResult_t CAReceiveMessage(int fd, CATransportFlags_t flags)
{
    char recvBuffer[COAP_MAX_PDU_SIZE];

    size_t len;
    int level, type, namelen;
    struct sockaddr_storage srcAddr;
    unsigned char *pktinfo = NULL;
    struct cmsghdr *cmp = NULL;
    struct iovec iov = { recvBuffer, sizeof (recvBuffer) };
    union control
    {
        struct cmsghdr cmsg;
        unsigned char data[CMSG_SPACE(sizeof (struct in6_pktinfo))];
    } cmsg;

    if (flags & CA_IPV6)
    {
        namelen = sizeof (struct sockaddr_in6);
        level = IPPROTO_IPV6;
        type = IPV6_PKTINFO;
        len = sizeof (struct in6_pktinfo);
    }
    else
    {
        namelen = sizeof (struct sockaddr_in);
        level = IPPROTO_IP;
        type = IP_PKTINFO;
        len = sizeof (struct in6_pktinfo);
    }

    struct msghdr msg = { .msg_name = &srcAddr,
                          .msg_namelen = namelen,
                          .msg_iov = &iov,
                          .msg_iovlen = 1,
                          .msg_control = &cmsg,
                          .msg_controllen = CMSG_SPACE(len) };

    ssize_t recvLen = recvmsg(fd, &msg, flags);
    if (-1 == recvLen)
    {
        OIC_LOG_V(ERROR, TAG, "Recvfrom failed %s", strerror(errno));
        return CA_STATUS_FAILED;
    }

    if (flags & CA_MULTICAST)
    {
        for (cmp = CMSG_FIRSTHDR(&msg); cmp != NULL; cmp = CMSG_NXTHDR(&msg, cmp))
        {
            if (cmp->cmsg_level == level && cmp->cmsg_type == type)
            {
                pktinfo = CMSG_DATA(cmp);
            }
        }
    }

    CASecureEndpoint_t sep = {.endpoint = {.adapter = CA_ADAPTER_IP, .flags = flags}};

    if (flags & CA_IPV6)
    {
        sep.endpoint.interface = ((struct sockaddr_in6 *)&srcAddr)->sin6_scope_id;
        ((struct sockaddr_in6 *)&srcAddr)->sin6_scope_id = 0;

        if ((flags & CA_MULTICAST) && pktinfo)
        {
            struct in6_addr *addr = &(((struct in6_pktinfo *)pktinfo)->ipi6_addr);
            unsigned char topbits = ((unsigned char *)addr)[0];
            if (topbits != 0xff)
            {
                sep.endpoint.flags &= ~CA_MULTICAST;
            }
        }
    }
    else
    {
        if ((flags & CA_MULTICAST) && pktinfo)
        {
            struct in_addr *addr = &((struct in_pktinfo *)pktinfo)->ipi_addr;
            uint32_t host = ntohl(addr->s_addr);
            unsigned char topbits = ((unsigned char *)&host)[3];
            if (topbits < 224 || topbits > 239)
            {
                sep.endpoint.flags &= ~CA_MULTICAST;
            }
        }
    }

    CAConvertAddrToName(&srcAddr, msg.msg_namelen, sep.endpoint.addr, &sep.endpoint.port);

    if (flags & CA_SECURE)
    {
#ifdef __WITH_DTLS__
        int ret = CAAdapterNetDtlsDecrypt(&sep, (uint8_t *)recvBuffer, recvLen);
        OIC_LOG_V(DEBUG, TAG, "CAAdapterNetDtlsDecrypt returns [%d]", ret);
#else
        OIC_LOG(ERROR, TAG, "Encrypted message but no DTLS");
#endif
    }
    else
    {
        if (g_packetReceivedCallback)
        {
            g_packetReceivedCallback(&sep, recvBuffer, recvLen);
        }
    }

    return CA_STATUS_OK;
}
Exemple #3
0
static void CAReceiveHandler(void *data)
{
    OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");

    fd_set readFds;
    int maxSd = 0;
    struct timeval timeout;
    char recvBuffer[COAP_MAX_PDU_SIZE] = { 0 };

    while (true != g_packetHandlerStopFlag)
    {
        timeout.tv_sec = 1;
        timeout.tv_usec = 0;
        FD_ZERO(&readFds);

        ca_mutex_lock(g_mutexServerInfoList);
        uint32_t listIndex = 0;
        uint32_t listLength = u_arraylist_length(g_serverInfoList);

        u_arraylist_t *tempServerInfoList = u_arraylist_create();
        if (!tempServerInfoList)
        {
            OIC_LOG(ERROR, IP_SERVER_TAG, "u_arraylist_create failed");
            ca_mutex_unlock(g_mutexServerInfoList);
            return;
        }

        for (listIndex = 0; listIndex < listLength; listIndex++)
        {
            CAServerInfo_t *info = (CAServerInfo_t *) u_arraylist_get(g_serverInfoList, listIndex);
            if (!info)
            {
                listIndex++;
                continue;
            }

            int sd = info->socketFd;
            //if valid socket descriptor then add to read list
            if (sd > 0)
            {
                FD_SET(sd, &readFds);
            }

            //highest file descriptor number, need it for the select function
            if (sd > maxSd)
            {
                maxSd = sd;
            }

            CAServerInfo_t *newInfo = (CAServerInfo_t *) OICMalloc(sizeof(CAServerInfo_t));
            if (!newInfo)
            {
                OIC_LOG(ERROR, IP_SERVER_TAG, "Malloc failed");
                CAClearServerInfoList(tempServerInfoList);
                ca_mutex_unlock(g_mutexServerInfoList);
                return;
            }

            *newInfo = *info;

            CAResult_t result = u_arraylist_add(tempServerInfoList, (void *) newInfo);
            if (CA_STATUS_OK != result)
            {
                OIC_LOG(ERROR, IP_SERVER_TAG, "u_arraylist_add failed!Thread exit");
                CAClearServerInfoList(tempServerInfoList);
                ca_mutex_unlock(g_mutexServerInfoList);
                return;
            }
        }

        ca_mutex_unlock(g_mutexServerInfoList);

        int ret = select(maxSd + 1, &readFds, NULL, NULL, &timeout);
        if (g_packetHandlerStopFlag)
        {
            OIC_LOG_V(DEBUG, IP_SERVER_TAG,
                      "Packet receiver handler Stop request received. Thread exited");
            CAClearServerInfoList(tempServerInfoList);
            break;
        }
        if (ret < 0)
        {
            OIC_LOG_V(FATAL, IP_SERVER_TAG, "select returned error %s", strerror(errno));
            CAClearServerInfoList(tempServerInfoList);
            continue;
        }

        listLength = u_arraylist_length(tempServerInfoList);
        for (listIndex = 0; listIndex < listLength; listIndex++)
        {
            CAServerInfo_t *info = (CAServerInfo_t *) u_arraylist_get(tempServerInfoList,
                                                                      listIndex);
            if (!info)
            {
                continue;
            }

            int sd = info->socketFd;
            if (FD_ISSET(sd , &readFds))
            {
                OIC_LOG_V(ERROR, IP_SERVER_TAG,
                          "data Received server information ip %s, port %d socket %d",
                          info->endpoint.addr, info->endpoint.port, sd);
                memset(recvBuffer, 0, sizeof(recvBuffer));

                struct sockaddr_in srcSockAddress = { 0 };
                socklen_t srcAddressLen = sizeof(srcSockAddress);

                //Reading from socket
                ssize_t recvLen = recvfrom(sd, recvBuffer, sizeof(recvBuffer), 0,
                                           (struct sockaddr *) &srcSockAddress, &srcAddressLen);
                if (-1 == recvLen)
                {
                    OIC_LOG_V(ERROR, IP_SERVER_TAG, "Recvfrom failed %s", strerror(errno));
                    continue;
                }
                else if (0 == recvLen)
                {
                    OIC_LOG_V(ERROR, IP_SERVER_TAG, "Server socket shutdown sock fd[%d]", sd);
                    ca_mutex_lock(g_mutexAdapterServerContext);
                    // Notify upper layer this exception
                    if (g_adapterIPServerContext->exceptionCallback)
                    {
                        // need to make proper exception callback.
                        //g_adapterIPServerContext->exceptionCallback(ctx->type);
                    }
                    ca_mutex_unlock(g_mutexAdapterServerContext);
                }

                char srcIPAddress[CA_IPADDR_SIZE] = { 0 };
                if (!inet_ntop(AF_INET, &srcSockAddress.sin_addr.s_addr, srcIPAddress,
                               sizeof(srcIPAddress)))
                {

                    OIC_LOG(ERROR, IP_SERVER_TAG, "inet_ntop is failed!");
                    continue;
                }

                uint16_t srcPort = ntohs(srcSockAddress.sin_port);

                OIC_LOG_V(DEBUG, IP_SERVER_TAG, "Received packet from %s:%d len %d",
                          srcIPAddress, srcPort, recvLen);

                char *netMask = NULL;
                if (CA_STATUS_OK != CAIPGetInterfaceSubnetMask(info->ifAddr, &netMask))
                {
                    OIC_LOG(ERROR, IP_SERVER_TAG, "Failed to get IP subnet");
                    continue;
                }

                if (!CAAdapterIsSameSubnet(info->ifAddr, srcIPAddress, netMask))
                {
                    OIC_LOG(DEBUG, IP_SERVER_TAG,
                            "Packet received from different subnet, Ignore!");
                    OICFree(netMask);
                    continue;
                }
                OICFree(netMask);

                CAEndpoint_t ep;
                strncpy(ep.addr, srcIPAddress, MAX_ADDR_STR_SIZE_CA);
                ep.port = srcPort;
                ep.flags = (CATransportFlags_t)CA_IPV4 | CA_IPV6;
                ep.adapter = CA_ADAPTER_IP;

                if (info->endpoint.flags & CA_SECURE)
                {
#ifdef __WITH_DTLS__
                    ep.flags |= CA_SECURE;
                    (void)CAAdapterNetDtlsDecrypt(&ep, (uint8_t *)recvBuffer, recvLen);
                    OIC_LOG_V(DEBUG, IP_SERVER_TAG,
                              "CAAdapterNetDtlsDecrypt returns [%d]", ret);
#endif
                }
                else //both multicast and unicast
                {
                    ca_mutex_lock(g_mutexAdapterServerContext);

                    if (g_adapterIPServerContext->packetReceivedCallback)
                    {
                        g_adapterIPServerContext->packetReceivedCallback(&ep,
                                                          recvBuffer, recvLen);
                    }

                    ca_mutex_unlock(g_mutexAdapterServerContext);
                }
            }
        }
        CAClearServerInfoList(tempServerInfoList);
    }
    OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
}