X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/5ff873f0d277e10ad9deffa92b00b38cbfef4914..refs/pull/1034/head:/tcpdump.c diff --git a/tcpdump.c b/tcpdump.c index 95162ecc..7538a49c 100644 --- a/tcpdump.c +++ b/tcpdump.c @@ -78,7 +78,9 @@ The Regents of the University of California. All rights reserved.\n"; #endif /* Capsicum-specific code requires macros from , which will fail * to compile if has already been included; including the headers - * in the opposite order works fine. + * in the opposite order works fine. For the most part anyway, because in + * FreeBSD declares bpf_dump() instead of . Thus + * interface.h takes care of it later to avoid a compiler warning. */ #ifdef HAVE_CAPSICUM #include @@ -161,6 +163,8 @@ The Regents of the University of California. All rights reserved.\n"; #include "print.h" +#include "diag-control.h" + #include "fptype.h" #ifndef PATH_MAX @@ -238,10 +242,6 @@ static int infoprint; char *program_name; -#ifdef HAVE_CASPER -cap_channel_t *capdns; -#endif - /* Forwards */ static void (*setsignal (int sig, void (*func)(int)))(int); static void cleanup(int); @@ -691,6 +691,7 @@ show_remote_devices_and_exit(void) #define OPTION_TSTAMP_NANO 134 #define OPTION_FP_TYPE 135 #define OPTION_COUNT 136 +#define OPTION_PRINT_SAMPLING 137 static const struct option longopts[] = { #if defined(HAVE_PCAP_CREATE) || defined(_WIN32) @@ -738,6 +739,7 @@ static const struct option longopts[] = { { "fp-type", no_argument, NULL, OPTION_FP_TYPE }, { "number", no_argument, NULL, '#' }, { "print", no_argument, NULL, OPTION_PRINT }, + { "print-sampling", required_argument, NULL, OPTION_PRINT_SAMPLING }, { "version", no_argument, NULL, OPTION_VERSION }, { NULL, 0, NULL, 0 } }; @@ -795,7 +797,7 @@ droproot(const char *username, const char *chroot_dir) error("Couldn't find user '%.32s'", username); #ifdef HAVE_LIBCAP_NG /* We don't need CAP_SETUID, CAP_SETGID and CAP_SYS_CHROOT any more. */ -DIAG_OFF_CLANG(assign-enum) +DIAG_OFF_ASSIGN_ENUM capng_updatev( CAPNG_DROP, CAPNG_EFFECTIVE | CAPNG_PERMITTED, @@ -803,7 +805,7 @@ DIAG_OFF_CLANG(assign-enum) CAP_SETGID, CAP_SYS_CHROOT, -1); -DIAG_ON_CLANG(assign-enum) +DIAG_ON_ASSIGN_ENUM capng_apply(CAPNG_SELECT_BOTH); #endif /* HAVE_LIBCAP_NG */ @@ -831,6 +833,8 @@ MakeFilename(char *buffer, char *orig_name, int cnt, int max_chars) char *filename = malloc(PATH_MAX + 1); if (filename == NULL) error("%s: malloc", __func__); + if (strlen(orig_name) == 0) + error("an empty string is not a valid file name"); /* Process with strftime if Gflag is set. */ if (Gflag != 0) { @@ -842,9 +846,25 @@ MakeFilename(char *buffer, char *orig_name, int cnt, int max_chars) } /* There's no good way to detect an error in strftime since a return - * value of 0 isn't necessarily failure. + * value of 0 isn't necessarily failure; if orig_name is an empty + * string, the formatted string will be empty. + * + * However, the C90 standard says that, if there *is* a + * buffer overflow, the content of the buffer is undefined, + * so we must check for a buffer overflow. + * + * So we check above for an empty orig_name, and only call + * strftime() if it's non-empty, in which case the return + * value will only be 0 if the formatted date doesn't fit + * in the buffer. + * + * (We check above because, even if we don't use -G, we + * want a better error message than "tcpdump: : No such + * file or directory" for this case.) */ - strftime(filename, PATH_MAX, orig_name, local_tm); + if (strftime(filename, PATH_MAX, orig_name, local_tm) == 0) { + error("%s: strftime", __func__); + } } else { strncpy(filename, orig_name, PATH_MAX); } @@ -1864,6 +1884,8 @@ main(int argc, char **argv) ndo->ndo_packettype = PT_SOMEIP; else if (ascii_strcasecmp(optarg, "domain") == 0) ndo->ndo_packettype = PT_DOMAIN; + else if (ascii_strcasecmp(optarg, "quic") == 0) + ndo->ndo_packettype = PT_QUIC; else error("unknown packet type `%s'", optarg); break; @@ -1958,6 +1980,14 @@ main(int argc, char **argv) print = 1; break; + case OPTION_PRINT_SAMPLING: + print = 1; + ++ndo->ndo_Sflag; + ndo->ndo_print_sampling = atoi(optarg); + if (ndo->ndo_print_sampling <= 0) + error("invalid print sampling %s", optarg); + break; + #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION case OPTION_TSTAMP_MICRO: ndo->ndo_tstamp_precision = PCAP_TSTAMP_PRECISION_MICRO; @@ -2337,33 +2367,33 @@ main(int argc, char **argv) /* Initialize capng */ capng_clear(CAPNG_SELECT_BOTH); if (username) { -DIAG_OFF_CLANG(assign-enum) +DIAG_OFF_ASSIGN_ENUM capng_updatev( CAPNG_ADD, CAPNG_PERMITTED | CAPNG_EFFECTIVE, CAP_SETUID, CAP_SETGID, -1); -DIAG_ON_CLANG(assign-enum) +DIAG_ON_ASSIGN_ENUM } if (chroot_dir) { -DIAG_OFF_CLANG(assign-enum) +DIAG_OFF_ASSIGN_ENUM capng_update( CAPNG_ADD, CAPNG_PERMITTED | CAPNG_EFFECTIVE, CAP_SYS_CHROOT ); -DIAG_ON_CLANG(assign-enum) +DIAG_ON_ASSIGN_ENUM } if (WFileName) { -DIAG_OFF_CLANG(assign-enum) +DIAG_OFF_ASSIGN_ENUM capng_update( CAPNG_ADD, CAPNG_PERMITTED | CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE ); -DIAG_ON_CLANG(assign-enum) +DIAG_ON_ASSIGN_ENUM } capng_apply(CAPNG_SELECT_BOTH); #endif /* HAVE_LIBCAP_NG */ @@ -2429,17 +2459,44 @@ DIAG_ON_CLANG(assign-enum) #endif if (Cflag != 0 || Gflag != 0) { #ifdef HAVE_CAPSICUM - dumpinfo.WFileName = strdup(basename(WFileName)); + /* + * basename() and dirname() may modify their input buffer + * and they do since FreeBSD 12.0, but they didn't before. + * Hence use the return value only, but always assume the + * input buffer has been modified and would need to be + * reset before the next use. + */ + char *WFileName_copy; + + if ((WFileName_copy = strdup(WFileName)) == NULL) { + error("Unable to allocate memory for file %s", + WFileName); + } + DIAG_OFF_C11_EXTENSIONS + dumpinfo.WFileName = strdup(basename(WFileName_copy)); + DIAG_ON_C11_EXTENSIONS if (dumpinfo.WFileName == NULL) { error("Unable to allocate memory for file %s", WFileName); } - dumpinfo.dirfd = open(dirname(WFileName), + free(WFileName_copy); + + if ((WFileName_copy = strdup(WFileName)) == NULL) { + error("Unable to allocate memory for file %s", + WFileName); + } + DIAG_OFF_C11_EXTENSIONS + char *WFileName_dirname = dirname(WFileName_copy); + DIAG_ON_C11_EXTENSIONS + dumpinfo.dirfd = open(WFileName_dirname, O_DIRECTORY | O_RDONLY); if (dumpinfo.dirfd < 0) { error("unable to open directory %s", - dirname(WFileName)); + WFileName_dirname); } + free(WFileName_dirname); + free(WFileName_copy); + cap_rights_init(&rights, CAP_CREATE, CAP_FCNTL, CAP_FTRUNCATE, CAP_LOOKUP, CAP_SEEK, CAP_WRITE); if (cap_rights_limit(dumpinfo.dirfd, &rights) < 0 && @@ -2654,6 +2711,8 @@ DIAG_ON_CLANG(assign-enum) */ dlt = new_dlt; ndo->ndo_if_printer = get_if_printer(dlt); + /* Free the old filter */ + pcap_freecode(&fcode); if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0) error("%s", pcap_geterr(pd)); } @@ -2688,7 +2747,7 @@ DIAG_ON_CLANG(assign-enum) free(cmdbuf); pcap_freecode(&fcode); - exit_tcpdump(status == -1 ? 1 : 0); + exit_tcpdump(status == -1 ? S_ERR_HOST_PROGRAM : S_SUCCESS); } /* @@ -2704,7 +2763,14 @@ static void memset(&new, 0, sizeof(new)); new.sa_handler = func; - if (sig == SIGCHLD) + if ((sig == SIGCHLD) +# ifdef SIGNAL_REQ_INFO + || (sig == SIGNAL_REQ_INFO) +# endif +# ifdef SIGNAL_FLUSH_PCAP + || (sig == SIGNAL_FLUSH_PCAP) +# endif + ) new.sa_flags = SA_RESTART; if (sigaction(sig, &new, &old) < 0) return (SIG_ERR); @@ -3174,7 +3240,7 @@ static void verbose_stats_dump(int sig _U_) } #endif /* _WIN32 */ -USES_APPLE_DEPRECATED_API +DIAG_OFF_DEPRECATION static void print_version(FILE *f) { @@ -3212,7 +3278,7 @@ print_version(FILE *f) # endif #endif /* __SANITIZE_ADDRESS__ or __has_feature */ } -USES_APPLE_RST +DIAG_ON_DEPRECATION static void print_usage(FILE *f) @@ -3233,9 +3299,11 @@ print_usage(FILE *f) "\t\t" m_FLAG_USAGE "\n"); #endif (void)fprintf(f, -"\t\t[ -M secret ] [ --number ] [ --print ]" Q_FLAG_USAGE "\n"); +"\t\t[ -M secret ] [ --number ] [ --print ]\n"); + (void)fprintf(f, +"\t\t[ --print-sampling nth ]" Q_FLAG_USAGE " [ -r file ]\n"); (void)fprintf(f, -"\t\t[ -r file ] [ -s snaplen ] [ -T type ] [ --version ]\n"); +"\t\t[ -s snaplen ] [ -T type ] [ --version ]\n"); (void)fprintf(f, "\t\t[ -V file ] [ -w file ] [ -W filecount ] [ -y datalinktype ]\n"); #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION