diff options
author | Guy Harris <guy@alum.mit.edu> | 2000-01-12 06:56:32 +0000 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2000-01-12 06:56:32 +0000 |
commit | bd7c6bda88272183dfbbf5fe146ccc638a864cd9 (patch) | |
tree | f83f83a6e406a98f2c64a40764fcb7b0ecdbb3a5 /capture.c | |
parent | 0a9f2233b86d305887f5ca6e55e13f57dd180120 (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.c | 47 |
1 files changed, 45 insertions, 2 deletions
@@ -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 */ |