aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorguy <guy>2001-12-10 05:49:40 +0000
committerguy <guy>2001-12-10 05:49:40 +0000
commit1a00bc6928e5d066a479025c6eab38086abaebda (patch)
tree50b6d5f156b2aae059afbb180668e8145fc9476b
parentfde2e99495fae8f5d5caca0c9142049adfdd3dce (diff)
Fixes from Phil Wood:
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.
-rw-r--r--CREDITS1
-rw-r--r--pcap-linux.c50
2 files changed, 48 insertions, 3 deletions
diff --git a/CREDITS b/CREDITS
index 3af010a9..77127dcf 100644
--- a/CREDITS
+++ b/CREDITS
@@ -38,6 +38,7 @@ Additional people who have contributed patches:
Onno van der Linden <onno@simplex.nl>
Pavel Kankovsky <kan@dcit.cz>
Peter Jeremy <peter.jeremy@alcatel.com.au>
+ Phil Wood <cpw@lanl.gov>
Rafal Maszkowski <rzm@icm.edu.pl>
Rick Jones <raj@cup.hp.com>
Scott Barron <sb125499@ohiou.edu>
diff --git a/pcap-linux.c b/pcap-linux.c
index 49058ab6..1fc90541 100644
--- a/pcap-linux.c
+++ b/pcap-linux.c
@@ -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.