carmwindows-cedhcpndis

receive ip frames using ndisuio


I'm writing a DHCP client for Windows ce. after doing it all with sockets I realized that I coudn't send packets from ip 0.0.0.0 so I found that I need to use NDISUIO. After googling about NDISUIO I can send working DHCP Discovery Packets BUT I can't receive the server response ( the program gets stuck waiting for packets). Note that I can see them in 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;
};

Anyone can push me in the right direction? thanks in advance


Solution

  • After reading and searching a lot, I found that the problem was on the call to DeviceIoControl with IOCTL_NDISUIO_SET_ETHER_TYPE. It turns out that uEther must be in network byte order so changing this variable to uEther = 0x0008; will do the trick.