使用 ndisuio 接收 ip 帧

receive ip frames using ndisuio

我正在为 Windows ce 编写 DHCP 客户端。在用套接字完成这一切之后,我意识到我无法从 ip 0.0.0.0 发送数据包,所以我发现我需要使用 NDISUIO。 谷歌搜索 NDISUIO 后,我可以发送工作的 DHCP 发现数据包,但我无法收到服务器响应(程序卡住等待数据包)。请注意,我可以在 wireshark 中看到它们。

int cUDP::Start()
{ 
    char MensajeLog[256];
    char buff[1024];
    TCHAR pDevName[1024];
    TCHAR pDevBuf[1024];
    PNDISUIO_QUERY_BINDING pQueryBinding;
    ULONG ulData;
    NDISUIO_SET_OID set_oid;
    //NDISUIO_QUERY_OID query_oid;

    //El ethernet type para el protocolo IP es 0x0800
    USHORT uEther                               =0x0800;


    //###########################################################

        if(m_hAdapter == INVALID_HANDLE_VALUE)
            m_hAdapter = CreateFile(                    
                                        NDISUIO_DEVICE_NAME,
                                        GENERIC_READ | GENERIC_WRITE,
                                        FILE_SHARE_READ | FILE_SHARE_WRITE,
                                        NULL,
                                        OPEN_EXISTING,
                                        FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
                                        INVALID_HANDLE_VALUE);

        if(m_hAdapter == INVALID_HANDLE_VALUE || m_hAdapter == NULL)
        {
            m_iLastError                = CUDP_SOCKET_ERROR;
            return 1;
        }

        pQueryBinding                   = (PNDISUIO_QUERY_BINDING) buff;
        pQueryBinding->BindingIndex     = 0;

        if(!DeviceIoControl(            m_hAdapter,
                                        IOCTL_NDISUIO_QUERY_BINDING,
                                        pQueryBinding,
                                        sizeof(NDISUIO_QUERY_BINDING),
                                        NULL,
                                        1024,
                                        &m_dwReturnedBytes,
                                        NULL))
        {
            CloseHandle(m_hAdapter);
            return 2;
        }
        else
        {
            memset(pDevName,0,1024);
            memcpy(pDevName,&buff[pQueryBinding->DeviceNameOffset], pQueryBinding->DeviceNameLength);
        }

        if(!DeviceIoControl(            m_hAdapter,
                                        IOCTL_NDISUIO_OPEN_DEVICE,
                                        pDevName,
                                        wcslen(pDevName)*sizeof(TCHAR),
                                        NULL,
                                        0,
                                        &m_dwReturnedBytes,
                                        NULL))
        {
            CloseHandle(m_hAdapter);
            return 3;
        }

        if(!DeviceIoControl(            m_hAdapter,
                                        IOCTL_NDISUIO_SET_ETHER_TYPE,
                                        &uEther,
                                        sizeof(uEther),
                                        NULL,
                                        0,
                                        &m_dwReturnedBytes,
                                        NULL))
        {
            CloseHandle(m_hAdapter);
            return 5;
        }

        ulData = NDIS_PACKET_TYPE_ALL_LOCAL|NDIS_PACKET_TYPE_BROADCAST|NDIS_PACKET_TYPE_PROMISCUOUS;
        set_oid.Oid                     = OID_GEN_CURRENT_PACKET_FILTER;

        CopyMemory(&set_oid.Data[0], &ulData,sizeof(ulData));
        set_oid.ptcDeviceName           = pDevName;

        if(!DeviceIoControl(            m_hAdapter,
                                        IOCTL_NDISUIO_SET_OID_VALUE,
                                        &set_oid,
                                        sizeof(set_oid),
                                        NULL,
                                        0,
                                        &m_dwReturnedBytes,
                                        NULL))
        {
            CloseHandle(m_hAdapter);
            return 6;
        }

    return 0;
};

int cUDP::ReceiveFrame      (       BYTE*       pBuffer, 
                                    DWORD       Timeout_ms )
{
    int     timeout;
    int     timepoint;
    DWORD   pdwReadBytes;

    socklen_t SendAddrlen           = sizeof(m_SendAddr);
    int BufferLen                   = sizeof(IPHeaderFormat) +
                                      sizeof(UDPHeaderFormat) +
                                      sizeof (DHCPMsgFormat);//sizeof (DHCPMsgFormat);


    timepoint                       = GetTickCount();
    do
    {
        timeout                     = GetTickCount();

                    {
            if(!ReadFile(           m_hAdapter,
                                    pBuffer,
                                    0,
                                    NULL,
                                    NULL))

            {
                m_iLastError        = CUDP_RECEIVING_ERROR;

            }
        }

    }while(((unsigned) (timeout - timepoint) < Timeout_ms));

    return m_iLastError;
};

任何人都可以把我推向正确的方向吗?提前致谢

经过大量阅读和搜索,我发现问题出在使用 IOCTL_NDISUIO_SET_ETHER_TYPE 调用 DeviceIoControl 时。事实证明,uEther 必须采用网络字节顺序,因此将此变量更改为 uEther = 0x0008; 即可。