windows-nt/Source/XPSP1/NT/net/dhcp/client/nt/dumpdhcp.c
2020-09-26 16:20:57 +08:00

472 lines
12 KiB
C

/*++
Copyright (C) 1999 Microsoft Corporation
Implements raw sockets stuff..
--*/
#include "precomp.h"
int show_all = 0;
int show_headers = 0;
void usage(void) {
fprintf(stderr, "usage: dumpdhcp local_ip_address [all] [headers]\n"
" local_ip_address -- binds to this ip address\n"
" all -- shows all UDP packets, not just MADCAP\n"
" hdr -- shows headers only\n"
);
exit(1);
}
void convert_time(DWORD_PTR TimeVal, char *time_buf)
{
struct tm* pTime;
char timeBuf[500];
strcpy(timeBuf, " <???>");
if (pTime = localtime(&TimeVal)) {
SYSTEMTIME systemTime;
int n;
systemTime.wYear = pTime->tm_year + 1900;
systemTime.wMonth = pTime->tm_mon + 1;
systemTime.wDayOfWeek = (WORD)pTime->tm_wday;
systemTime.wDay = (WORD)pTime->tm_mday;
systemTime.wHour = (WORD)pTime->tm_hour;
systemTime.wMinute = (WORD)pTime->tm_min;
systemTime.wSecond = (WORD)pTime->tm_sec;
systemTime.wMilliseconds = 0;
timeBuf[0] = ' ';
n = GetDateFormatA(
LOCALE_NEUTRAL,
DATE_SHORTDATE,
&systemTime,
NULL,
&timeBuf[1],
sizeof(timeBuf)
);
timeBuf[n] = ' ';
GetTimeFormatA(
LOCALE_NEUTRAL, 0, &systemTime,
NULL, &timeBuf[n+1], sizeof(timeBuf) - n - 2
);
}
strcpy(time_buf, timeBuf);
}
void socket_error(char *str) {
fprintf(stderr, "FATAL: %s [0x%lx]\n", str, WSAGetLastError());
exit(1);
}
void DumpInt(
char *s, unsigned long x
)
{
printf(s, x);
}
void DumpBytes(
int tab_offset, int nbytes_per_line, int halfwaymark,
unsigned char separation_character,
unsigned char *buffer,
unsigned long length
)
{
unsigned long dumped;
dumped = 0;
while( dumped < length ) {
if( tab_offset && 0 == (dumped % nbytes_per_line) ) {
int i;
if( dumped ) putchar('\n');
for( i = 0; i < tab_offset; i ++ ) putchar(' ');
} else if( tab_offset && halfwaymark ) {
if( 0 == (dumped % halfwaymark ) ) {
putchar(separation_character);
}
}
printf( (separation_character)?"%02X%c":"%02X",
(unsigned long)(*buffer++), separation_character
);
dumped++;
}
}
typedef struct {
unsigned char HeaderLen:4;
unsigned char Version:4;
unsigned char TOS;
unsigned short Length;
unsigned char Id;
unsigned short Offset;
unsigned char TTL;
unsigned char Proto;
unsigned char Xsum;
struct in_addr Source;
struct in_addr Dest;
} IP_HEADER, *PIP_HEADER;
typedef struct
{
unsigned short SourcePort;
unsigned short DestPort;
unsigned short Length;
unsigned short Xsum;
} UDP_HEADER, *PUDP_HEADER;
#define MADCAP_SERVER_PORT 2535
#define DHCP_SERVER_PORT 67
#define DHCP_CLIENT_PORT 68
#define MADCAP_OPTION_END 0
#define MADCAP_OPTION_LEASE_TIME 1
#define MADCAP_OPTION_SERVER_ID 2
#define MADCAP_OPTION_CLIENT_ID 3
#define MADCAP_OPTION_MCAST_SCOPE 4
#define MADCAP_OPTION_REQUEST_LIST 5
#define MADCAP_OPTION_START_TIME 6
#define MADCAP_OPTION_ADDR_COUNT 7
#define MADCAP_OPTION_REQUESTED_LANG 8
#define MADCAP_OPTION_MCAST_SCOPE_LIST 9
#define MADCAP_OPTION_ADDR_LIST 10
#define MADCAP_OPTION_TIME 11
#define MADCAP_OPTION_FEATURE_LIST 12
#define MADCAP_OPTION_RETRY_TIME 13
#define MADCAP_OPTION_MIN_LEASE_TIME 14
#define MADCAP_OPTION_MAX_START_TIME 15
char *madcap_option_list[] = {
"End", "LeaseTime", "ServerId", "ClientId",
"Scope", "RequestList", "StartTime", "AddressCount",
"RequestedLanguage", "ScopeList", "AddressList",
"Time", "FeatureList", "RetryTime", "MinLeaseTime",
"MaxStartTime",
};
char *madcap_message_types[] = {
"Unknown", "Discover",
"Offer", "Request", "Renew", "Ack", "Nack", "Release", "Inform"
};
char *
MadcapMessageType(
unsigned long type
)
{
static char type_buf[30];
if( type > sizeof(madcap_message_types)/sizeof(madcap_message_types[0])) {
sprintf(type_buf, "Unknown Message Type %ld", type);
return type_buf;
}
return madcap_message_types[type];
}
typedef struct {
WORD Type, Length;
} MADCAP_OPTION_HEADER, *PMADCAP_OPTION_HEADER;
void DumpMadcapOption(
unsigned long OptionType,
unsigned long OptionLength,
char *Buffer
)
{
int nOptions = sizeof(madcap_option_list)/sizeof(madcap_option_list[0]);
DWORD Value;
DWORD AddressFamily;
struct in_addr ipaddr;
int fprint_time = 0;
char time_buf[500];
time_buf[0] = ' ';
time_buf[1] = '\0';
do {
if( OptionType > (unsigned long)nOptions ) break;
if( 0 == OptionLength ) break;
switch( OptionType ) {
case MADCAP_OPTION_END :
case MADCAP_OPTION_CLIENT_ID :
case MADCAP_OPTION_REQUEST_LIST :
case MADCAP_OPTION_REQUESTED_LANG :
case MADCAP_OPTION_MCAST_SCOPE_LIST :
case MADCAP_OPTION_ADDR_LIST :
case MADCAP_OPTION_FEATURE_LIST :
break;
case MADCAP_OPTION_START_TIME :
case MADCAP_OPTION_MAX_START_TIME :
case MADCAP_OPTION_TIME :
case MADCAP_OPTION_RETRY_TIME :
fprint_time = TRUE;
case MADCAP_OPTION_LEASE_TIME :
case MADCAP_OPTION_MCAST_SCOPE :
case MADCAP_OPTION_ADDR_COUNT :
case MADCAP_OPTION_MIN_LEASE_TIME :
//
// print DWORD
//
if( sizeof(DWORD) != OptionLength ) break;
Value = ntohl(*(DWORD UNALIGNED *)Buffer);
if( fprint_time ) {
convert_time(Value, time_buf);
}
printf(
" Option %-20s :%s%ld\n",
madcap_option_list[OptionType], time_buf, Value
);
return;
case MADCAP_OPTION_SERVER_ID :
//
//
//
AddressFamily = (unsigned long)*Buffer;
if( AF_INET != AddressFamily ) break;
if( sizeof(ipaddr) + 1 != OptionLength ) break;
Buffer ++;
ipaddr = *((struct in_addr UNALIGNED *)Buffer);
printf(
" Option %-20s : %s\n",
madcap_option_list[OptionType], inet_ntoa(ipaddr)
);
return;
}
} while ( 0 );
//
// some error..
//
if( OptionType > (unsigned long)nOptions ) {
printf(" Option %-20ld : ", OptionType );
} else printf(" Option %-20s : ", madcap_option_list[OptionType]);
DumpBytes(0, 32, 16, ' ', Buffer, OptionLength); printf("\n");
}
void DumpMadcap(
char *Buffer,
unsigned long Size
)
{
PMADCAP_MESSAGE Message = (PMADCAP_MESSAGE) Buffer;
MADCAP_OPTION_HEADER Header;
unsigned long DumpedSize;
DumpBytes(8, 32, 16, ' ', Buffer, Size); printf("\n\n");
printf(
" %s Xid:0x%lx Version:0x%lx AddressFamily:0x%lx\n",
MadcapMessageType(Message->MessageType),
ntohl(Message->TransactionID), (DWORD)Message->Version, (DWORD)Message->MessageType,
(DWORD)ntohs(Message->AddressFamily)
);
Buffer += sizeof(MADCAP_MESSAGE);
DumpedSize = sizeof(MADCAP_MESSAGE);
while( DumpedSize + sizeof(Header) <= Size ) {
DumpedSize += sizeof(Header);
Header = *(MADCAP_OPTION_HEADER UNALIGNED *)Buffer;
Buffer += sizeof(Header);
Header.Type = ntohs(Header.Type);
Header.Length = ntohs(Header.Length);
if( DumpedSize + Header.Length > Size ) {
printf(" Type: 0x%lx, Length 0x%lx overrruns message end.\n",
Header.Type, Header.Length);
break;
} else {
DumpMadcapOption(Header.Type, Header.Length, Buffer);
Buffer += Header.Length;
DumpedSize += Header.Length;
if( Header.Type == MADCAP_OPTION_END ) break;
}
}
if( DumpedSize < Size ) {
printf(" Trailing bytes:\n");
DumpBytes(4, 16, 8, ' ', Buffer, Size - DumpedSize );
printf("\n");
}
printf("\n");
}
void DumpDhcp(
char *Buffer,
unsigned long Size
)
{
}
void DumpBuffer(
char *Buffer,
unsigned long Size
)
{
PIP_HEADER Ip;
PUDP_HEADER Udp;
unsigned long IpLength, UdpLength;
unsigned long SrcPort, DestPort;
int IsDhcp, IsMadcap;
char time_buf[100];
char *proto;
Ip = (PIP_HEADER)Buffer;
if( Size < sizeof(IP_HEADER) ) {
DumpInt("IP header too small 0x%lx\n", Size);
} else if( (IpLength = 4*((unsigned long)Ip->HeaderLen)) < sizeof(IP_HEADER ) ) {
DumpInt("IP header reports wrong length 0x%lx\n", IpLength);
} else if( (UdpLength = ntohs(Ip->Length)) < IpLength ) {
DumpInt("Data length incorrect: 0x%lx\n", UdpLength);
} else if( Ip->Proto != IPPROTO_UDP ) {
//
// Not UDP so ignore it
//
} else if( (UdpLength -= IpLength) < sizeof(UDP_HEADER)) {
DumpInt("UDP Header size too small: 0x%lx\n", UdpLength);
} else do {
Udp = (PUDP_HEADER)(Buffer + IpLength);
UdpLength = ntohs(Udp->Length) - sizeof(UDP_HEADER);
Buffer = (char *)(&Udp[1]);
SrcPort = ntohs(Udp->SourcePort);
DestPort = ntohs(Udp->DestPort);
IsDhcp = (SrcPort == DHCP_SERVER_PORT || DestPort == DHCP_SERVER_PORT
|| SrcPort == DHCP_CLIENT_PORT || DestPort == DHCP_CLIENT_PORT );
IsMadcap = (DestPort == MADCAP_SERVER_PORT || SrcPort == MADCAP_SERVER_PORT);
if( IsMadcap ) {
proto = "MADCAP";
} else if( IsDhcp ) {
if( !show_headers && !show_all ) break;
proto = "DHCP" ;
} else {
if( !show_all ) break;
proto = "UDP" ;
}
_strtime(time_buf); printf("%s ", time_buf);
printf("%s ", proto );
printf("%s:%ld ---> ", inet_ntoa(Ip->Source), ntohs(Udp->SourcePort));
printf("%s:%ld ", inet_ntoa(Ip->Dest), ntohs(Udp->DestPort));
printf("%ld bytes\n", UdpLength);
if( IsMadcap ) DumpMadcap(Buffer, UdpLength);
// else if( IsDhcp ) DumpDhcp(Buffer, UdpLength);
else {
if( show_headers ) break;
DumpBytes( 8, 32, 16, ' ', Buffer, UdpLength );
printf("\n\n");
}
} while ( 0 );
}
char Buffer[70000];
struct sockaddr_in SockAddr;
void _cdecl main (int argc, char *argv[])
{
SOCKET s;
int Error;
DWORD RecvCount, Flags, dwEnable, dwDontCare;
WSABUF WsaBufs[1];
WSADATA WsaData;
char *ipaddrstring = "0.0.0.0";
if( argc > 1 ) {
ipaddrstring = argv[1];
}
show_all = 0;
show_headers = 0;
if( argc > 2 ) {
if( 0 == _stricmp(argv[2], "all" ) ) show_all = 1;
else if( 0 == _stricmp(argv[2], "hdr") ) show_headers = 1;
else usage();
}
if( argc > 3 ) {
if( 0 == _stricmp(argv[3], "all" ) ) show_all = 1;
else if( 0 == _stricmp(argv[3], "hdr") ) show_headers = 1;
else usage();
}
Error = WSAStartup(MAKEWORD(2,0), &WsaData);
if( 0 != Error ) {
socket_error("WSAStartup");
}
s = WSASocket(
AF_INET, SOCK_RAW, IPPROTO_IGMP, NULL, 0, 0
);
if( INVALID_SOCKET == s ) {
socket_error("WSASocket");
}
SockAddr.sin_family = PF_INET;
SockAddr.sin_addr.s_addr = inet_addr(ipaddrstring);
Error = bind(s, (struct sockaddr *)&SockAddr, sizeof(SockAddr));
if( 0 != Error ) {
socket_error("bind");
}
dwEnable = 1;
Error = WSAIoctl(
s, SIO_RCVALL, (char *)&dwEnable, sizeof(dwEnable),
NULL, 0, &dwDontCare, NULL, NULL
);
if( 0 != Error ) {
socket_error("SIO_RCVALL");
}
while ( TRUE ) {
WsaBufs[0].len = sizeof(Buffer);
WsaBufs[0].buf = (char *)Buffer;
Flags = 0;
Error = WSARecv(
s, WsaBufs, sizeof(WsaBufs)/sizeof(WsaBufs[0]),
&RecvCount, &Flags, NULL, NULL
);
if( 0 != Error ) {
socket_error("WSARecv");
}
DumpBuffer((char*)Buffer, RecvCount);
}
}