X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/60761585472a90c34d7de7bdf50475f0d7261b2d..ad06a893cfd3acca3fba38d8b39b6b15dd3053ea:/tcpdump.c diff --git a/tcpdump.c b/tcpdump.c index 73afb273..e8a89fbe 100644 --- a/tcpdump.c +++ b/tcpdump.c @@ -30,7 +30,7 @@ static const char copyright[] = "@(#) 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[] = - "@(#) $Header: /tcpdump/master/tcpdump/tcpdump.c,v 1.192 2002-12-19 09:27:57 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/tcpdump/tcpdump.c,v 1.201 2003-01-23 09:05:38 guy Exp $ (LBL)"; #endif /* @@ -83,6 +83,7 @@ int Rflag = 1; /* print sequence # field in AH/ESP*/ int sflag = 0; /* use the libsmi to translate OIDs */ int Sflag; /* print raw TCP sequence numbers */ int tflag = 1; /* print packet arrival time */ +int Uflag = 0; /* "unbuffered" output of dump files */ int uflag = 0; /* Print undecoded NFS handles */ int vflag; /* verbose */ int xflag; /* print packet in hex */ @@ -97,8 +98,8 @@ char *espsecret = NULL; /* ESP secret key */ int packettype; -int infodelay; -int infoprint; +static int infodelay; +static int infoprint; char *program_name; @@ -109,6 +110,7 @@ static RETSIGTYPE cleanup(int); static void usage(void) __attribute__((noreturn)); static void show_dlts_and_exit(pcap_t *pd) __attribute__((noreturn)); +static void print_packet(u_char *, const struct pcap_pkthdr *, const u_char *); static void dump_packet_and_trunc(u_char *, const struct pcap_pkthdr *, const u_char *); static void dump_packet(u_char *, const struct pcap_pkthdr *, const u_char *); @@ -116,16 +118,23 @@ static void dump_packet(u_char *, const struct pcap_pkthdr *, const u_char *); RETSIGTYPE requestinfo(int); #endif +static void info(int); + /* Length of saved portion of packet. */ int snaplen = DEFAULT_SNAPLEN; +typedef u_int (*if_printer)(const struct pcap_pkthdr *, const u_char *); + struct printer { - pcap_handler f; + if_printer f; int type; }; static struct printer printers[] = { { arcnet_if_print, DLT_ARCNET }, +#ifdef DLT_ARCNET_LINUX + { arcnet_linux_if_print, DLT_ARCNET_LINUX }, +#endif { ether_if_print, DLT_EN10MB }, { token_if_print, DLT_IEEE802 }, #ifdef DLT_LANE8023 @@ -193,7 +202,7 @@ static struct printer printers[] = { { NULL, 0 }, }; -static pcap_handler +static if_printer lookup_printer(int type) { struct printer *p; @@ -212,6 +221,10 @@ extern int optind; extern int opterr; extern char *optarg; +struct print_info { + if_printer printer; +}; + struct dump_info { char *WFileName; pcap_t *pd; @@ -253,18 +266,43 @@ show_dlts_and_exit(pcap_t *pd) exit(0); } +/* + * Set up flags that might or might not be supported depending on the + * version of libpcap we're using. + */ +#ifdef WIN32 +#define B_FLAG "B:" +#define B_FLAG_USAGE " [ -B size ]" +#else /* WIN32 */ +#define B_FLAG +#define B_FLAG_USAGE +#endif /* WIN32 */ + +#ifdef HAVE_PCAP_FINDALLDEVS +#define D_FLAG "D" +#else +#define D_FLAG +#endif + +#ifdef HAVE_PCAP_DUMP_FLUSH +#define U_FLAG "U" +#else +#define U_FLAG +#endif + int main(int argc, char **argv) { register int cnt, op, i; bpf_u_int32 localnet, netmask; register char *cp, *infile, *cmdbuf, *device, *RFileName, *WFileName; + pcap_handler callback; int type; - pcap_handler printer; struct bpf_program fcode; #ifndef WIN32 RETSIGTYPE (*oldhandler)(int); #endif + struct print_info printinfo; struct dump_info dumpinfo; u_char *pcap_userdata; char ebuf[PCAP_ERRBUF_SIZE]; @@ -303,15 +341,7 @@ main(int argc, char **argv) opterr = 0; while ( -#ifdef WIN32 - (op = getopt(argc, argv, "aAB:c:C:dDeE:fF:i:lLm:nNOpqr:Rs:StT:uvw:xXy:Y")) != -1) -#else /* WIN32 */ -#ifdef HAVE_PCAP_FINDALLDEVS - (op = getopt(argc, argv, "aAc:C:dDeE:fF:i:lLm:nNOpqr:Rs:StT:uvw:xXy:Y")) != -1) -#else /* HAVE_PCAP_FINDALLDEVS */ - (op = getopt(argc, argv, "aAc:C:deE:fF:i:lLm:nNOpqr:Rs:StT:uvw:xXy:Y")) != -1) -#endif /* HAVE_PCAP_FINDALLDEVS */ -#endif /* WIN32 */ + (op = getopt(argc, argv, "aA" B_FLAG "c:C:d" D_FLAG "eE:fF:i:lLm:nNOpqr:Rs:StT:u" U_FLAG "vw:xXy:Y")) != -1) switch (op) { case 'a': @@ -513,6 +543,12 @@ main(int argc, char **argv) ++uflag; break; +#ifdef HAVE_PCAP_DUMP_FLUSH + case 'U': + ++Uflag; + break; +#endif + case 'v': ++vflag; break; @@ -667,38 +703,45 @@ main(int argc, char **argv) if (p == NULL) error("%s", pcap_geterr(pd)); if (Cflag != 0) { - printer = dump_packet_and_trunc; + callback = dump_packet_and_trunc; dumpinfo.WFileName = WFileName; dumpinfo.pd = pd; dumpinfo.p = p; pcap_userdata = (u_char *)&dumpinfo; } else { - printer = dump_packet; + callback = dump_packet; pcap_userdata = (u_char *)p; } } else { type = pcap_datalink(pd); - printer = lookup_printer(type); - if (printer == NULL) { + printinfo.printer = lookup_printer(type); + if (printinfo.printer == NULL) { dlt_name = pcap_datalink_val_to_name(type); if (dlt_name != NULL) error("unsupported data link type %s", dlt_name); else error("unsupported data link type %d", type); } - pcap_userdata = 0; + callback = print_packet; + pcap_userdata = (u_char *)&printinfo; } #ifdef SIGINFO (void)setsignal(SIGINFO, requestinfo); #endif #ifndef WIN32 if (RFileName == NULL) { - (void)fprintf(stderr, "%s: listening on %s\n", - program_name, device); + if (!vflag && !WFileName) { + (void)fprintf(stderr, + "%s: verbose output suppressed, use -v or -vv for full protocol decode\n", + program_name); + } else + (void)fprintf(stderr, "%s: ", program_name); + (void)fprintf(stderr, "listening on %s, capture size %u bytes\n", + device, snaplen); (void)fflush(stderr); } #endif /* WIN32 */ - if (pcap_loop(pd, cnt, printer, pcap_userdata) < 0) { + if (pcap_loop(pd, cnt, callback, pcap_userdata) < 0) { (void)fprintf(stderr, "%s: pcap_loop: %s\n", program_name, pcap_geterr(pd)); cleanup(0); @@ -726,7 +769,7 @@ cleanup(int signo) exit(0); } -void +static void info(register int verbose) { struct pcap_stat stat; @@ -806,6 +849,10 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s } pcap_dump((u_char *)dump_info->p, h, sp); +#ifdef HAVE_PCAP_DUMP_FLUSH + if (Uflag) + pcap_dump_flush(dump_info->p); +#endif --infodelay; if (infoprint) @@ -818,6 +865,57 @@ dump_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) ++infodelay; pcap_dump(user, h, sp); +#ifdef HAVE_PCAP_DUMP_FLUSH + if (Uflag) + pcap_dump_flush((pcap_dumper_t *)user); +#endif + + --infodelay; + if (infoprint) + info(0); +} + +static void +print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) +{ + struct print_info *print_info; + u_int hdrlen; + + ++infodelay; + ts_print(&h->ts); + + print_info = (struct print_info *)user; + + /* + * Some printers want to check that they're not walking off the + * end of the packet. + * Rather than pass it all the way down, we set this global. + */ + snapend = sp + h->caplen; + + hdrlen = (*print_info->printer)(h, sp); + if (xflag) { + /* + * Print the raw packet data. + */ + if (xflag > 1) { + /* + * Include the link-layer header. + */ + default_print_unaligned(sp, h->caplen); + } else { + /* + * Don't include the link-layer header - and if + * we have nothing past the link-layer header, + * print nothing. + */ + if (h->caplen > hdrlen) + default_print_unaligned(sp + hdrlen, + h->caplen - hdrlen); + } + } + + putchar('\n'); --infodelay; if (infoprint) @@ -884,31 +982,6 @@ default_print(register const u_char *bp, register u_int length) default_print_unaligned(bp, length); } -/* - * By default, print the packet out in hex; if eflag is set, print - * everything, otherwise print everything except for the link-layer - * header. - */ -void -default_print_packet(register const u_char *bp, register u_int length, - u_int hdr_length) -{ - if (xflag > 1) { - /* - * Include the link-layer header. - */ - default_print_unaligned(bp, length); - } else { - /* - * Don't include the link-layer header - and if we have - * nothing past the link-layer header, print nothing. - */ - if (length > hdr_length) - default_print_unaligned(bp + hdr_length, - length - hdr_length); - } -} - #ifdef SIGINFO RETSIGTYPE requestinfo(int signo _U_) { @@ -937,15 +1010,7 @@ usage(void) (void)fprintf(stderr, "libpcap version %s\n", pcap_version); #endif /* WIN32 */ (void)fprintf(stderr, -#ifdef WIN32 -"Usage: %s [-aAdDeflLnNOpqRStuvxX] [-B size] [-c count] [ -C file_size ]\n", program_name); -#else /* WIN32 */ -#ifdef HAVE_PCAP_FINDALLDEVS -"Usage: %s [-aAdDeflLnNOpqRStuvxX] [-c count] [ -C file_size ]\n", program_name); -#else /* HAVE_PCAP_FINDALLDEVS */ -"Usage: %s [-aAdeflLnNOpqRStuvxX] [-c count] [ -C file_size ]\n", program_name); -#endif /* HAVE_PCAP_FINDALLDEVS */ -#endif /* WIN32 */ +"Usage: %s [-aAd" D_FLAG "eflLnNOpqRStu" U_FLAG "vxX]" B_FLAG_USAGE " [-c count] [ -C file_size ]\n", program_name); (void)fprintf(stderr, "\t\t[ -E algo:secret ] [ -F file ] [ -i interface ] [ -r file ]\n"); (void)fprintf(stderr,