aboutsummaryrefslogtreecommitdiffstats
path: root/capture.c
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2000-01-12 06:56:32 +0000
committerGuy Harris <guy@alum.mit.edu>2000-01-12 06:56:32 +0000
commitbd7c6bda88272183dfbbf5fe146ccc638a864cd9 (patch)
treef83f83a6e406a98f2c64a40764fcb7b0ecdbb3a5 /capture.c
parent0a9f2233b86d305887f5ca6e55e13f57dd180120 (diff)
Enough is enough. Requiring anybody who uses Ethereal on Linux to
update their libpcap probably isn't going to scale - the increasing frequency with which "Ethereal hangs when I try to capture packets" shows up on "ethereal-dev" suggests that, unless and until a libpcap with the "select()" in it becomes ubiquitous on Linux, that'll be the source of a constant support burden - so we'll just put the "select()" in Ethereal if it's being built for Linux. (Putting it in for platforms where the read timeout argument to "pcap_open_live()" works adds an extra useless system call at best and, at worst, could make Ethereal not work - "select()" doesn't work on "/dev/bpf" devices on FreeBSD 3.3, at least, unless you're in "immediate mode", and, whilst "immediate mode" would make Ethereal respond more quickly when packets arrive, it might cause Ethereal to respond too quickly, doing reads for every new packet rather than waiting for multiple packets to arrive and reading them all with one "read()", which appears to be at least part of the intent of the read timeout on "/dev/bpf" devices in BSD.) svn path=/trunk/; revision=1451
Diffstat (limited to 'capture.c')
-rw-r--r--capture.c47
1 files changed, 45 insertions, 2 deletions
diff --git a/capture.c b/capture.c
index afd57a11f0..798c6238bd 100644
--- a/capture.c
+++ b/capture.c
@@ -1,7 +1,7 @@
/* capture.c
* Routines for packet capture windows
*
- * $Id: capture.c,v 1.88 2000/01/03 06:59:07 guy Exp $
+ * $Id: capture.c,v 1.89 2000/01/12 06:56:32 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -474,6 +474,11 @@ cap_file_input_cb(gpointer data, gint source, GdkInputCondition condition)
NULL);
}
+/*
+ * Timeout, in milliseconds, for reads from the stream of captured packets.
+ */
+#define CAP_READ_TIMEOUT 250
+
/* Do the low-level work of a capture.
Returns TRUE if it succeeds, FALSE otherwise. */
int
@@ -488,6 +493,11 @@ capture(void)
time_t upd_time, cur_time;
int err, inpkts;
char errmsg[1024+1];
+#ifdef linux
+ fd_set set1;
+ struct timeval timeout;
+ int pcap_fd;
+#endif
ld.go = TRUE;
ld.counts.total = 0;
@@ -505,7 +515,7 @@ capture(void)
ld.pdh = NULL;
/* Open the network interface to capture from it. */
- pch = pcap_open_live(cf.iface, cf.snap, 1, 250, err_str);
+ pch = pcap_open_live(cf.iface, cf.snap, 1, CAP_READ_TIMEOUT, err_str);
if (pch == NULL) {
/* Well, we couldn't start the capture.
@@ -653,9 +663,42 @@ capture(void)
gtk_grab_add(cap_w);
upd_time = time(NULL);
+#ifdef linux
+ pcap_fd = pcap_fileno(pch);
+#endif
while (ld.go) {
while (gtk_events_pending()) gtk_main_iteration();
+#ifdef linux
+ /*
+ * Sigh. The semantics of the read timeout argument to
+ * "pcap_open_live()" aren't particularly well specified by
+ * the "pcap" man page - at least with the BSD BPF code, the
+ * intent appears to be, at least in part, a way of cutting
+ * down the number of reads done on a capture, by blocking
+ * until the buffer fills or a timer expires - and the Linux
+ * libpcap doesn't actually support it, so we can't use it
+ * to break out of the "pcap_dispatch()" every 1/4 of a second
+ * or so.
+ *
+ * Thus, on Linux, we do a "select()" on the file descriptor for the
+ * capture, with a timeout of CAP_READ_TIMEOUT milliseconds, or
+ * CAP_READ_TIMEOUT*1000 microseconds.
+ */
+ FD_ZERO(&set1);
+ FD_SET(pcap_fd, &set1);
+ timeout.tv_sec = 0;
+ timeout.tv_usec = CAP_READ_TIMEOUT*1000;
+ if (select(pcap_fd+1, &set1, NULL, NULL, &timeout) != 0) {
+ /*
+ * "select()" says we can read from it without blocking; go for
+ * it.
+ */
+ inpkts = pcap_dispatch(pch, 1, capture_pcap_cb, (u_char *) &ld);
+ } else
+ inpkts = 0;
+#else
inpkts = pcap_dispatch(pch, 1, capture_pcap_cb, (u_char *) &ld);
+#endif
if (inpkts > 0)
ld.sync_packets += inpkts;
/* Only update once a second so as not to overload slow displays */