]> The Tcpdump Group git mirrors - libpcap/commitdiff
When activating a device, return PCAP_ERROR_IFACE_NOT_UP if the device
authorguy <guy>
Tue, 1 Jul 2008 08:04:02 +0000 (08:04 +0000)
committerguy <guy>
Tue, 1 Jul 2008 08:04:02 +0000 (08:04 +0000)
isn't up, so applications can report that differently from a generic
error (the latter could mean there's a bug somewhere in libpcap).

When capturing on a device without mmap on Linux, ignore ENETDOWN, so
that we can continue to capture traffic if the interface goes down and
comes back up again; comments in the kernel indicate that we'll just
block waiting for packets if we try to receive from a socket that
delivered ENETDOWN, and, if we're using a memory-mapped buffer, we won't
even get notified of "network down" events.

pcap-bpf.c
pcap-linux.c
pcap.c
pcap/pcap.h
pcap_activate.3pcap

index 5dfd646ac36d155b1ee6805bed4de81daa6fcc00..052fbda004210725dc0878f4510a38b53da36559 100644 (file)
@@ -20,7 +20,7 @@
  */
 #ifndef lint
 static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.99.2.11 2008-04-14 20:41:51 guy Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.99.2.12 2008-07-01 08:04:02 guy Exp $ (LBL)";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -413,11 +413,23 @@ pcap_can_set_rfmon_bpf(pcap_t *p)
         */
        (void)strncpy(ifr.ifr_name, p->opt.source, sizeof(ifr.ifr_name));
        if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) {
-               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-                   "BIOCSETIF: %s: %s",
-                   p->opt.source, pcap_strerror(errno));
-               close(fd);
-               return (PCAP_ERROR);
+               if (errno == ENETDOWN) {
+                       /*
+                        * Return a "network down" indication, so that
+                        * the application can report that rather than
+                        * saying we had a mysterious failure and
+                        * suggest that they report a problem to the
+                        * libpcap developers.
+                        */
+                       close(fd);
+                       return (PCAP_ERROR_IFACE_NOT_UP);
+               } else {
+                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                           "BIOCSETIF: %s: %s",
+                           p->opt.source, pcap_strerror(errno));
+                       close(fd);
+                       return (PCAP_ERROR);
+               }
        }
 
        /*
@@ -1016,6 +1028,15 @@ check_setif_failure(pcap_t *p, int error)
                 */
                strcpy(p->errbuf, "");
                return (PCAP_ERROR_NO_SUCH_DEVICE);
+       } else if (errno == ENETDOWN) {
+               /*
+                * Return a "network down" indication, so that
+                * the application can report that rather than
+                * saying we had a mysterious failure and
+                * suggest that they report a problem to the
+                * libpcap developers.
+                */
+               return (PCAP_ERROR_IFACE_NOT_UP);
        } else {
                /*
                 * Some other error; fill in the error string, and
index db561367bd2e82bc2d816bb8be37cdd4d7938431..8e3142713c8c78fac307d292887b519b03d84e5d 100644 (file)
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.129.2.20 2008-06-24 06:45:04 guy Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.129.2.21 2008-07-01 08:04:03 guy Exp $ (LBL)";
 #endif
 
 /*
@@ -646,8 +646,21 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
        offset = 0;
 #endif
 
-       /* Receive a single packet from the kernel */
-
+       /*
+        * Receive a single packet from the kernel.
+        * We ignore EINTR, as that might just be due to a signal
+        * being delivered - if the signal should interrupt the
+        * loop, the signal handler should call pcap_breakloop()
+        * to set handle->break_loop (we ignore it on other
+        * platforms as well).
+        * We also ignore ENETDOWN, so that we can continue to
+        * capture traffic if the interface goes down and comes
+        * back up again; comments in the kernel indicate that
+        * we'll just block waiting for packets if we try to
+        * receive from a socket that delivered ENETDOWN, and,
+        * if we're using a memory-mapped buffer, we won't even
+        * get notified of "network down" events.
+        */
        bp = handle->buffer + handle->offset;
        do {
                /*
@@ -667,7 +680,7 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
                        handle->fd, bp + offset,
                        handle->bufsize - offset, MSG_TRUNC,
                        (struct sockaddr *) &from, &fromlen);
-       } while (packet_len == -1 && errno == EINTR);
+       } while (packet_len == -1 && (errno == EINTR || errno == ENETDOWN));
 
        /* Check if an error occured */
 
@@ -1722,10 +1735,10 @@ activate_new(pcap_t *handle)
                }
 
                if ((err = iface_bind(sock_fd, handle->md.ifindex,
-                   handle->errbuf)) < 0) {
+                   handle->errbuf)) != 1) {
                        close(sock_fd);
-                       if (err == -2)
-                               return PCAP_ERROR;
+                       if (err < 0)
+                               return err;
                        else
                                return 0;       /* try old mechanism */
                }
@@ -2183,6 +2196,8 @@ iface_get_id(int fd, const char *device, char *ebuf)
 
 /*
  *  Bind the socket associated with FD to the given device.
+ *  Return 1 on success, 0 if we should try a SOCK_PACKET socket,
+ *  or a PCAP_ERROR_ value on a hard error.
  */
 static int
 iface_bind(int fd, int ifindex, char *ebuf)
@@ -2197,9 +2212,20 @@ iface_bind(int fd, int ifindex, char *ebuf)
        sll.sll_protocol        = htons(ETH_P_ALL);
 
        if (bind(fd, (struct sockaddr *) &sll, sizeof(sll)) == -1) {
-               snprintf(ebuf, PCAP_ERRBUF_SIZE,
-                        "bind: %s", pcap_strerror(errno));
-               return -1;
+               if (errno == ENETDOWN) {
+                       /*
+                        * Return a "network down" indication, so that
+                        * the application can report that rather than
+                        * saying we had a mysterious failure and
+                        * suggest that they report a problem to the
+                        * libpcap developers.
+                        */
+                       return PCAP_ERROR_IFACE_NOT_UP;
+               } else {
+                       snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                                "bind: %s", pcap_strerror(errno));
+                       return PCAP_ERROR;
+               }
        }
 
        /* Any pending errors, e.g., network is down? */
@@ -2207,16 +2233,25 @@ iface_bind(int fd, int ifindex, char *ebuf)
        if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {
                snprintf(ebuf, PCAP_ERRBUF_SIZE,
                        "getsockopt: %s", pcap_strerror(errno));
-               return -2;
+               return 0;
        }
 
-       if (err > 0) {
+       if (err == ENETDOWN) {
+               /*
+                * Return a "network down" indication, so that
+                * the application can report that rather than
+                * saying we had a mysterious failure and
+                * suggest that they report a problem to the
+                * libpcap developers.
+                */
+               return PCAP_ERROR_IFACE_NOT_UP;
+       } else if (err > 0) {
                snprintf(ebuf, PCAP_ERRBUF_SIZE,
                        "bind: %s", pcap_strerror(err));
-               return -2;
+               return 0;
        }
 
-       return 0;
+       return 1;
 }
 
 /*
diff --git a/pcap.c b/pcap.c
index 2a088956bd7ab1471b8c9841b1898f7b5aaa3d42..bceed2c61aeefd113f9b54a996b265eeb86b7a88 100644 (file)
--- a/pcap.c
+++ b/pcap.c
@@ -33,7 +33,7 @@
 
 #ifndef lint
 static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.112.2.10 2008-05-26 19:58:59 guy Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.112.2.11 2008-07-01 08:04:03 guy Exp $ (LBL)";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -951,6 +951,9 @@ pcap_statustostr(int errnum)
 
        case PCAP_ERROR_PERM_DENIED:
                return ("You don't have permission to capture on that device");
+
+       case PCAP_ERROR_IFACE_NOT_UP:
+               return ("That device is not up");
        }
        (void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum);
        return(ebuf);
index bdd11ea9d5f9deadeb671b309b5a11fd292d6a13..5957a3de29cdcd1dac778e59c7847e27ccfb5599 100644 (file)
@@ -31,7 +31,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * @(#) $Header: /tcpdump/master/libpcap/pcap/pcap.h,v 1.4.2.9 2008-05-30 01:36:06 guy Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/libpcap/pcap/pcap.h,v 1.4.2.10 2008-07-01 08:04:03 guy Exp $ (LBL)
  */
 
 #ifndef lib_pcap_pcap_h
@@ -243,6 +243,7 @@ typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,
 #define PCAP_ERROR_RFMON_NOTSUP                -6      /* this device doesn't support rfmon (monitor) mode */
 #define PCAP_ERROR_NOT_RFMON           -7      /* operation supported only in monitor mode */
 #define PCAP_ERROR_PERM_DENIED         -8      /* no permission to open the device */
+#define PCAP_ERROR_IFACE_NOT_UP                -9      /* interface isn't up */
 
 /*
  * Warning codes for the pcap API.
index 2a5367ab4cec23aecb32ca78742169ea27e614a1..5b191360477f6166f28e27f081f4a247817a8a57 100644 (file)
@@ -1,4 +1,4 @@
-.\" @(#) $Header: /tcpdump/master/libpcap/pcap_activate.3pcap,v 1.1.2.4 2008-04-09 21:26:37 guy Exp $
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_activate.3pcap,v 1.1.2.5 2008-07-01 08:04:03 guy Exp $
 .\"
 .\" Copyright (c) 1994, 1996, 1997
 .\"    The Regents of the University of California.  All rights reserved.
@@ -54,9 +54,11 @@ exist,
 if the process doesn't have permission to open the capture source,
 .B PCAP_ERROR_RFMON_NOTSUP
 if monitor mode was specified but the capture source doesn't support
-monitor mode, and
+monitor mode,
+.B PCAP_ERROR_IFACE_NOT_UP
+if the capture source is not up, and
 .B PCAP_ERROR
-if an error occurred.
+if another error occurred.
 If
 .B PCAP_WARNING
 or