]> The Tcpdump Group git mirrors - libpcap/blobdiff - pcap-bpf.c
Update config.{guess,sub}, timestamps 2023-01-01,2023-01-21
[libpcap] / pcap-bpf.c
index e2d16aefaa885b0be92be1f9a51948c5515a94ee..2898e598d8e3916c598c6535d79c9851b008d6b0 100644 (file)
@@ -152,7 +152,7 @@ struct pcap_bpf {
         * As there is a header on the front size of the mmap'd buffer, only
         * some of the buffer is exposed to libpcap as a whole via bufsize;
         * zbufsize is the true size.  zbuffer tracks the current zbuf
-        * assocated with buffer so that it can be used to decide which the
+        * associated with buffer so that it can be used to decide which the
         * next buffer to read will be.
         */
        u_char *zbuf1, *zbuf2, *zbuffer;
@@ -312,7 +312,7 @@ pcap_next_zbuf_shm(pcap_t *p, int *cc)
                    atomic_load_acq_int(&bzh->bzh_kernel_gen)) {
                        pb->bzh = bzh;
                        pb->zbuffer = (u_char *)pb->zbuf2;
-                       p->buffer = pb->zbuffer + sizeof(*bzh);
+                       p->buffer = pb->zbuffer + sizeof(*bzh);
                        *cc = bzh->bzh_kernel_len;
                        return (1);
                }
@@ -444,7 +444,7 @@ pcap_create_interface(const char *device _U_, char *ebuf)
 {
        pcap_t *p;
 
-       p = pcap_create_common(ebuf, sizeof (struct pcap_bpf));
+       p = PCAP_CREATE_COMMON(ebuf, struct pcap_bpf);
        if (p == NULL)
                return (NULL);
 
@@ -455,7 +455,6 @@ pcap_create_interface(const char *device _U_, char *ebuf)
         * We claim that we support microsecond and nanosecond time
         * stamps.
         */
-       p->tstamp_precision_count = 2;
        p->tstamp_precision_list = malloc(2 * sizeof(u_int));
        if (p->tstamp_precision_list == NULL) {
                pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, errno,
@@ -465,6 +464,7 @@ pcap_create_interface(const char *device _U_, char *ebuf)
        }
        p->tstamp_precision_list[0] = PCAP_TSTAMP_PRECISION_MICRO;
        p->tstamp_precision_list[1] = PCAP_TSTAMP_PRECISION_NANO;
+       p->tstamp_precision_count = 2;
 #endif /* BIOCSTSTAMP */
        return (p);
 }
@@ -478,7 +478,7 @@ bpf_open(char *errbuf)
 {
        int fd = -1;
        static const char cloning_device[] = "/dev/bpf";
-       int n = 0;
+       u_int n = 0;
        char device[sizeof "/dev/bpf0000000000"];
        static int no_cloning_bpf = 0;
 
@@ -503,12 +503,17 @@ bpf_open(char *errbuf)
            ((errno != EACCES && errno != ENOENT) ||
             (fd = open(cloning_device, O_RDONLY)) == -1)) {
                if (errno != ENOENT) {
-                       if (errno == EACCES)
+                       if (errno == EACCES) {
                                fd = PCAP_ERROR_PERM_DENIED;
-                       else
+                               snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                                   "Attempt to open %s failed - root privileges may be required",
+                                   cloning_device);
+                       } else {
                                fd = PCAP_ERROR;
-                       pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
-                           errno, "(cannot open device) %s", cloning_device);
+                               pcap_fmt_errmsg_for_errno(errbuf,
+                                   PCAP_ERRBUF_SIZE, errno,
+                                   "(cannot open device) %s", cloning_device);
+                       }
                        return (fd);
                }
                no_cloning_bpf = 1;
@@ -521,7 +526,7 @@ bpf_open(char *errbuf)
                 * that isn't in use.
                 */
                do {
-                       (void)snprintf(device, sizeof(device), "/dev/bpf%d", n++);
+                       (void)snprintf(device, sizeof(device), "/dev/bpf%u", n++);
                        /*
                         * Initially try a read/write open (to allow the inject
                         * method to work).  If that fails due to permission
@@ -577,8 +582,9 @@ bpf_open(char *errbuf)
                         * if any.
                         */
                        fd = PCAP_ERROR_PERM_DENIED;
-                       pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
-                           errno, "(cannot open BPF device) %s", device);
+                       snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "Attempt to open %s failed - root privileges may be required",
+                           device);
                        break;
 
                default:
@@ -636,7 +642,7 @@ bpf_bind(int fd, const char *name, char *errbuf)
                /* The name is too long, so it can't possibly exist. */
                return (PCAP_ERROR_NO_SUCH_DEVICE);
        }
-       (void)strncpy(ifr.lifr_name, name, sizeof(ifr.lifr_name));
+       (void)pcap_strlcpy(ifr.lifr_name, name, sizeof(ifr.lifr_name));
        status = ioctl(fd, BIOCSETLIF, (caddr_t)&ifr);
 #else
        struct ifreq ifr;
@@ -645,7 +651,7 @@ bpf_bind(int fd, const char *name, char *errbuf)
                /* The name is too long, so it can't possibly exist. */
                return (PCAP_ERROR_NO_SUCH_DEVICE);
        }
-       (void)strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+       (void)pcap_strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
        status = ioctl(fd, BIOCSETIF, (caddr_t)&ifr);
 #endif
 
@@ -655,7 +661,11 @@ bpf_bind(int fd, const char *name, char *errbuf)
                case ENXIO:
                        /*
                         * There's no such device.
+                        *
+                        * There's nothing more to say, so clear out the
+                        * error message.
                         */
+                       errbuf[0] = '\0';
                        return (PCAP_ERROR_NO_SUCH_DEVICE);
 
                case ENETDOWN:
@@ -680,7 +690,7 @@ bpf_bind(int fd, const char *name, char *errbuf)
                            errno, "The requested buffer size for %s is too large",
                            name);
                        return (BPF_BIND_BUFFER_TOO_BIG);
-                       
+
                default:
                        pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
                            errno, "Binding interface %s to BPF device failed",
@@ -735,29 +745,19 @@ bpf_open_and_bind(const char *name, char *errbuf)
        return (fd);
 }
 
+#ifdef __APPLE__
 static int
 device_exists(int fd, const char *name, char *errbuf)
 {
        int status;
-#ifdef LIFNAMSIZ
-       struct lifreq ifr;
-
-       if (strlen(name) >= sizeof(ifr.lifr_name)) {
-               /* The name is too long, so it can't possibly exist. */
-               return (PCAP_ERROR_NO_SUCH_DEVICE);
-       }
-       (void)strncpy(ifr.lifr_name, name, sizeof(ifr.lifr_name));
-       status = ioctl(fd, SIOCGLIFFLAGS, (caddr_t)&ifr);
-#else
        struct ifreq ifr;
 
        if (strlen(name) >= sizeof(ifr.ifr_name)) {
                /* The name is too long, so it can't possibly exist. */
                return (PCAP_ERROR_NO_SUCH_DEVICE);
        }
-       (void)strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+       (void)pcap_strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
        status = ioctl(fd, SIOCGIFFLAGS, (caddr_t)&ifr);
-#endif
 
        if (status < 0) {
                if (errno == ENXIO || errno == EINVAL) {
@@ -784,6 +784,7 @@ device_exists(int fd, const char *name, char *errbuf)
         */
        return (0);
 }
+#endif
 
 #ifdef BIOCGDLTLIST
 static int
@@ -1186,6 +1187,9 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
 
        /*
         * Loop through each packet.
+        *
+        * This assumes that a single buffer of packets will have
+        * <= INT_MAX packets, so the packet count doesn't overflow.
         */
 #ifdef BIOCSTSTAMP
 #define bhp ((struct bpf_xhdr *)bp)
@@ -1561,7 +1565,7 @@ pcap_cleanup_bpf(pcap_t *p)
                                    strerror(errno));
                        } else {
                                memset(&req, 0, sizeof(req));
-                               strncpy(req.ifm_name, pb->device,
+                               pcap_strlcpy(req.ifm_name, pb->device,
                                    sizeof(req.ifm_name));
                                if (ioctl(sock, SIOCGIFMEDIA, &req) < 0) {
                                        fprintf(stderr,
@@ -1575,7 +1579,7 @@ pcap_cleanup_bpf(pcap_t *p)
                                                 * turn it off.
                                                 */
                                                memset(&ifr, 0, sizeof(ifr));
-                                               (void)strncpy(ifr.ifr_name,
+                                               (void)pcap_strlcpy(ifr.ifr_name,
                                                    pb->device,
                                                    sizeof(ifr.ifr_name));
                                                ifr.ifr_media =
@@ -1643,19 +1647,17 @@ pcap_cleanup_bpf(pcap_t *p)
        pcap_cleanup_live_common(p);
 }
 
+#ifdef __APPLE__
 static int
 check_setif_failure(pcap_t *p, int error)
 {
-#ifdef __APPLE__
        int fd;
        int err;
-#endif
 
        if (error == PCAP_ERROR_NO_SUCH_DEVICE) {
                /*
                 * No such device exists.
                 */
-#ifdef __APPLE__
                if (p->opt.rfmon && strncmp(p->opt.device, "wlt", 3) == 0) {
                        /*
                         * Monitor mode was requested, and we're trying
@@ -1713,7 +1715,7 @@ check_setif_failure(pcap_t *p, int error)
                        }
                        return (err);
                }
-#endif
+
                /*
                 * No such device.
                 */
@@ -1726,6 +1728,17 @@ check_setif_failure(pcap_t *p, int error)
         */
        return (error);
 }
+#else
+static int
+check_setif_failure(pcap_t *p _U_, int error)
+{
+       /*
+        * Just return the error status; it's what we want, and, if it's
+        * PCAP_ERROR, the error string has been filled in.
+        */
+       return (error);
+}
+#endif
 
 /*
  * Default capture buffer size.
@@ -1751,7 +1764,8 @@ pcap_activate_bpf(pcap_t *p)
        int retv;
 #endif
        int fd;
-#ifdef LIFNAMSIZ
+#if defined(LIFNAMSIZ) && defined(ZONENAME_MAX) && defined(lifr_zoneid)
+       struct lifreq ifr;
        char *zonesep;
 #endif
        struct bpf_version bv;
@@ -1969,6 +1983,7 @@ pcap_activate_bpf(pcap_t *p)
                         * it when the pcap_t is closed.
                         */
                        int s;
+                       struct ifreq ifr;
 
                        /*
                         * Open a socket to use for ioctls to
@@ -2189,7 +2204,7 @@ pcap_activate_bpf(pcap_t *p)
                                 *
                                 * Otherwise, fail.
                                 */
-                               if (errno != BPF_BIND_BUFFER_TOO_BIG) {
+                               if (status != BPF_BIND_BUFFER_TOO_BIG) {
                                        /*
                                         * Special checks on macOS to deal
                                         * with the way monitor mode was
@@ -2884,7 +2899,7 @@ get_if_flags(const char *name, bpf_u_int32 *flags, char *errbuf)
                return (-1);
        }
        memset(&req, 0, sizeof(req));
-       strncpy(req.ifm_name, name, sizeof(req.ifm_name));
+       pcap_strlcpy(req.ifm_name, name, sizeof(req.ifm_name));
        if (ioctl(sock, SIOCGIFMEDIA, &req) < 0) {
                if (errno == EOPNOTSUPP || errno == EINVAL || errno == ENOTTY ||
                    errno == ENODEV || errno == EPERM
@@ -2966,7 +2981,7 @@ get_if_flags(const char *name, bpf_u_int32 *flags, char *errbuf)
 }
 #else
 static int
-get_if_flags(const char *name _U_, bpf_u_int32 *flags _U_, char *errbuf _U_)
+get_if_flags(const char *name _U_, bpf_u_int32 *flags, char *errbuf _U_)
 {
        /*
         * Nothing we can do other than mark loopback devices as "the
@@ -3027,7 +3042,7 @@ monitor_mode(pcap_t *p, int set)
        }
 
        memset(&req, 0, sizeof req);
-       strncpy(req.ifm_name, p->opt.device, sizeof req.ifm_name);
+       pcap_strlcpy(req.ifm_name, p->opt.device, sizeof req.ifm_name);
 
        /*
         * Find out how many media types we have.
@@ -3041,7 +3056,11 @@ monitor_mode(pcap_t *p, int set)
                case ENXIO:
                        /*
                         * There's no such device.
+                        *
+                        * There's nothing more to say, so clear the
+                        * error message.
                         */
+                       p->errbuf[0] = '\0';
                        close(sock);
                        return (PCAP_ERROR_NO_SUCH_DEVICE);
 
@@ -3137,7 +3156,7 @@ monitor_mode(pcap_t *p, int set)
                                return (PCAP_ERROR);
                        }
                        memset(&ifr, 0, sizeof(ifr));
-                       (void)strncpy(ifr.ifr_name, p->opt.device,
+                       (void)pcap_strlcpy(ifr.ifr_name, p->opt.device,
                            sizeof(ifr.ifr_name));
                        ifr.ifr_media = req.ifm_current | IFM_IEEE80211_MONITOR;
                        if (ioctl(sock, SIOCSIFMEDIA, &ifr) == -1) {