]> The Tcpdump Group git mirrors - tcpdump/blobdiff - tcpdump.c
Merge pull request #827 from NanXiao/patch-1
[tcpdump] / tcpdump.c
index 9790a4e3f7c057c2f6bcca927662c79c38a2349b..107cdbb6b175e43fd2db2156efd8897c892bbe61 100644 (file)
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -92,6 +92,19 @@ The Regents of the University of California.  All rights reserved.\n";
 #endif /* HAVE_CASPER */
 #endif /* HAVE_CAPSICUM */
 #ifdef HAVE_PCAP_OPEN
+/*
+ * We found pcap_open() in the capture library, so we'll be using
+ * the remote capture APIs; define PCAP_REMOTE before we include pcap.h,
+ * so we get those APIs declared, and the types and #defines that they
+ * use defined.
+ *
+ * WinPcap's headers require that PCAP_REMOTE be defined in order to get
+ * remote-capture APIs declared and types and #defines that they use
+ * defined.
+ *
+ * (Versions of libpcap with those APIs, and thus Npcap, which is based on
+ * those versions of libpcap, don't require it.)
+ */
 #define HAVE_REMOTE
 #endif
 #include <pcap.h>
@@ -137,6 +150,8 @@ The Regents of the University of California.  All rights reserved.\n";
 
 #include "print.h"
 
+#include "fptype.h"
+
 #ifndef PATH_MAX
 #define PATH_MAX 1024
 #endif
@@ -190,6 +205,7 @@ static int Iflag;                   /* rfmon (monitor) mode */
 static int Jflag;                      /* list available time stamp types */
 static int jflag = -1;                 /* packet time stamp source */
 #endif
+static int lflag;                      /* line-buffered output */
 static int pflag;                      /* don't go promiscuous */
 #ifdef HAVE_PCAP_SETDIRECTION
 static int Qflag = -1;                 /* restrict captured packet by send/receive direction */
@@ -200,6 +216,7 @@ static int Uflag;                   /* "unbuffered" output of dump files */
 static int Wflag;                      /* recycle output files after this number of files */
 static int WflagChars;
 static char *zflag = NULL;             /* compress each savefile using a specified command (like gzip or bzip2) */
+static int timeout = 1000;             /* default timeout = 1000 ms = 1 s */
 #ifdef HAVE_PCAP_SET_IMMEDIATE_MODE
 static int immediate_mode;
 #endif
@@ -670,6 +687,9 @@ show_remote_devices_and_exit(void)
 #define OPTION_IMMEDIATE_MODE          130
 #define OPTION_PRINT                   131
 #define OPTION_LIST_REMOTE_INTERFACES  132
+#define OPTION_TSTAMP_MICRO            133
+#define OPTION_TSTAMP_NANO             134
+#define OPTION_FP_TYPE                 135
 
 static const struct option longopts[] = {
 #if defined(HAVE_PCAP_CREATE) || defined(_WIN32)
@@ -689,6 +709,8 @@ static const struct option longopts[] = {
        { "list-time-stamp-types", no_argument, NULL, 'J' },
 #endif
 #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
+       { "micro", no_argument, NULL, OPTION_TSTAMP_MICRO},
+       { "nano", no_argument, NULL, OPTION_TSTAMP_NANO},
        { "time-stamp-precision", required_argument, NULL, OPTION_TSTAMP_PRECISION},
 #endif
        { "dont-verify-checksums", no_argument, NULL, 'K' },
@@ -711,6 +733,7 @@ static const struct option longopts[] = {
        { "debug-filter-parser", no_argument, NULL, 'Y' },
 #endif
        { "relinquish-privileges", required_argument, NULL, 'Z' },
+       { "fp-type", no_argument, NULL, OPTION_FP_TYPE },
        { "number", no_argument, NULL, '#' },
        { "print", no_argument, NULL, OPTION_PRINT },
        { "version", no_argument, NULL, OPTION_VERSION },
@@ -729,12 +752,6 @@ static const struct option longopts[] = {
 #define IMMEDIATE_MODE_USAGE ""
 #endif
 
-#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
-#define TIME_STAMP_PRECISION_USAGE " [ --time-stamp-precision precision ]"
-#else
-#define TIME_STAMP_PRECISION_USAGE
-#endif
-
 #ifndef _WIN32
 /* Drop root privileges and chroot if necessary */
 static void
@@ -833,7 +850,7 @@ MakeFilename(char *buffer, char *orig_name, int cnt, int max_chars)
        if (cnt == 0 && max_chars == 0)
                strncpy(buffer, filename, PATH_MAX + 1);
        else
-               if (nd_snprintf(buffer, PATH_MAX + 1, "%s%0*d", filename, max_chars, cnt) > PATH_MAX)
+               if (snprintf(buffer, PATH_MAX + 1, "%s%0*d", filename, max_chars, cnt) > PATH_MAX)
                   /* Report an error if the filename is too large */
                   error("too many output files or filename is too long (> %d)", PATH_MAX);
         free(filename);
@@ -843,13 +860,15 @@ static char *
 get_next_file(FILE *VFile, char *ptr)
 {
        char *ret;
+       size_t len;
 
        ret = fgets(ptr, PATH_MAX, VFile);
        if (!ret)
                return NULL;
 
-       if (ptr[strlen(ptr) - 1] == '\n')
-               ptr[strlen(ptr) - 1] = '\0';
+       len = strlen (ptr);
+       if (len > 0 && ptr[len - 1] == '\n')
+               ptr[len - 1] = '\0';
 
        return ret;
 }
@@ -1030,7 +1049,8 @@ copy_argv(char **argv)
 static char *
 read_infile(char *fname)
 {
-       int i, fd, cc;
+       int i, fd;
+       ssize_t cc;
        char *cp;
        struct stat buf;
 
@@ -1049,7 +1069,7 @@ read_infile(char *fname)
        if (cc < 0)
                error("read %s: %s", fname, pcap_strerror(errno));
        if (cc != buf.st_size)
-               error("short read %s (%d != %d)", fname, cc, (int)buf.st_size);
+               error("short read %s (%zd != %d)", fname, cc, (int)buf.st_size);
 
        close(fd);
        /* replace "# comment" with spaces */
@@ -1215,7 +1235,7 @@ open_interface(const char *device, netdissect_options *ndo, char *ebuf)
                 */
                *ebuf = '\0';
                pc = pcap_open(device, ndo->ndo_snaplen,
-                   pflag ? 0 : PCAP_OPENFLAG_PROMISCUOUS, 1000, NULL,
+                   pflag ? 0 : PCAP_OPENFLAG_PROMISCUOUS, timeout, NULL,
                    ebuf);
                if (pc == NULL) {
                        /*
@@ -1297,7 +1317,7 @@ open_interface(const char *device, netdissect_options *ndo, char *ebuf)
                        error("%s: Can't set monitor mode: %s",
                            device, pcap_statustostr(status));
        }
-       status = pcap_set_timeout(pc, 1000);
+       status = pcap_set_timeout(pc, timeout);
        if (status != 0)
                error("%s: pcap_set_timeout failed: %s",
                    device, pcap_statustostr(status));
@@ -1331,10 +1351,8 @@ open_interface(const char *device, netdissect_options *ndo, char *ebuf)
                        /*
                         * Return an error for our caller to handle.
                         */
-                       nd_snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s\n(%s)",
+                       snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s\n(%s)",
                            device, pcap_statustostr(status), cp);
-                       pcap_close(pc);
-                       return (NULL);
                } else if (status == PCAP_ERROR_PERM_DENIED && *cp != '\0')
                        error("%s: %s\n(%s)", device,
                            pcap_statustostr(status), cp);
@@ -1345,7 +1363,7 @@ open_interface(const char *device, netdissect_options *ndo, char *ebuf)
                        char sysctl[32];
                        size_t s = sizeof(parent);
 
-                       nd_snprintf(sysctl, sizeof(sysctl),
+                       snprintf(sysctl, sizeof(sysctl),
                            "net.wlan.%d.%%parent", atoi(device + 4));
                        sysctlbyname(sysctl, parent, &s, NULL, 0);
                        strlcpy(newdev, device, sizeof(newdev));
@@ -1365,6 +1383,8 @@ open_interface(const char *device, netdissect_options *ndo, char *ebuf)
                else
                        error("%s: %s", device,
                            pcap_statustostr(status));
+               pcap_close(pc);
+               return (NULL);
        } else if (status > 0) {
                /*
                 * pcap_activate() succeeded, but it's warning us
@@ -1396,8 +1416,8 @@ open_interface(const char *device, netdissect_options *ndo, char *ebuf)
         * specified, default to 256KB.
         */
        if (ndo->ndo_snaplen == 0)
-               ndo->ndo_snaplen = 262144;
-       pc = pcap_open_live(device, ndo->ndo_snaplen, !pflag, 1000, ebuf);
+               ndo->ndo_snaplen = MAXIMUM_SNAPLEN;
+       pc = pcap_open_live(device, ndo->ndo_snaplen, !pflag, timeout, ebuf);
        if (pc == NULL) {
                /*
                 * If this failed with "No such device", that means
@@ -1434,8 +1454,10 @@ main(int argc, char **argv)
        u_char *pcap_userdata;
        char ebuf[PCAP_ERRBUF_SIZE];
        char VFileLine[PATH_MAX + 1];
-       char *username = NULL;
-       char *chroot_dir = NULL;
+       const char *username = NULL;
+#ifndef _WIN32
+       const char *chroot_dir = NULL;
+#endif
        char *ret = NULL;
        char *end;
 #ifdef HAVE_PCAP_FINDALLDEVS
@@ -1652,6 +1674,7 @@ main(int argc, char **argv)
                        setvbuf(stdout, NULL, _IOLBF, 0);
 #endif
 #endif /* _WIN32 */
+                       lflag = 1;
                        break;
 
                case 'K':
@@ -1716,7 +1739,7 @@ main(int argc, char **argv)
                        break;
 
                case 's':
-                       ndo->ndo_snaplen = strtol(optarg, &end, 0);
+                       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)",
@@ -1766,6 +1789,8 @@ main(int argc, char **argv)
                                ndo->ndo_packettype = PT_LMP;
                        else if (ascii_strcasecmp(optarg, "resp") == 0)
                                ndo->ndo_packettype = PT_RESP;
+                       else if (ascii_strcasecmp(optarg, "ptp") == 0)
+                               ndo->ndo_packettype = PT_PTP;
                        else
                                error("unknown packet type `%s'", optarg);
                        break;
@@ -1860,6 +1885,27 @@ main(int argc, char **argv)
                        print = 1;
                        break;
 
+#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
+               case OPTION_TSTAMP_MICRO:
+                       ndo->ndo_tstamp_precision = PCAP_TSTAMP_PRECISION_MICRO;
+                       break;
+
+               case OPTION_TSTAMP_NANO:
+                       ndo->ndo_tstamp_precision = PCAP_TSTAMP_PRECISION_NANO;
+                       break;
+#endif
+
+               case OPTION_FP_TYPE:
+                       /*
+                        * Print out the type of floating-point arithmetic
+                        * we're doing; it's probably IEEE, unless somebody
+                        * tries to run this on a VAX, but the precision
+                        * may differ (e.g., it might be 32-bit, 64-bit,
+                        * or 80-bit).
+                        */
+                       float_type_check(0x4e93312d);
+                       return 0;
+
                default:
                        print_usage();
                        exit_tcpdump(S_ERR_HOST_PROGRAM);
@@ -1896,19 +1942,18 @@ main(int argc, char **argv)
        if (VFileName != NULL && RFileName != NULL)
                error("-V and -r are mutually exclusive.");
 
-#ifdef HAVE_PCAP_SET_IMMEDIATE_MODE
        /*
-        * If we're printing dissected packets to the standard output
-        * and the standard output is a terminal, use immediate mode,
-        * as the user's probably expecting to see packets pop up
-        * immediately.
+        * If we're printing dissected packets to the standard output,
+        * and either the standard output is a terminal or we're doing
+        * "line" buffering, set the capture timeout to .1 second rather
+        * than 1 second, as the user's probably expecting to see packets
+        * pop up immediately shortly after they arrive.
         *
-        * XXX - set the timeout to a lower value, instead?  If so,
-        * what value would be appropriate?
+        * XXX - would there be some value appropriate for all cases,
+        * based on, say, the buffer size and packet input rate?
         */
-       if ((WFileName == NULL || print) && isatty(1))
-               immediate_mode = 1;
-#endif
+       if ((WFileName == NULL || print) && (isatty(1) || lflag))
+               timeout = 100;
 
 #ifdef WITH_CHROOT
        /* if run as root, prepare for chrooting */
@@ -1996,6 +2041,29 @@ main(int argc, char **argv)
                if (dlt == DLT_LINUX_SLL2)
                        fprintf(stderr, "Warning: interface names might be incorrect\n");
 #endif
+       } else if (dflag && !device) {
+               int dump_dlt = DLT_EN10MB;
+               /*
+                * We're dumping the compiled code without an explicit
+                * device specification.  (If a device is specified, we
+                * definitely want to open it to use the DLT of that device.)
+                * Either default to DLT_EN10MB with a warning, or use
+                * the user-specified value if supplied.
+                */
+               /*
+                * If no snapshot length was specified, or a length of 0 was
+                * specified, default to 256KB.
+                */
+               if (ndo->ndo_snaplen == 0)
+                       ndo->ndo_snaplen = MAXIMUM_SNAPLEN;
+               /*
+                * If a DLT was specified with the -y flag, use that instead.
+                */
+               if (yflag_dlt != -1)
+                       dump_dlt = yflag_dlt;
+               else
+                       fprintf(stderr, "Warning: assuming Ethernet\n");
+               pd = pcap_open_dead(dump_dlt, ndo->ndo_snaplen);
        } else {
                /*
                 * We're doing a live capture.
@@ -3039,9 +3107,6 @@ print_version(void)
        smi_version_string = nd_smi_version_string();
        if (smi_version_string != NULL)
                (void)fprintf (stderr, "SMI-library: %s\n", smi_version_string);
-#ifdef HAVE_DNET_HTOA
-       (void)fprintf(stderr, "libdnet unknown version\n");
-#endif
 
 #if defined(__SANITIZE_ADDRESS__)
        (void)fprintf (stderr, "Compiled with AddressSanitizer/GCC.\n");
@@ -3074,11 +3139,13 @@ print_usage(void)
        (void)fprintf(stderr,
 "\t\t[ -M secret ] [ --number ] [ --print ]" Q_FLAG_USAGE "\n");
        (void)fprintf(stderr,
-"\t\t[ -r file ] [ -s snaplen ]" TIME_STAMP_PRECISION_USAGE "\n");
+"\t\t[ -r file ] [ -s snaplen ] [ -T type ] [ --version ]\n");
        (void)fprintf(stderr,
-"\t\t[ -T type ] [ --version ] [ -V file ] [ -w file ]\n");
+"\t\t[ -V file ] [ -w file ] [ -W filecount ] [ -y datalinktype ]\n");
+#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
        (void)fprintf(stderr,
-"\t\t[ -W filecount ] [ -y datalinktype ]\n");
+"\t\t[ --time-stamp-precision precision ] [ --micro ] [ --nano ]\n");
+#endif
        (void)fprintf(stderr,
 "\t\t[ -z postrotate-command ] [ -Z user ] [ expression ]\n");
 }