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
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.