472 lines
12 KiB
C
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);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|