]> The Tcpdump Group git mirrors - tcpdump/blobdiff - tcpdump.c
CI: Add warning exemptions for Sun C (suncc-5.14) on Solaris 10
[tcpdump] / tcpdump.c
index 56dc2145bdcfe98acc8a8bcb614ff72c61c43a4b..e59756716de5438422efb332861807e4ed647f06 100644 (file)
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -34,6 +34,9 @@
  */
 
 #include <config.h>
+#ifndef TCPDUMP_CONFIG_H_
+#error "The included config.h header is not from the tcpdump build."
+#endif
 
 #include "netdissect-stdinc.h"
 
@@ -137,11 +140,9 @@ The Regents of the University of California.  All rights reserved.\n";
 #include <sys/sysctl.h>
 #endif /* __FreeBSD__ */
 
-#include "netdissect-stdinc.h"
 #include "netdissect.h"
 #include "interface.h"
 #include "addrtoname.h"
-#include "pcap-missing.h"
 #include "ascii_strcasecmp.h"
 
 #include "print.h"
@@ -165,11 +166,7 @@ The Regents of the University of California.  All rights reserved.\n";
 #endif
 
 static int Bflag;                      /* buffer size */
-#ifdef HAVE_PCAP_DUMP_FTELL64
 static int64_t Cflag;                  /* rotate dump files after this many bytes */
-#else
-static long Cflag;                     /* rotate dump files after this many bytes */
-#endif
 static int Cflag_count;                        /* Keep track of which file number we're writing */
 static int Dflag;                      /* list available devices and exit */
 #ifdef HAVE_PCAP_FINDALLDEVS_EX
@@ -205,13 +202,15 @@ static int Qflag = -1;                    /* restrict captured packet by send/receive direction *
 static int Uflag;                      /* "unbuffered" output of dump files */
 static int Wflag;                      /* recycle output files after this number of files */
 static int WflagChars;
+#if defined(HAVE_FORK) || defined(HAVE_VFORK)
 static char *zflag = NULL;             /* compress each savefile using a specified command (like gzip or bzip2) */
+#endif
 static int timeout = 1000;             /* default timeout = 1000 ms = 1 s */
 #ifdef HAVE_PCAP_SET_IMMEDIATE_MODE
 static int immediate_mode;
 #endif
 static int count_mode;
-static u_int packets_skipped;
+static u_int packets_to_skip;
 
 static int infodelay;
 static int infoprint;
@@ -219,9 +218,17 @@ static int infoprint;
 char *program_name;
 
 /* Forwards */
+static int parse_int(const char *argname, const char *string, char **endp,
+    int minval, int maxval, int base);
+static u_int parse_u_int(const char *argname, const char *string, char **endp,
+    u_int minval, u_int maxval, int base);
+static int64_t parse_int64(const char *argname, const char *string,
+    char **endp, int64_t minval, int64_t maxval, int base);
 static void (*setsignal (int sig, void (*func)(int)))(int);
 static void cleanup(int);
+#if defined(HAVE_FORK) || defined(HAVE_VFORK)
 static void child_cleanup(int);
+#endif
 static void print_version(FILE *);
 static void print_usage(FILE *);
 
@@ -609,7 +616,27 @@ show_remote_devices_and_exit(void)
 #define m_FLAG_USAGE "[ -m module ] ..."
 #endif
 
-#define SHORTOPTS "aAbB:c:C:dDeE:fF:G:hHi:I" j_FLAG J_FLAG "KlLm:M:nNOpqQ:r:s:StT:uUvV:w:W:xXy:Yz:Z:#"
+#if defined(HAVE_FORK) || defined(HAVE_VFORK)
+#define z_FLAG         "z:"
+#define z_FLAG_USAGE    "[ -z postrotate-command ] "
+#else
+#define z_FLAG
+#define z_FLAG_USAGE
+#endif
+
+#ifdef HAVE_LIBCRYPTO
+#define E_FLAG         "E:"
+#define E_FLAG_USAGE    "[ -E algo:secret ] "
+#define M_FLAG         "M:"
+#define M_FLAG_USAGE   "[ -M secret ] "
+#else
+#define E_FLAG
+#define E_FLAG_USAGE
+#define M_FLAG
+#define M_FLAG_USAGE
+#endif
+
+#define SHORTOPTS "aAbB:c:C:dDe" E_FLAG "fF:G:hHi:I" j_FLAG J_FLAG "KlLm:" M_FLAG "nNOpqQ:r:s:StT:uUvV:w:W:xXy:Y" z_FLAG "Z:#"
 
 /*
  * Long options.
@@ -724,7 +751,7 @@ droproot(const char *username, const char *chroot_dir)
                {
                        int ret = capng_change_id(pw->pw_uid, pw->pw_gid, CAPNG_NO_FLAG);
                        if (ret < 0)
-                               error("capng_change_id(): return %d\n", ret);
+                               error("capng_change_id(): return %d", ret);
                        else
                                fprintf(stderr, "dropped privs to %s\n", username);
                }
@@ -1344,6 +1371,11 @@ open_interface(const char *device, netdissect_options *ndo, char *ebuf)
                } else if (status == PCAP_ERROR_PERM_DENIED && *cp != '\0')
                        error("%s: %s\n(%s)", device,
                            pcap_statustostr(status), cp);
+#ifdef PCAP_ERROR_CAPTURE_NOTSUP
+               else if (status == PCAP_ERROR_CAPTURE_NOTSUP && *cp != '\0')
+                       error("%s: %s\n(%s)", device,
+                           pcap_statustostr(status), cp);
+#endif
 #ifdef __FreeBSD__
                else if (status == PCAP_ERROR_RFMON_NOTSUP &&
                    strncmp(device, "wlan", 4) == 0) {
@@ -1361,7 +1393,7 @@ open_interface(const char *device, netdissect_options *ndo, char *ebuf)
                         * specific case would be an error message that looks a bit odd.
                         */
                        newdev[strlen(newdev)-1]++;
-                       error("%s is not a monitor mode VAP\n"
+                       error("%s is not a monitor mode VAP"
                            "To create a new monitor mode VAP use:\n"
                            "  ifconfig %s create wlandev %s wlanmode monitor\n"
                            "and use %s as the tcpdump interface",
@@ -1422,7 +1454,6 @@ main(int argc, char **argv)
        const char *chroot_dir = NULL;
 #endif
        char *ret = NULL;
-       char *end;
        pcap_if_t *devlist;
        long devnum;
        int status;
@@ -1645,26 +1676,24 @@ main(int argc, char **argv)
                        break;
 
                case 'B':
-                       Bflag = atoi(optarg)*1024;
-                       if (Bflag <= 0)
-                               error("invalid packet buffer size %s", optarg);
+                       Bflag = parse_int("packet buffer size", optarg, NULL, 1,
+                           INT_MAX, 10);
+                       /*
+                        * Will multiplying it by 1024 overflow?
+                        */
+                       if (Bflag > INT_MAX / 1024)
+                               error("packet buffer size %s is too large", optarg);
+                       Bflag *= 1024;
                        break;
 
                case 'c':
-                       cnt = atoi(optarg);
-                       if (cnt <= 0)
-                               error("invalid packet count %s", optarg);
+                       cnt = parse_int("packet count", optarg, NULL, 1,
+                           INT_MAX, 10);
                        break;
 
                case 'C':
-                       errno = 0;
-#ifdef HAVE_PCAP_DUMP_FTELL64
-                       Cflag = strtoint64_t(optarg, &endp, 10);
-#else
-                       Cflag = strtol(optarg, &endp, 10);
-#endif
-                       if (endp == optarg || errno != 0 || Cflag <= 0)
-                               error("invalid file size %s", optarg);
+                       Cflag = parse_int64("file size", optarg, &endp, 1,
+                           INT64_MAX, 10);
 
                        if (*endp == '\0') {
                                /*
@@ -1709,7 +1738,7 @@ main(int argc, char **argv)
                                        break;
 
                                default:
-                                       error("invalid file size %s", optarg);
+                                       error("invalid file size %s (invalid units)", optarg);
                                }
 
                                /*
@@ -1720,7 +1749,7 @@ main(int argc, char **argv)
                                endp++;
                                if (*endp != '\0') {
                                        /* Yes - error */
-                                       error("invalid file size %s", optarg);
+                                       error("invalid file size %s (invalid units)", optarg);
                                }
                        }
 
@@ -1728,7 +1757,7 @@ main(int argc, char **argv)
                         * Will multiplying it by multiplier overflow?
                         */
 #ifdef HAVE_PCAP_DUMP_FTELL64
-                       if (Cflag > INT64_T_CONSTANT(0x7fffffffffffffff) / Cflagmult)
+                       if (Cflag > INT64_MAX / Cflagmult)
 #else
                        if (Cflag > LONG_MAX / Cflagmult)
 #endif
@@ -1758,12 +1787,11 @@ main(int argc, char **argv)
                        ++ndo->ndo_eflag;
                        break;
 
+#ifdef HAVE_LIBCRYPTO
                case 'E':
-#ifndef HAVE_LIBCRYPTO
-                       warning("crypto code not compiled in");
-#endif
                        ndo->ndo_espsecret = optarg;
                        break;
+#endif
 
                case 'f':
                        ++ndo->ndo_fflag;
@@ -1774,9 +1802,8 @@ main(int argc, char **argv)
                        break;
 
                case 'G':
-                       Gflag = atoi(optarg);
-                       if (Gflag < 0)
-                               error("invalid number of seconds %s", optarg);
+                       Gflag = parse_int("number of seconds", optarg, NULL, 0,
+                           INT_MAX, 10);
 
                         /* We will create one file initially. */
                         Gflag_count = 0;
@@ -1850,13 +1877,12 @@ main(int argc, char **argv)
                        }
                        break;
 
+#ifdef HAVE_LIBCRYPTO
                case 'M':
                        /* TCP-MD5 shared secret */
-#ifndef HAVE_LIBCRYPTO
-                       warning("crypto code not compiled in");
-#endif
                        ndo->ndo_sigsecret = optarg;
                        break;
+#endif
 
                case 'n':
                        ++ndo->ndo_nflag;
@@ -1895,11 +1921,8 @@ main(int argc, char **argv)
                        break;
 
                case 's':
-                       ndo->ndo_snaplen = (int)strtol(optarg, &end, 0);
-                       if (optarg == end || *end != '\0'
-                           || ndo->ndo_snaplen < 0 || ndo->ndo_snaplen > MAXIMUM_SNAPLEN)
-                               error("invalid snaplen %s (must be >= 0 and <= %d)",
-                                     optarg, MAXIMUM_SNAPLEN);
+                       ndo->ndo_snaplen = parse_int("snaplen", optarg, NULL,
+                           0, MAXIMUM_SNAPLEN, 0);
                        break;
 
                case 'S':
@@ -1978,9 +2001,8 @@ main(int argc, char **argv)
                        break;
 
                case 'W':
-                       Wflag = atoi(optarg);
-                       if (Wflag <= 0)
-                               error("invalid number of output files %s", optarg);
+                       Wflag = parse_int("number of output files", optarg,
+                           NULL, 1, INT_MAX, 10);
                        WflagChars = getWflagChars(Wflag);
                        break;
 
@@ -2010,9 +2032,12 @@ main(int argc, char **argv)
                        }
                        break;
 #endif
+
+#if defined(HAVE_FORK) || defined(HAVE_VFORK)
                case 'z':
                        zflag = optarg;
                        break;
+#endif
 
                case 'Z':
                        username = optarg;
@@ -2056,17 +2081,13 @@ main(int argc, char **argv)
                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);
+                       ndo->ndo_print_sampling = parse_int("print sampling",
+                           optarg, NULL, 1, INT_MAX, 10);
                        break;
 
                case OPTION_SKIP:
-                       errno = 0;
-                       packets_skipped = (u_int)strtoul(optarg, &end, 0);
-                       if (optarg[0] == '-' || optarg == end || *end != '\0' ||
-                           errno != 0)
-                               error("invalid packet skipped %s", optarg);
+                       packets_to_skip = parse_u_int("packet skip count",
+                           optarg, NULL, 0, INT_MAX, 0);
                        break;
 
 #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
@@ -2100,6 +2121,27 @@ main(int argc, char **argv)
                        /* NOTREACHED */
                }
 
+       if (ndo->ndo_Aflag && ndo->ndo_xflag)
+               error("-A and -x[x] are mutually exclusive.");
+       if (ndo->ndo_Aflag && ndo->ndo_Xflag)
+               error("-A and -X[X] are mutually exclusive.");
+       if (ndo->ndo_xflag && ndo->ndo_Xflag)
+               error("-x[x] and -X[X] are mutually exclusive.");
+       if (Cflag != 0 && WFileName == NULL)
+               error("-C cannot be used without -w.");
+       if (Gflag != 0 && WFileName == NULL)
+               error("-G cannot be used without -w.");
+#if defined(HAVE_FORK) || defined(HAVE_VFORK)
+       if (zflag != NULL && (WFileName == NULL || (Cflag == 0 && Gflag == 0)))
+               error("-z cannot be used without -w and (-C or -G).");
+#endif
+
+       if (cnt != -1)
+               if ((int)packets_to_skip > (INT_MAX - cnt))
+                       // cnt + (int)packets_to_skip used in pcap_loop() call
+                       error("Overflow (-c count) %d + (--skip count) %d", cnt,
+                             (int)packets_to_skip);
+
        if (Dflag)
                show_devices_and_exit();
 #ifdef HAVE_PCAP_FINDALLDEVS_EX
@@ -2123,7 +2165,7 @@ main(int argc, char **argv)
        }
 
        if (ndo->ndo_fflag != 0 && (VFileName != NULL || RFileName != NULL))
-               error("-f can not be used with -V or -r");
+               error("-f cannot be used with -V or -r.");
 
        if (VFileName != NULL && RFileName != NULL)
                error("-V and -r are mutually exclusive.");
@@ -2191,11 +2233,11 @@ main(int argc, char **argv)
                                VFile = fopen(VFileName, "r");
 
                        if (VFile == NULL)
-                               error("Unable to open file: %s\n", pcap_strerror(errno));
+                               error("Unable to open file: %s", pcap_strerror(errno));
 
                        ret = get_next_file(VFile, VFileLine);
                        if (!ret)
-                               error("Nothing in %s\n", VFileName);
+                               error("Nothing in %s", VFileName);
                        RFileName = VFileLine;
                }
 
@@ -2367,7 +2409,11 @@ DIAG_ON_WARN_UNUSED_RESULT
 #ifdef HAVE_PCAP_SET_OPTIMIZER_DEBUG
        pcap_set_optimizer_debug(dflag);
 #endif
-       if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0)
+       /*
+        * netmask is in network byte order, pcap_compile() takes it
+        * in host byte order.
+        */
+       if (pcap_compile(pd, &fcode, cmdbuf, Oflag, ntohl(netmask)) < 0)
                error("%s", pcap_geterr(pd));
        if (dflag) {
                bpf_dump(&fcode, dflag);
@@ -2382,6 +2428,7 @@ DIAG_ON_WARN_UNUSED_RESULT
                capdns = capdns_setup();
 #endif /* HAVE_CASPER */
 
+       // Both localnet and netmask are in network byte order.
        init_print(ndo, localnet, netmask);
 
 #ifndef _WIN32
@@ -2696,7 +2743,7 @@ DIAG_ON_ASSIGN_ENUM
 
        do {
                status = pcap_loop(pd,
-                                  cnt + (cnt == -1 ? 0 : packets_skipped),
+                                  (cnt == -1 ? -1 : cnt + (int)packets_to_skip),
                                   callback, pcap_userdata);
                if (WFileName == NULL) {
                        /*
@@ -2785,7 +2832,11 @@ DIAG_ON_ASSIGN_ENUM
                                        ndo->ndo_if_printer = get_if_printer(dlt);
                                        /* Free the old filter */
                                        pcap_freecode(&fcode);
-                                       if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0)
+                                       /*
+                                        * netmask is in network byte order, pcap_compile() takes it
+                                        * in host byte order.
+                                        */
+                                       if (pcap_compile(pd, &fcode, cmdbuf, Oflag, ntohl(netmask)) < 0)
                                                error("%s", pcap_geterr(pd));
                                }
 
@@ -2822,6 +2873,134 @@ DIAG_ON_ASSIGN_ENUM
        exit_tcpdump(status == -1 ? S_ERR_HOST_PROGRAM : S_SUCCESS);
 }
 
+/*
+ * Routines to parse numerical command-line arguments and check for
+ * errors, including "too large for that type".
+ */
+static int
+parse_int(const char *argname, const char *string, char **endpp,
+    int minval, int maxval, int base)
+{
+       long val;
+       char *endp;
+
+       errno = 0;
+       val = strtol(string, &endp, base);
+
+       /*
+        * Did it either not parse any of the string, find extra stuff
+        * at the end that the caller isn't interested in, or get
+        * another parsing error?
+        */
+       if (string == endp || (endpp == NULL && *endp != '\0') ||
+           (val == 0 && errno == EINVAL)) {
+               error("invalid %s \"%s\" (not a valid number)", argname,
+                   string);
+       }
+
+       /*
+        * Did it get a value that's out of range?
+        */
+       if (((val == LONG_MAX || val == LONG_MIN) && errno == ERANGE) ||
+           val < minval || val > maxval) {
+               error("invalid %s %s (must be >= %d and <= %d)",
+                   argname, string, minval, maxval);
+       }
+
+       /*
+        * OK, it passes all the tests.
+        */
+       if (endpp != NULL)
+               *endpp = endp;
+       return ((int)val);
+}
+
+static u_int
+parse_u_int(const char *argname, const char *string, char **endpp,
+    u_int minval, u_int maxval, int base)
+{
+       unsigned long val;
+       char *endp;
+
+       errno = 0;
+
+       /*
+        * strtoul() does *NOT* report an error if the string
+        * begins with a minus sign. We do.
+        */
+       if (*string == '-') {
+               error("invalid %s \"%s\" (not a valid unsigned number)",
+                   argname, string);
+       }
+
+       val = strtoul(string, &endp, base);
+
+       /*
+        * Did it either not parse any of the string, find extra stuff
+        * at the end that the caller isn't interested in, or get
+        * another parsing error?
+        */
+       if (string == endp || (endpp == NULL && *endp != '\0') ||
+           (val == 0 && errno == EINVAL)) {
+               error("invalid %s \"%s\" (not a valid unsigned number)",
+                   argname, string);
+       }
+
+       /*
+        * Did it get a value that's out of range?
+        */
+       if ((val == ULONG_MAX && errno == ERANGE) ||
+           val < minval || val > maxval) {
+               error("invalid %s %s (must be >= %u and <= %u)",
+                   argname, string, minval, maxval);
+       }
+
+       /*
+        * OK, it passes all the tests.
+        */
+       if (endpp != NULL)
+               *endpp = endp;
+       return ((u_int)val);
+}
+
+static int64_t
+parse_int64(const char *argname, const char *string, char **endpp,
+    int64_t minval, int64_t maxval, int base)
+{
+       intmax_t val;
+       char *endp;
+
+       errno = 0;
+       val = strtoimax(string, &endp, base);
+
+       /*
+        * Did it either not parse any of the string, find extra stuff
+        * at the end that the caller isn't interested in, or get
+        * another parsing error?
+        */
+       if (string == endp || (endpp == NULL && *endp != '\0') ||
+           (val == 0 && errno == EINVAL)) {
+               error("invalid %s \"%s\" (not a valid number)", argname,
+                   string);
+       }
+
+       /*
+        * Did it get a value that's out of range?
+        */
+       if (((val == INTMAX_MAX || val == INTMAX_MIN) && errno == ERANGE) ||
+           val < minval || val > maxval) {
+               error("invalid %s %s (must be >= %" PRId64 " and <= %" PRId64 ")",
+                   argname, string, minval, maxval);
+       }
+
+       /*
+        * OK, it passes all the tests.
+        */
+       if (endpp != NULL)
+               *endpp = endp;
+       return ((int64_t)val);
+}
+
 /*
  * Catch a signal.
  */
@@ -2957,8 +3136,8 @@ compress_savefile(const char *filename)
        child = fork_subprocess();
        if (child == -1) {
                fprintf(stderr,
-                       "compress_savefile: fork failed: %s\n",
-                       pcap_strerror(errno));
+                       "%s: fork failed: %s\n",
+                       __func__, pcap_strerror(errno));
                return;
        }
        if (child != 0) {
@@ -2977,24 +3156,15 @@ compress_savefile(const char *filename)
 #endif
        if (execlp(zflag, zflag, filename, (char *)NULL) == -1)
                fprintf(stderr,
-                       "compress_savefile: execlp(%s, %s) failed: %s\n",
-                       zflag,
-                       filename,
-                       pcap_strerror(errno));
+                       "%s: execlp(%s, %s) failed: %s\n",
+                       __func__, zflag, filename, pcap_strerror(errno));
 #ifdef HAVE_FORK
        exit(S_ERR_HOST_PROGRAM);
 #else
        _exit(S_ERR_HOST_PROGRAM);
 #endif
 }
-#else  /* HAVE_FORK && HAVE_VFORK */
-static void
-compress_savefile(const char *filename)
-{
-       fprintf(stderr,
-               "compress_savefile failed. Functionality not implemented under your system\n");
-}
-#endif /* HAVE_FORK && HAVE_VFORK */
+#endif /* HAVE_FORK || HAVE_VFORK */
 
 static void
 close_old_dump_file(struct dump_info *dump_info)
@@ -3004,11 +3174,13 @@ close_old_dump_file(struct dump_info *dump_info)
         */
        pcap_dump_close(dump_info->pdd);
 
+#if defined(HAVE_FORK) || defined(HAVE_VFORK)
        /*
         * Compress the file we just closed, if the user asked for it.
         */
        if (zflag != NULL)
                compress_savefile(dump_info->CurrentFileName);
+#endif
 }
 
 static void
@@ -3059,7 +3231,7 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s
 
        dump_info = (struct dump_info *)user;
 
-       if (packets_captured <= packets_skipped)
+       if (packets_captured <= packets_to_skip)
                return;
 
        /*
@@ -3191,7 +3363,7 @@ dump_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
 
        dump_info = (struct dump_info *)user;
 
-       if (packets_captured <= packets_skipped)
+       if (packets_captured <= packets_to_skip)
                return;
 
        pcap_dump((u_char *)dump_info->pdd, h, sp);
@@ -3213,7 +3385,7 @@ print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
 
        ++infodelay;
 
-       if (!count_mode && packets_captured > packets_skipped)
+       if (!count_mode && packets_captured > packets_to_skip)
                pretty_print_packet((netdissect_options *)user, h, sp, packets_captured);
 
        --infodelay;
@@ -3307,7 +3479,7 @@ print_usage(FILE *f)
        (void)fprintf(f,
 "Usage: %s [-AbdDefhHI" J_FLAG "KlLnNOpqStuUvxX#] [ -B size ] [ -c count ] [--count]\n", program_name);
        (void)fprintf(f,
-"\t\t[ -C file_size ] [ -E algo:secret ] [ -F file ] [ -G seconds ]\n");
+"\t\t[ -C file_size ] " E_FLAG_USAGE "[ -F file ] [ -G seconds ]\n");
        (void)fprintf(f,
 "\t\t[ -i interface ]" IMMEDIATE_MODE_USAGE j_FLAG_USAGE "\n");
        (void)fprintf(f,
@@ -3317,11 +3489,11 @@ print_usage(FILE *f)
 "\t\t" m_FLAG_USAGE "\n");
 #endif
        (void)fprintf(f,
-"\t\t[ -M secret ] [ --number ] [ --print ]\n");
+"\t\t" M_FLAG_USAGE "[ --number ] [ --print ]\n");
        (void)fprintf(f,
 "\t\t[ --print-sampling nth ] [ -Q in|out|inout ] [ -r file ]\n");
        (void)fprintf(f,
-"\t\t[ -s snaplen ] [ -T type ] [ --version ]\n");
+"\t\t[ -s snaplen ] [ --skip count ] [ -T type ] [ --version ]\n");
        (void)fprintf(f,
 "\t\t[ -V file ] [ -w file ] [ -W filecount ] [ -y datalinktype ]\n");
 #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
@@ -3329,5 +3501,5 @@ print_usage(FILE *f)
 "\t\t[ --time-stamp-precision precision ] [ --micro ] [ --nano ]\n");
 #endif
        (void)fprintf(f,
-"\t\t[ -z postrotate-command ] [ -Z user ] [ expression ]\n");
+"\t\t" z_FLAG_USAGE "[ -Z user ] [ expression ]\n");
 }