X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/51166947eea5867eab23960ba3abad06f70334c8..refs/pull/1034/head:/tcpdump.c diff --git a/tcpdump.c b/tcpdump.c index 5e0afd24..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 @@ -124,6 +126,16 @@ The Regents of the University of California. All rights reserved.\n"; #include #endif /* _WIN32 */ +/* + * Pathname separator. + * Use this in pathnames, but do *not* use it in URLs. + */ +#ifdef _WIN32 +#define PATH_SEPARATOR '\\' +#else +#define PATH_SEPARATOR '/' +#endif + /* capabilities convenience library */ /* If a code depends on HAVE_LIBCAP_NG, it depends also on HAVE_CAP_NG_H. * If HAVE_CAP_NG_H is not defined, undefine HAVE_LIBCAP_NG. @@ -141,6 +153,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" @@ -150,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 @@ -227,34 +242,16 @@ static int infoprint; char *program_name; -#ifdef HAVE_CASPER -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); @@ -361,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; @@ -381,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; @@ -397,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; @@ -422,15 +419,15 @@ show_tstamp_types_and_exit(pcap_t *pc, const char *device) device); exit_tcpdump(S_SUCCESS); } - fprintf(stderr, "Time stamp types for %s (use option -j to set):\n", + fprintf(stdout, "Time stamp types for %s (use option -j to set):\n", device); for (i = 0; i < n_tstamp_types; i++) { tstamp_type_name = pcap_tstamp_type_val_to_name(tstamp_types[i]); if (tstamp_type_name != NULL) { - (void) fprintf(stderr, " %s (%s)\n", tstamp_type_name, + (void) fprintf(stdout, " %s (%s)\n", tstamp_type_name, pcap_tstamp_type_val_to_description(tstamp_types[i])); } else { - (void) fprintf(stderr, " %d\n", tstamp_types[i]); + (void) fprintf(stdout, " %d\n", tstamp_types[i]); } } pcap_free_tstamp_types(tstamp_types); @@ -438,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; @@ -459,28 +456,30 @@ show_dlts_and_exit(pcap_t *pc, const char *device) * monitor mode might be different from the ones available when * not in monitor mode). */ + (void) fprintf(stdout, "Data link types for "); if (supports_monitor_mode) - (void) fprintf(stderr, "Data link types for %s %s (use option -y to set):\n", + (void) fprintf(stdout, "%s %s", device, Iflag ? "when in monitor mode" : "when not in monitor mode"); else - (void) fprintf(stderr, "Data link types for %s (use option -y to set):\n", + (void) fprintf(stdout, "%s", device); + (void) fprintf(stdout, " (use option -y to set):\n"); for (i = 0; i < n_dlts; i++) { dlt_name = pcap_datalink_val_to_name(dlts[i]); if (dlt_name != NULL) { - (void) fprintf(stderr, " %s (%s)", dlt_name, + (void) fprintf(stdout, " %s (%s)", dlt_name, pcap_datalink_val_to_description(dlts[i])); /* * OK, does tcpdump handle that type? */ if (!has_printer(dlts[i])) - (void) fprintf(stderr, " (printing not supported)"); - fprintf(stderr, "\n"); + (void) fprintf(stdout, " (printing not supported)"); + fprintf(stdout, "\n"); } else { - (void) fprintf(stderr, " DLT %d (printing not supported)\n", + (void) fprintf(stdout, " DLT %d (printing not supported)\n", dlts[i]); } } @@ -491,7 +490,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; @@ -556,7 +555,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; @@ -692,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) @@ -739,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 } }; @@ -796,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, @@ -804,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,7 +832,9 @@ 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__); + 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) { @@ -839,13 +842,29 @@ 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 - * 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); } @@ -1025,7 +1044,7 @@ copy_argv(char **argv) buf = (char *)malloc(len); if (buf == NULL) - error("copy_argv: malloc"); + error("%s: malloc", __func__); p = argv; dst = buf; @@ -1055,15 +1074,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, @@ -1072,7 +1098,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 */ @@ -1477,6 +1504,7 @@ main(int argc, char **argv) int yflag_dlt = -1; const char *yflag_dlt_name = NULL; int print = 0; + long Cflagmult; netdissect_options Ndo; netdissect_options *ndo = &Ndo; @@ -1498,7 +1526,7 @@ main(int argc, char **argv) VFile = NULL; WFileName = NULL; dlt = -1; - if ((cp = strrchr(argv[0], '/')) != NULL) + if ((cp = strrchr(argv[0], PATH_SEPARATOR)) != NULL) ndo->program_name = program_name = cp + 1; else ndo->program_name = program_name = argv[0]; @@ -1558,19 +1586,77 @@ main(int argc, char **argv) #else Cflag = strtol(optarg, &endp, 10); #endif - if (endp == optarg || *endp != '\0' || errno != 0 - || Cflag <= 0) + if (endp == optarg || errno != 0 || Cflag <= 0) error("invalid file size %s", optarg); + + if (*endp == '\0') { + /* + * There's nothing after the file size, + * so the size is in units of 1 MB + * (1,000,000 bytes). + */ + Cflagmult = 1000000; + } else { + /* + * There's something after the file + * size. + * + * If it's a single letter, then: + * + * if the letter is k or K, the size + * is in units of 1 KiB (1024 bytes); + * + * if the letter is m or M, the size + * is in units of 1 MiB (1,048,576 bytes); + * + * if the letter is g or G, the size + * is in units of 1 GiB (1,073,741,824 bytes). + * + * Otherwise, it's an error. + */ + switch (*endp) { + + case 'k': + case 'K': + Cflagmult = 1024; + break; + + case 'm': + case 'M': + Cflagmult = 1024*1024; + break; + + case 'g': + case 'G': + Cflagmult = 1024*1024*1024; + break; + + default: + error("invalid file size %s", optarg); + } + + /* + * OK, there was a letter that we treat + * as a units indication; was there + * anything after it? + */ + endp++; + if (*endp != '\0') { + /* Yes - error */ + error("invalid file size %s", optarg); + } + } + /* - * Will multiplying it by 1000000 overflow? + * Will multiplying it by multiplier overflow? */ #ifdef HAVE_PCAP_DUMP_FTELL64 - if (Cflag > INT64_T_CONSTANT(0x7fffffffffffffff) / 1000000) + if (Cflag > INT64_T_CONSTANT(0x7fffffffffffffff) / Cflagmult) #else - if (Cflag > LONG_MAX / 1000000) + if (Cflag > LONG_MAX / Cflagmult) #endif error("file size %s is too large", optarg); - Cflag *= 1000000; + Cflag *= Cflagmult; break; case 'd': @@ -1622,13 +1708,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; @@ -1798,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; @@ -1870,7 +1958,7 @@ main(int argc, char **argv) break; case OPTION_VERSION: - print_version(); + print_version(stdout); exit_tcpdump(S_SUCCESS); break; @@ -1892,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; @@ -1918,7 +2014,7 @@ main(int argc, char **argv) break; default: - print_usage(); + print_usage(stderr); exit_tcpdump(S_ERR_HOST_PROGRAM); /* NOTREACHED */ } @@ -1932,6 +2028,14 @@ main(int argc, char **argv) show_remote_devices_and_exit(); #endif +#if defined(DLT_LINUX_SLL2) && defined(HAVE_PCAP_SET_DATALINK) +/* Set default linktype DLT_LINUX_SLL2 when capturing on the "any" device */ + if (device != NULL && + strncmp (device, "any", strlen("any")) == 0 + && yflag_dlt == -1) + yflag_dlt = DLT_LINUX_SLL2; +#endif + switch (ndo->ndo_tflag) { case 0: /* Default */ @@ -2180,7 +2284,8 @@ main(int argc, char **argv) } #endif (void)fprintf(stderr, "%s: data link type %s\n", - program_name, yflag_dlt_name); + program_name, + pcap_datalink_val_to_name(yflag_dlt)); (void)fflush(stderr); } i = pcap_snapshot(pd); @@ -2262,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 */ @@ -2354,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 && @@ -2391,7 +2523,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; @@ -2402,7 +2534,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; } @@ -2419,11 +2551,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 /* @@ -2461,7 +2596,7 @@ DIAG_ON_CLANG(assign-enum) */ if (!ndo->ndo_vflag && !WFileName) { (void)fprintf(stderr, - "%s: verbose output suppressed, use -v or -vv for full protocol decode\n", + "%s: verbose output suppressed, use -v[v]... for full protocol decode\n", program_name); } else (void)fprintf(stderr, "%s: ", program_name); @@ -2575,7 +2710,9 @@ 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); + /* Free the old filter */ + pcap_freecode(&fcode); if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0) error("%s", pcap_geterr(pd)); } @@ -2605,12 +2742,12 @@ 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); pcap_freecode(&fcode); - exit_tcpdump(status == -1 ? 1 : 0); + exit_tcpdump(status == -1 ? S_ERR_HOST_PROGRAM : S_SUCCESS); } /* @@ -2626,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); @@ -2818,8 +2962,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)); } @@ -2960,7 +3104,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); @@ -3096,9 +3240,9 @@ static void verbose_stats_dump(int sig _U_) } #endif /* _WIN32 */ -USES_APPLE_DEPRECATED_API +DIAG_OFF_DEPRECATION static void -print_version(void) +print_version(FILE *f) { #ifndef HAVE_PCAP_LIB_VERSION #ifdef HAVE_PCAP_VERSION @@ -3109,61 +3253,63 @@ 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 +DIAG_ON_DEPRECATION 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, -"\t\t[ -M secret ] [ --number ] [ --print ]" Q_FLAG_USAGE "\n"); - (void)fprintf(stderr, -"\t\t[ -r file ] [ -s snaplen ] [ -T type ] [ --version ]\n"); - (void)fprintf(stderr, + (void)fprintf(f, +"\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[ -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 - (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"); }