X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/af44e60e4e7d7a6bd71cab9bd64b9245a5d39949..bfadcfe91ffc2584d00b6a9def079fa1e6b5cdfc:/tcpdump.c?ds=sidebyside diff --git a/tcpdump.c b/tcpdump.c index ce32be5e..3f175c28 100644 --- a/tcpdump.c +++ b/tcpdump.c @@ -26,11 +26,11 @@ */ #ifndef lint -static const char copyright[] = +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[] = - "@(#) $Header: /tcpdump/master/tcpdump/tcpdump.c,v 1.214 2003-08-08 09:47:45 risso Exp $ (LBL)"; +static const char rcsid[] _U_ = + "@(#) $Header: /tcpdump/master/tcpdump/tcpdump.c,v 1.216.2.12 2004-06-15 00:01:52 guy Exp $ (LBL)"; #endif /* @@ -118,6 +118,7 @@ RETSIGTYPE requestinfo(int); #endif static void info(int); +static u_int packets_captured; /* Length of saved portion of packet. */ int snaplen = DEFAULT_SNAPLEN; @@ -204,6 +205,9 @@ static struct printer printers[] = { #endif #ifdef DLT_ENC { enc_if_print, DLT_ENC }, +#endif +#ifdef DLT_APPLE_IP_OVER_IEEE1394 + { ap1394_if_print, DLT_APPLE_IP_OVER_IEEE1394 }, #endif { NULL, 0 }, }; @@ -255,7 +259,8 @@ show_dlts_and_exit(pcap_t *pd) while (--n_dlts >= 0) { dlt_name = pcap_datalink_val_to_name(dlts[n_dlts]); if (dlt_name != NULL) { - (void) fprintf(stderr, " %s", dlt_name); + (void) fprintf(stderr, " %s (%s)", dlt_name, + pcap_datalink_val_to_description(dlts[n_dlts])); /* * OK, does tcpdump handle that type? @@ -316,6 +321,7 @@ main(int argc, char **argv) pcap_if_t *devpointer; int devnum; #endif + int status; #ifdef WIN32 u_int UserBufferSize = 1000000; if(wsockinit() != 0) return 1; @@ -452,11 +458,24 @@ main(int argc, char **argv) break; case 'l': +#ifdef WIN32 + /* + * _IOLBF is the same as _IOFBF in Microsoft's C + * libraries; the only alternative they offer + * is _IONBF. + * + * XXX - this should really be checking for MSVC++, + * not WIN32, if, for example, MinGW has its own + * C library that is more UNIX-compatible. + */ + setvbuf(stdout, NULL, _IONBF, 0); +#else /* WIN32 */ #ifdef HAVE_SETLINEBUF setlinebuf(stdout); #else setvbuf(stdout, NULL, _IOLBF, 0); #endif +#endif /* WIN32 */ break; case 'n': @@ -478,6 +497,7 @@ main(int argc, char **argv) program_name, optarg); (void)fprintf(stderr, "(no libsmi support)\n"); #endif + break; case 'O': Oflag = 0; @@ -595,7 +615,7 @@ main(int argc, char **argv) /* NOTREACHED */ } - if (tflag > 0) + if (tflag > 0 || tflag == -3) thiszone = gmt2local(0); if (RFileName != NULL) { @@ -619,10 +639,15 @@ main(int argc, char **argv) error("%s", ebuf); dlt = pcap_datalink(pd); dlt_name = pcap_datalink_val_to_name(dlt); - if (dlt_name == NULL) - dlt_name = "???"; - printf("reading from file %s, link-type %u (%s)\n", - RFileName, dlt, dlt_name); + if (dlt_name == NULL) { + fprintf(stderr, "reading from file %s, link-type %u\n", + RFileName, dlt); + } else { + fprintf(stderr, + "reading from file %s, link-type %s (%s)\n", + RFileName, dlt_name, + pcap_datalink_val_to_description(dlt)); + } localnet = 0; netmask = 0; if (fflag != 0) @@ -634,11 +659,8 @@ main(int argc, char **argv) error("%s", ebuf); } #ifdef WIN32 - if(IsTextUnicode(device, - wcslen((short*)device), // Device always ends with a double \0, so this way to determine its - // length should be always valid - NULL)) - { + if(strlen(device) == 1) //we assume that an ASCII string is always longer than 1 char + { //a Unicode string has a \0 as second byte (so strlen() is 1) fprintf(stderr, "%s: listening on %ws\n", program_name, device); } else @@ -768,39 +790,82 @@ main(int argc, char **argv) (void)fprintf(stderr, "%s: ", program_name); dlt = pcap_datalink(pd); dlt_name = pcap_datalink_val_to_name(dlt); - if (dlt_name == NULL) - dlt_name = "???"; - (void)fprintf(stderr, "listening on %s, link-type %u (%s), capture size %u bytes\n", - device, dlt, dlt_name, snaplen); + if (dlt_name == NULL) { + (void)fprintf(stderr, "listening on %s, link-type %u, capture size %u bytes\n", + device, dlt, snaplen); + } else { + (void)fprintf(stderr, "listening on %s, link-type %s (%s), capture size %u bytes\n", + device, dlt_name, + pcap_datalink_val_to_description(dlt), snaplen); + } (void)fflush(stderr); } #endif /* WIN32 */ - if (pcap_loop(pd, cnt, callback, pcap_userdata) < 0) { + status = pcap_loop(pd, cnt, callback, pcap_userdata); + if (WFileName == NULL) { + /* + * We're printing packets. Flush the printed output, + * so it doesn't get intermingled with error output. + */ + if (status == -2) { + /* + * We got interrupted, so perhaps we didn't + * manage to finish a line we were printing. + * Print an extra newline, just in case. + */ + putchar('\n'); + } + (void)fflush(stdout); + } + if (status == -1) { + /* + * Error. Report it. + */ (void)fprintf(stderr, "%s: pcap_loop: %s\n", program_name, pcap_geterr(pd)); - cleanup(0); - pcap_close(pd); - exit(1); } - if (RFileName == NULL) + if (RFileName == NULL) { + /* + * We're doing a live capture. Report the capture + * statistics. + */ info(1); + } pcap_close(pd); - exit(0); + exit(status == -1 ? 1 : 0); } /* make a clean exit on interrupts */ static RETSIGTYPE -cleanup(int signo) +cleanup(int signo _U_) { - - /* Can't print the summary if reading from a savefile */ +#ifdef HAVE_PCAP_BREAKLOOP + /* + * We have "pcap_breakloop()"; use it, so that we do as little + * as possible in the signal handler (it's probably not safe + * to do anything with standard I/O streams in a signal handler - + * the ANSI C standard doesn't say it is). + */ + pcap_breakloop(pd); +#else + /* + * We don't have "pcap_breakloop()"; this isn't safe, but + * it's the best we can do. Print the summary if we're + * not reading from a savefile - i.e., if we're doing a + * live capture - and exit. + */ if (pd != NULL && pcap_file(pd) == NULL) { + /* + * We got interrupted, so perhaps we didn't + * manage to finish a line we were printing. + * Print an extra newline, just in case. + */ + putchar('\n'); (void)fflush(stdout); - putc('\n', stderr); info(1); } - if (signo) - exit(0); + exit(0); +#endif } static void @@ -816,6 +881,11 @@ info(register int verbose) if (!verbose) fprintf(stderr, "%s: ", program_name); + (void)fprintf(stderr, "%u packets captured", packets_captured); + if (!verbose) + fputs(", ", stderr); + else + putc('\n', stderr); (void)fprintf(stderr, "%d packets received by filter", stat.ps_recv); if (!verbose) fputs(", ", stderr); @@ -859,6 +929,8 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s static uint cnt = 2; char *name; + ++packets_captured; + ++infodelay; dump_info = (struct dump_info *)user; @@ -869,13 +941,18 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s * file could put it over Cflag. */ if (ftell((FILE *)dump_info->p) > Cflag) { + /* + * Close the current file and open a new one. + */ + pcap_dump_close(dump_info->p); + if (cnt >= 1000) + error("too many output files"); name = (char *) malloc(strlen(dump_info->WFileName) + 4); if (name == NULL) error("dump_packet_and_trunc: malloc"); strcpy(name, dump_info->WFileName); swebitoa(cnt, name + strlen(dump_info->WFileName)); cnt++; - pcap_dump_close(dump_info->p); dump_info->p = pcap_dump_open(dump_info->pd, name); free(name); if (dump_info->p == NULL) @@ -896,6 +973,8 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s static void dump_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) { + ++packets_captured; + ++infodelay; pcap_dump(user, h, sp); @@ -915,6 +994,8 @@ print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) struct print_info *print_info; u_int hdrlen; + ++packets_captured; + ++infodelay; ts_print(&h->ts); @@ -936,7 +1017,7 @@ print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) /* * Include the link-layer header. */ - default_print_unaligned(sp, h->caplen); + default_print(sp, h->caplen); } else { /* * Don't include the link-layer header - and if @@ -944,7 +1025,7 @@ print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) * print nothing. */ if (h->caplen > hdrlen) - default_print_unaligned(sp + hdrlen, + default_print(sp + hdrlen, h->caplen - hdrlen); } } @@ -956,32 +1037,6 @@ print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) info(0); } -/* Like default_print() but data need not be aligned */ -void -default_print_unaligned(register const u_char *cp, register u_int length) -{ - register u_int i, s; - register int nshorts; - - if (Xflag) { - ascii_print(cp, length); - return; - } - nshorts = (u_int) length / sizeof(u_short); - i = 0; - while (--nshorts >= 0) { - if ((i++ % 8) == 0) - (void)printf("\n\t\t\t"); - s = *cp++; - (void)printf(" %02x%02x", s, *cp++); - } - if (length & 1) { - if ((i % 8) == 0) - (void)printf("\n\t\t\t"); - (void)printf(" %02x", *cp); - } -} - #ifdef WIN32 /* * XXX - there should really be libpcap calls to get the version @@ -1004,7 +1059,7 @@ default_print_unaligned(register const u_char *cp, register u_int length) char WDversion[]="current-cvs.tcpdump.org"; char version[]="current-cvs.tcpdump.org"; char pcap_version[]="current-cvs.tcpdump.org"; - char Wpcap_version[]="3.0 alpha"; + char Wpcap_version[]="3.1"; #endif /* @@ -1013,7 +1068,7 @@ default_print_unaligned(register const u_char *cp, register u_int length) void default_print(register const u_char *bp, register u_int length) { - default_print_unaligned(bp, length); + ascii_print("\n\t", bp, length); /* pass on lf and identation string */ } #ifdef SIGINFO @@ -1039,8 +1094,12 @@ usage(void) #endif /* HAVE_PCAP_LIB_VERSION */ #ifdef HAVE_PCAP_LIB_VERSION +#ifdef WIN32 + (void)fprintf(stderr, "%s version %s, based on tcpdump version %s\n", program_name, WDversion, version); +#else /* WIN32 */ (void)fprintf(stderr, "%s version %s\n", program_name, version); - (void)fprintf(stderr, "%s\n", pcap_lib_version()); +#endif /* WIN32 */ + (void)fprintf(stderr, "%s\n",pcap_lib_version()); #else /* HAVE_PCAP_LIB_VERSION */ #ifdef WIN32 (void)fprintf(stderr, "%s version %s, based on tcpdump version %s\n", program_name, WDversion, version);