|
|
/*++
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)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); } }
|