X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/9574a70f4c4171bb1fc5038af89661535418551c..90c94a826593a4c543f11ba4cefa71eafb7ae1c0:/tcpdump.c diff --git a/tcpdump.c b/tcpdump.c index 9f8a1394..7e1f1299 100644 --- a/tcpdump.c +++ b/tcpdump.c @@ -30,7 +30,7 @@ static const char copyright[] _U_ = "@(#) 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.263 2005-10-25 09:29:44 hannes Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/tcpdump/tcpdump.c,v 1.269 2006-05-05 23:13:01 guy Exp $ (LBL)"; #endif /* @@ -65,6 +65,9 @@ extern int SIZE_BUF; #include #include #include +#include +#include +#include #ifndef WIN32 #include #include @@ -88,6 +91,7 @@ netdissect_options *gndo = &Gndo; 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; @@ -98,6 +102,7 @@ int32_t thiszone; /* seconds offset from gmt to local time */ /* 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)); @@ -260,6 +265,9 @@ static struct printer printers[] = { #endif #ifdef DLT_JUNIPER_CHDLC { juniper_chdlc_print, DLT_JUNIPER_CHDLC }, +#endif +#ifdef DLT_MFR + { mfr_if_print, DLT_MFR }, #endif { NULL, 0 }, }; @@ -289,6 +297,7 @@ struct print_info { struct dump_info { char *WFileName; + char *CurrentFileName; pcap_t *pd; pcap_dumper_t *p; }; @@ -463,7 +472,7 @@ main(int argc, char **argv) { 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; @@ -514,7 +523,7 @@ main(int argc, char **argv) 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': @@ -590,18 +599,17 @@ main(int argc, char **argv) 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': @@ -660,19 +668,15 @@ main(int argc, char **argv) #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' ", @@ -689,6 +693,14 @@ main(int argc, char **argv) tcpmd5secret = optarg; break; + case 'n': + ++nflag; + break; + + case 'N': + ++Nflag; + break; + case 'O': Oflag = 0; break; @@ -810,6 +822,15 @@ main(int argc, char **argv) } break; #endif + case 'z': + if (optarg) { + zflag = strdup(optarg); + } else { + usage(); + /* NOTREACHED */ + } + break; + case 'Z': if (optarg) { username = strdup(optarg); @@ -835,10 +856,11 @@ main(int argc, char **argv) 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; } @@ -950,7 +972,7 @@ main(int argc, char **argv) } #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); @@ -977,12 +999,14 @@ main(int argc, char **argv) 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) @@ -993,20 +1017,19 @@ main(int argc, char **argv) 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); - free(WFileNameAlt); + p = pcap_dump_open(pd, dumpinfo.CurrentFileName); if (p == NULL) error("%s", pcap_geterr(pd)); if (Cflag != 0 || Gflag != 0) { @@ -1162,6 +1185,12 @@ cleanup(int signo _U_) #endif } +static RETSIGTYPE +child_cleanup(int signo _U_) +{ + wait(NULL); +} + static void info(register int verbose) { @@ -1189,11 +1218,31 @@ 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; @@ -1202,60 +1251,73 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s 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 @@ -1267,17 +1329,25 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s * 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)); } @@ -1454,7 +1524,7 @@ RETSIGTYPE requestinfo(int signo _U_) */ #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; @@ -1501,13 +1571,13 @@ usage(void) #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);