blocking examine.c
/*
examine.c
written by Richard Gordon
last modified 3/8/00
This program displays all packets arriving on a specific interface.
It is called by
examine <interface>
where <interface> is "eth0", "eth1", etc. To quit the program
type CONTROL-C (i.e. interrupt).
*/
#include <stdio.h>
#include <signal.h>
#include <sys/socket.h>
#include <linux/if_arp.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <unistd.h>
#define BUFFER_LEN 1600
/* local prototypes */
static void interrupt_handler( int i );
void set_promiscuous_mode( char* interface );
void clear_promiscuous_mode( char* interface );
/* static variables */
static char* interface;
int main( int argc, char** argv )
{
char buffer[ BUFFER_LEN ];
int sock;
/* the call must be of the form examine <interface> */
if (argc != 2)
{
fprintf( stderr, "usage: examine <interface>\n" );
exit(1);
}
interface = argv[1];
/* catch interrupts */
signal( SIGINT, interrupt_handler );
/* open a socket for catching raw packets */
if ((sock = socket( PF_INET, SOCK_PACKET, htons(ETH_P_ALL) ))<0)
{
perror( "examine: socket" );
exit(1);
}
/* put the interface into promiscuous mode */
set_promiscuous_mode( interface );
/* loop until interrupted */
while (1)
{
struct sockaddr address;
socklen_t address_len;
int packet_len;
/* block until you receive a packet from any interface */
address_len = sizeof( address );
packet_len = recvfrom( sock, buffer, BUFFER_LEN, 0, &address, &address_len );
/* check the interface the packet arrived on */
/* only handle packets on the specified interface */
if (strcmp( address.sa_data, interface ) == 0)
{
int i;
fprintf( stdout, "\nlength = %d\n\n", packet_len );
for (i=0; i<packet_len; i++)
{
fprintf( stdout, "%2.2hX ", (unsigned char) buffer[ i ] );
if (i%16 == 15)
fprintf( stdout, "\n" );
}
fprintf( stdout, "\n" );
}
}
return 0;
}
void interrupt_handler( int i )
{
clear_promiscuous_mode( interface );
exit(0);
}
void set_promiscuous_mode( char* interface )
{
int sock;
struct ifreq flags;
sock = socket( PF_INET, SOCK_PACKET, htons( ETH_P_ALL ) );
strcpy( flags.ifr_name, interface );
ioctl( sock, SIOCGIFFLAGS, &flags );
flags.ifr_flags |= IFF_PROMISC;
ioctl( sock, SIOCSIFFLAGS, &flags );
close( sock );
}
void clear_promiscuous_mode( char* interface )
{
int sock;
struct ifreq flags;
sock = socket( PF_INET, SOCK_PACKET, htons(ETH_P_ALL));
strcpy( flags.ifr_name, interface );
ioctl( sock, SIOCGIFFLAGS, &flags );
flags.ifr_flags &= ~IFF_PROMISC;
ioctl( sock, SIOCSIFFLAGS, &flags );
close( sock );
}
all: examine examine: examine.c gcc -o examine examine.c clean: -rm -f *~ examine