You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
872 lines
21 KiB
872 lines
21 KiB
/*++
|
|
|
|
Copyright (C) 1999-2002 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
isdhcp.c
|
|
|
|
Abstract:
|
|
|
|
test program to see if a DHCP server is around or not.
|
|
|
|
Environment:
|
|
|
|
Win2K+
|
|
|
|
History:
|
|
|
|
Code provided by JRuan on May 8, 2002 and integrated into
|
|
CYS by JeffJon
|
|
|
|
--*/
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <windows.h>
|
|
#include <winsock2.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <time.h>
|
|
#include <dhcpcapi.h>
|
|
#include <iprtrmib.h>
|
|
#include <iphlpapi.h>
|
|
#include <stdio.h>
|
|
|
|
#define OPTION_PAD 0
|
|
#define OPTION_HOST_NAME 12
|
|
#define OPTION_MESSAGE_TYPE 53
|
|
#define OPTION_SERVER_IDENTIFIER 54
|
|
#define OPTION_PARAMETER_REQUEST_LIST 55
|
|
#define OPTION_CLIENT_ID 61
|
|
#define OPTION_END 255
|
|
|
|
#define DHCP_CLIENT_PORT 68
|
|
#define DHCP_SERVR_PORT 67
|
|
|
|
BYTE HardwareAddress[16];
|
|
BYTE HardwareAddressLength = 6;
|
|
#define SOCKET_RECEIVE_BUFFER_SIZE 1024 * 4 // 4K max.
|
|
#define AUTH_SERVERS_MAX 64
|
|
#define SMALL_BUFFER_SIZE 32
|
|
#define ALERT_INTERVAL 5 * 60 // 5 mins
|
|
#define ALERT_MESSAGE_LENGTH 256
|
|
#define MAX_ALERT_NAMES 256
|
|
|
|
#define BOOT_REQUEST 1
|
|
#define DHCP_BROADCAST 0x8000
|
|
#define DHCP_DISCOVER_MESSAGE 1
|
|
#define DHCP_INFORM_MESSAGE 8
|
|
|
|
#define DHCP_MESSAGE_SIZE 576
|
|
#define DHCP_RECV_MESSAGE_SIZE 4096
|
|
|
|
#define BOOT_FILE_SIZE 128
|
|
#define BOOT_SERVER_SIZE 64
|
|
#define DHCP_MAGIC_COOKIE_BYTE1 99
|
|
#define DHCP_MAGIC_COOKIE_BYTE2 130
|
|
#define DHCP_MAGIC_COOKIE_BYTE3 83
|
|
#define DHCP_MAGIC_COOKIE_BYTE4 99
|
|
|
|
#include <packon.h>
|
|
typedef struct _OPTION {
|
|
BYTE OptionType;
|
|
BYTE OptionLength;
|
|
BYTE OptionValue[1];
|
|
} OPTION, *POPTION, *LPOPTION;
|
|
typedef struct _DHCP_MESSAGE {
|
|
BYTE Operation;
|
|
BYTE HardwareAddressType;
|
|
BYTE HardwareAddressLength;
|
|
BYTE HopCount;
|
|
DWORD TransactionID;
|
|
WORD SecondsSinceBoot;
|
|
WORD Reserved;
|
|
ULONG ClientIpAddress;
|
|
ULONG YourIpAddress;
|
|
ULONG BootstrapServerAddress;
|
|
ULONG RelayAgentIpAddress;
|
|
BYTE HardwareAddress[16];
|
|
BYTE HostName[ BOOT_SERVER_SIZE ];
|
|
BYTE BootFileName[BOOT_FILE_SIZE];
|
|
OPTION Option;
|
|
} DHCP_MESSAGE, *PDHCP_MESSAGE, *LPDHCP_MESSAGE;
|
|
#include <packoff.h>
|
|
|
|
LPOPTION
|
|
DhcpAppendOption(
|
|
LPOPTION Option,
|
|
BYTE OptionType,
|
|
PVOID OptionValue,
|
|
ULONG OptionLength,
|
|
LPBYTE OptionEnd
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function writes a DHCP option to message buffer.
|
|
|
|
Arguments:
|
|
|
|
Option - A pointer to a message buffer.
|
|
|
|
OptionType - The option number to append.
|
|
|
|
OptionValue - A pointer to the option data.
|
|
|
|
OptionLength - The length, in bytes, of the option data.
|
|
|
|
OptionEnd - End of Option Buffer.
|
|
|
|
Return Value:
|
|
|
|
A pointer to the end of the appended option.
|
|
|
|
--*/
|
|
{
|
|
if (!Option)
|
|
{
|
|
return Option;
|
|
}
|
|
|
|
if ( OptionType == OPTION_END ) {
|
|
|
|
//
|
|
// we should alway have atleast one BYTE space in the buffer
|
|
// to append this option.
|
|
//
|
|
|
|
Option->OptionType = OPTION_END;
|
|
return( (LPOPTION) ((LPBYTE)(Option) + 1) );
|
|
|
|
}
|
|
|
|
if ( OptionType == OPTION_PAD ) {
|
|
|
|
//
|
|
// add this option only iff we have enough space in the buffer.
|
|
//
|
|
|
|
if(((LPBYTE)Option + 1) < (OptionEnd - 1) ) {
|
|
Option->OptionType = OPTION_PAD;
|
|
return( (LPOPTION) ((LPBYTE)(Option) + 1) );
|
|
}
|
|
|
|
return Option;
|
|
}
|
|
|
|
|
|
//
|
|
// add this option only iff we have enough space in the buffer.
|
|
//
|
|
|
|
if(((LPBYTE)Option + 2 + OptionLength) >= (OptionEnd - 1) ) {
|
|
return Option;
|
|
}
|
|
|
|
if( OptionLength <= 0xFF ) {
|
|
// simple option.. no need to use OPTION_MSFT_CONTINUED
|
|
Option->OptionType = OptionType;
|
|
Option->OptionLength = (BYTE)OptionLength;
|
|
memcpy( Option->OptionValue, OptionValue, OptionLength );
|
|
return( (LPOPTION) ((LPBYTE)(Option) + Option->OptionLength + 2) );
|
|
}
|
|
|
|
// option size is > 0xFF --> need to continue it using multiple ones..
|
|
// there are OptionLenght / 0xFF occurances using 0xFF+2 bytes + one
|
|
// using 2 + (OptionLength % 0xFF ) space..
|
|
|
|
// check to see if we have the space first..
|
|
|
|
if( 2 + (OptionLength%0xFF) + 0x101*(OptionLength/0xFF)
|
|
+ (LPBYTE)Option >= (OptionEnd - 1) ) {
|
|
return Option;
|
|
}
|
|
|
|
return Option;
|
|
}
|
|
|
|
LPBYTE
|
|
DhcpAppendMagicCookie(
|
|
LPBYTE Option,
|
|
LPBYTE OptionEnd
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine appends magic cookie to a DHCP message.
|
|
|
|
Arguments:
|
|
|
|
Option - A pointer to the place to append the magic cookie.
|
|
|
|
OptionEnd - End of Option buffer.
|
|
|
|
Return Value:
|
|
|
|
A pointer to the end of the appended cookie.
|
|
|
|
Note : The magic cookie is :
|
|
|
|
--------------------
|
|
| 99 | 130 | 83 | 99 |
|
|
--------------------
|
|
|
|
--*/
|
|
{
|
|
if( (Option + 4) < (OptionEnd - 1) ) {
|
|
*Option++ = (BYTE)DHCP_MAGIC_COOKIE_BYTE1;
|
|
*Option++ = (BYTE)DHCP_MAGIC_COOKIE_BYTE2;
|
|
*Option++ = (BYTE)DHCP_MAGIC_COOKIE_BYTE3;
|
|
*Option++ = (BYTE)DHCP_MAGIC_COOKIE_BYTE4;
|
|
}
|
|
|
|
return( Option );
|
|
}
|
|
|
|
LPOPTION
|
|
DhcpAppendClientIDOption(
|
|
LPOPTION Option,
|
|
BYTE ClientHWType,
|
|
LPBYTE ClientHWAddr,
|
|
BYTE ClientHWAddrLength,
|
|
LPBYTE OptionEnd
|
|
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine appends client ID option to a DHCP message.
|
|
|
|
History:
|
|
8/26/96 Frankbee Removed 16 byte limitation on the hardware
|
|
address
|
|
|
|
Arguments:
|
|
|
|
Option - A pointer to the place to append the option request.
|
|
|
|
ClientHWType - Client hardware type.
|
|
|
|
ClientHWAddr - Client hardware address
|
|
|
|
ClientHWAddrLength - Client hardware address length.
|
|
|
|
OptionEnd - End of Option buffer.
|
|
|
|
Return Value:
|
|
|
|
A pointer to the end of the newly appended option.
|
|
|
|
Note : The client ID option will look like as below in the message:
|
|
|
|
-----------------------------------------------------------------
|
|
| OpNum | Len | HWType | HWA1 | HWA2 | ..... | HWAn |
|
|
-----------------------------------------------------------------
|
|
|
|
--*/
|
|
{
|
|
struct _CLIENT_ID {
|
|
BYTE bHardwareAddressType;
|
|
BYTE pbHardwareAddress[1];
|
|
} *pClientID;
|
|
|
|
LPOPTION lpNewOption = 0;
|
|
|
|
pClientID = LocalAlloc(LMEM_FIXED, sizeof( struct _CLIENT_ID ) + ClientHWAddrLength);
|
|
|
|
//
|
|
// currently there is no way to indicate failure. simply return unmodified option
|
|
// list
|
|
//
|
|
|
|
if ( !pClientID )
|
|
return Option;
|
|
|
|
pClientID->bHardwareAddressType = ClientHWType;
|
|
memcpy( pClientID->pbHardwareAddress, ClientHWAddr, ClientHWAddrLength );
|
|
|
|
lpNewOption = DhcpAppendOption(
|
|
Option,
|
|
OPTION_CLIENT_ID,
|
|
(LPBYTE)pClientID,
|
|
(BYTE)(ClientHWAddrLength + sizeof(BYTE)),
|
|
OptionEnd );
|
|
|
|
LocalFree( pClientID );
|
|
|
|
return lpNewOption;
|
|
}
|
|
|
|
DWORD
|
|
OpenSocket(
|
|
SOCKET *Socket,
|
|
unsigned long IpAddress,
|
|
unsigned short Port
|
|
)
|
|
{
|
|
DWORD Error = 0;
|
|
SOCKET Sock;
|
|
DWORD OptValue = TRUE;
|
|
|
|
struct sockaddr_in SocketName;
|
|
|
|
//
|
|
// Create a socket
|
|
//
|
|
|
|
Sock = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP );
|
|
|
|
if ( Sock == INVALID_SOCKET ) {
|
|
Error = WSAGetLastError();
|
|
goto error;
|
|
}
|
|
|
|
//
|
|
// Make the socket share-able
|
|
//
|
|
|
|
Error = setsockopt(
|
|
Sock,
|
|
SOL_SOCKET,
|
|
SO_REUSEADDR,
|
|
(char*)&OptValue,
|
|
sizeof(OptValue) );
|
|
|
|
if ( Error != ERROR_SUCCESS ) {
|
|
|
|
Error = WSAGetLastError();
|
|
goto error;
|
|
}
|
|
|
|
OptValue = TRUE;
|
|
Error = setsockopt(
|
|
Sock,
|
|
SOL_SOCKET,
|
|
SO_BROADCAST,
|
|
(char*)&OptValue,
|
|
sizeof(OptValue) );
|
|
|
|
if ( Error != ERROR_SUCCESS ) {
|
|
|
|
Error = WSAGetLastError();
|
|
goto error;
|
|
}
|
|
|
|
OptValue = SOCKET_RECEIVE_BUFFER_SIZE;
|
|
Error = setsockopt(
|
|
Sock,
|
|
SOL_SOCKET,
|
|
SO_RCVBUF,
|
|
(char*)&OptValue,
|
|
sizeof(OptValue) );
|
|
|
|
if ( Error != ERROR_SUCCESS ) {
|
|
|
|
Error = WSAGetLastError();
|
|
goto error;
|
|
}
|
|
|
|
SocketName.sin_family = PF_INET;
|
|
SocketName.sin_port = Port;
|
|
SocketName.sin_addr.s_addr = IpAddress;
|
|
RtlZeroMemory( SocketName.sin_zero, 8);
|
|
|
|
//
|
|
// Bind this socket to the DHCP server port
|
|
//
|
|
|
|
Error = bind(
|
|
Sock,
|
|
(struct sockaddr FAR *)&SocketName,
|
|
sizeof( SocketName )
|
|
);
|
|
|
|
if ( Error != ERROR_SUCCESS ) {
|
|
|
|
Error = WSAGetLastError();
|
|
goto error;
|
|
}
|
|
|
|
*Socket = Sock;
|
|
Error = ERROR_SUCCESS;
|
|
|
|
error:
|
|
|
|
if( Error != ERROR_SUCCESS ) {
|
|
|
|
//
|
|
// if we aren't successful, close the socket if it is opened.
|
|
//
|
|
|
|
if( Sock != INVALID_SOCKET ) {
|
|
closesocket( Sock );
|
|
}
|
|
}
|
|
|
|
return( Error );
|
|
}
|
|
|
|
DWORD
|
|
SendInformOrDiscover(
|
|
SOCKET Sock,
|
|
ULONG uClientIp,
|
|
BYTE ucMessageType,
|
|
PBYTE pMessageBuffer,
|
|
ULONG uMessageBufferSize,
|
|
ULONG DestIp,
|
|
PULONG puXid
|
|
)
|
|
{
|
|
DWORD Error = 0;
|
|
PDHCP_MESSAGE dhcpMessage = (PDHCP_MESSAGE)pMessageBuffer;
|
|
LPOPTION option = 0;
|
|
LPBYTE OptionEnd = 0;
|
|
BYTE value = 0;
|
|
ULONG uXid = 0;
|
|
LPSTR HostName = "detective";
|
|
ULONG uNumOfRequestOptions = 0;
|
|
UCHAR ucRequestOptions[256];
|
|
struct sockaddr_in socketName;
|
|
DWORD i;
|
|
|
|
uXid = (rand() & 0xff);
|
|
uXid <<= 8;
|
|
uXid |= (rand() & 0xff);
|
|
uXid <<= 8;
|
|
uXid |= (rand() & 0xff);
|
|
uXid <<= 8;
|
|
uXid |= (rand() & 0xff);
|
|
|
|
HardwareAddressLength = 6;
|
|
for (i = 0; i < HardwareAddressLength; i++) {
|
|
HardwareAddress[i] = (BYTE)(rand() & 0xff);
|
|
}
|
|
|
|
//
|
|
// prepare message.
|
|
//
|
|
|
|
RtlZeroMemory( dhcpMessage, uMessageBufferSize );
|
|
|
|
dhcpMessage->Operation = BOOT_REQUEST;
|
|
dhcpMessage->ClientIpAddress = uClientIp;
|
|
dhcpMessage->HardwareAddressType = 1;
|
|
dhcpMessage->SecondsSinceBoot = 60; // random value ??
|
|
dhcpMessage->Reserved = htons(DHCP_BROADCAST);
|
|
dhcpMessage->TransactionID = uXid;
|
|
*puXid = uXid;
|
|
|
|
memcpy(
|
|
dhcpMessage->HardwareAddress,
|
|
HardwareAddress,
|
|
HardwareAddressLength
|
|
);
|
|
|
|
dhcpMessage->HardwareAddressLength = (BYTE)HardwareAddressLength;
|
|
|
|
option = &dhcpMessage->Option;
|
|
OptionEnd = (LPBYTE)dhcpMessage + uMessageBufferSize;
|
|
|
|
//
|
|
// always add magic cookie first
|
|
//
|
|
|
|
option = (LPOPTION) DhcpAppendMagicCookie( (LPBYTE) option, OptionEnd );
|
|
|
|
value = ucMessageType;
|
|
option = DhcpAppendOption(
|
|
option,
|
|
OPTION_MESSAGE_TYPE,
|
|
&value,
|
|
1,
|
|
OptionEnd );
|
|
|
|
|
|
//
|
|
// Add client ID Option.
|
|
//
|
|
|
|
option = DhcpAppendClientIDOption(
|
|
option,
|
|
1,
|
|
HardwareAddress,
|
|
HardwareAddressLength,
|
|
OptionEnd );
|
|
|
|
//
|
|
// add Host name and comment options.
|
|
//
|
|
|
|
option = DhcpAppendOption(
|
|
option,
|
|
OPTION_HOST_NAME,
|
|
(LPBYTE)HostName,
|
|
(BYTE)((strlen(HostName) + 1) * sizeof(CHAR)),
|
|
OptionEnd );
|
|
|
|
//
|
|
// Add requested option
|
|
//
|
|
|
|
uNumOfRequestOptions = 0;
|
|
ucRequestOptions[uNumOfRequestOptions++] = 3;
|
|
option = DhcpAppendOption(
|
|
option,
|
|
OPTION_PARAMETER_REQUEST_LIST,
|
|
ucRequestOptions,
|
|
uNumOfRequestOptions,
|
|
OptionEnd
|
|
);
|
|
|
|
//
|
|
// Add END option.
|
|
//
|
|
|
|
option = DhcpAppendOption( option, OPTION_END, NULL, 0, OptionEnd );
|
|
|
|
//
|
|
// Initialize the outgoing address.
|
|
//
|
|
|
|
socketName.sin_family = PF_INET;
|
|
socketName.sin_port = htons( DHCP_SERVR_PORT );
|
|
socketName.sin_addr.s_addr = DestIp;
|
|
|
|
for ( i = 0; i < 8 ; i++ ) {
|
|
socketName.sin_zero[i] = 0;
|
|
}
|
|
|
|
Error = sendto(
|
|
Sock,
|
|
(char*)pMessageBuffer,
|
|
(int)(((PBYTE)option) - pMessageBuffer),
|
|
0,
|
|
(struct sockaddr *)&socketName,
|
|
sizeof( struct sockaddr )
|
|
);
|
|
|
|
if ( Error == SOCKET_ERROR ) {
|
|
Error = WSAGetLastError();
|
|
return( Error );
|
|
}
|
|
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
|
|
DWORD
|
|
GetSpecifiedMessage(
|
|
SOCKET Sock,
|
|
PBYTE pMessageBuffer,
|
|
ULONG uMessageBufferSize,
|
|
ULONG uXid,
|
|
ULONG uTimeout,
|
|
ULONG * pServerIpAddress
|
|
)
|
|
{
|
|
DWORD Error = 0;
|
|
fd_set readSocketSet;
|
|
struct timeval timeout;
|
|
struct sockaddr socketName;
|
|
int socketNameSize = sizeof( socketName );
|
|
PDHCP_MESSAGE dhcpMessage = (PDHCP_MESSAGE)pMessageBuffer;
|
|
time_t start_time = 0, now = 0;
|
|
PUCHAR pucOption = NULL;
|
|
ULONG uBytesRemain = 0;
|
|
ULONG uOptionSize = 0;
|
|
BOOL bWellFormedPacket = FALSE;
|
|
ULONG uRemainingTime = 0;
|
|
BOOL continueLooping = TRUE;
|
|
BOOL continueInternalLoop = TRUE;
|
|
BOOL continueInternalLoop2 = FALSE;
|
|
|
|
BYTE ReqdCookie[] = {
|
|
(BYTE)DHCP_MAGIC_COOKIE_BYTE1,
|
|
(BYTE)DHCP_MAGIC_COOKIE_BYTE2,
|
|
(BYTE)DHCP_MAGIC_COOKIE_BYTE3,
|
|
(BYTE)DHCP_MAGIC_COOKIE_BYTE4
|
|
};
|
|
|
|
time(&now);
|
|
start_time = now;
|
|
|
|
*pServerIpAddress = 0;
|
|
|
|
while (continueLooping) {
|
|
time(&now);
|
|
uRemainingTime = uTimeout - (ULONG)(now - start_time);
|
|
|
|
FD_ZERO( &readSocketSet );
|
|
|
|
|
|
// FD_SET( Sock, &readSocketSet );
|
|
// Had to inline the macro because the compiler was complaining
|
|
// about the while(0) that was present in FD_SET
|
|
|
|
do {
|
|
u_int __i;
|
|
for (__i = 0; __i < ((fd_set FAR *)(&readSocketSet))->fd_count; __i++) {
|
|
if (((fd_set FAR *)(&readSocketSet))->fd_array[__i] == (Sock)) {
|
|
continueInternalLoop2 = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
if (__i == ((fd_set FAR *)(&readSocketSet))->fd_count) {
|
|
if (((fd_set FAR *)(&readSocketSet))->fd_count < FD_SETSIZE) {
|
|
((fd_set FAR *)(&readSocketSet))->fd_array[__i] = (Sock);
|
|
((fd_set FAR *)(&readSocketSet))->fd_count++;
|
|
}
|
|
}
|
|
} while(continueInternalLoop2);
|
|
|
|
timeout.tv_sec = uRemainingTime;
|
|
timeout.tv_usec = 0;
|
|
|
|
Error = select(1, &readSocketSet, NULL, NULL, &timeout);
|
|
|
|
if (Error == 0) {
|
|
Error = ERROR_SEM_TIMEOUT;
|
|
continueLooping = FALSE;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// receive available message.
|
|
//
|
|
|
|
Error = recvfrom(
|
|
Sock,
|
|
(char*)pMessageBuffer,
|
|
uMessageBufferSize,
|
|
0,
|
|
&socketName,
|
|
&socketNameSize
|
|
);
|
|
|
|
if ( Error == SOCKET_ERROR ) {
|
|
|
|
Error = WSAGetLastError();
|
|
|
|
//
|
|
// Don't bail out here.
|
|
//
|
|
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Some sanity check
|
|
//
|
|
if (Error < sizeof(DHCP_MESSAGE)) {
|
|
continue;
|
|
}
|
|
|
|
if (dhcpMessage->HardwareAddressLength != HardwareAddressLength) {
|
|
continue;
|
|
}
|
|
|
|
if (memcmp(dhcpMessage->HardwareAddress, HardwareAddress, HardwareAddressLength) != 0) {
|
|
continue;
|
|
}
|
|
|
|
if (dhcpMessage->TransactionID != uXid) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Make sure the option part is well-formed
|
|
// +--------------+----------+----------+-------------+
|
|
// | magic cookie | Option 1 | Length 1 | Option Data 1 ...
|
|
// +--------------+----------+----------+-------------+
|
|
//
|
|
|
|
pucOption = (PUCHAR)(&dhcpMessage->Option);
|
|
uBytesRemain = Error - (ULONG)(pucOption - ((PUCHAR)dhcpMessage));
|
|
if (uBytesRemain < sizeof(ReqdCookie)) {
|
|
continue;
|
|
}
|
|
|
|
if (0 != memcmp(pucOption, ReqdCookie, sizeof(ReqdCookie))) {
|
|
continue;
|
|
}
|
|
|
|
pucOption += sizeof(ReqdCookie);
|
|
uBytesRemain -= sizeof(ReqdCookie);
|
|
bWellFormedPacket = FALSE;
|
|
|
|
while (continueInternalLoop) {
|
|
|
|
//
|
|
// Make sure pucOption[0] is readable
|
|
//
|
|
if (uBytesRemain < 1) {
|
|
continueInternalLoop = FALSE;
|
|
break;
|
|
}
|
|
|
|
if (pucOption[0] == OPTION_PAD) {
|
|
pucOption++;
|
|
uBytesRemain--;
|
|
continue;
|
|
}
|
|
|
|
if (pucOption[0] == OPTION_END) {
|
|
//
|
|
// See the OPTION_END. This is a well-formed packet
|
|
//
|
|
bWellFormedPacket = TRUE;
|
|
continueInternalLoop = FALSE;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Make sure pucOption[1] is readable
|
|
//
|
|
if (uBytesRemain < 2) {
|
|
continueInternalLoop = FALSE;
|
|
break;
|
|
}
|
|
|
|
uOptionSize = pucOption[1];
|
|
|
|
//
|
|
// Make sure there is enough bytes for the option data
|
|
//
|
|
if (uBytesRemain < uOptionSize) {
|
|
continueInternalLoop = FALSE;
|
|
break;
|
|
}
|
|
|
|
if (pucOption[0] == OPTION_SERVER_IDENTIFIER) {
|
|
if (uOptionSize != sizeof(ULONG)) {
|
|
continueInternalLoop = FALSE;
|
|
break;
|
|
}
|
|
memcpy(pServerIpAddress, pucOption + 2, sizeof(ULONG));
|
|
}
|
|
|
|
|
|
//
|
|
// Skip the option head and option data and move
|
|
// to the next option
|
|
//
|
|
uBytesRemain -= uOptionSize + 2;
|
|
pucOption += uOptionSize + 2;
|
|
}
|
|
|
|
if (bWellFormedPacket) {
|
|
Error = ERROR_SUCCESS;
|
|
continueLooping = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return( Error );
|
|
}
|
|
|
|
|
|
// This will first attempt a DHCP_INFORM to detect a DHCP server.
|
|
// If that fails it will attempt a DHCP_DISCOVER.
|
|
|
|
DWORD
|
|
AnyDHCPServerRunning(
|
|
ULONG uClientIp,
|
|
ULONG * pServerIp
|
|
)
|
|
{
|
|
CHAR MessageBuffer[DHCP_RECV_MESSAGE_SIZE];
|
|
SOCKET Sock = INVALID_SOCKET;
|
|
ULONG DestIp = htonl(INADDR_BROADCAST);
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
ULONG uXid = 0;
|
|
ULONG uMessageBufferSize = sizeof(MessageBuffer);
|
|
ULONG uTimeout = 4;
|
|
int retries = 0;
|
|
|
|
if (!pServerIp)
|
|
{
|
|
dwError = ERROR_INVALID_PARAMETER;
|
|
goto error;
|
|
}
|
|
|
|
dwError = OpenSocket(
|
|
&Sock,
|
|
uClientIp,
|
|
htons(DHCP_CLIENT_PORT)
|
|
);
|
|
|
|
if( dwError != ERROR_SUCCESS ) {
|
|
goto error;
|
|
}
|
|
|
|
for (retries = 0; retries < 3; retries++) {
|
|
//
|
|
// Try inform
|
|
//
|
|
dwError =
|
|
SendInformOrDiscover(
|
|
Sock,
|
|
uClientIp,
|
|
DHCP_INFORM_MESSAGE,
|
|
(PBYTE)MessageBuffer,
|
|
uMessageBufferSize,
|
|
DestIp,
|
|
&uXid);
|
|
|
|
if (dwError != ERROR_SUCCESS) {
|
|
goto error;
|
|
}
|
|
|
|
dwError = GetSpecifiedMessage(
|
|
Sock,
|
|
(PBYTE)MessageBuffer,
|
|
uMessageBufferSize,
|
|
uXid,
|
|
uTimeout,
|
|
pServerIp
|
|
);
|
|
if (dwError != ERROR_SEM_TIMEOUT && *pServerIp != htonl(INADDR_ANY) && *pServerIp != htonl(INADDR_BROADCAST)) {
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Try discover
|
|
//
|
|
dwError =
|
|
SendInformOrDiscover(
|
|
Sock,
|
|
uClientIp,
|
|
DHCP_DISCOVER_MESSAGE,
|
|
(PBYTE)MessageBuffer,
|
|
uMessageBufferSize,
|
|
DestIp,
|
|
&uXid);
|
|
|
|
if (dwError != ERROR_SUCCESS) {
|
|
goto error;
|
|
}
|
|
|
|
dwError = GetSpecifiedMessage(
|
|
Sock,
|
|
(PBYTE)MessageBuffer,
|
|
uMessageBufferSize,
|
|
uXid,
|
|
uTimeout,
|
|
pServerIp
|
|
);
|
|
if (dwError != ERROR_SEM_TIMEOUT && *pServerIp != htonl(INADDR_ANY) && *pServerIp != htonl(INADDR_BROADCAST)) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
error:
|
|
if (Sock != INVALID_SOCKET) {
|
|
closesocket(Sock);
|
|
}
|
|
|
|
return dwError;
|
|
}
|