X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/1b15fedd1cb65a9d00c1d03bf7652e197006d19d..f12dbbcd916fbc735fc5b12143b20aee044129ea:/tcpdump.c diff --git a/tcpdump.c b/tcpdump.c index 4e524082..37ac27a7 100644 --- a/tcpdump.c +++ b/tcpdump.c @@ -115,7 +115,8 @@ static void ndo_default_print(netdissect_options *, const u_char *, u_int); 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 *); static void droproot(const char *, const char *); -static void ndo_error(netdissect_options *ndo, const char *fmt, ...); +static void ndo_error(netdissect_options *ndo, const char *fmt, ...) + __attribute__ ((noreturn, format (printf, 2, 3))); static void ndo_warning(netdissect_options *ndo, const char *fmt, ...); #ifdef SIGINFO @@ -133,10 +134,6 @@ RETSIGTYPE requestinfo(int); static void info(int); static u_int packets_captured; -typedef u_int (*if_printer)(const struct pcap_pkthdr *, const u_char *); -typedef u_int (*if_ndo_printer)(struct netdissect_options *ndo, - const struct pcap_pkthdr *, const u_char *); - struct printer { if_printer f; int type; @@ -154,7 +151,6 @@ static struct printer printers[] = { #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 { lane_if_print, DLT_LANE8023 }, @@ -306,6 +302,7 @@ static struct printer printers[] = { }; static struct ndo_printer ndo_printers[] = { + { ether_if_print, DLT_EN10MB }, #ifdef DLT_IPNET { ipnet_if_print, DLT_IPNET }, #endif @@ -314,11 +311,20 @@ static struct ndo_printer ndo_printers[] = { #endif #ifdef DLT_IEEE802_15_4_NOFCS { ieee802_15_4_if_print, DLT_IEEE802_15_4_NOFCS }, +#endif +#ifdef DLT_PPI + { ppi_if_print, DLT_PPI }, +#endif +#ifdef DLT_ETHERNET_HILSCHER + { ether_hilscher_if_print, DLT_ETHERNET_HILSCHER }, +#endif +#ifdef DLT_ETHERNET_HILSCHER_TRANSPARENT + { ether_hilscher_transparent_if_print, DLT_ETHERNET_HILSCHER_TRANSPARENT }, #endif { NULL, 0 }, }; -static if_printer +if_printer lookup_printer(int type) { struct printer *p; @@ -331,7 +337,7 @@ lookup_printer(int type) /* NOTREACHED */ } -static if_ndo_printer +if_ndo_printer lookup_ndo_printer(int type) { struct ndo_printer *p; @@ -652,9 +658,8 @@ main(int argc, char **argv) smiInit("tcpdump"); #endif - opterr = 0; while ( - (op = getopt(argc, argv, "aAb" B_FLAG "c:C:d" D_FLAG "eE:fF:G:hi:" I_FLAG j_FLAG J_FLAG "KlLm:M:nNOpqr:Rs:StT:u" U_FLAG "vw:W:xXy:Yz:Z:")) != -1) + (op = getopt(argc, argv, "aAb" B_FLAG "c:C:d" D_FLAG "eE:fF:G:hHi:" I_FLAG j_FLAG J_FLAG "KlLm:M:nNOpqr:Rs:StT:u" U_FLAG "vw:W:xXy:Yz:Z:")) != -1) switch (op) { case 'a': @@ -748,7 +753,11 @@ main(int argc, char **argv) break; case 'h': - ++hflag; + usage(); + break; + + case 'H': + ++Hflag; break; case 'i': @@ -1250,14 +1259,40 @@ main(int argc, char **argv) (void)setsignal(SIGPIPE, cleanup); (void)setsignal(SIGTERM, cleanup); (void)setsignal(SIGINT, cleanup); - (void)setsignal(SIGCHLD, child_cleanup); #endif /* WIN32 */ +#if defined(HAVE_FORK) || defined(HAVE_VFORK) + (void)setsignal(SIGCHLD, child_cleanup); +#endif /* Cooperate with nohup(1) */ #ifndef WIN32 if ((oldhandler = setsignal(SIGHUP, cleanup)) != SIG_DFL) (void)setsignal(SIGHUP, oldhandler); #endif /* WIN32 */ +#ifndef WIN32 + /* + * If a user name was specified with "-Z", attempt to switch to + * that user's UID. This would probably be used with sudo, + * to allow tcpdump to be run in a special restricted + * account (if you just want to allow users to open capture + * devices, and can't just give users that permission, + * you'd make tcpdump set-UID or set-GID). + * + * Tcpdump doesn't necessarily write only to one savefile; + * the general only way to allow a -Z instance to write to + * savefiles as the user under whose UID it's run, rather + * than as the user specified with -Z, would thus be to switch + * to the original user ID before opening a capture file and + * then switch back to the -Z user ID after opening the savefile. + * Switching to the -Z user ID only after opening the first + * savefile doesn't handle the general case. + */ + if (getuid() == 0 || geteuid() == 0) { + if (username || chroot_dir) + droproot(username, chroot_dir); + } +#endif /* WIN32 */ + if (pcap_setfilter(pd, &fcode) < 0) error("%s", pcap_geterr(pd)); if (WFileName) { @@ -1311,16 +1346,7 @@ main(int argc, char **argv) callback = print_packet; pcap_userdata = (u_char *)&printinfo; } -#ifndef WIN32 - /* - * We cannot do this earlier, because we want to be able to open - * the file (if done) for writing before giving up permissions. - */ - if (getuid() == 0 || geteuid() == 0) { - if (username || chroot_dir) - droproot(username, chroot_dir); - } -#endif /* WIN32 */ + #ifdef SIGINFO /* * We can't get statistics when reading from a file rather @@ -1449,13 +1475,13 @@ cleanup(int signo _U_) On windows, we do not use a fork, so we do not care less about waiting a child processes to die */ -#ifndef WIN32 +#if defined(HAVE_FORK) || defined(HAVE_VFORK) static RETSIGTYPE child_cleanup(int signo _U_) { wait(NULL); } -#endif /* WIN32 */ +#endif /* HAVE_FORK && HAVE_VFORK */ static void info(register int verbose) @@ -1476,34 +1502,41 @@ info(register int verbose) if (!verbose) fprintf(stderr, "%s: ", program_name); - (void)fprintf(stderr, "%u packets captured", packets_captured); + (void)fprintf(stderr, "%u packet%s captured", packets_captured, + PLURAL_SUFFIX(packets_captured)); if (!verbose) fputs(", ", stderr); else putc('\n', stderr); - (void)fprintf(stderr, "%u packets received by filter", stat.ps_recv); + (void)fprintf(stderr, "%u packet%s received by filter", stat.ps_recv, + PLURAL_SUFFIX(stat.ps_recv)); if (!verbose) fputs(", ", stderr); else putc('\n', stderr); - (void)fprintf(stderr, "%u packets dropped by kernel", stat.ps_drop); + (void)fprintf(stderr, "%u packet%s dropped by kernel", stat.ps_drop, + PLURAL_SUFFIX(stat.ps_drop)); if (stat.ps_ifdrop != 0) { if (!verbose) fputs(", ", stderr); else putc('\n', stderr); - (void)fprintf(stderr, "%u packets dropped by interface\n", - stat.ps_ifdrop); + (void)fprintf(stderr, "%u packet%s dropped by interface\n", + stat.ps_ifdrop, PLURAL_SUFFIX(stat.ps_ifdrop)); } else putc('\n', stderr); infoprint = 0; } -#ifndef WIN32 +#if defined(HAVE_FORK) || defined(HAVE_VFORK) static void compress_savefile(const char *filename) { +# ifdef HAVE_FORK if (fork()) +# else + if (vfork()) +# endif return; /* * Set to lowest priority so that this doesn't disturb the capture @@ -1519,15 +1552,20 @@ compress_savefile(const char *filename) zflag, filename, strerror(errno)); +# ifdef HAVE_FORK + exit(1); +# else + _exit(1); +# endif } -#else /* WIN32 */ +#else /* HAVE_FORK && HAVE_VFORK */ static void compress_savefile(const char *filename) { fprintf(stderr, - "compress_savefile failed. Functionality not implemented under windows\n"); + "compress_savefile failed. Functionality not implemented under your system\n"); } -#endif /* WIN32 */ +#endif /* HAVE_FORK && HAVE_VFORK */ static void dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) @@ -1866,7 +1904,7 @@ usage(void) #endif /* WIN32 */ #endif /* HAVE_PCAP_LIB_VERSION */ (void)fprintf(stderr, -"Usage: %s [-aAbd" D_FLAG "ef" I_FLAG J_FLAG "KlLnNOpqRStu" U_FLAG "vxX]" B_FLAG_USAGE " [ -c count ]\n", program_name); +"Usage: %s [-aAbd" D_FLAG "efhH" I_FLAG J_FLAG "KlLnNOpqRStu" U_FLAG "vxX]" B_FLAG_USAGE " [ -c count ]\n", program_name); (void)fprintf(stderr, "\t\t[ -C file_size ] [ -E algo:secret ] [ -F file ] [ -G seconds ]\n"); (void)fprintf(stderr,