]> The Tcpdump Group git mirrors - libpcap/commitdiff
If attempting to turn memory-mapped access on fails for any reason other
authorguy <guy>
Wed, 19 Nov 2008 10:01:30 +0000 (10:01 +0000)
committerguy <guy>
Wed, 19 Nov 2008 10:01:30 +0000 (10:01 +0000)
than "the kernel doesn't support memory-mapped access to PF_PACKET
sockets", treat that as an error.  If it fails for that reason, don't
leave gunk behind in the pcap_t's error buffer.

Clean up the error messages a bit (the result of strerror() suffices; we
don't need the numeric value of errno, nor do we need the file
descriptor number of the socket on which we're working).

pcap-linux.c

index b18c4d2cf88a68f3546af80376ee65f2b8b2a8d0..e1499dc6dd21c57c17e92b056188506c53cd74b3 100644 (file)
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.159 2008-11-19 08:20:39 guy Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.160 2008-11-19 10:01:30 guy Exp $ (LBL)";
 #endif
 
 /*
@@ -508,7 +508,6 @@ pcap_activate_linux(pcap_t *handle)
 {
        const char      *device;
        int             status = 0;
-       int             activate_ok = 0;
 
        device = handle->opt.source;
 
@@ -555,27 +554,56 @@ pcap_activate_linux(pcap_t *handle)
         */
 
        if ((status = activate_new(handle)) == 1) {
-               activate_ok = 1;
                /*
+                * Success.
                 * Try to use memory-mapped access.
                 */
-               if (activate_mmap(handle) == 1)
-                       return 0;       /* we succeeded; nothing more to do */
+               switch (activate_mmap(handle)) {
+
+               case 1:
+                       /* we succeeded; nothing more to do */
+                       return 0;
+
+               case 0:
+                       /*
+                        * Kernel doesn't support it - just continue
+                        * with non-memory-mapped access.
+                        */
+                       break;
+
+               case -1:
+                       /*
+                        * We failed to set up to use it, or kernel
+                        * supports it, but we failed to enable it;
+                        * return an error.  handle->errbuf contains
+                        * an error message.
+                        */
+                       status = PCAP_ERROR;
+                       goto fail;
+               }
        }
        else if (status == 0) {
                /* Non-fatal error; try old way */
-               if ((status = activate_old(handle)) == 1)
-                       activate_ok = 1;
-       }
-       if (!activate_ok) {
+               if ((status = activate_old(handle)) != 1) {
+                       /*
+                        * Both methods to open the packet socket failed.
+                        * Tidy up and report our failure (handle->errbuf
+                        * is expected to be set by the functions above).
+                        */
+                       goto fail;
+               }
+       } else {
                /*
-                * Both methods to open the packet socket failed. Tidy
-                * up and report our failure (ebuf is expected to be
-                * set by the functions above).
+                * Fatal error with the new way; just fail.
+                * status has the error return; if it's PCAP_ERROR,
+                * handle->errbuf has been set appropriately.
                 */
                goto fail;
        }
 
+       /*
+        * We set up the socket, but not with memory-mapped access.
+        */
        if (handle->opt.buffer_size != 0) {
                /*
                 * Set the socket buffer size to the specified value.
@@ -1941,10 +1969,10 @@ activate_mmap(pcap_t *handle)
                handle->opt.buffer_size = 2*1024*1024;
        }
        ret = prepare_tpacket_socket(handle);
-       if (ret == 0)
+       if (ret != 1)
                return ret;
        ret = create_ring(handle);
-       if (ret == 0)
+       if (ret != 1)
                return ret;
 
        /* override some defaults and inherit the other fields from
@@ -1981,11 +2009,13 @@ prepare_tpacket_socket(pcap_t *handle)
        len = sizeof(val);
        if (getsockopt(handle->fd, SOL_PACKET, PACKET_HDRLEN, &val, &len) < 0) {
                if (errno == ENOPROTOOPT)
-                       return 1;
+                       return 1;       /* no - just drive on */
+
+               /* Yes - treat as a failure. */
                snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-                        "can't get TPACKET_V2 header len on socket %d: %d-%s",
-                        handle->fd, errno, pcap_strerror(errno));
-               return 0;
+                   "can't get TPACKET_V2 header len on packet socket: %s",
+                   pcap_strerror(errno));
+               return -1;
        }
        handle->md.tp_hdrlen = val;
 
@@ -1993,9 +2023,9 @@ prepare_tpacket_socket(pcap_t *handle)
        if (setsockopt(handle->fd, SOL_PACKET, PACKET_VERSION, &val,
                       sizeof(val)) < 0) {
                snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-                        "can't activate TPACKET_V2 on socket %d: %d-%s",
-                        handle->fd, errno, pcap_strerror(errno));
-               return 0;
+                   "can't activate TPACKET_V2 on packet socket: %s",
+                   pcap_strerror(errno));
+               return -1;
        }
        handle->md.tp_version = TPACKET_V2;
 
@@ -2004,9 +2034,9 @@ prepare_tpacket_socket(pcap_t *handle)
        if (setsockopt(handle->fd, SOL_PACKET, PACKET_RESERVE, &val,
                       sizeof(val)) < 0) {
                snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-                        "can't set up reserve on socket %d: %d-%s",
-                        handle->fd, errno, pcap_strerror(errno));
-               return 0;
+                   "can't set up reserve on packet socket: %s",
+                   pcap_strerror(errno));
+               return -1;
        }
 
 #endif /* HAVE_TPACKET2 */
@@ -2058,9 +2088,15 @@ retry:
                        req.tp_block_nr = req.tp_frame_nr/frames_per_block;
                        goto retry;
                }
-               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "can't create rx ring on "
-                               "packet socket %d: %d-%s", handle->fd, errno, 
-                               pcap_strerror(errno));
+               if (errno == ENOPROTOOPT) {
+                       /*
+                        * We don't have ring buffer support in this kernel.
+                        */
+                       return 0;
+               }
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   "can't create rx ring on packet socket: %s",
+                   pcap_strerror(errno));
                return 0;
        }