Folks,
I discovered an intermittent problem with pcap_stats which was the result
of an incorrect length value. Actually, I think it was related to what
gcc/libc combo was in effect when pcap was built. 'cause it worked on
some boxes, and failed others.
The symptom was potential bad drop info (normally none) 'cause the system call
would fail and the code would fall through to setting the received value from
the one accumulated in the packet receive code. The failure was because the
length value was incorrect (most likely 0?)
I've attached a diff (to the current as of 2001.12.08) of pcap-linux.c.
I don't think pcap_stats has changed since 0.6.2, so it shouldn't be too
difficult to incorporate the changes.
By the way, for some reason when tcpdump quits normally (like after -c <pktcnt>)it
will not dump the stats. However, if you just let it run and then break
out you get the stats.
Happy sniffing,
PS: Are there any debian folks out their using 2.2.x or preferably 2.4.x
kernel's? I've got an interesting set of modifications to the tcpdump.org
libpcap which can be built as a shared library to replace the debian
one. Using environment variables, I'm able to coerce a precompiled
tcpdump and probably snort (haven't got that far) in to using a 32768
shared memory ring buffer (shared between kernel and user space). All
you need is enough memory (PCAP_FRAMES * 2048) for the ring buffer and
plus whatever else is needed day to day. Or, you can indicate with an
environment variable a smaller ring size.
Example:
# PCAP_FRAMES=max PCAP_VERBOSE=1 tcpdump -i eth0 -w /tmp/foo.pcap
The VERBOSE flag causes pcap to dump a message to stderr indicating
some of the characteristics being used.
Note, the environment variables override switches on the command line.
--
Phil Wood, [EMAIL PROTECTED]
--- pcap-linux.c-2001.12.08 Sat Dec 8 20:22:32 2001
+++ pcap-linux.c Sat Dec 8 21:05:23 2001
@@ -626,17 +626,45 @@
pcap_stats(pcap_t *handle, struct pcap_stat *stats)
{
#ifdef HAVE_TPACKET_STATS
+ if (handle->fd > -1)
+ {
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);
+ handle->md.stat.ps_recv = kstats.tp_packets;
+ /*
+ * check out linux/net/packet/af_packet.c if you don't believe
+ * this. The total number of packets seen by the kernel is
+ * actually (kstats.tp_packets + kstats.tp_drops). And to be
+ * more accurate (kstats.tp_packets - md.stat.ps_recv) would be
+ * the number of packets that were not processed by pcap at
+ * the time pcap_stats was called. The kernel increments
+ * tp_drops when it does not have a place to put the packet.
+ * It increments tp_packets if it has some place to put the
+ * packet. md.stat.ps_recv is incremented each time pcap
+ * passes a packet to the pcap application. So, we are
+ * loosing some information here. -- [EMAIL PROTECTED]
+ */
handle->md.stat.ps_drop = kstats.tp_drops;
}
+ else
+ {
+ printf(handle->errbuf, PCAP_ERRBUF_SIZE, "pcap_stats: %s",
+ pcap_strerror(errno));
+ *stats = handle->md.stat;
+ /*
+ * an error of 1 could be used to signal that we do not have
+ * drop stats, but do have md.stat.ps_recv. Applications
+ * do not know this, so we just set it to 0.
+ */
+ return (0);
+ }
+ }
#endif
/*
* "ps_recv" counts only packets that passed the filter.