// Module: rcvall.c
//
// Description:
// This sample shows how to use the ioctls SIO_RCVALL,
// SIO_RCVALL_MCAST, and SIO_RCVALL_IGMPMCAST. This sample
// captures all packets of the given type and also is able
// to set filters on source and destination IP addresses
// and ports. This sample is Windows 2000 only.
//
// Compile:
// cl rcvall.c parser.c ws2_32.lib
//
// Command Line Arguments/Parameters
// rcvall.exe -t:[ip|igmp|multicast] -i:int -sa:IP -sp:port
// -da:IP -dp:port
// -t:string Filter traffic type
// ip Capture all IP packets
// igmp Capture all IGMP packets only
// multicast Capture all multicast IP packets
// -i:int Capture on this interface
// This is a zero based index of the
// local interfaces
// -sa:IP Filter on source address
// -sp:Port Filter on source port
// -da:IP Filter on dest address
// -dp:Port Filter on dest port
//
//
#include "parser.h"
//
// Filters
//
unsigned int uiSourceAddr=0,
uiDestAddr=0;
unsigned short usSourcePort = 0,
usDestPort = 0;
BOOL bFilter=FALSE;
void PrintInterfaceList();
int GetInterface(SOCKET s, SOCKADDR_IN *ifx, int num);
//
// Function: usage
//
// Description:
// Prints usage information.
//
void usage(char *progname)
{
printf("usage: %s -t:traffic-type [interface-num]\n\n", progname);
printf(" -t:string Filter traffic type\n");
printf(" Available traffic types:\n");
printf(" ip Capture all IP packets\n");
printf(" igmp Capture all IGMP packets only\n");
printf(" multicast Capture all multicast IP packets\n");
printf(" -i:int Capture on this interface\n");
printf(" Available interfaces:\n");
PrintInterfaceList();
printf(" -sa:IP Filter on source address\n");
printf(" -sp:Port Filter on source port\n");
printf(" -da:IP Filter on dest address\n");
printf(" -dp:Port Filter on dest port\n");
WSACleanup();
ExitProcess(-1);
}
//
// Function: ValidateArgs
//
// Description:
// This function parses the command line arguments and
// sets global variables to indicate how the app should act.
//
void ValidateArgs(int argc, char **argv)
{
int i;
char *ptr;
for(i=1; i < argc ;i++)
{
if (strlen(argv[i]) < 2)
continue;
if ((argv[i][0] == '-') || (argv[i][0] == '/'))
{
switch (tolower(argv[i][1]))
{
case 't': // traffic type
ptr = &argv[i][3];
while (*ptr)
*ptr++ = tolower(*ptr);
if (!strcmp(&argv[i][3], "ip"))
{
dwIoControlCode = SIO_RCVALL;
dwProtocol = IPPROTO_IP;
}
else if (!strcmp(&argv[i][3], "igmp"))
{
dwIoControlCode = SIO_RCVALL_IGMPMCAST;
dwProtocol = IPPROTO_IGMP;
}
else if (!strcmp(&argv[i][3], "multicast"))
{
dwIoControlCode = SIO_RCVALL_MCAST;
dwProtocol = IPPROTO_IGMP;
}
else
usage(argv[0]);
break;
case 'i': // interface number
dwInterface = atoi(&argv[i][3]);
break;
case 's': // Filter on source ip or port
if (tolower(argv[i][2]) == 'a')
uiSourceAddr = ntohl(inet_addr(&argv[i][4]));
else if (tolower(argv[i][2]) == 'p')
usSourcePort = (unsigned short)atoi(&argv[i][4]);
else
usage(argv[0]);
bFilter = TRUE;
break;
case 'd': // Filter on dest ip or port
if (tolower(argv[i][2]) == 'a')
uiDestAddr = ntohl(inet_addr(&argv[i][4]));
else if (tolower(argv[i][2]) == 'p')
usDestPort = (unsigned short)atoi(&argv[i][4]);
else
usage(argv[0]);
bFilter = TRUE;
break;
default:
usage(argv[0]);
}
}
}
return;
}
//
// Function: PrintInterfaceList
//
// Description:
// This function prints all local IP interfaces.
//
void PrintInterfaceList()
{
SOCKET_ADDRESS_LIST *slist=NULL;
SOCKET s;
char buf[2048];
DWORD dwBytesRet;
int ret,
i;
s = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (s == SOCKET_ERROR)
{
printf("socket() failed: %d\n", WSAGetLastError());
return;
}
ret = WSAIoctl(s, SIO_ADDRESS_LIST_QUERY, NULL, 0, buf, 2048,
&dwBytesRet, NULL, NULL);
if (ret == SOCKET_ERROR)
{
printf("WSAIoctl(SIO_ADDRESS_LIST_QUERY) failed: %d\n",
WSAGetLastError());
return;
}
slist = (SOCKET_ADDRESS_LIST *)buf;
for(i=0; i < slist->iAddressCount ;i++)
{
printf(" %d [%s]\n", i,
inet_ntoa(((SOCKADDR_IN *)slist->Address[i].lpSockaddr)->sin_addr));
}
closesocket(s);
return;
}
//
// Function: GetInterface
//
// Description:
// This function retrieves a zero based index and returns
// the IP interface corresponding to that.
//
int GetInterface(SOCKET s, SOCKADDR_IN *ifx, int num)
{
SOCKET_ADDRESS_LIST *slist=NULL;
char buf[2048];
DWORD dwBytesRet;
int ret;
//
// Function: main
//
// Description:
// This function loads Winsock, parses the command line, and
// begins receiving packets. Once a packet is received they
// are decoded. Because we are receiving IP datagrams, the
// receive call will return whole datagrams.
//
int main(int argc, char **argv)
{
SOCKET s;
WSADATA wsd;
SOCKADDR_IN if0;
int ret,
count;
unsigned int optval;
DWORD dwBytesRet,
dwFlags,
nproc;
char rcvbuf[MAX_IP_SIZE];
WSABUF wbuf;
// Load Winsock
//
if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
{
printf("WSAStartup() failed: %d\n", GetLastError());
return -1;
}
// Parse the command line
//
ValidateArgs(argc, argv);
if (bFilter)
{
printf("Source Port: %d\n", usSourcePort);
printf("Dest Port: %d\n", usDestPort);
}
// Create a raw socket for receiving IP datagrams
//
s = WSASocket(AF_INET, SOCK_RAW, dwProtocol, NULL, 0, WSA_FLAG_OVERLAPPED);
if (s == INVALID_SOCKET)
{
printf("WSASocket() failed: %d\n", WSAGetLastError());
return -1;
}
// Get an interface to read IP packets on
//
if (GetInterface(s, &if0, dwInterface) != 0)
{
printf("Unable to obtain an interface\n");
return -1;
}
printf("Binding to IF: %s\n", inet_ntoa(if0.sin_addr));
//
// This socket must be bound before calling the ioctl
//
if0.sin_family = AF_INET;
if0.sin_port = htons(0);
if (bind(s, (SOCKADDR *)&if0, sizeof(if0)) == SOCKET_ERROR)
{
printf("bind() failed: %d\n", WSAGetLastError());
return -1;
}
//
// Set the SIO_RCVALLxxx ioctl
//
optval = 1;
if (WSAIoctl(s, dwIoControlCode, &optval, sizeof(optval),
NULL, 0, &dwBytesRet, NULL, NULL) == SOCKET_ERROR)
{
printf("WSAIotcl(%d) failed; %d\n", dwIoControlCode,
WSAGetLastError());
return -1;
}
// Start receiving IP datagrams until interrupted
//
count = 0;
while (1)
{
wbuf.len = MAX_IP_SIZE;
wbuf.buf = rcvbuf;
dwFlags = 0;
ret = WSARecv(s, &wbuf, 1, &dwBytesRet, &dwFlags, NULL, NULL);
if (ret == SOCKET_ERROR)
{
printf("WSARecv() failed: %d\n", WSAGetLastError());
return -1;
}
// Decode the IP header
//
if (!(nproc = DecodeIPHeader(&wbuf, uiSourceAddr, usSourcePort,
uiDestAddr, usDestPort)))
{
printf("Error decoding IP header!\n");
break;
}
}
// Cleanup
//
closesocket(s);
WSACleanup();
return 0;
}
//parser.h
void PrintRawBytes (BYTE *ptr, DWORD len);
int DecodeIGMPHeader(WSABUF *wsabuf, DWORD iphdrlen);
int DecodeUDPHeader (WSABUF *wsabuf, DWORD iphdrlen);
int DecodeTCPHeader (WSABUF *wsabuf, DWORD iphdrlenz);
int DecodeIPHeader (WSABUF *wasbuf, unsigned int srcaddr,
unsigned short srcport, unsigned int destaddr, unsigned short destport);
#endif
// Module: parser.c
//
// Description:
// This file is the companion to rcvall.c and contains
// the parser routines for printing out IP, UDP, TCP,
// ICMP, and IGMP packets.
//
// Compile:
// cl /c parser.c
//
// Command Line Arguments/Parameters
// None
//
#include <stdio.h>
#include <stdlib.h>
//
// Function: PrintRawBytes
//
// Description:
// This function simply prints out a series of bytes
// as hexadecimal digits.
//
void PrintRawBytes(BYTE *ptr, DWORD len)
{
int i;
while (len > 0)
{
for(i=0; i < 20 ;i++)
{
printf("%x%x ", HI_WORD(*ptr), LO_WORD(*ptr));
len--;
ptr++;
if (len == 0)
break;
}
printf("\n");
}
}
//
// Function: DecodeIGMPHeader
//
// Description:
// This function takes a pointer to a buffer containing
// an IGMP packet and prints it out in a readable form.
//
int DecodeIGMPHeader(WSABUF *wsabuf, DWORD iphdrlen)
{
BYTE *hdr = (BYTE *)(wsabuf->buf + iphdrlen);
unsigned short chksum,
version,
type,
maxresptime;
SOCKADDR_IN addr;
version = HI_WORD(*hdr);
type = LO_WORD(*hdr);
hdr++;
printf(" IGMP HEADER:\n");
if ((type == 1) || (type == 2))
version = 1;
else
version = 2;
printf(" IGMP Version = %d\n", version);
printf(" IGMP Type = %s\n", szIgmpType[type]);
if (version == 2)
printf(" Max Resp Time = %d\n", maxresptime);
printf(" IGMP Grp Addr = %s\n", inet_ntoa(addr.sin_addr));
//ExitProcess(0);
return 0;
}
//
// Function: DecodeUDPHeader
//
// Description:
// This function takes a buffer which points to a UDP
// header and prints it out in a readable form.
//
int DecodeUDPHeader(WSABUF *wsabuf, DWORD iphdrlen)
{
BYTE *hdr = (BYTE *)(wsabuf->buf + iphdrlen);
unsigned short shortval,
udp_src_port,
udp_dest_port,
udp_len,
udp_chksum;
//
// Function: DecodeTCPHeader
//
// Description:
// This function takes a buffer pointing to a TCP header
// and prints it out in a readable form.
//
int DecodeTCPHeader(WSABUF *wsabuf, DWORD iphdrlen)
{
BYTE *hdr = (BYTE *)(wsabuf->buf + iphdrlen);
unsigned short shortval;
unsigned int longval;
//
// Function: DecodeIPHeader
//
// Description:
// This function takes a pointer to an IP header and prints
// it out in a readable form.
//
int DecodeIPHeader(WSABUF *wsabuf, unsigned int srcip, unsigned short srcport,
unsigned int destip, unsigned short destport)
{
BYTE *hdr = (BYTE *)wsabuf->buf,
*nexthdr = NULL;
unsigned short shortval;
SOCKADDR_IN srcaddr,
destaddr;