aboutsummaryrefslogtreecommitdiff
path: root/pcap-linux.c
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2013-12-10 15:59:16 -0800
committerGuy Harris <guy@alum.mit.edu>2013-12-10 15:59:16 -0800
commitee4085152260466ea845d9e9109a251a39ded93b (patch)
tree517d3481765d7fa76fc279fb19b07345df7f54b3 /pcap-linux.c
parent7eb0a94dd54e77c6fb885654418287f3aa6f3ce0 (diff)
Work around a TPACKET_V3 issue with a timeout of 0.
See https://github.com/the-tcpdump-group/libpcap/issues/335 for details.
Diffstat (limited to 'pcap-linux.c')
-rw-r--r--pcap-linux.c26
1 files changed, 23 insertions, 3 deletions
diff --git a/pcap-linux.c b/pcap-linux.c
index 7c077931..764ad012 100644
--- a/pcap-linux.c
+++ b/pcap-linux.c
@@ -4073,9 +4073,29 @@ static int pcap_wait_for_frames_mmap(pcap_t *handle)
pollinfo.fd = handle->fd;
pollinfo.events = POLLIN;
- if (handlep->timeout == 0)
- timeout = -1; /* block forever */
- else if (handlep->timeout > 0)
+ if (handlep->timeout == 0) {
+ /*
+ * XXX - due to a set of (mis)features in the
+ * TPACKET_V3 kernel code, blocking forever with
+ * a TPACKET_V3 socket can, if few packets
+ * are arriving and passing the socket filter,
+ * cause most packets to be dropped. See
+ * libpcap issue #335 for the full painful
+ * story. The workaround is to have poll()
+ * time out very quickly, so we grab the
+ * frames handed to us, and return them to
+ * the kernel, ASAP.
+ *
+ * If those issues are ever fixed, we might
+ * want to check the kernel version and block
+ * forever with TPACKET_V3 if we're running
+ * with a kernel that has the fix.
+ */
+ if (handlep->tp_version == TPACKET_V3)
+ timeout = 1; /* don't block for very long */
+ else
+ timeout = -1; /* block forever */
+ } else if (handlep->timeout > 0)
timeout = handlep->timeout; /* block for that amount of time */
else
timeout = 0; /* non-blocking mode - poll to pick up errors */