1099 lines
23 KiB
C
1099 lines
23 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1994 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
dhcploc.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This apps is used to detect the rogue DHCP server on a subnet.
|
||
|
|
||
|
To build, 'nmake UMTEST=dhcpcli'
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Madan Appiah (madana) 21-Oct-1993
|
||
|
|
||
|
Environment:
|
||
|
|
||
|
User Mode - Win32
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Oct 1996, (a-martih) Martin Holladay
|
||
|
Corrected AV bug when passed an unknown cmd-line parameter.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include <dhcpcli.h>
|
||
|
#include <conio.h>
|
||
|
#include <locmsg.h>
|
||
|
#include <time.h>
|
||
|
#include <lmcons.h>
|
||
|
#include <lmmsg.h>
|
||
|
|
||
|
#define RECEIVE_TIMEOUT 5 // in secs. 5 secs
|
||
|
#define THREAD_TERMINATION_TIMEOUT 10000 // in msecs. 10 secs
|
||
|
#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
|
||
|
|
||
|
DWORD GlobalAuthServers[AUTH_SERVERS_MAX];
|
||
|
BOOL GlobalNoAuthPrint = FALSE;
|
||
|
DWORD GlobalAuthServersCount = 0;
|
||
|
HANDLE GlobalRecvThreadHandle = NULL;
|
||
|
BOOL GlobalTerminate = FALSE;
|
||
|
DWORD GlobalIpAddress = 0;
|
||
|
time_t GlobalLastAlertTime = 0;
|
||
|
DWORD GlobalAlertInterval = ALERT_INTERVAL;
|
||
|
LPWSTR GlobalAlertNames[MAX_ALERT_NAMES];
|
||
|
DWORD GlobalAlertNamesCount = 0;
|
||
|
|
||
|
#if DBG
|
||
|
|
||
|
VOID
|
||
|
DhcpPrintRoutine(
|
||
|
IN DWORD DebugFlag,
|
||
|
IN LPSTR Format,
|
||
|
...
|
||
|
)
|
||
|
|
||
|
{
|
||
|
|
||
|
#define MAX_PRINTF_LEN 1024 // Arbitrary.
|
||
|
|
||
|
va_list arglist;
|
||
|
char OutputBuffer[MAX_PRINTF_LEN];
|
||
|
ULONG length = 0;
|
||
|
|
||
|
//
|
||
|
// Put a the information requested by the caller onto the line
|
||
|
//
|
||
|
|
||
|
va_start(arglist, Format);
|
||
|
length += (ULONG) vsprintf(&OutputBuffer[length], Format, arglist);
|
||
|
va_end(arglist);
|
||
|
|
||
|
DhcpAssert(length <= MAX_PRINTF_LEN);
|
||
|
|
||
|
//
|
||
|
// Output to the debug terminal,
|
||
|
//
|
||
|
|
||
|
printf( "%s", OutputBuffer);
|
||
|
}
|
||
|
|
||
|
#endif // DBG
|
||
|
|
||
|
DWORD
|
||
|
OpenSocket(
|
||
|
SOCKET *Socket,
|
||
|
DWORD IpAddress,
|
||
|
DWORD Port
|
||
|
)
|
||
|
{
|
||
|
DWORD Error;
|
||
|
SOCKET Sock;
|
||
|
DWORD OptValue;
|
||
|
|
||
|
struct sockaddr_in SocketName;
|
||
|
|
||
|
//
|
||
|
// Create a socket
|
||
|
//
|
||
|
|
||
|
Sock = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP );
|
||
|
|
||
|
if ( Sock == INVALID_SOCKET ) {
|
||
|
Error = WSAGetLastError();
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Make the socket share-able
|
||
|
//
|
||
|
|
||
|
OptValue = TRUE;
|
||
|
Error = setsockopt(
|
||
|
Sock,
|
||
|
SOL_SOCKET,
|
||
|
SO_REUSEADDR,
|
||
|
(LPBYTE)&OptValue,
|
||
|
sizeof(OptValue) );
|
||
|
|
||
|
if ( Error != ERROR_SUCCESS ) {
|
||
|
|
||
|
Error = WSAGetLastError();
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
OptValue = TRUE;
|
||
|
Error = setsockopt(
|
||
|
Sock,
|
||
|
SOL_SOCKET,
|
||
|
SO_BROADCAST,
|
||
|
(LPBYTE)&OptValue,
|
||
|
sizeof(OptValue) );
|
||
|
|
||
|
if ( Error != ERROR_SUCCESS ) {
|
||
|
|
||
|
Error = WSAGetLastError();
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
OptValue = SOCKET_RECEIVE_BUFFER_SIZE;
|
||
|
Error = setsockopt(
|
||
|
Sock,
|
||
|
SOL_SOCKET,
|
||
|
SO_RCVBUF,
|
||
|
(LPBYTE)&OptValue,
|
||
|
sizeof(OptValue) );
|
||
|
|
||
|
if ( Error != ERROR_SUCCESS ) {
|
||
|
|
||
|
Error = WSAGetLastError();
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
SocketName.sin_family = PF_INET;
|
||
|
SocketName.sin_port = htons( (unsigned short)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 Cleanup;
|
||
|
}
|
||
|
|
||
|
*Socket = Sock;
|
||
|
Error = ERROR_SUCCESS;
|
||
|
|
||
|
Cleanup:
|
||
|
|
||
|
if( Error != ERROR_SUCCESS ) {
|
||
|
|
||
|
//
|
||
|
// if we aren't successful, close the socket if it is opened.
|
||
|
//
|
||
|
|
||
|
if( Sock != INVALID_SOCKET ) {
|
||
|
closesocket( Sock );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return( Error );
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
IsAuthServer(
|
||
|
DWORD IpAddress
|
||
|
)
|
||
|
{
|
||
|
DWORD i;
|
||
|
|
||
|
for( i = 0; i < GlobalAuthServersCount; i++ ) {
|
||
|
if( IpAddress == GlobalAuthServers[i] ){
|
||
|
return( TRUE );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
ExtractOptions1(
|
||
|
POPTION Option,
|
||
|
PDHCP_OPTIONS DhcpOptions,
|
||
|
DWORD MessageSize
|
||
|
)
|
||
|
{
|
||
|
POPTION start = Option;
|
||
|
POPTION nextOption;
|
||
|
LPBYTE MagicCookie;
|
||
|
|
||
|
//
|
||
|
// initialize option data.
|
||
|
//
|
||
|
|
||
|
RtlZeroMemory( DhcpOptions, sizeof( DHCP_OPTIONS ) );
|
||
|
|
||
|
if ( MessageSize == 0 ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// check magic cookie.
|
||
|
//
|
||
|
|
||
|
MagicCookie = (LPBYTE) Option;
|
||
|
|
||
|
if( (*MagicCookie != (BYTE)DHCP_MAGIC_COOKIE_BYTE1) ||
|
||
|
(*(MagicCookie+1) != (BYTE)DHCP_MAGIC_COOKIE_BYTE2) ||
|
||
|
(*(MagicCookie+2) != (BYTE)DHCP_MAGIC_COOKIE_BYTE3) ||
|
||
|
(*(MagicCookie+3) != (BYTE)DHCP_MAGIC_COOKIE_BYTE4)) {
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
Option = (LPOPTION) (MagicCookie + 4);
|
||
|
|
||
|
while ( Option->OptionType != OPTION_END ) {
|
||
|
|
||
|
if ( Option->OptionType == OPTION_PAD ||
|
||
|
Option->OptionType == OPTION_END ) {
|
||
|
|
||
|
nextOption = (LPOPTION)( (LPBYTE)(Option) + 1);
|
||
|
|
||
|
} else {
|
||
|
|
||
|
nextOption = (LPOPTION)( (LPBYTE)(Option) + Option->OptionLength + 2);
|
||
|
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Make sure that we don't walk off the edge of the message, due
|
||
|
// to a forgotten OPTION_END option.
|
||
|
//
|
||
|
|
||
|
if ((PCHAR)nextOption - (PCHAR)start > (long)MessageSize ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
switch ( Option->OptionType ) {
|
||
|
|
||
|
case OPTION_MESSAGE_TYPE:
|
||
|
DhcpAssert( Option->OptionLength == sizeof(BYTE) );
|
||
|
DhcpOptions->MessageType =
|
||
|
(BYTE UNALIGNED *)&Option->OptionValue;
|
||
|
break;
|
||
|
|
||
|
case OPTION_SUBNET_MASK:
|
||
|
DhcpAssert( Option->OptionLength == sizeof(DWORD) );
|
||
|
DhcpOptions->SubnetMask =
|
||
|
(DHCP_IP_ADDRESS UNALIGNED *)&Option->OptionValue;
|
||
|
break;
|
||
|
|
||
|
case OPTION_LEASE_TIME:
|
||
|
DhcpAssert( Option->OptionLength == sizeof(DWORD) );
|
||
|
DhcpOptions->LeaseTime =
|
||
|
(DWORD UNALIGNED *)&Option->OptionValue;
|
||
|
break;
|
||
|
|
||
|
case OPTION_SERVER_IDENTIFIER:
|
||
|
DhcpAssert( Option->OptionLength == sizeof(DWORD) );
|
||
|
DhcpOptions->ServerIdentifier =
|
||
|
(DHCP_IP_ADDRESS UNALIGNED *)&Option->OptionValue;
|
||
|
break;
|
||
|
|
||
|
case OPTION_RENEWAL_TIME:
|
||
|
DhcpAssert( Option->OptionLength == sizeof(DWORD) );
|
||
|
DhcpOptions->T1Time =
|
||
|
(DWORD UNALIGNED *)&Option->OptionValue;
|
||
|
break;
|
||
|
|
||
|
case OPTION_REBIND_TIME:
|
||
|
DhcpAssert( Option->OptionLength == sizeof(DWORD) );
|
||
|
DhcpOptions->T2Time =
|
||
|
(DWORD UNALIGNED *)&Option->OptionValue;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
Option = nextOption;
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
SendDiscovery(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
DWORD Error;
|
||
|
BYTE MessageBuffer[DHCP_SEND_MESSAGE_SIZE];
|
||
|
PDHCP_MESSAGE dhcpMessage = (PDHCP_MESSAGE)MessageBuffer;
|
||
|
LPOPTION option;
|
||
|
LPBYTE OptionEnd;
|
||
|
BYTE value;
|
||
|
|
||
|
BYTE *HardwareAddress = "123456";
|
||
|
BYTE HardwareAddressLength = 6;
|
||
|
LPSTR HostName = "ROGUE";
|
||
|
|
||
|
SOCKET Sock;
|
||
|
struct sockaddr_in socketName;
|
||
|
DWORD i;
|
||
|
|
||
|
//
|
||
|
// prepare message.
|
||
|
//
|
||
|
|
||
|
RtlZeroMemory( dhcpMessage, DHCP_SEND_MESSAGE_SIZE );
|
||
|
|
||
|
dhcpMessage->Operation = BOOT_REQUEST;
|
||
|
dhcpMessage->HardwareAddressType = 1;
|
||
|
|
||
|
//
|
||
|
// Transaction ID is filled in during send
|
||
|
//
|
||
|
|
||
|
dhcpMessage->SecondsSinceBoot = 60; // random value ??
|
||
|
dhcpMessage->Reserved = htons(DHCP_BROADCAST);
|
||
|
|
||
|
memcpy(
|
||
|
dhcpMessage->HardwareAddress,
|
||
|
HardwareAddress,
|
||
|
HardwareAddressLength
|
||
|
);
|
||
|
|
||
|
dhcpMessage->HardwareAddressLength = (BYTE)HardwareAddressLength;
|
||
|
|
||
|
option = &dhcpMessage->Option;
|
||
|
OptionEnd = (LPBYTE)dhcpMessage + DHCP_SEND_MESSAGE_SIZE;
|
||
|
|
||
|
//
|
||
|
// always add magic cookie first
|
||
|
//
|
||
|
|
||
|
option = (LPOPTION) DhcpAppendMagicCookie( (LPBYTE) option, OptionEnd );
|
||
|
|
||
|
value = DHCP_DISCOVER_MESSAGE;
|
||
|
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 END option.
|
||
|
//
|
||
|
|
||
|
option = DhcpAppendOption( option, OPTION_END, NULL, 0, OptionEnd );
|
||
|
|
||
|
//
|
||
|
// Send the message
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// open socket.
|
||
|
//
|
||
|
|
||
|
Error = OpenSocket(
|
||
|
&Sock,
|
||
|
GlobalIpAddress,
|
||
|
DHCP_SERVR_PORT );
|
||
|
|
||
|
if( Error != ERROR_SUCCESS ) {
|
||
|
|
||
|
printf("OpenReceiveSocket failed %ld.", Error );
|
||
|
return( Error );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Initialize the outgoing address.
|
||
|
//
|
||
|
|
||
|
socketName.sin_family = PF_INET;
|
||
|
socketName.sin_port = htons( DHCP_SERVR_PORT );
|
||
|
socketName.sin_addr.s_addr = (DHCP_IP_ADDRESS)(INADDR_BROADCAST);
|
||
|
|
||
|
for ( i = 0; i < 8 ; i++ ) {
|
||
|
socketName.sin_zero[i] = 0;
|
||
|
}
|
||
|
|
||
|
Error = sendto(
|
||
|
Sock,
|
||
|
(PCHAR)MessageBuffer,
|
||
|
DHCP_SEND_MESSAGE_SIZE,
|
||
|
0,
|
||
|
(struct sockaddr *)&socketName,
|
||
|
sizeof( struct sockaddr )
|
||
|
);
|
||
|
|
||
|
if ( Error == SOCKET_ERROR ) {
|
||
|
Error = WSAGetLastError();
|
||
|
printf("sendto failed %ld\n", Error );
|
||
|
return( Error );
|
||
|
}
|
||
|
|
||
|
return( ERROR_SUCCESS );
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
LogEvent(
|
||
|
LPSTR MsgTypeString,
|
||
|
LPSTR IpAddressString,
|
||
|
LPSTR ServerAddressString
|
||
|
)
|
||
|
{
|
||
|
HANDLE EventlogHandle;
|
||
|
LPSTR Strings[3];
|
||
|
|
||
|
//
|
||
|
// open event registry.
|
||
|
//
|
||
|
|
||
|
EventlogHandle = RegisterEventSourceA(
|
||
|
NULL,
|
||
|
"DhcpTools" );
|
||
|
|
||
|
if (EventlogHandle == NULL) {
|
||
|
|
||
|
printf("RegisterEventSourceA failed %ld.", GetLastError() );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
Strings[0] = MsgTypeString;
|
||
|
Strings[1] = ServerAddressString;
|
||
|
Strings[2] = IpAddressString;
|
||
|
|
||
|
if( !ReportEventA(
|
||
|
EventlogHandle,
|
||
|
(WORD)EVENTLOG_INFORMATION_TYPE,
|
||
|
0, // event category
|
||
|
DHCP_ROGUE_SERVER_MESSAGE,
|
||
|
NULL,
|
||
|
(WORD)3,
|
||
|
0,
|
||
|
Strings,
|
||
|
NULL
|
||
|
) ) {
|
||
|
|
||
|
printf("ReportEventA failed %ld.", GetLastError() );
|
||
|
}
|
||
|
|
||
|
DeregisterEventSource(EventlogHandle);
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
RaiseAlert(
|
||
|
LPSTR MsgTypeString,
|
||
|
LPSTR IpAddressString,
|
||
|
LPSTR ServerAddressString
|
||
|
)
|
||
|
{
|
||
|
|
||
|
time_t TimeNow;
|
||
|
DWORD Error;
|
||
|
|
||
|
TimeNow = time( NULL );
|
||
|
|
||
|
if( TimeNow > (time_t)(GlobalLastAlertTime + GlobalAlertInterval) ) {
|
||
|
|
||
|
WCHAR uIpAddressString[SMALL_BUFFER_SIZE];
|
||
|
WCHAR uServerAddressString[SMALL_BUFFER_SIZE];
|
||
|
WCHAR uMsgTypeString[SMALL_BUFFER_SIZE];
|
||
|
DWORD i;
|
||
|
|
||
|
LPWSTR MessageParams[3];
|
||
|
WCHAR AlertMessage[ ALERT_MESSAGE_LENGTH ];
|
||
|
DWORD MsgLength;
|
||
|
|
||
|
MessageParams[0] =
|
||
|
DhcpOemToUnicode( MsgTypeString, uMsgTypeString );
|
||
|
MessageParams[1] =
|
||
|
DhcpOemToUnicode( ServerAddressString, uServerAddressString );
|
||
|
MessageParams[2] =
|
||
|
DhcpOemToUnicode( IpAddressString, uIpAddressString );
|
||
|
|
||
|
MsgLength = FormatMessage(
|
||
|
FORMAT_MESSAGE_FROM_HMODULE |
|
||
|
FORMAT_MESSAGE_ARGUMENT_ARRAY,
|
||
|
NULL,
|
||
|
DHCP_ROGUE_SERVER_MESSAGE,
|
||
|
0, // language id.
|
||
|
AlertMessage, // return buffer place holder.
|
||
|
ALERT_MESSAGE_LENGTH, // minimum buffer size (in characters) to allocate.
|
||
|
(va_list *)MessageParams // insert strings.
|
||
|
);
|
||
|
|
||
|
if( MsgLength == 0 ) {
|
||
|
|
||
|
printf("FormatMessage failed %ld.", GetLastError() );
|
||
|
}
|
||
|
else {
|
||
|
|
||
|
//
|
||
|
// send alert message.
|
||
|
//
|
||
|
|
||
|
for( i = 0; i < GlobalAlertNamesCount; i++) {
|
||
|
|
||
|
Error = NetMessageBufferSend(
|
||
|
NULL,
|
||
|
GlobalAlertNames[i],
|
||
|
NULL,
|
||
|
(LPBYTE)AlertMessage,
|
||
|
MsgLength * sizeof(WCHAR) );
|
||
|
|
||
|
if( Error != ERROR_SUCCESS ) {
|
||
|
|
||
|
printf("NetMessageBufferSend failed %ld.", Error );
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
GlobalLastAlertTime = TimeNow;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
DisplayMessage(
|
||
|
LPSTR MessageBuffer,
|
||
|
DWORD BufferLength,
|
||
|
struct sockaddr_in *source
|
||
|
)
|
||
|
{
|
||
|
DHCP_OPTIONS DhcpOptions;
|
||
|
PDHCP_MESSAGE DhcpMessage;
|
||
|
SYSTEMTIME SystemTime;
|
||
|
DWORD MessageType;
|
||
|
LPSTR MessageTypeString;
|
||
|
|
||
|
BOOL AuthServer = FALSE;
|
||
|
|
||
|
CHAR IpAddressString[SMALL_BUFFER_SIZE];
|
||
|
CHAR ServerAddressString[SMALL_BUFFER_SIZE];
|
||
|
|
||
|
//
|
||
|
// check to see this is valid DHCP packet.
|
||
|
//
|
||
|
|
||
|
if( BufferLength < DHCP_MESSAGE_FIXED_PART_SIZE ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
DhcpMessage = (LPDHCP_MESSAGE) MessageBuffer;
|
||
|
|
||
|
if( (DhcpMessage->Operation != BOOT_REQUEST) &&
|
||
|
(DhcpMessage->Operation != BOOT_REPLY) ) {
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// extract options.
|
||
|
//
|
||
|
|
||
|
ExtractOptions1(
|
||
|
&DhcpMessage->Option,
|
||
|
&DhcpOptions,
|
||
|
BufferLength - DHCP_MESSAGE_FIXED_PART_SIZE );
|
||
|
|
||
|
if( DhcpOptions.MessageType == NULL ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
MessageType = *DhcpOptions.MessageType;
|
||
|
|
||
|
if( (MessageType < DHCP_DISCOVER_MESSAGE ) ||
|
||
|
(MessageType > DHCP_RELEASE_MESSAGE ) ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// packet is valid dhcp packet, print info.
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// if this packet is from one of the auth server and we are asked
|
||
|
// not to print auth servers packet, so so.
|
||
|
//
|
||
|
|
||
|
|
||
|
if( DhcpOptions.ServerIdentifier != NULL ) {
|
||
|
AuthServer = IsAuthServer(*DhcpOptions.ServerIdentifier);
|
||
|
}
|
||
|
|
||
|
if( GlobalNoAuthPrint && AuthServer ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
GetLocalTime( &SystemTime );
|
||
|
printf("%02u:%02u:%02u ",
|
||
|
SystemTime.wHour,
|
||
|
SystemTime.wMinute,
|
||
|
SystemTime.wSecond );
|
||
|
|
||
|
|
||
|
switch ( MessageType ) {
|
||
|
case DHCP_DISCOVER_MESSAGE:
|
||
|
MessageTypeString = "DISCOVER";
|
||
|
|
||
|
case DHCP_OFFER_MESSAGE:
|
||
|
MessageTypeString = "OFFER";
|
||
|
break;
|
||
|
|
||
|
case DHCP_REQUEST_MESSAGE:
|
||
|
MessageTypeString = "REQUEST";
|
||
|
break;
|
||
|
|
||
|
case DHCP_DECLINE_MESSAGE:
|
||
|
MessageTypeString = "DECLINE";
|
||
|
break;
|
||
|
|
||
|
case DHCP_ACK_MESSAGE:
|
||
|
MessageTypeString = "ACK";
|
||
|
break;
|
||
|
|
||
|
case DHCP_NACK_MESSAGE:
|
||
|
MessageTypeString = "NACK";
|
||
|
break;
|
||
|
|
||
|
case DHCP_RELEASE_MESSAGE:
|
||
|
MessageTypeString = "RELEASE";
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
MessageTypeString = "UNKNOWN";
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
|
||
|
printf("%8s ", MessageTypeString);
|
||
|
|
||
|
strcpy(
|
||
|
IpAddressString,
|
||
|
inet_ntoa(*(struct in_addr *)&DhcpMessage->YourIpAddress) );
|
||
|
|
||
|
printf("(IP)%-15s ", IpAddressString );
|
||
|
|
||
|
if(DhcpOptions.ServerIdentifier != NULL ) {
|
||
|
|
||
|
DWORD ServerId;
|
||
|
|
||
|
ServerId = *DhcpOptions.ServerIdentifier;
|
||
|
strcpy( ServerAddressString, inet_ntoa(*(struct in_addr *)&ServerId) );
|
||
|
|
||
|
printf("(S)%-15s ", ServerAddressString );
|
||
|
|
||
|
if( source->sin_addr.s_addr != ServerId ) {
|
||
|
|
||
|
printf("(S1)%-15s ",
|
||
|
inet_ntoa(*(struct in_addr *)&source->sin_addr.s_addr) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// beep if this it is a non-auth server.
|
||
|
//
|
||
|
|
||
|
if( AuthServer == FALSE ) {
|
||
|
printf("***");
|
||
|
MessageBeep( MB_ICONASTERISK );
|
||
|
|
||
|
//
|
||
|
// log an event.
|
||
|
//
|
||
|
|
||
|
LogEvent(
|
||
|
MessageTypeString,
|
||
|
IpAddressString,
|
||
|
ServerAddressString );
|
||
|
|
||
|
RaiseAlert(
|
||
|
MessageTypeString,
|
||
|
IpAddressString,
|
||
|
ServerAddressString );
|
||
|
}
|
||
|
|
||
|
printf("\n");
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
ReceiveDatagram(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
DWORD Error;
|
||
|
SOCKET Sock;
|
||
|
BOOL SocketOpened = FALSE;
|
||
|
fd_set readSocketSet;
|
||
|
struct timeval timeout;
|
||
|
struct sockaddr socketName;
|
||
|
int socketNameSize = sizeof( socketName );
|
||
|
|
||
|
CHAR MessageBuffer[DHCP_MESSAGE_SIZE];
|
||
|
|
||
|
Error = OpenSocket(
|
||
|
&Sock,
|
||
|
GlobalIpAddress,
|
||
|
DHCP_CLIENT_PORT );
|
||
|
|
||
|
if( Error != ERROR_SUCCESS ) {
|
||
|
|
||
|
printf("OpenReceiveSocket failed %ld.", Error );
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
SocketOpened = TRUE;
|
||
|
|
||
|
//
|
||
|
// receive message.
|
||
|
//
|
||
|
|
||
|
while( GlobalTerminate != TRUE ) {
|
||
|
|
||
|
FD_ZERO( &readSocketSet );
|
||
|
FD_SET( Sock, &readSocketSet );
|
||
|
|
||
|
timeout.tv_sec = RECEIVE_TIMEOUT;
|
||
|
timeout.tv_usec = 0;
|
||
|
|
||
|
Error = select( 0, &readSocketSet, NULL, NULL, &timeout);
|
||
|
|
||
|
if ( Error == 0 ) {
|
||
|
|
||
|
//
|
||
|
// Timeout before read data is available.
|
||
|
//
|
||
|
|
||
|
// printf("Receive timeout.\n");
|
||
|
}
|
||
|
else {
|
||
|
|
||
|
//
|
||
|
// receive available message.
|
||
|
//
|
||
|
|
||
|
Error = recvfrom(
|
||
|
Sock,
|
||
|
MessageBuffer,
|
||
|
sizeof(MessageBuffer),
|
||
|
0,
|
||
|
&socketName,
|
||
|
&socketNameSize
|
||
|
);
|
||
|
|
||
|
if ( Error == SOCKET_ERROR ) {
|
||
|
|
||
|
Error = WSAGetLastError();
|
||
|
printf("recvfrom failed %ld\n", Error );
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
if( GlobalTerminate == TRUE ) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
DisplayMessage(
|
||
|
MessageBuffer,
|
||
|
Error, // buffer length returned.
|
||
|
(struct sockaddr_in *)&socketName );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Cleanup:
|
||
|
|
||
|
if( SocketOpened == TRUE ) {
|
||
|
|
||
|
//
|
||
|
// close socket.
|
||
|
//
|
||
|
|
||
|
closesocket( Sock );
|
||
|
}
|
||
|
|
||
|
GlobalTerminate = TRUE;
|
||
|
return( Error );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
DWORD __cdecl
|
||
|
main(
|
||
|
int argc,
|
||
|
char **argv
|
||
|
)
|
||
|
{
|
||
|
|
||
|
DWORD Error;
|
||
|
LPSTR AppName = NULL;
|
||
|
WSADATA wsaData;
|
||
|
DWORD ThreadId;
|
||
|
|
||
|
//
|
||
|
// parse input parameters.
|
||
|
//
|
||
|
|
||
|
if( argc < 1 ) {
|
||
|
goto Usage;
|
||
|
}
|
||
|
|
||
|
AppName = argv[0];
|
||
|
argv++;
|
||
|
argc--;
|
||
|
|
||
|
if( argc < 1 ) {
|
||
|
goto Usage;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// parse flag parameter.
|
||
|
//
|
||
|
|
||
|
while( (argv[0][0] == '-') || (argv[0][0] == '/') ) {
|
||
|
|
||
|
switch (argv[0][1] ) {
|
||
|
case 'p':
|
||
|
GlobalNoAuthPrint = TRUE;
|
||
|
break;
|
||
|
|
||
|
case 'i':
|
||
|
GlobalAlertInterval = atoi( &argv[0][3] ) * 60;
|
||
|
break;
|
||
|
|
||
|
case 'a': {
|
||
|
|
||
|
LPSTR NextName;
|
||
|
LPSTR Ptr;
|
||
|
|
||
|
Ptr = &argv[0][3];
|
||
|
|
||
|
//
|
||
|
// skip blanks.
|
||
|
//
|
||
|
|
||
|
while( *Ptr == ' ' ) {
|
||
|
Ptr++;
|
||
|
}
|
||
|
NextName = Ptr;
|
||
|
|
||
|
while( *Ptr != '\0' ) {
|
||
|
|
||
|
if( *Ptr == ' ' ) {
|
||
|
|
||
|
//
|
||
|
// found another name.
|
||
|
//
|
||
|
|
||
|
*Ptr++ = '\0';
|
||
|
|
||
|
GlobalAlertNames[GlobalAlertNamesCount] =
|
||
|
DhcpOemToUnicode( NextName, NULL );
|
||
|
GlobalAlertNamesCount++;
|
||
|
|
||
|
if( GlobalAlertNamesCount >= MAX_ALERT_NAMES ) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// skip blanks.
|
||
|
//
|
||
|
|
||
|
while( *Ptr == ' ' ) {
|
||
|
Ptr++;
|
||
|
}
|
||
|
NextName = Ptr;
|
||
|
}
|
||
|
else {
|
||
|
|
||
|
Ptr++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if( GlobalAlertNamesCount < MAX_ALERT_NAMES ) {
|
||
|
if( NextName != Ptr ) {
|
||
|
GlobalAlertNames[GlobalAlertNamesCount] =
|
||
|
DhcpOemToUnicode( NextName, NULL );
|
||
|
GlobalAlertNamesCount++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// (a-martih) - Bug Fix
|
||
|
//
|
||
|
default:
|
||
|
if ((_stricmp(argv[0], "/?")) &&
|
||
|
(_stricmp(argv[0], "-?")) &&
|
||
|
(_stricmp(argv[0], "/h")) &&
|
||
|
(_stricmp(argv[0], "-h")) ) {
|
||
|
printf( "\nunknown flag, %s \n", argv[0] );
|
||
|
}
|
||
|
goto Usage;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
argv++;
|
||
|
argc--;
|
||
|
}
|
||
|
|
||
|
if( argc < 1 ) {
|
||
|
goto Usage;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// read ipaddress parameter.
|
||
|
//
|
||
|
|
||
|
GlobalIpAddress = inet_addr( argv[0] );
|
||
|
|
||
|
argv++;
|
||
|
argc--;
|
||
|
|
||
|
//
|
||
|
// now read auth dhcp servers ipaddresses.
|
||
|
//
|
||
|
|
||
|
while( (argc > 0) && (GlobalAuthServersCount < AUTH_SERVERS_MAX) ) {
|
||
|
|
||
|
GlobalAuthServers[GlobalAuthServersCount++] =
|
||
|
inet_addr( argv[0] );
|
||
|
|
||
|
argv++;
|
||
|
argc--;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// init socket.
|
||
|
//
|
||
|
|
||
|
Error = WSAStartup( WS_VERSION_REQUIRED, &wsaData);
|
||
|
|
||
|
if( Error != ERROR_SUCCESS ) {
|
||
|
printf( "WSAStartup failed %ld.\n", Error );
|
||
|
return(1);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// create receive datagrams thread.
|
||
|
//
|
||
|
|
||
|
GlobalRecvThreadHandle =
|
||
|
CreateThread(
|
||
|
NULL,
|
||
|
0,
|
||
|
(LPTHREAD_START_ROUTINE)ReceiveDatagram,
|
||
|
NULL,
|
||
|
0,
|
||
|
&ThreadId );
|
||
|
|
||
|
if( GlobalRecvThreadHandle == NULL ) {
|
||
|
printf("CreateThread failed %ld.\n", GetLastError() );
|
||
|
return(1);
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// read input.
|
||
|
//
|
||
|
|
||
|
while ( GlobalTerminate != TRUE ) {
|
||
|
CHAR ch;
|
||
|
|
||
|
ch = (CHAR)_getch();
|
||
|
|
||
|
switch( ch ) {
|
||
|
case 'q':
|
||
|
case 'Q':
|
||
|
// case '\c':
|
||
|
GlobalTerminate = TRUE;
|
||
|
break;
|
||
|
|
||
|
case 'd':
|
||
|
case 'D':
|
||
|
|
||
|
//
|
||
|
// send out discover message.
|
||
|
//
|
||
|
|
||
|
Error = SendDiscovery();
|
||
|
|
||
|
if(Error != ERROR_SUCCESS ) {
|
||
|
printf("SendDiscover failed %ld.\n", Error );
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
case 'h':
|
||
|
case 'H':
|
||
|
default:
|
||
|
|
||
|
printf("Type d - to discover; q - to quit; h - for help.\n");
|
||
|
|
||
|
//
|
||
|
// print out help message.
|
||
|
//
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// terminate receive thread.
|
||
|
//
|
||
|
|
||
|
WaitForSingleObject(
|
||
|
GlobalRecvThreadHandle,
|
||
|
THREAD_TERMINATION_TIMEOUT );
|
||
|
|
||
|
|
||
|
CloseHandle( GlobalRecvThreadHandle );
|
||
|
|
||
|
// Cleanup:
|
||
|
|
||
|
return(0);
|
||
|
|
||
|
Usage:
|
||
|
printf("\nUSAGE:\n\n");
|
||
|
printf("%s [-p] [-a:\"list-of-alertnames\"] [-i:alertinterval] "
|
||
|
"machine-ip-address "
|
||
|
"[list of valid dhcp servers ip addresses]", AppName );
|
||
|
|
||
|
return(1);
|
||
|
}
|
||
|
|
||
|
|