"@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
The Regents of the University of California. All rights reserved.\n";
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/tcpdump.c,v 1.262 2005-10-20 07:43:52 hannes Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/tcpdump.c,v 1.269 2006-05-05 23:13:01 guy Exp $ (LBL)";
#endif
/*
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <limits.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
#ifndef WIN32
#include <pwd.h>
#include <grp.h>
int dflag; /* print filter code */
int Lflag; /* list available data link types and exit */
+char *zflag = NULL; /* compress each savefile using a specified command (like gzip or bzip2) */
static int infodelay;
static int infoprint;
/* Forwards */
static RETSIGTYPE cleanup(int);
+static RETSIGTYPE child_cleanup(int);
static void usage(void) __attribute__((noreturn));
static void show_dlts_and_exit(pcap_t *pd) __attribute__((noreturn));
#endif
#ifdef DLT_JUNIPER_CHDLC
{ juniper_chdlc_print, DLT_JUNIPER_CHDLC },
+#endif
+#ifdef DLT_MFR
+ { mfr_if_print, DLT_MFR },
#endif
{ NULL, 0 },
};
struct dump_info {
char *WFileName;
+ char *CurrentFileName;
pcap_t *pd;
pcap_dumper_t *p;
};
if (snprintf(buffer, NAME_MAX + 1, "%s%0*d", filename, max_chars, cnt) > NAME_MAX)
/* Report an error if the filename is too large */
error("too many output files or filename is too long (> %d)", NAME_MAX);
+ free(filename);
}
static int tcpdump_printf(netdissect_options *ndo _U_,
{
register int cnt, op, i;
bpf_u_int32 localnet, netmask;
- register char *cp, *infile, *cmdbuf, *device, *RFileName, *WFileName, *WFileNameAlt;
+ register char *cp, *infile, *cmdbuf, *device, *RFileName, *WFileName;
pcap_handler callback;
int type;
struct bpf_program fcode;
opterr = 0;
while (
- (op = getopt(argc, argv, "aA" B_FLAG "c:C:d" D_FLAG "eE:fF:G:i:lLm:M:nNOpqr:Rs:StT:u" U_FLAG "vw:W:xXy:YZ:")) != -1)
+ (op = getopt(argc, argv, "aA" B_FLAG "c:C:d" D_FLAG "eE:fF:G:i:KlLm:M:nNOpqr:Rs:StT:u" U_FLAG "vw:W:xXy:Yz:Z:")) != -1)
switch (op) {
case 'a':
case 'G':
Gflag = atoi(optarg);
- /* We will create one file initially. */
- Gflag_count = 0;
- /* Grab the current time for rotation use. */
- {
- struct timeval t;
- if (gettimeofday(&t, NULL) != 0) {
- error("main: gettimeofday");
- }
- Gflag_time = t.tv_sec;
- }
if (Gflag < 0)
error("invalid number of seconds %s", optarg);
+
+ /* We will create one file initially. */
+ Gflag_count = 0;
+
+ /* Grab the current time for rotation use. */
+ if ((Gflag_time = time(NULL)) == (time_t)-1) {
+ error("main: can't get current time: %s",
+ pcap_strerror(errno));
+ }
break;
case 'i':
#endif /* WIN32 */
break;
- case 'n':
- ++nflag;
- break;
-
- case 'N':
- ++Nflag;
+ case 'K':
+ ++Kflag;
break;
case 'm':
#ifdef LIBSMI
- if (smiLoadModule(optarg) == 0) {
+ if (smiLoadModule(optarg) == 0) {
error("could not load MIB module %s", optarg);
- }
+ }
sflag = 1;
#else
(void)fprintf(stderr, "%s: ignoring option `-m %s' ",
tcpmd5secret = optarg;
break;
+ case 'n':
+ ++nflag;
+ break;
+
+ case 'N':
+ ++Nflag;
+ break;
+
case 'O':
Oflag = 0;
break;
}
break;
#endif
+ case 'z':
+ if (optarg) {
+ zflag = strdup(optarg);
+ } else {
+ usage();
+ /* NOTREACHED */
+ }
+ break;
+
case 'Z':
if (optarg) {
username = strdup(optarg);
case 1: /* No time stamp */
case 2: /* Unix timeval style */
case 3: /* Microseconds since previous packet */
+ case 5: /* Microseconds since first packet */
break;
default: /* Not supported */
- error("only -t, -tt, -ttt, and -tttt are supported");
+ error("only -t, -tt, -ttt, -tttt and -ttttt are supported");
break;
}
}
#endif
(void)fprintf(stderr, "%s: data link type %s\n",
- program_name, gndo->ndo_dltname);
+ program_name, gndo->ndo_dltname);
(void)fflush(stderr);
}
i = pcap_snapshot(pd);
exit(0);
}
init_addrtoname(localnet, netmask);
+ init_checksum();
#ifndef WIN32
(void)setsignal(SIGPIPE, cleanup);
#endif /* WIN32 */
(void)setsignal(SIGTERM, cleanup);
(void)setsignal(SIGINT, cleanup);
+ (void)setsignal(SIGCHLD, child_cleanup);
/* Cooperate with nohup(1) */
#ifndef WIN32
if ((oldhandler = setsignal(SIGHUP, cleanup)) != SIG_DFL)
error("%s", pcap_geterr(pd));
if (WFileName) {
pcap_dumper_t *p;
- /* Do not exceed the default NAME_MAX for files. */
- WFileNameAlt = (char *)malloc(NAME_MAX + 1);
+ /* Do not exceed the default NAME_MAX for files. */
+ dumpinfo.CurrentFileName = (char *)malloc(NAME_MAX + 1);
- if (WFileNameAlt == NULL)
- error("malloc of WFileNameAlt");
+ if (dumpinfo.CurrentFileName == NULL)
+ error("malloc of dumpinfo.CurrentFileName");
- /* We do not need numbering for dumpfiles if Cflag isn't set. */
- if (Cflag != 0)
- MakeFilename(WFileNameAlt, WFileName, 0, WflagChars);
- else
- MakeFilename(WFileNameAlt, WFileName, 0, 0);
+ /* We do not need numbering for dumpfiles if Cflag isn't set. */
+ if (Cflag != 0)
+ MakeFilename(dumpinfo.CurrentFileName, WFileName, 0, WflagChars);
+ else
+ MakeFilename(dumpinfo.CurrentFileName, WFileName, 0, 0);
- p = pcap_dump_open(pd, WFileNameAlt);
+ p = pcap_dump_open(pd, dumpinfo.CurrentFileName);
if (p == NULL)
error("%s", pcap_geterr(pd));
if (Cflag != 0 || Gflag != 0) {
#endif
}
+static RETSIGTYPE
+child_cleanup(int signo _U_)
+{
+ wait(NULL);
+}
+
static void
info(register int verbose)
{
infoprint = 0;
}
+static void
+compress_savefile(const char *filename)
+{
+ if (fork())
+ return;
+ /*
+ * Set to lowest priority so that this doesn't disturb the capture
+ */
+#ifdef NZERO
+ setpriority(PRIO_PROCESS, 0, NZERO - 1);
+#else
+ setpriority(PRIO_PROCESS, 0, 19);
+#endif
+ if (execlp(zflag, zflag, filename, NULL) == -1)
+ fprintf(stderr,
+ "compress_savefile:execlp(%s, %s): %s\n",
+ zflag,
+ filename,
+ strerror(errno));
+}
+
static void
dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
{
struct dump_info *dump_info;
- char *name;
++packets_captured;
dump_info = (struct dump_info *)user;
/*
- * XXX - this won't force the file to rotate on the specified time
- * boundary, but it will rotate on the first packet received after the
- * specified Gflag number of seconds. Note: if a Gflag time boundary
- * and a Cflag size boundary coincide, the time rotation will occur
- * first thereby cancelling the Cflag boundary (since the file should
- * be 0).
+ * XXX - this won't force the file to rotate on the specified time
+ * boundary, but it will rotate on the first packet received after the
+ * specified Gflag number of seconds. Note: if a Gflag time boundary
+ * and a Cflag size boundary coincide, the time rotation will occur
+ * first thereby cancelling the Cflag boundary (since the file should
+ * be 0).
*/
- if (Gflag != 0) {
- /* Check if it is time to rotate */
- struct timeval t;
+ if (Gflag != 0) {
+ /* Check if it is time to rotate */
+ time_t t;
- /* Get the current time */
- if (gettimeofday(&t, NULL) != 0) {
- error("dump_and_trunc_packet: gettimeofday");
- }
+ /* Get the current time */
+ if ((t = time(NULL)) == (time_t)-1) {
+ error("dump_and_trunc_packet: can't get current_time: %s",
+ pcap_strerror(errno));
+ }
- /* If the time is greater than the specified window, rotate */
- if (t.tv_sec - Gflag_time >= Gflag) {
- /* Update the Gflag_time */
- Gflag_time = t.tv_sec;
- /* Update Gflag_count */
- Gflag_count++;
- /*
- * Close the current file and open a new one.
- */
- pcap_dump_close(dump_info->p);
-
- /* Check to see if we've exceeded the Wflag (when not using Cflag). */
- if (Cflag == 0 && Wflag > 0 && Gflag_count >= Wflag) {
- (void)fprintf(stderr, "Maximum file limit reached: %d\n", Wflag);
- (void)fflush(stderr);
- exit(0);
- /* NOTREACHED */
- }
- /* Allocate space for max filename + \0. */
- name = (char *)malloc(NAME_MAX + 1);
- if (name == NULL)
- error("dump_packet_and_trunc: malloc");
- /* This is always the first file in the Cflag rotation: e.g. 0
- * We also don't need numbering if Cflag is not set.
- */
- if (Cflag != 0)
- MakeFilename(name, dump_info->WFileName, 0, WflagChars);
- else
- MakeFilename(name, dump_info->WFileName, 0, 0);
-
- dump_info->p = pcap_dump_open(dump_info->pd, name);
- free(name);
- if (dump_info->p == NULL)
- error("%s", pcap_geterr(pd));
+ /* If the time is greater than the specified window, rotate */
+ if (t - Gflag_time >= Gflag) {
+ /* Update the Gflag_time */
+ Gflag_time = t;
+ /* Update Gflag_count */
+ Gflag_count++;
+ /*
+ * Close the current file and open a new one.
+ */
+ pcap_dump_close(dump_info->p);
- }
- }
+ /*
+ * Compress the file we just closed, if the user asked for it
+ */
+ if (zflag != NULL)
+ compress_savefile(dump_info->CurrentFileName);
+
+ /*
+ * Check to see if we've exceeded the Wflag (when
+ * not using Cflag).
+ */
+ if (Cflag == 0 && Wflag > 0 && Gflag_count >= Wflag) {
+ (void)fprintf(stderr, "Maximum file limit reached: %d\n",
+ Wflag);
+ exit(0);
+ /* NOTREACHED */
+ }
+ if (dump_info->CurrentFileName != NULL)
+ free(dump_info->CurrentFileName);
+ /* Allocate space for max filename + \0. */
+ dump_info->CurrentFileName = (char *)malloc(NAME_MAX + 1);
+ if (dump_info->CurrentFileName == NULL)
+ error("dump_packet_and_trunc: malloc");
+ /*
+ * This is always the first file in the Cflag
+ * rotation: e.g. 0
+ * We also don't need numbering if Cflag is not set.
+ */
+ if (Cflag != 0)
+ MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, 0,
+ WflagChars);
+ else
+ MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, 0, 0);
+
+ dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName);
+ if (dump_info->p == NULL)
+ error("%s", pcap_geterr(pd));
+ }
+ }
/*
* XXX - this won't prevent capture files from getting
* Close the current file and open a new one.
*/
pcap_dump_close(dump_info->p);
+
+ /*
+ * Compress the file we just closed, if the user asked for it
+ */
+ if (zflag != NULL)
+ compress_savefile(dump_info->CurrentFileName);
+
Cflag_count++;
if (Wflag > 0) {
if (Cflag_count >= Wflag)
Cflag_count = 0;
}
- name = (char *)malloc(NAME_MAX + 1);
- if (name == NULL)
+ if (dump_info->CurrentFileName != NULL)
+ free(dump_info->CurrentFileName);
+ dump_info->CurrentFileName = (char *)malloc(NAME_MAX + 1);
+ if (dump_info->CurrentFileName == NULL)
error("dump_packet_and_trunc: malloc");
- MakeFilename(name, dump_info->WFileName, Cflag_count, WflagChars);
- dump_info->p = pcap_dump_open(dump_info->pd, name);
- free(name);
+ MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, Cflag_count, WflagChars);
+ dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName);
if (dump_info->p == NULL)
error("%s", pcap_geterr(pd));
}
*/
#ifdef USE_WIN32_MM_TIMER
void CALLBACK verbose_stats_dump (UINT timer_id _U_, UINT msg _U_, DWORD_PTR arg _U_,
- DWORD_PTR dw1 _U_, DWORD_PTR dw2 _U_)
+ DWORD_PTR dw1 _U_, DWORD_PTR dw2 _U_)
{
struct pcap_stat stat;
#endif /* WIN32 */
#endif /* HAVE_PCAP_LIB_VERSION */
(void)fprintf(stderr,
-"Usage: %s [-aAd" D_FLAG "eflLnNOpqRStu" U_FLAG "vxX]" B_FLAG_USAGE " [-c count] [ -C file_size ]\n", program_name);
+"Usage: %s [-aAd" D_FLAG "efKlLnNOpqRStu" U_FLAG "vxX]" B_FLAG_USAGE " [-c count] [ -C file_size ]\n", program_name);
(void)fprintf(stderr,
"\t\t[ -E algo:secret ] [ -F file ] [ -G seconds ] [ -i interface ]\n");
(void)fprintf(stderr,
"\t\t[ -M secret ] [ -r file ] [ -s snaplen ] [ -T type ] [ -w file ]\n");
(void)fprintf(stderr,
-"\t\t[ -W filecount ] [ -y datalinktype ] [ -Z user ]\n");
+"\t\t[ -W filecount ] [ -y datalinktype ] [ -z command ] [ -Z user ]\n");
(void)fprintf(stderr,
"\t\t[ expression ]\n");
exit(1);