/****************************************************************************
**
** File: ipgrab.c
**
** Author: Mike Borella
**
** Sniffs all packets on the link and dumps the fields of the data link,
** IP, TCP, and UDP headers.
**
** $Id: ipgrab.c,v 1.18 2001/11/15 19:28:45 mborella Exp $
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU Library General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
*****************************************************************************/
#include "global.h"
#include "datalink.h"
#include "ipgrab.h"
#include "open_pcap.h"
#include "ip_protocols.h"
#include "error.h"
#include "stats.h"
#include "dynports.h"
#include "file.h"
char * pcap_cmd; /* command string for pcap */
pcap_t * pd; /* pcap device descriptor */
int cnt; /* number of packets to read */
pcap_handler dev_prcsr; /* ptr to func that processes packet for a device */
pcap_dumper_t * p; /* pointer to pcap dump file for writing */
struct arg_t * my_args; /* Command line arguments */
RETSIGTYPE cleanup(void);
RETSIGTYPE cleanup_pcap(void);
/*----------------------------------------------------------------------------
*
* main()
*
*----------------------------------------------------------------------------
*/
int main(int argc, char *argv[])
{
u_int8_t * userdata;
int link;
/*
* Initiatilize the IP family module and the stats collection module
*/
init_ip_protocols();
stats_init();
/*
* Set the layer
*/
set_layer(LAYER_NONE);
/*
* Clear packet count
*/
cnt = -1;
/*
* Parse command line for options, take care for version and packet count
*/
my_args = Cmdline(argc, argv);
if (my_args->v)
{
printf("%s\n", VERSION);
return 0;
}
if (my_args->c)
cnt = my_args->c;
/*
* Make stdout buffered, if necessary
*/
if (my_args->b)
#ifdef HAVE_SETLINEBUF
setlinebuf(stdout);
#else
setvbuf(stdout, NULL, _IOLBF, 0);
#endif
/*
* Parse any dynamic port bindings
*/
if (my_args->P)
dynports_parse(my_args->P);
/*
* If we're reading a file, do things in a generic fashion. Otherwise
* use standard libpcap functions to do a live read.
*/
if (my_args->r)
{
int ret;
/*Get rid of root privs, not needed for reading files */
setuid(getuid());
/*
* Set the signals so that we can clean up when ctrl-C is pressed
* or some other reason causes the program to stop
*/
signal(SIGTERM, (sighandler_t) cleanup);
signal(SIGINT, (sighandler_t) cleanup);
signal(SIGQUIT, (sighandler_t) cleanup);
signal(SIGABRT, (sighandler_t) cleanup);
/* Try to ID the trace file type */
ret = file_id(my_args->r);
if (ret == 0)
error_fatal("unrecognized file type: %s", my_args->r);
/* Open the file */
file_open(my_args->r);
/* Read the packets */
file_read(cnt);
/* When done, dump the stats */
stats_dump();
}
else
{
/* This is just for live packet capture, not reading from a file */
/*
* Set the signals so that we can clean up when ctrl-C is pressed
* or some other reason causes the program to stop
*/
signal(SIGTERM, (sighandler_t) cleanup_pcap);
signal(SIGINT, (sighandler_t) cleanup_pcap);
signal(SIGQUIT, (sighandler_t) cleanup_pcap);
signal(SIGABRT, (sighandler_t) cleanup_pcap);
/*
* Copy filter command into a string only if there is a command
*/
if (my_args->optind)
pcap_cmd = argv2str(&argv[my_args->optind]);
/*
* Open the pcap device for sniffing
*/
link = open_pcap();
/*
* Get rid of root privs
*/
setuid(getuid());
/*
* Print intro stuff to stderr so output files have consistent
* format
*/
fprintf(stderr, "%s %s\n", PACKAGE, VERSION);
fprintf(stderr, "Listening on device %s ", my_args->i);
switch(link)
{
case DLT_NULL:
fprintf(stderr,"(loopback)\n");
break;
case DLT_EN10MB:
fprintf(stderr, "(ethernet)\n");
break;
case DLT_SLIP:
fprintf(stderr, "(slip)\n");
break;
#ifdef DLT_RAW /* Not supported in some arch or older pcap versions */
case DLT_RAW:
fprintf(stderr, "(raw)\n");
break;
#endif
case DLT_PPP:
fprintf(stderr, "(ppp)\n");
break;
default:
error_fatal("\n%s cannot handle data link type %d", argv[0], link);
}
/*
* Put the link type into a string
*/
userdata = (u_char *) &link;
/*
* Open the file for writing if -w is used
*/
if (my_args->w)
{
p = pcap_dump_open(pd, my_args->w);
if (p == NULL)
error_system("pcap_dump_open: %s", pcap_geterr(pd));
/* Read the specified number of packets */
if (pcap_loop(pd, cnt, pcap_dump, (u_char *) p) < 0)
error_fatal("pcap_loop: %s", pcap_geterr(pd));
}
else
{
/* Read all packets on the device. Continue until cnt packets read */
if (pcap_loop(pd, cnt, (pcap_func_t) datalink_pcap, userdata) < 0)
error_fatal("pcap_loop: %s", pcap_geterr(pd));
}
cleanup_pcap();
}
return 0;
}
/*----------------------------------------------------------------------------
*
* cleanup_pcap()
*
* Cleanup and collect PCAP statistics
*
*----------------------------------------------------------------------------
*/
RETSIGTYPE cleanup_pcap(void)
{
struct pcap_stat stats;
if (pcap_stats(pd, &stats) < 0)
fprintf(stderr, "pcap_stats: %s\n", pcap_geterr(pd));
else
{
fprintf(stderr, "%d packets received\n", stats.ps_recv);
fprintf(stderr, "%d packets dropped by kernel\n", stats.ps_drop);
}
/* Close the pcap device */
pcap_close(pd);
/* If there was a dump file open for writing, close that too */
if (my_args->w)
pcap_dump_close(p);
/* Display any other states that were collected */
cleanup();
}
/*----------------------------------------------------------------------------
**
** cleanup()
**
** Cleans up any files and displays stats.
**
**----------------------------------------------------------------------------
*/
RETSIGTYPE cleanup (void)
{
stats_dump();
exit(0);
}
syntax highlighted by Code2HTML, v. 0.9.1