From 8e4f9c438f662b96a76aebe49319ce7f198e080b Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Thu, 22 Oct 2015 16:31:18 +0200 Subject: Fix a bug in pcap-linux causing a report of funny interface drops If tcpdump is run in promiscuous mode under Linux and is configured to drop privileges, it can read /proc/net/dev the first time to take a copy of the interface drops counter, but cannot do it at the end of the capture, causing linux_if_drops() to return zero. Thus it computes 0 - initial counter and reports this as an unsigned value. And this is clearly visible using strace : mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7005000 write(1, "15:08:36.559021 IP 192.168.0.199"..., 13515:08:36.559021 IP 192.168.0.199.22 > 192.168.0.176.53795: Flags [P.], seq 3145801660:3145801768, ack 2935410867, win 1004, length 108) = 135 write(2, "here: linux_if_drops:1085\n", 26here: linux_if_drops:1085) = 26 open("/proc/net/dev", O_RDONLY|O_LARGEFILE) = -1 EACCES (Permission denied) getsockopt(3, SOL_PACKET, PACKET_STATISTICS, {packets=111, drops=77}, [8]) = 0 write(2, "1 packet captured", 171 packet captured) = 17 write(2, "\n", 1) = 1 write(2, "111 packets received by filter", 30111 packets received by filter) = 30 write(2, "\n", 1) = 1 write(2, "77 packets dropped by kernel", 2877 packets dropped by kernel) = 28 write(2, "\n", 1) = 1 write(2, "4294964326 packets dropped by in"..., 404294964326 packets dropped by interface) = 40 setsockopt(3, SOL_PACKET, PACKET_RX_RING, {block_size=0, block_nr=0, frame_size=0, frame_nr=0}, 16) = -1 EBUSY (Device or resource busy) munmap(0xb7013000, 3670016) = 0 munmap(0xb7393000, 266240) = 0 close(3) = 0 exit_group(0) = ? Here we ensure not to change the ps_ifdrop value as documented in the pcap_stats() man page in case we can't compute the amount of drops. This makes tcpdump not report this bogus counter in this case, just as when it cannot get the information. This issue has already been reported by other people, example : http://serverfault.com/questions/588158/massively-large-number-of-packets-dropped-by-interface --- pcap-linux.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pcap-linux.c b/pcap-linux.c index 13d79ff..fa104c5 100644 --- a/pcap-linux.c +++ b/pcap-linux.c @@ -2090,7 +2090,8 @@ pcap_stats_linux(pcap_t *handle, struct pcap_stat *stats) { if_dropped = handlep->proc_dropped; handlep->proc_dropped = linux_if_drops(handlep->device); - handlep->stat.ps_ifdrop += (handlep->proc_dropped - if_dropped); + if (handlep->proc_dropped) + handlep->stat.ps_ifdrop += (handlep->proc_dropped - if_dropped); } #ifdef HAVE_TPACKET_STATS -- 1.7.12.1