]> The Tcpdump Group git mirrors - libpcap/commitdiff
Fixes from Phil Wood:
authorguy <guy>
Mon, 10 Dec 2001 05:49:40 +0000 (05:49 +0000)
committerguy <guy>
Mon, 10 Dec 2001 05:49:40 +0000 (05:49 +0000)
Don't subtract "tp_drops" from "tp_packets" - "ps_recv", on BSD,
at least, includes packets dropped due to lack of buffer space,
so it should do so on Linux as well.

The "len" argument to "getsockopt()" is a value-result
parameter, initially containing the size of the buffer being
supplied; set it before the call.

Catch "getsockopt()" errors and, if it's an error other than
EOPNOTSUPP, return an error.

CREDITS
pcap-linux.c

diff --git a/CREDITS b/CREDITS
index 3af010a9b3a3c6537b58225013e5b135210025a7..77127dcfe9feee2466c6e9644f94638fc28869d9 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -38,6 +38,7 @@ Additional people who have contributed patches:
        Onno van der Linden             <[email protected]>
        Pavel Kankovsky                 <[email protected]>
        Peter Jeremy                    <[email protected]>
+       Phil Wood                       <[email protected]>
        Rafal Maszkowski                <[email protected]>
        Rick Jones                      <[email protected]>
        Scott Barron                    <[email protected]>
index 49058ab6ec890733fd1a4a84f072fbdc509d1a1d..1fc90541d414e6382ac10c9ee5b22c7de24c0fb9 100644 (file)
@@ -26,7 +26,7 @@
  */
 #ifndef lint
 static const char rcsid[] =
-    "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.71 2001-10-25 18:09:59 guy Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.72 2001-12-10 05:49:40 guy Exp $ (LBL)";
 #endif
 
 /*
@@ -627,16 +627,60 @@ pcap_stats(pcap_t *handle, struct pcap_stat *stats)
 {
 #ifdef HAVE_TPACKET_STATS
        struct tpacket_stats kstats;
-       socklen_t len;
+       socklen_t len = sizeof (struct tpacket_stats);
 
        /*
         * Try to get the packet counts from the kernel.
         */
        if (getsockopt(handle->fd, SOL_PACKET, PACKET_STATISTICS,
                        &kstats, &len) > -1) {
-               handle->md.stat.ps_recv = (kstats.tp_packets - kstats.tp_drops);
+               /*
+                * In "linux/net/packet/af_packet.c", at least in the
+                * 2.4.9 kernel, "tp_packets" is incremented for every
+                * packet that passes the packet filter *and* is
+                * successfully queued on the socket; "tp_drops" is
+                * incremented for every packet dropped because there's
+                * not enough free space in the socket buffer.
+                *
+                * When the statistics are returned for a PACKET_STATISTICS
+                * "getsockopt()" call, "tp_drops" is added to "tp_packets",
+                * so that "tp_packets" counts all packets handed to
+                * the PF_PACKET socket, including packets dropped because
+                * there wasn't room on the socket buffer - but not
+                * including packets that didn't pass the filter.
+                *
+                * In the BSD BPF, the count of received packets is
+                * incremented for every packet handed to BPF, regardless
+                * of whether it passed the filter.
+                *
+                * We can't make "pcap_stats()" work the same on both
+                * platforms, but the best approximation is to return
+                * "tp_packets" as the count of packets and "tp_drops"
+                * as the count of drops.
+                *
+                * Note that "tp_packets" may include packets not yet
+                * processed by libpcap; the packets may have been
+                * queued on the socket but not read yet.  (The equivalent
+                * may be true on other platforms.)
+                */
+               handle->md.stat.ps_recv = kstats.tp_packets;
                handle->md.stat.ps_drop = kstats.tp_drops;
        }
+       else
+       {
+               /*
+                * If the error was EOPNOTSUPP, fall through, so that
+                * if you build the library on a system with
+                * "struct tpacket_stats" and run it on a system
+                * that doesn't, it works as it does if the library
+                * is built on a system without "struct tpacket_stats".
+                */
+               if (errno != EOPNOTSUPP) {
+                       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                           "pcap_stats: %s", pcap_strerror(errno));
+                       return -1;
+               }
+       }
 #endif
        /*
         * "ps_recv" counts only packets that passed the filter.