【问题标题】:WSASendMsg return error if set UDP source address如果设置了 UDP 源地址,WSASendMsg 返回错误
【发布时间】:2020-08-04 12:27:26
【问题描述】:

类似于:Howto set the UDP source address on Windows 这对我不起作用。无法设置源端口并出现错误:

我已经创建了套接字:

bool CUDPTransport::OpenConnection(void) {
    // Create UDP socket
    this->m_hSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (this->m_hSocket == INVALID_SOCKET) {
        return false;
    }

    // Success
    return true;
}

我可以通过 UDP 传输发送:

bool CUDPTransport::SendMessage(const CString& sBuffer, const CSyslogOptions& oSyslogOptions) {
    // Convert using the local code page
    CT2A sASCII(sBuffer);

    // Create address
    struct sockaddr_in sin;
    memset(&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_port = htons(this->m_nPort);
    sin.sin_addr.s_addr = htonl(this->m_nCollectorIPv4);

    // Create buffer to send
    WSABUF oBuffer;
    oBuffer.buf = sASCII.m_psz;
    oBuffer.len = (int)strlen(sASCII.m_psz);

    // Declare
    char aControlData[WSA_CMSG_SPACE(sizeof(struct in_pktinfo))];
    memset(&aControlData, 0, sizeof(aControlData));

    // Create a message
    WSAMSG oMessage;
    memset(&oMessage, 0, sizeof(oMessage));
    oMessage.name = (struct sockaddr*)&sin;
    oMessage.namelen = sizeof(sin);
    oMessage.lpBuffers = &oBuffer;
    oMessage.dwBufferCount = 1;
    /* TODO: set source address
    oMessage.Control.buf = (char*)&aControlData;
    oMessage.Control.len = sizeof(aControlData);

    // Create messge header
    WSACMSGHDR* oHeader = WSA_CMSG_FIRSTHDR(&oMessage);
    // memset(oHeader, 0, WSA_CMSG_SPACE(sizeof(struct in_pktinfo)));
    oHeader->cmsg_level = IPPROTO_IP;
    oHeader->cmsg_type = IP_PKTINFO;
    oHeader->cmsg_len = WSA_CMSG_LEN(sizeof(struct in_pktinfo));
    struct in_pktinfo* pktinfo = (struct in_pktinfo*)WSA_CMSG_DATA(oHeader);
    pktinfo->ipi_addr.s_addr = htonl(oSyslogOptions.m_nSenderIPv4);
    */

    // Declare variable
    unsigned long nSentBytes = 0;

    // Send an initial buffer
    int nResult = WSASendMsg(this->m_hSocket, &oMessage, 0, &nSentBytes, NULL, NULL);
    if (nResult == SOCKET_ERROR) {
        int nErrorNo = this->getSocketLastOSErrorNo();
        CString sErrorMsg = this->getSocketLastOSErrorString(nErrorNo);
        closesocket(this->m_hSocket);
        return false;
    }
    return true;
}

当我希望设置源 IP 地址时,我取消注释使用控制数据

bool CUDPTransport::SendMessage(const CString& sBuffer, const CSyslogOptions& oSyslogOptions) {
    // Convert using the local code page
    CT2A sASCII(sBuffer);

    // Create address
    struct sockaddr_in sin;
    memset(&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_port = htons(this->m_nPort);
    sin.sin_addr.s_addr = htonl(this->m_nCollectorIPv4);

    // Create buffer to send
    WSABUF oBuffer;
    oBuffer.buf = sASCII.m_psz;
    oBuffer.len = (int)strlen(sASCII.m_psz);

    // Declare
    char aControlData[WSA_CMSG_SPACE(sizeof(struct in_pktinfo))];
    memset(&aControlData, 0, sizeof(aControlData));

    // Create a message
    WSAMSG oMessage;
    memset(&oMessage, 0, sizeof(oMessage));
    oMessage.name = (struct sockaddr*)&sin;
    oMessage.namelen = sizeof(sin);
    oMessage.lpBuffers = &oBuffer;
    oMessage.dwBufferCount = 1;
    oMessage.Control.buf = (char*)&aControlData;
    oMessage.Control.len = sizeof(aControlData);

    // Create messge header
    WSACMSGHDR* oHeader = WSA_CMSG_FIRSTHDR(&oMessage);
    // memset(oHeader, 0, WSA_CMSG_SPACE(sizeof(struct in_pktinfo)));
    oHeader->cmsg_level = IPPROTO_IP;
    oHeader->cmsg_type = IP_PKTINFO;
    oHeader->cmsg_len = WSA_CMSG_LEN(sizeof(struct in_pktinfo));
    struct in_pktinfo* pktinfo = (struct in_pktinfo*)WSA_CMSG_DATA(oHeader);
    pktinfo->ipi_addr.s_addr = htonl(oSyslogOptions.m_nSenderIPv4);

    // Declare variable
    unsigned long nSentBytes = 0;

    // Send an initial buffer
    int nResult = WSASendMsg(this->m_hSocket, &oMessage, 0, &nSentBytes, NULL, NULL);
    if (nResult == SOCKET_ERROR) {
        int nErrorNo = this->getSocketLastOSErrorNo();
        CString sErrorMsg = this->getSocketLastOSErrorString(nErrorNo);
        closesocket(this->m_hSocket);
        return false;
    }
    return true;
}

并得到错误,错误号:10022 和消息:“提供了一个无效的参数”。有人可以帮我理解这个问题吗?谢谢!

【问题讨论】:

  • WSASendMsg: "s参数中的socket描述符必须在socket类型设置为SOCK_DGRAM或者SOCK_RAW的情况下打开。"你是这样做的吗?
  • 是的,“this->m_hSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)”。 SOCK_DGRAM

标签: c++ windows networking udp


【解决方案1】:

-1.绑定解决的错误:

bool CUDPTransport::OpenConnection(void) {
    // Create UDP socket
    this->m_hSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (this->m_hSocket == INVALID_SOCKET) {
        return false;
    }

    // Create source address (2130706433 =  127.0.0.1)
    struct sockaddr_in sin;
    memset(&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_port = 0;
    sin.sin_addr.s_addr = htonl(2130706433);

    // Bind socker
    int nResult = bind(this->m_hSocket, (struct sockaddr*)&sin, sizeof(sin));
    if (nResult == SOCKET_ERROR) {
        int nErrorNo = this->getSocketLastOSErrorNo();
        CString sErrorMsg = this->getSocketLastOSErrorString(nErrorNo);
        closesocket(this->m_hSocket);
        return false;
    }


    // Success
    return true;
}

-2.Send 方法工作正常。

bool CUDPTransport::SendMessage(const CString& sBuffer, const CSyslogOptions& oSyslogOptions) {

    // Convert using the local code page
    CT2A sASCII(sBuffer);

    // Create address
    struct sockaddr_in sin;
    memset(&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_port = htons(this->m_nPort);
    sin.sin_addr.s_addr = htonl(this->m_nCollectorIPv4);

    // Create buffer to send
    WSABUF oBuffer;
    oBuffer.buf = sASCII.m_psz;
    oBuffer.len = (int)strlen(sASCII.m_psz);

    // Declare
    char aControlData[WSA_CMSG_SPACE(sizeof(struct in_pktinfo))];
    memset(&aControlData, 0, sizeof(aControlData));

    // Create a message
    WSAMSG oMessage;
    memset(&oMessage, 0, sizeof(oMessage));
    oMessage.name = (struct sockaddr*)&sin;
    oMessage.namelen = sizeof(sin);
    oMessage.lpBuffers = &oBuffer;
    oMessage.dwBufferCount = 1;
    oMessage.Control.buf = (char*)&aControlData;
    oMessage.Control.len = sizeof(aControlData);

    // Create message header
    WSACMSGHDR* oHeader = WSA_CMSG_FIRSTHDR(&oMessage);
    memset(oHeader, 0, WSA_CMSG_SPACE(sizeof(struct in_pktinfo)));
    oHeader->cmsg_level = IPPROTO_IP;
    oHeader->cmsg_type = IP_PKTINFO;
    oHeader->cmsg_len = WSA_CMSG_LEN(sizeof(struct in_pktinfo));
    struct in_pktinfo* pktinfo = (struct in_pktinfo*)WSA_CMSG_DATA(oHeader);
    pktinfo->ipi_addr.s_addr = htonl(oSyslogOptions.m_nSenderIPv4);

    // Declare variable
    unsigned long nSentBytes = 0;

    // Send an initial buffer
    int nResult = WSASendMsg(this->m_hSocket, &oMessage, 0, &nSentBytes, NULL, NULL);
    if (nResult == SOCKET_ERROR) {
        int nErrorNo = this->getSocketLastOSErrorNo();
        CString sErrorMsg = this->getSocketLastOSErrorString(nErrorNo);
        closesocket(this->m_hSocket);
        return false;
    }
    return true;
}

-3.但是由于https://security.stackexchange.com/questions/184001/is-ip-spoofing-possible-in-windows-desktop-with-user-privileges导致源ip地址没有改变

【讨论】:

    猜你喜欢
    • 2013-03-17
    • 1970-01-01
    • 1970-01-01
    • 2015-08-26
    • 2011-08-10
    • 2013-01-06
    • 2012-03-02
    • 2021-01-24
    • 1970-01-01
    相关资源
    最近更新 更多