]> The Tcpdump Group git mirrors - tcpdump/blobdiff - tcpdump.c
NTP: Use tstr for truncation indicator.
[tcpdump] / tcpdump.c
index a0c273af86282a779f5f7684349b98420567dc96..270f79b4b92658d2188727f8b475b8ecc395e1ca 100644 (file)
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -44,9 +44,10 @@ The Regents of the University of California.  All rights reserved.\n";
 #endif
 
 /*
- * Mac OS X may ship pcap.h from libpcap 0.6 with a libpcap based on
- * 0.8.  That means it has pcap_findalldevs() but the header doesn't
- * define pcap_if_t, meaning that we can't actually *use* pcap_findalldevs().
+ * Some older versions of Mac OS X may ship pcap.h from libpcap 0.6 with a
+ * libpcap based on 0.8.  That means it has pcap_findalldevs() but the
+ * header doesn't define pcap_if_t, meaning that we can't actually *use*
+ * pcap_findalldevs().
  */
 #ifdef HAVE_PCAP_FINDALLDEVS
 #ifndef HAVE_PCAP_IF_T
@@ -113,6 +114,10 @@ The Regents of the University of California.  All rights reserved.\n";
 #endif /* HAVE_CAP_NG_H */
 #endif /* HAVE_LIBCAP_NG */
 
+#ifdef __FreeBSD__
+#include <sys/sysctl.h>
+#endif /* __FreeBSD__ */
+
 #include "netdissect.h"
 #include "interface.h"
 #include "addrtoname.h"
@@ -135,7 +140,7 @@ The Regents of the University of California.  All rights reserved.\n";
 #endif
 
 static int Bflag;                      /* buffer size */
-static int Cflag;                      /* rotate dump files after this many bytes */
+static long Cflag;                     /* rotate dump files after this many bytes */
 static int Cflag_count;                        /* Keep track of which file number we're writing */
 static int Dflag;                      /* list available devices and exit */
 /*
@@ -180,26 +185,17 @@ cap_channel_t *capdns;
 #endif
 
 /* Forwards */
-static void error(const char *, ...)
-     __attribute__((noreturn))
-#ifdef __ATTRIBUTE___FORMAT_OK
-     __attribute__((format (printf, 1, 2)))
-#endif /* __ATTRIBUTE___FORMAT_OK */
-     ;
-static void warning(const char *, ...)
-#ifdef __ATTRIBUTE___FORMAT_OK
-     __attribute__((format (printf, 1, 2)))
-#endif /* __ATTRIBUTE___FORMAT_OK */
-     ;
-static void exit_tcpdump(int) __attribute__((noreturn));
+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 RETSIGTYPE cleanup(int);
 static RETSIGTYPE child_cleanup(int);
 static void print_version(void);
 static void print_usage(void);
-static void show_tstamp_types_and_exit(pcap_t *, const char *device) __attribute__((noreturn));
-static void show_dlts_and_exit(pcap_t *, const char *device) __attribute__((noreturn));
+static NORETURN void show_tstamp_types_and_exit(pcap_t *, const char *device);
+static NORETURN void show_dlts_and_exit(pcap_t *, const char *device);
 #ifdef HAVE_PCAP_FINDALLDEVS
-static void show_devices_and_exit (void) __attribute__((noreturn));
+static NORETURN void show_devices_and_exit(void);
 #endif
 
 static void print_packet(u_char *, const struct pcap_pkthdr *, const u_char *);
@@ -1040,10 +1036,16 @@ open_interface(const char *device, netdissect_options *ndo, char *ebuf)
                supports_monitor_mode = 1;
        else
                supports_monitor_mode = 0;
-       status = pcap_set_snaplen(pc, ndo->ndo_snaplen);
-       if (status != 0)
-               error("%s: Can't set snapshot length: %s",
-                   device, pcap_statustostr(status));
+       if (ndo->ndo_snaplen != 0) {
+               /*
+                * A snapshot length was explicitly specified;
+                * use it.
+                */
+               status = pcap_set_snaplen(pc, ndo->ndo_snaplen);
+               if (status != 0)
+                       error("%s: Can't set snapshot length: %s",
+                           device, pcap_statustostr(status));
+       }
        status = pcap_set_promisc(pc, !pflag);
        if (status != 0)
                error("%s: Can't set promiscuous mode: %s",
@@ -1084,13 +1086,37 @@ open_interface(const char *device, netdissect_options *ndo, char *ebuf)
                        /*
                         * Return an error for our caller to handle.
                         */
-                       pcap_close(pc);
                        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);
+#ifdef __FreeBSD__
+               else if (status == PCAP_ERROR_RFMON_NOTSUP &&
+                   strncmp(device, "wlan", 4) == 0) {
+                       char parent[8], newdev[8];
+                       char sysctl[32];
+                       size_t s = sizeof(parent);
+
+                       snprintf(sysctl, sizeof(sysctl),
+                           "net.wlan.%d.%%parent", atoi(device + 4));
+                       sysctlbyname(sysctl, parent, &s, NULL, 0);
+                       strlcpy(newdev, device, sizeof(newdev));
+                       /* Suggest a new wlan device. */
+                       /* FIXME: incrementing the index this way is not going to work well
+                        * when the index is 9 or greater but the only consequence in this
+                        * 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"
+                           "To create a new monitor mode VAP use:\n"
+                           "  ifconfig %s create wlandev %s wlanmode monitor\n"
+                           "and use %s as the tcpdump interface",
+                           device, newdev, parent, newdev);
+               }
+#endif
                else
                        error("%s: %s", device,
                            pcap_statustostr(status));
@@ -1120,6 +1146,12 @@ open_interface(const char *device, netdissect_options *ndo, char *ebuf)
 #endif /* HAVE_PCAP_SETDIRECTION */
 #else /* HAVE_PCAP_CREATE */
        *ebuf = '\0';
+       /*
+        * If no snapshot length was specified, or a length of 0 was
+        * specified, default to 256KB.
+        */
+       if (ndo->ndo_snaplen == 0)
+               ndo->ndo_snaplen = 262144;
        pc = pcap_open_live(device, ndo->ndo_snaplen, !pflag, 1000, ebuf);
        if (pc == NULL) {
                /*
@@ -1186,7 +1218,6 @@ main(int argc, char **argv)
 
        memset(ndo, 0, sizeof(*ndo));
        ndo_set_function_pointers(ndo);
-       ndo->ndo_snaplen = DEFAULT_SNAPLEN;
 
        cnt = -1;
        device = NULL;
@@ -1416,8 +1447,6 @@ main(int argc, char **argv)
                        if (optarg == end || *end != '\0'
                            || ndo->ndo_snaplen < 0 || ndo->ndo_snaplen > MAXIMUM_SNAPLEN)
                                error("invalid snaplen %s", optarg);
-                       else if (ndo->ndo_snaplen == 0)
-                               ndo->ndo_snaplen = MAXIMUM_SNAPLEN;
                        break;
 
                case 'S':
@@ -1755,7 +1784,8 @@ main(int argc, char **argv)
                }
 
                /*
-                * Let user own process after socket has been opened.
+                * Let user own process after capture device has
+                * been opened.
                 */
 #ifndef _WIN32
                if (setgid(getgid()) != 0 || setuid(getuid()) != 0)
@@ -1790,7 +1820,11 @@ main(int argc, char **argv)
                }
                i = pcap_snapshot(pd);
                if (ndo->ndo_snaplen < i) {
-                       warning("snaplen raised from %d to %d", ndo->ndo_snaplen, i);
+                       if (ndo->ndo_snaplen != 0)
+                               warning("snaplen raised from %d to %d", ndo->ndo_snaplen, i);
+                       ndo->ndo_snaplen = i;
+               } else if (ndo->ndo_snaplen > i) {
+                       warning("snaplen lowered from %d to %d", ndo->ndo_snaplen, i);
                        ndo->ndo_snaplen = i;
                }
                 if(ndo->ndo_fflag != 0) {
@@ -1899,7 +1933,12 @@ main(int argc, char **argv)
        if (RFileName == NULL && VFileName == NULL) {
                static const unsigned long cmds[] = { BIOCGSTATS, BIOCROTZBUF };
 
-               cap_rights_init(&rights, CAP_IOCTL, CAP_READ);
+               /*
+                * The various libpcap devices use a combination of
+                * read (bpf), ioctl (bpf, netmap), poll (netmap)
+                * so we add the relevant access rights.
+                */
+               cap_rights_init(&rights, CAP_IOCTL, CAP_READ, CAP_EVENT);
                if (cap_rights_limit(pcap_fileno(pd), &rights) < 0 &&
                    errno != ENOSYS) {
                        error("unable to limit pcap descriptor");
@@ -2648,6 +2687,14 @@ 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);
+
+#if defined(__SANITIZE_ADDRESS__)
+       (void)fprintf (stderr, "Compiled with AddressSanitizer/GCC.\n");
+#elif defined(__has_feature)
+#  if __has_feature(address_sanitizer)
+       (void)fprintf (stderr, "Compiled with AddressSanitizer/CLang.\n");
+#  endif
+#endif /* __SANITIZE_ADDRESS__ or __has_feature */
 }
 USES_APPLE_RST