使用ndisuio接收ip帧

时间:2017-10-02 06:17:50

标签: c arm windows-ce dhcp ndis

我正在为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;
};

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

1 个答案:

答案 0 :(得分:1)

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