X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/27ede6609cad295a3100fe7c11fca35192da8d74..244754b3f0d3e733dc5b7dba8dcba33a3e107afe:/tcpdump.c diff --git a/tcpdump.c b/tcpdump.c index 1aa285e3..0bde6468 100644 --- a/tcpdump.c +++ b/tcpdump.c @@ -151,6 +151,7 @@ The Regents of the University of California. All rights reserved.\n"; #include #endif /* __FreeBSD__ */ +#include "netdissect-stdinc.h" #include "netdissect.h" #include "interface.h" #include "addrtoname.h" @@ -242,29 +243,15 @@ cap_channel_t *capdns; #endif /* Forwards */ -static NORETURN void error(FORMAT_STRING(const char *), ...) PRINTFLIKE(1, 2); -static void warning(FORMAT_STRING(const char *), ...) PRINTFLIKE(1, 2); -static NORETURN void exit_tcpdump(int); static void (*setsignal (int sig, void (*func)(int)))(int); static void cleanup(int); static void child_cleanup(int); -static void print_version(void); -static void print_usage(void); -#ifdef HAVE_PCAP_SET_TSTAMP_TYPE -static NORETURN void show_tstamp_types_and_exit(pcap_t *, const char *device); -#endif -static NORETURN void show_dlts_and_exit(pcap_t *, const char *device); -#ifdef HAVE_PCAP_FINDALLDEVS -static NORETURN void show_devices_and_exit(void); -#endif -#ifdef HAVE_PCAP_FINDALLDEVS_EX -static NORETURN void show_remote_devices_and_exit(void); -#endif +static void print_version(FILE *); +static void print_usage(FILE *); 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 *); -static void droproot(const char *, const char *); #ifdef SIGNAL_REQ_INFO static void requestinfo(int); @@ -371,9 +358,16 @@ extern void pcap_set_optimizer_debug(int); #endif +static void NORETURN +exit_tcpdump(const int status) +{ + nd_cleanup(); + exit(status); +} + /* VARARGS */ -static void -error(const char *fmt, ...) +static void NORETURN PRINTFLIKE(1, 2) +error(FORMAT_STRING(const char *fmt), ...) { va_list ap; @@ -391,8 +385,8 @@ error(const char *fmt, ...) } /* VARARGS */ -static void -warning(const char *fmt, ...) +static void PRINTFLIKE(1, 2) +warning(FORMAT_STRING(const char *fmt), ...) { va_list ap; @@ -407,15 +401,8 @@ warning(const char *fmt, ...) } } -static void -exit_tcpdump(int status) -{ - nd_cleanup(); - exit(status); -} - #ifdef HAVE_PCAP_SET_TSTAMP_TYPE -static void +static void NORETURN show_tstamp_types_and_exit(pcap_t *pc, const char *device) { int n_tstamp_types; @@ -448,7 +435,7 @@ show_tstamp_types_and_exit(pcap_t *pc, const char *device) } #endif -static void +static void NORETURN show_dlts_and_exit(pcap_t *pc, const char *device) { int n_dlts, i; @@ -501,7 +488,7 @@ show_dlts_and_exit(pcap_t *pc, const char *device) } #ifdef HAVE_PCAP_FINDALLDEVS -static void +static void NORETURN show_devices_and_exit(void) { pcap_if_t *dev, *devlist; @@ -566,7 +553,7 @@ show_devices_and_exit(void) #endif /* HAVE_PCAP_FINDALLDEVS */ #ifdef HAVE_PCAP_FINDALLDEVS_EX -static void +static void NORETURN show_remote_devices_and_exit(void) { pcap_if_t *dev, *devlist; @@ -841,7 +828,7 @@ MakeFilename(char *buffer, char *orig_name, int cnt, int max_chars) { char *filename = malloc(PATH_MAX + 1); if (filename == NULL) - error("Makefilename: malloc"); + error("%s: malloc", __func__); /* Process with strftime if Gflag is set. */ if (Gflag != 0) { @@ -849,7 +836,7 @@ MakeFilename(char *buffer, char *orig_name, int cnt, int max_chars) /* Convert Gflag_time to a usable format */ if ((local_tm = localtime(&Gflag_time)) == NULL) { - error("MakeTimedFilename: localtime"); + error("%s: localtime", __func__); } /* There's no good way to detect an error in strftime since a return @@ -1035,7 +1022,7 @@ copy_argv(char **argv) buf = (char *)malloc(len); if (buf == NULL) - error("copy_argv: malloc"); + error("%s: malloc", __func__); p = argv; dst = buf; @@ -1065,15 +1052,22 @@ read_infile(char *fname) int i, fd; ssize_t cc; char *cp; - struct stat buf; + our_statb buf; fd = open(fname, O_RDONLY|O_BINARY); if (fd < 0) error("can't open %s: %s", fname, pcap_strerror(errno)); - if (fstat(fd, &buf) < 0) + if (our_fstat(fd, &buf) < 0) error("can't stat %s: %s", fname, pcap_strerror(errno)); + /* + * Reject files whose size doesn't fit into an int; a filter + * *that* large will probably be too big. + */ + if (buf.st_size > INT_MAX) + error("%s is too large", fname); + cp = malloc((u_int)buf.st_size + 1); if (cp == NULL) error("malloc(%d) for %s: %s", (u_int)buf.st_size + 1, @@ -1082,7 +1076,8 @@ read_infile(char *fname) if (cc < 0) error("read %s: %s", fname, pcap_strerror(errno)); if (cc != buf.st_size) - error("short read %s (%zd != %d)", fname, cc, (int)buf.st_size); + error("short read %s (%d != %d)", fname, (int) cc, + (int)buf.st_size); close(fd); /* replace "# comment" with spaces */ @@ -1632,13 +1627,13 @@ main(int argc, char **argv) /* 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)); + error("%s: can't get current time: %s", + __func__, pcap_strerror(errno)); } break; case 'h': - print_usage(); + print_usage(stdout); exit_tcpdump(S_SUCCESS); break; @@ -1880,7 +1875,7 @@ main(int argc, char **argv) break; case OPTION_VERSION: - print_version(); + print_version(stdout); exit_tcpdump(S_SUCCESS); break; @@ -1928,7 +1923,7 @@ main(int argc, char **argv) break; default: - print_usage(); + print_usage(stderr); exit_tcpdump(S_ERR_HOST_PROGRAM); /* NOTREACHED */ } @@ -2410,7 +2405,7 @@ DIAG_ON_CLANG(assign-enum) } if (print) { dlt = pcap_datalink(pd); - ndo->ndo_if_printer = get_if_printer(ndo, dlt); + ndo->ndo_if_printer = get_if_printer(dlt); dumpinfo.ndo = ndo; } else dumpinfo.ndo = NULL; @@ -2421,7 +2416,7 @@ DIAG_ON_CLANG(assign-enum) #endif } else { dlt = pcap_datalink(pd); - ndo->ndo_if_printer = get_if_printer(ndo, dlt); + ndo->ndo_if_printer = get_if_printer(dlt); callback = print_packet; pcap_userdata = (u_char *)ndo; } @@ -2438,11 +2433,14 @@ DIAG_ON_CLANG(assign-enum) (void)setsignal(SIGNAL_FLUSH_PCAP, flushpcap); #endif - if (ndo->ndo_vflag > 0 && WFileName && !print) { + if (ndo->ndo_vflag > 0 && WFileName && RFileName == NULL && !print) { /* * When capturing to a file, if "--print" wasn't specified, *"-v" means tcpdump should, once per second, * "v"erbosely report the number of packets captured. + * Except when reading from a file, because -r, -w and -v + * together used to make a corner case, in which pcap_loop() + * errored due to EINTR (see GH #155 for details). */ #ifdef _WIN32 /* @@ -2594,7 +2592,7 @@ DIAG_ON_CLANG(assign-enum) * the new DLT. */ dlt = new_dlt; - ndo->ndo_if_printer = get_if_printer(ndo, dlt); + ndo->ndo_if_printer = get_if_printer(dlt); if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0) error("%s", pcap_geterr(pd)); } @@ -2624,7 +2622,7 @@ DIAG_ON_CLANG(assign-enum) while (ret != NULL); if (count_mode && RFileName != NULL) - fprintf(stderr, "%u packet%s\n", packets_captured, + fprintf(stdout, "%u packet%s\n", packets_captured, PLURAL_SUFFIX(packets_captured)); free(cmdbuf); @@ -2837,8 +2835,8 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s /* 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)); + error("%s: can't get current_time: %s", + __func__, pcap_strerror(errno)); } @@ -2979,7 +2977,7 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s free(dump_info->CurrentFileName); dump_info->CurrentFileName = (char *)malloc(PATH_MAX + 1); if (dump_info->CurrentFileName == NULL) - error("dump_packet_and_trunc: malloc"); + error("%s: malloc", __func__); MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, Cflag_count, WflagChars); #ifdef HAVE_LIBCAP_NG capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); @@ -3117,7 +3115,7 @@ static void verbose_stats_dump(int sig _U_) USES_APPLE_DEPRECATED_API static void -print_version(void) +print_version(FILE *f) { #ifndef HAVE_PCAP_LIB_VERSION #ifdef HAVE_PCAP_VERSION @@ -3128,61 +3126,61 @@ print_version(void) #endif /* HAVE_PCAP_LIB_VERSION */ const char *smi_version_string; - (void)fprintf(stderr, "%s version " PACKAGE_VERSION "\n", program_name); + (void)fprintf(f, "%s version " PACKAGE_VERSION "\n", program_name); #ifdef HAVE_PCAP_LIB_VERSION - (void)fprintf(stderr, "%s\n", pcap_lib_version()); + (void)fprintf(f, "%s\n", pcap_lib_version()); #else /* HAVE_PCAP_LIB_VERSION */ - (void)fprintf(stderr, "libpcap version %s\n", pcap_version); + (void)fprintf(f, "libpcap version %s\n", pcap_version); #endif /* HAVE_PCAP_LIB_VERSION */ #if defined(HAVE_LIBCRYPTO) && defined(SSLEAY_VERSION) - (void)fprintf (stderr, "%s\n", SSLeay_version(SSLEAY_VERSION)); + (void)fprintf (f, "%s\n", SSLeay_version(SSLEAY_VERSION)); #endif smi_version_string = nd_smi_version_string(); if (smi_version_string != NULL) - (void)fprintf (stderr, "SMI-library: %s\n", smi_version_string); + (void)fprintf (f, "SMI-library: %s\n", smi_version_string); #if defined(__SANITIZE_ADDRESS__) - (void)fprintf (stderr, "Compiled with AddressSanitizer/GCC.\n"); + (void)fprintf (f, "Compiled with AddressSanitizer/GCC.\n"); #elif defined(__has_feature) # if __has_feature(address_sanitizer) - (void)fprintf (stderr, "Compiled with AddressSanitizer/Clang.\n"); + (void)fprintf (f, "Compiled with AddressSanitizer/Clang.\n"); # elif __has_feature(memory_sanitizer) - (void)fprintf (stderr, "Compiled with MemorySanitizer/Clang.\n"); + (void)fprintf (f, "Compiled with MemorySanitizer/Clang.\n"); # endif #endif /* __SANITIZE_ADDRESS__ or __has_feature */ } USES_APPLE_RST static void -print_usage(void) +print_usage(FILE *f) { - print_version(); - (void)fprintf(stderr, + print_version(f); + (void)fprintf(f, "Usage: %s [-Abd" D_FLAG "efhH" I_FLAG J_FLAG "KlLnNOpqStu" U_FLAG "vxX#]" B_FLAG_USAGE " [ -c count ] [--count]\n", program_name); - (void)fprintf(stderr, + (void)fprintf(f, "\t\t[ -C file_size ] [ -E algo:secret ] [ -F file ] [ -G seconds ]\n"); - (void)fprintf(stderr, + (void)fprintf(f, "\t\t[ -i interface ]" IMMEDIATE_MODE_USAGE j_FLAG_USAGE "\n"); #ifdef HAVE_PCAP_FINDALLDEVS_EX - (void)fprintf(stderr, + (void)fprintf(f, "\t\t" LIST_REMOTE_INTERFACES_USAGE "\n"); #endif #ifdef USE_LIBSMI - (void)fprintf(stderr, + (void)fprintf(f, "\t\t" m_FLAG_USAGE "\n"); #endif - (void)fprintf(stderr, + (void)fprintf(f, "\t\t[ -M secret ] [ --number ] [ --print ]" Q_FLAG_USAGE "\n"); - (void)fprintf(stderr, + (void)fprintf(f, "\t\t[ -r file ] [ -s snaplen ] [ -T type ] [ --version ]\n"); - (void)fprintf(stderr, + (void)fprintf(f, "\t\t[ -V file ] [ -w file ] [ -W filecount ] [ -y datalinktype ]\n"); #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION - (void)fprintf(stderr, + (void)fprintf(f, "\t\t[ --time-stamp-precision precision ] [ --micro ] [ --nano ]\n"); #endif - (void)fprintf(stderr, + (void)fprintf(f, "\t\t[ -z postrotate-command ] [ -Z user ] [ expression ]\n"); }