]> The Tcpdump Group git mirrors - tcpdump/blobdiff - tcpdump.c
DCCP: Fix printing "Timestamp" and "Timestamp Echo" options
[tcpdump] / tcpdump.c
index f9facaf2faaf173a2baacac7d068cecf8446416d..8ea4925148bcae0853bcfdc5604dda004282de9a 100644 (file)
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -142,12 +142,16 @@ The Regents of the University of California.  All rights reserved.\n";
 #define PATH_MAX 1024
 #endif
 
-#ifdef SIGINFO
+#if defined(SIGINFO)
 #define SIGNAL_REQ_INFO SIGINFO
-#elif SIGUSR1
+#elif defined(SIGUSR1)
 #define SIGNAL_REQ_INFO SIGUSR1
 #endif
 
+#if defined(HAVE_PCAP_DUMP_FLUSH) && defined(SIGUSR2)
+#define SIGNAL_FLUSH_PCAP SIGUSR2
+#endif
+
 static int Bflag;                      /* buffer size */
 #ifdef HAVE_PCAP_DUMP_FTELL64
 static int64_t Cflag;                  /* rotate dump files after this many bytes */
@@ -192,7 +196,9 @@ 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) */
+#ifdef HAVE_PCAP_SET_IMMEDIATE_MODE
 static int immediate_mode;
+#endif
 
 static int infodelay;
 static int infoprint;
@@ -227,7 +233,11 @@ static void dump_packet(u_char *, const struct pcap_pkthdr *, const u_char *);
 static void droproot(const char *, const char *);
 
 #ifdef SIGNAL_REQ_INFO
-void requestinfo(int);
+static void requestinfo(int);
+#endif
+
+#ifdef SIGNAL_FLUSH_PCAP
+static void flushpcap(int);
 #endif
 
 #ifdef _WIN32
@@ -249,11 +259,15 @@ static const struct tok status_flags[] = {
        { PCAP_IF_RUNNING,  "Running"  },
 #endif
        { PCAP_IF_LOOPBACK, "Loopback" },
+#ifdef PCAP_IF_WIRELESS
+       { PCAP_IF_WIRELESS, "Wireless" },
+#endif
        { 0, NULL }
 };
 #endif
 
 static pcap_t *pd;
+static pcap_dumper_t *pdd = NULL;
 
 static int supports_monitor_mode;
 
@@ -265,7 +279,7 @@ struct dump_info {
        char    *WFileName;
        char    *CurrentFileName;
        pcap_t  *pd;
-       pcap_dumper_t *p;
+       pcap_dumper_t *pdd;
        netdissect_options *ndo;
 #ifdef HAVE_CAPSICUM
        int     dirfd;
@@ -466,8 +480,50 @@ show_devices_and_exit(void)
                printf("%d.%s", i+1, dev->name);
                if (dev->description != NULL)
                        printf(" (%s)", dev->description);
-               if (dev->flags != 0)
-                       printf(" [%s]", bittok2str(status_flags, "none", dev->flags));
+               if (dev->flags != 0) {
+                       printf(" [");
+                       printf("%s", bittok2str(status_flags, "none", dev->flags));
+#ifdef PCAP_IF_WIRELESS
+                       if (dev->flags & PCAP_IF_WIRELESS) {
+                               switch (dev->flags & PCAP_IF_CONNECTION_STATUS) {
+
+                               case PCAP_IF_CONNECTION_STATUS_UNKNOWN:
+                                       printf(", Association status unknown");
+                                       break;
+
+                               case PCAP_IF_CONNECTION_STATUS_CONNECTED:
+                                       printf(", Associated");
+                                       break;
+
+                               case PCAP_IF_CONNECTION_STATUS_DISCONNECTED:
+                                       printf(", Not associated");
+                                       break;
+
+                               case PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE:
+                                       break;
+                               }
+                       } else {
+                               switch (dev->flags & PCAP_IF_CONNECTION_STATUS) {
+
+                               case PCAP_IF_CONNECTION_STATUS_UNKNOWN:
+                                       printf(", Connection status unknown");
+                                       break;
+
+                               case PCAP_IF_CONNECTION_STATUS_CONNECTED:
+                                       printf(", Connected");
+                                       break;
+
+                               case PCAP_IF_CONNECTION_STATUS_DISCONNECTED:
+                                       printf(", Disconnected");
+                                       break;
+
+                               case PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE:
+                                       break;
+                               }
+                       }
+#endif
+                       printf("]");
+               }
                printf("\n");
        }
        pcap_freealldevs(devlist);
@@ -1012,9 +1068,35 @@ read_infile(char *fname)
 static long
 parse_interface_number(const char *device)
 {
+       const char *p;
        long devnum;
        char *end;
 
+       /*
+        * Search for a colon, terminating any scheme at the beginning
+        * of the device.
+        */
+       p = strchr(device, ':');
+       if (p != NULL) {
+               /*
+                * We found it.  Is it followed by "//"?
+                */
+               p++;    /* skip the : */
+               if (strncmp(p, "//", 2) == 0) {
+                       /*
+                        * Yes.  Search for the next /, at the end of the
+                        * authority part of the URL.
+                        */
+                       p += 2; /* skip the // */
+                       p = strchr(p, '/');
+                       if (p != NULL) {
+                               /*
+                                * OK, past the / is the path.
+                                */
+                               device = p + 1;
+                       }
+               }
+       }
        devnum = strtol(device, &end, 10);
        if (device != end && *end == '\0') {
                /*
@@ -1037,14 +1119,54 @@ parse_interface_number(const char *device)
 }
 
 static char *
-find_interface_by_number(long devnum)
+find_interface_by_number(const char *url, long devnum)
 {
        pcap_if_t *dev, *devlist;
        long i;
        char ebuf[PCAP_ERRBUF_SIZE];
        char *device;
+#ifdef HAVE_PCAP_FINDALLDEVS_EX
+       const char *endp;
+       char *host_url;
+#endif
+       int status;
 
-       if (pcap_findalldevs(&devlist, ebuf) < 0)
+#ifdef HAVE_PCAP_FINDALLDEVS_EX
+       /*
+        * Search for a colon, terminating any scheme at the beginning
+        * of the URL.
+        */
+       endp = strchr(url, ':');
+       if (endp != NULL) {
+               /*
+                * We found it.  Is it followed by "//"?
+                */
+               endp++; /* skip the : */
+               if (strncmp(endp, "//", 2) == 0) {
+                       /*
+                        * Yes.  Search for the next /, at the end of the
+                        * authority part of the URL.
+                        */
+                       endp += 2;      /* skip the // */
+                       endp = strchr(endp, '/');
+               } else
+                       endp = NULL;
+       }
+       if (endp != NULL) {
+               /*
+                * OK, everything from device to endp is a URL to hand
+                * to pcap_findalldevs_ex().
+                */
+               endp++; /* Include the trailing / in the URL; pcap_findalldevs_ex() requires it */
+               host_url = malloc(endp - url + 1);
+               memcpy(host_url, url, endp - url);
+               host_url[endp - url] = '\0';
+               status = pcap_findalldevs_ex(host_url, NULL, &devlist, ebuf);
+               free(host_url);
+       } else
+#endif
+       status = pcap_findalldevs(&devlist, ebuf);
+       if (status < 0)
                error("%s", ebuf);
        /*
         * Look for the devnum-th entry in the list of devices (1-based).
@@ -1085,18 +1207,19 @@ open_interface(const char *device, netdissect_options *ndo, char *ebuf)
                 * Yes.  Open it with pcap_open().
                 */
                *ebuf = '\0';
-fprintf(stderr, "Opening %s\n", device);
                pc = pcap_open(device, ndo->ndo_snaplen,
                    pflag ? 0 : PCAP_OPENFLAG_PROMISCUOUS, 1000, NULL,
                    ebuf);
                if (pc == NULL) {
                        /*
-                        * If this failed with "No such device", that means
+                        * If this failed with "No such device" or "The system
+                        * cannot find the device specified", that means
                         * the interface doesn't exist; return NULL, so that
                         * the caller can see whether the device name is
                         * actually an interface index.
                         */
-                       if (strstr(ebuf, "No such device") != NULL)
+                       if (strstr(ebuf, "No such device") != NULL ||
+                           strstr(ebuf, "The system cannot find the device specified") != NULL)
                                return (NULL);
                        error("%s", ebuf);
                }
@@ -1923,7 +2046,7 @@ main(int argc, char **argv)
                         * find_interface_by_number() exits if it
                         * couldn't be found.
                         */
-                       device = find_interface_by_number(devnum);
+                       device = find_interface_by_number(device, devnum);
                        pd = open_interface(device, ndo, ebuf);
                        if (pd == NULL)
                                error("%s", ebuf);
@@ -2089,7 +2212,7 @@ DIAG_ON_CLANG(assign-enum)
        if (pcap_setfilter(pd, &fcode) < 0)
                error("%s", pcap_geterr(pd));
 #ifdef HAVE_CAPSICUM
-       if (RFileName == NULL && VFileName == NULL) {
+       if (RFileName == NULL && VFileName == NULL && pcap_fileno(pd) != -1) {
                static const unsigned long cmds[] = { BIOCGSTATS, BIOCROTZBUF };
 
                /*
@@ -2109,7 +2232,6 @@ DIAG_ON_CLANG(assign-enum)
        }
 #endif
        if (WFileName) {
-               pcap_dumper_t *p;
                /* Do not exceed the default PATH_MAX for files. */
                dumpinfo.CurrentFileName = (char *)malloc(PATH_MAX + 1);
 
@@ -2122,7 +2244,7 @@ DIAG_ON_CLANG(assign-enum)
                else
                  MakeFilename(dumpinfo.CurrentFileName, WFileName, 0, 0);
 
-               p = pcap_dump_open(pd, dumpinfo.CurrentFileName);
+               pdd = pcap_dump_open(pd, dumpinfo.CurrentFileName);
 #ifdef HAVE_LIBCAP_NG
                /* Give up CAP_DAC_OVERRIDE capability.
                 * Only allow it to be restored if the -C or -G flag have been
@@ -2136,7 +2258,7 @@ DIAG_ON_CLANG(assign-enum)
                        );
                capng_apply(CAPNG_SELECT_BOTH);
 #endif /* HAVE_LIBCAP_NG */
-               if (p == NULL)
+               if (pdd == NULL)
                        error("%s", pcap_geterr(pd));
 #ifdef HAVE_CAPSICUM
                set_dumper_capsicum_rights(p);
@@ -2169,13 +2291,13 @@ DIAG_ON_CLANG(assign-enum)
 #endif
                        callback = dump_packet_and_trunc;
                        dumpinfo.pd = pd;
-                       dumpinfo.p = p;
+                       dumpinfo.pdd = pdd;
                        pcap_userdata = (u_char *)&dumpinfo;
                } else {
                        callback = dump_packet;
                        dumpinfo.WFileName = WFileName;
                        dumpinfo.pd = pd;
-                       dumpinfo.p = p;
+                       dumpinfo.pdd = pdd;
                        pcap_userdata = (u_char *)&dumpinfo;
                }
                if (print) {
@@ -2187,7 +2309,7 @@ DIAG_ON_CLANG(assign-enum)
 
 #ifdef HAVE_PCAP_DUMP_FLUSH
                if (Uflag)
-                       pcap_dump_flush(p);
+                       pcap_dump_flush(pdd);
 #endif
        } else {
                dlt = pcap_datalink(pd);
@@ -2204,6 +2326,9 @@ DIAG_ON_CLANG(assign-enum)
        if (RFileName == NULL)
                (void)setsignal(SIGNAL_REQ_INFO, requestinfo);
 #endif
+#ifdef SIGNAL_FLUSH_PCAP
+       (void)setsignal(SIGNAL_FLUSH_PCAP, flushpcap);
+#endif
 
        if (ndo->ndo_vflag > 0 && WFileName && !print) {
                /*
@@ -2619,7 +2744,7 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s
                        /*
                         * Close the current file and open a new one.
                         */
-                       pcap_dump_close(dump_info->p);
+                       pcap_dump_close(dump_info->pdd);
 
                        /*
                         * Compress the file we just closed, if the user asked for it
@@ -2679,18 +2804,18 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s
                                error("unable to fdopen file %s",
                                    dump_info->CurrentFileName);
                        }
-                       dump_info->p = pcap_dump_fopen(dump_info->pd, fp);
+                       dump_info->pdd = pcap_dump_fopen(dump_info->pd, fp);
 #else  /* !HAVE_CAPSICUM */
-                       dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName);
+                       dump_info->pdd = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName);
 #endif
 #ifdef HAVE_LIBCAP_NG
                        capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE);
                        capng_apply(CAPNG_SELECT_BOTH);
 #endif /* HAVE_LIBCAP_NG */
-                       if (dump_info->p == NULL)
+                       if (dump_info->pdd == NULL)
                                error("%s", pcap_geterr(pd));
 #ifdef HAVE_CAPSICUM
-                       set_dumper_capsicum_rights(dump_info->p);
+                       set_dumper_capsicum_rights(dump_info->pdd);
 #endif
                }
        }
@@ -2702,7 +2827,7 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s
         */
        if (Cflag != 0) {
 #ifdef HAVE_PCAP_DUMP_FTELL64
-               int64_t size = pcap_dump_ftell64(dump_info->p);
+               int64_t size = pcap_dump_ftell64(dump_info->pdd);
 #else
                /*
                 * XXX - this only handles a Cflag value > 2^31-1 on
@@ -2710,7 +2835,7 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s
                 * Windows) or LLP64 (64-bit Windows) would require
                 * a version of libpcap with pcap_dump_ftell64().
                 */
-               long size = pcap_dump_ftell(dump_info->p);
+               long size = pcap_dump_ftell(dump_info->pdd);
 #endif
 
                if (size == -1)
@@ -2724,7 +2849,7 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s
                        /*
                         * Close the current file and open a new one.
                         */
-                       pcap_dump_close(dump_info->p);
+                       pcap_dump_close(dump_info->pdd);
 
                        /*
                         * Compress the file we just closed, if the user
@@ -2760,26 +2885,26 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s
                                error("unable to fdopen file %s",
                                    dump_info->CurrentFileName);
                        }
-                       dump_info->p = pcap_dump_fopen(dump_info->pd, fp);
+                       dump_info->pdd = pcap_dump_fopen(dump_info->pd, fp);
 #else  /* !HAVE_CAPSICUM */
-                       dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName);
+                       dump_info->pdd = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName);
 #endif
 #ifdef HAVE_LIBCAP_NG
                        capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE);
                        capng_apply(CAPNG_SELECT_BOTH);
 #endif /* HAVE_LIBCAP_NG */
-                       if (dump_info->p == NULL)
+                       if (dump_info->pdd == NULL)
                                error("%s", pcap_geterr(pd));
 #ifdef HAVE_CAPSICUM
-                       set_dumper_capsicum_rights(dump_info->p);
+                       set_dumper_capsicum_rights(dump_info->pdd);
 #endif
                }
        }
 
-       pcap_dump((u_char *)dump_info->p, h, sp);
+       pcap_dump((u_char *)dump_info->pdd, h, sp);
 #ifdef HAVE_PCAP_DUMP_FLUSH
        if (Uflag)
-               pcap_dump_flush(dump_info->p);
+               pcap_dump_flush(dump_info->pdd);
 #endif
 
        if (dump_info->ndo != NULL)
@@ -2801,10 +2926,10 @@ dump_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
 
        dump_info = (struct dump_info *)user;
 
-       pcap_dump((u_char *)dump_info->p, h, sp);
+       pcap_dump((u_char *)dump_info->pdd, h, sp);
 #ifdef HAVE_PCAP_DUMP_FLUSH
        if (Uflag)
-               pcap_dump_flush(dump_info->p);
+               pcap_dump_flush(dump_info->pdd);
 #endif
 
        if (dump_info->ndo != NULL)
@@ -2830,7 +2955,8 @@ print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
 }
 
 #ifdef SIGNAL_REQ_INFO
-void requestinfo(int signo _U_)
+static void
+requestinfo(int signo _U_)
 {
        if (infodelay)
                ++infoprint;
@@ -2839,6 +2965,15 @@ void requestinfo(int signo _U_)
 }
 #endif
 
+#ifdef SIGNAL_FLUSH_PCAP
+static void
+flushpcap(int signo _U_)
+{
+       if (pdd != NULL)
+               pcap_dump_flush(pdd);
+}
+#endif
+
 static void
 print_packets_captured (void)
 {