Example #1
0
BOOL ProcessIpv6Msg(LPWSAMSG pWSAMsg)
{
    PWSACMSGHDR pCtrlInfo = NULL;
    PIN6_PKTINFO pPktInfo = NULL;

    pCtrlInfo = WSA_CMSG_FIRSTHDR(pWSAMsg);

    if ((IPPROTO_IPV6 == pCtrlInfo->cmsg_level) &&
            (IPV6_PKTINFO == pCtrlInfo->cmsg_type))
    {
        pPktInfo = (PIN6_PKTINFO)WSA_CMSG_DATA(pCtrlInfo);

        //do something with pPktInfo

        return TRUE;

    }

    return FALSE;
}
int MDDSocket_Recvfrom(MDDSocket_t sockets, unsigned char *buf, int buf_len, MDDSocketAddr_t *from, MDDIface_t *iface)
{
    struct sockaddr_in sa;
    struct sockaddr_in6 sa6;

    WSAMSG msg;
    WSABUF io;
    char aux[1024];
    DWORD recv_len = 0;

    if (sockets == INVALID_SOCKET) {
        return MDD_ERROR;
    }

    io.buf = (CHAR *)buf;
    io.len = buf_len;

    SecureZeroMemory (&msg, sizeof(msg));
    msg.lpBuffers = &io;
    msg.dwBufferCount = 1;
    msg.dwFlags = 0;
    msg.Control.buf = aux;
    msg.Control.len = sizeof(aux);

    if (from->family == MDDNet_INET) {
        msg.name = (LPSOCKADDR)&sa;
        msg.namelen = sizeof(sa);
    } else if (from->family == MDDNet_INET6) {
        msg.name = (LPSOCKADDR)&sa6;
        msg.namelen = sizeof(sa6);
    } else {
        LOG_ERROR("MDDSocket_Recvfrom error, need to specific family on from address\n");
        return MDD_ERROR;
    }

    if (SOCKET_ERROR == fpWSARecvMsg(sockets,
                                   &msg,
                                   &recv_len,
                                   NULL,
                                   NULL))
    {
        if (WSAGetLastError() != WSAEWOULDBLOCK)
        {
            LOG_ERROR("MDDSocket_Recvfrom fatal error, error: %d\n", WSAGetLastError());
            return MDD_ERROR;
        }

        return 0;
    }
    else {
        WSACMSGHDR *cmsg;

        if (from->family == MDDNet_INET) {
            from->port = sa.sin_port;
            from->addr.ip.ipv4 = (unsigned long int)sa.sin_addr.s_addr;
        } else if (from->family == MDDNet_INET6) {
            from->port = sa6.sin6_port;
            memcpy(from->addr.ip.ipv6, sa6.sin6_addr.u.Word, 16);
        }

        for (cmsg = WSA_CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = WSA_CMSG_NXTHDR(&msg, cmsg)) {
            if (cmsg->cmsg_level == IPPROTO_IP) {
                switch (cmsg->cmsg_type) {
                    case IP_TTL:
                        LOG_TRACE("MDDSocket_Recvfrom got ttl: %d\n", (*(int *) WSA_CMSG_DATA(cmsg)));
                        break;

                    case IP_PKTINFO: {
                        PIN_PKTINFO i = (PIN_PKTINFO) WSA_CMSG_DATA(cmsg);

                        LOG_TRACE("MDDSocket_Recvfrom got ifindex: %d\n", i->ipi_ifindex);
                        if (iface != NULL) {
                            iface->ifindex = i->ipi_ifindex;
                            iface->addr.family = MDDNet_INET;
                            iface->addr.ip.ipv4 = i->ipi_addr.S_un.S_addr;
                        }
                        break;
                    }

                    default:
                        LOG_DEBUG("Unhandled cmsg_type: %d", cmsg->cmsg_type);
                        break;
                }
            } else if (cmsg->cmsg_level == IPPROTO_IPV6) {
                switch (cmsg->cmsg_type) {
                    case IPV6_HOPLIMIT:
                        LOG_TRACE("MDDSocket_Recvfrom got ttl: %d\n", (*(int *) WSA_CMSG_DATA(cmsg)));
                        break;

                    case IPV6_PKTINFO: {
                        PIN6_PKTINFO i = (PIN6_PKTINFO) WSA_CMSG_DATA(cmsg);

                        LOG_TRACE("MDDSocket_Recvfrom got ifindex: %d\n", i->ipi6_ifindex);
                        if (iface != NULL) {
                            iface->ifindex = i->ipi6_ifindex;
                            iface->addr.family = MDDNet_INET6;
                            memcpy(iface->addr.ip.ipv6, i->ipi6_addr.u.Byte, 16);
                        }
                        break;
                    }

                    default:
                        LOG_DEBUG("Unhandled cmsg_type: %d", cmsg->cmsg_type);
                        break;
                }
            }
        }
        LOG_TRACE("MDDSocket_Recvfrom recv_len: %d\n", recv_len);
        return recv_len;
    }
}
int MDDSocket_Sendto(MDDSocket_t socket, unsigned char *buf, int buf_len, MDDSocketAddr_t *to, MDDIface_t *iface)
{
    struct sockaddr_in sa;
    struct sockaddr_in6 sa6;

    WSAMSG msg;
    WSABUF io;

    DWORD sent_len = 0;
    INT nRet = 0;

    if (socket == INVALID_SOCKET) {
        return MDD_ERROR;
    }

    SecureZeroMemory(&io, sizeof(io));
    io.buf = (char *)buf;
    io.len = buf_len;

    SecureZeroMemory (&msg, sizeof(msg));
    msg.lpBuffers = &io;
    msg.dwBufferCount = 1;
    msg.dwFlags = 0;

    if (to->family == MDDNet_INET) {
        memset(&sa, 0, sizeof(sa));
        sa.sin_family = AF_INET;
        sa.sin_port = to->port;
        sa.sin_addr.s_addr = to->addr.ip.ipv4;

        msg.name = (LPSOCKADDR)(&sa);
        msg.namelen = sizeof(sa);
    } else if (to->family == MDDNet_INET6) {
        memset(&sa6, 0, sizeof(sa6));
        sa6.sin6_family = AF_INET6;
        sa6.sin6_port = to->port;
        memcpy(sa6.sin6_addr.s6_addr, to->addr.ip.ipv6, 16);

        msg.name = (LPSOCKADDR)(&sa6);
        msg.namelen = sizeof(sa6);
    } else {
        return MDD_ERROR;
    }

    if (iface != NULL && iface->ifindex > 0) {
        if (to->family == MDDNet_INET) {
            PIN_PKTINFO pkti;
            WSACMSGHDR *cmsg;
            char in[WSA_CMSG_SPACE(sizeof(struct in_pktinfo))];
            int sum = 0;

            memset(in, 0, sizeof(in));

            msg.Control.buf = (char *)∈
            msg.Control.len = sizeof(in);
            
            cmsg = WSA_CMSG_FIRSTHDR(&msg);
            memset(cmsg, 0, WSA_CMSG_SPACE(sizeof(struct in_pktinfo)));
            cmsg->cmsg_level = IPPROTO_IP;
            cmsg->cmsg_type = IP_PKTINFO;
            
            cmsg->cmsg_len = WSA_CMSG_LEN(sizeof(struct in_pktinfo));

            pkti = (PIN_PKTINFO) WSA_CMSG_DATA(cmsg);

            if (iface->ifindex > 0)
            {
                pkti->ipi_ifindex = iface->ifindex;
                pkti->ipi_addr.S_un.S_addr = iface->addr.ip.ipv4;
                // [email protected], 2012/07/24, workaround to resolve can't sent in release mode. DO NOT remove this printf until find solution
                printf("");
            }

            sum += WSA_CMSG_SPACE(sizeof(struct in_pktinfo));

            msg.Control.len = sum;
        } else if (to->family == MDDNet_INET6) {
            PIN6_PKTINFO pkti;
            WSACMSGHDR *cmsg;
            char in[WSA_CMSG_SPACE(sizeof(struct in6_pktinfo))];
            int sum = 0;

            memset(in, 0, sizeof(in));

            msg.Control.buf = (char *)∈
            msg.Control.len = sizeof(in);

            cmsg = WSA_CMSG_FIRSTHDR(&msg);
            memset(cmsg, 0, WSA_CMSG_SPACE(sizeof(struct in6_pktinfo)));
            cmsg->cmsg_level = IPPROTO_IPV6;
            cmsg->cmsg_type = IPV6_PKTINFO;

            cmsg->cmsg_len = WSA_CMSG_LEN(sizeof(struct in6_pktinfo));

            pkti = (PIN6_PKTINFO) WSA_CMSG_DATA(cmsg);

            if (iface->ifindex > 0)
            {
                pkti->ipi6_ifindex = iface->ifindex;
                memcpy(&pkti->ipi6_addr.u.Byte, iface->addr.ip.ipv6, 16);
                // [email protected], 2012/07/24, workaround to resolve can't sent in release mode. DO NOT remove this printf until find solution
                printf("");
            }

            sum += WSA_CMSG_SPACE(sizeof(struct in6_pktinfo));

            msg.Control.len = sum;
        }
    }

    if (SOCKET_ERROR == (nRet = fpWSASendMsg(socket,
                                           &msg,
                                           0,
                                           &sent_len,
                                           NULL,
                                           NULL)))
    {
        LOG_ERROR("MDDSocket_Sendto by WSASendMsg error %d\n", WSAGetLastError());
        return MDD_ERROR;
    } else {
        return sent_len;
    }
}