X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/f4e513061799a0550c3cb72f2f8b32aecb1860ac..48ecdd0e0bb33d17852063fbf839b593f1dfc8bf:/tcpdump.c diff --git a/tcpdump.c b/tcpdump.c index 65e108a0..561c9149 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.267 2006-02-09 20:33:49 hannes Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/tcpdump/tcpdump.c,v 1.271.2.5 2008-01-29 10:50:28 guy Exp $ (LBL)"; #endif /* @@ -65,12 +65,16 @@ extern int SIZE_BUF; #include #include #include +#include #ifndef WIN32 +#include +#include #include #include #include #endif /* WIN32 */ + #include "netdissect.h" #include "interface.h" #include "addrtoname.h" @@ -88,6 +92,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 +103,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)); @@ -186,7 +192,7 @@ static struct printer printers[] = { #ifdef DLT_LTALK { ltalk_if_print, DLT_LTALK }, #endif -#ifdef DLT_PFLOG +#if defined(DLT_PFLOG) && defined(HAVE_NET_PFVAR_H) { pflog_if_print, DLT_PFLOG }, #endif #ifdef DLT_FR @@ -216,6 +222,9 @@ static struct printer printers[] = { #ifdef DLT_APPLE_IP_OVER_IEEE1394 { ap1394_if_print, DLT_APPLE_IP_OVER_IEEE1394 }, #endif +#ifdef DLT_IEEE802_11_RADIO_AVS + { ieee802_11_radio_avs_if_print, DLT_IEEE802_11_RADIO_AVS }, +#endif #ifdef DLT_JUNIPER_ATM1 { juniper_atm1_print, DLT_JUNIPER_ATM1 }, #endif @@ -263,6 +272,9 @@ static struct printer printers[] = { #endif #ifdef DLT_MFR { mfr_if_print, DLT_MFR }, +#endif +#ifdef DLT_BLUETOOTH_HCI_H4_WITH_PHDR + { bt_if_print, DLT_BLUETOOTH_HCI_H4_WITH_PHDR}, #endif { NULL, 0 }, }; @@ -292,6 +304,7 @@ struct print_info { struct dump_info { char *WFileName; + char *CurrentFileName; pcap_t *pd; pcap_dumper_t *p; }; @@ -321,10 +334,10 @@ show_dlts_and_exit(pcap_t *pd) * OK, does tcpdump handle that type? */ if (lookup_printer(dlts[n_dlts]) == NULL) - (void) fprintf(stderr, " (not supported)"); + (void) fprintf(stderr, " (printing not supported)"); putchar('\n'); } else { - (void) fprintf(stderr, " DLT %d (not supported)\n", + (void) fprintf(stderr, " DLT %d (printing not supported)\n", dlts[n_dlts]); } } @@ -466,7 +479,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; @@ -517,7 +530,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': @@ -662,12 +675,8 @@ main(int argc, char **argv) #endif /* WIN32 */ break; - case 'n': - ++nflag; - break; - - case 'N': - ++Nflag; + case 'K': + ++Kflag; break; case 'm': @@ -691,6 +700,14 @@ main(int argc, char **argv) tcpmd5secret = optarg; break; + case 'n': + ++nflag; + break; + + case 'N': + ++Nflag; + break; + case 'O': Oflag = 0; break; @@ -812,6 +829,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); @@ -984,9 +1010,10 @@ main(int argc, char **argv) #ifndef WIN32 (void)setsignal(SIGPIPE, cleanup); -#endif /* WIN32 */ (void)setsignal(SIGTERM, cleanup); (void)setsignal(SIGINT, cleanup); + (void)setsignal(SIGCHLD, child_cleanup); +#endif /* WIN32 */ /* Cooperate with nohup(1) */ #ifndef WIN32 if ((oldhandler = setsignal(SIGHUP, cleanup)) != SIG_DFL) @@ -998,19 +1025,18 @@ main(int argc, char **argv) if (WFileName) { pcap_dumper_t *p; /* Do not exceed the default NAME_MAX for files. */ - WFileNameAlt = (char *)malloc(NAME_MAX + 1); + 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); + MakeFilename(dumpinfo.CurrentFileName, WFileName, 0, WflagChars); else - MakeFilename(WFileNameAlt, WFileName, 0, 0); + 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) { @@ -1048,7 +1074,12 @@ main(int argc, char **argv) } #endif /* WIN32 */ #ifdef SIGINFO - (void)setsignal(SIGINFO, requestinfo); + /* + * We can't get statistics when reading from a file rather + * than capturing from a device. + */ + if (RFileName == NULL) + (void)setsignal(SIGINFO, requestinfo); #endif if (vflag > 0 && WFileName) { @@ -1166,6 +1197,18 @@ cleanup(int signo _U_) #endif } +/* + On windows, we do not use a fork, so we do not care less about + waiting a child processes to die + */ +#ifndef WIN32 +static RETSIGTYPE +child_cleanup(int signo _U_) +{ + wait(NULL); +} +#endif /* WIN32 */ + static void info(register int verbose) { @@ -1173,6 +1216,7 @@ info(register int verbose) if (pcap_stats(pd, &stat) < 0) { (void)fprintf(stderr, "pcap_stats: %s\n", pcap_geterr(pd)); + infoprint = 0; return; } @@ -1193,11 +1237,40 @@ info(register int verbose) infoprint = 0; } +#ifndef WIN32 +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)); +} +#else /* WIN32 */ +static void +compress_savefile(const char *filename) +{ + fprintf(stderr, + "compress_savefile failed. Functionality not implemented under windows\n"); +} +#endif /* WIN32 */ + 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; @@ -1235,6 +1308,12 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s */ 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). @@ -1245,9 +1324,11 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s exit(0); /* NOTREACHED */ } + if (dump_info->CurrentFileName != NULL) + free(dump_info->CurrentFileName); /* Allocate space for max filename + \0. */ - name = (char *)malloc(NAME_MAX + 1); - if (name == NULL) + 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 @@ -1255,13 +1336,12 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s * We also don't need numbering if Cflag is not set. */ if (Cflag != 0) - MakeFilename(name, dump_info->WFileName, 0, + MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, 0, WflagChars); else - MakeFilename(name, dump_info->WFileName, 0, 0); + MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, 0, 0); - dump_info->p = pcap_dump_open(dump_info->pd, name); - free(name); + dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName); if (dump_info->p == NULL) error("%s", pcap_geterr(pd)); } @@ -1277,17 +1357,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)); } @@ -1511,13 +1599,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);