aboutsummaryrefslogtreecommitdiffstats
path: root/pcap-linux.c
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2009-10-12 16:24:57 -0700
committerGuy Harris <guy@alum.mit.edu>2009-10-12 16:24:57 -0700
commitbf7491046a6123f40be6993a24a61e9525a44666 (patch)
treebc3a96b59c7017a0aec797d5bd3a0c5294025aa1 /pcap-linux.c
parent9dd13b012f23cca0ba7061fbff232d29773635c3 (diff)
In pcap_read_linux_mmap(), if there are no frames available, call poll()
even if we're in non-blocking mode, to pick up any error indications - in that case, use a timeout of 0, so poll() doesn't block. Don't test individual exceptional-condition bits in the poll() return unless one of them is set, so we just do one test in the typical (no exceptional condition) case.
Diffstat (limited to 'pcap-linux.c')
-rw-r--r--pcap-linux.c33
1 files changed, 19 insertions, 14 deletions
diff --git a/pcap-linux.c b/pcap-linux.c
index 8356ba5..48cad3a 100644
--- a/pcap-linux.c
+++ b/pcap-linux.c
@@ -2929,42 +2929,47 @@ pcap_get_ring_frame(pcap_t *handle, int status)
return h.raw;
}
+#ifndef POLLRDHUP
+#define POLLRDHUP 0
+#endif
+
static int
pcap_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback,
u_char *user)
{
+ int timeout;
int pkts = 0;
char c;
/* wait for frames availability.*/
- if ((handle->md.timeout >= 0) &&
- !pcap_get_ring_frame(handle, TP_STATUS_USER)) {
+ if (!pcap_get_ring_frame(handle, TP_STATUS_USER)) {
struct pollfd pollinfo;
int ret;
pollinfo.fd = handle->fd;
pollinfo.events = POLLIN;
+ if (handle->md.timeout == 0)
+ timeout = -1; /* block forever */
+ else if (handle->md.timeout > 0)
+ timeout = handle->md.timeout; /* block for that amount of time */
+ else
+ timeout = 0; /* non-blocking mode - poll to pick up errors */
do {
- /* poll() requires a negative timeout to wait forever */
- ret = poll(&pollinfo, 1, (handle->md.timeout > 0)?
- handle->md.timeout: -1);
- if ((ret < 0) && (errno != EINTR)) {
+ ret = poll(&pollinfo, 1, timeout);
+ if (ret < 0 && errno != EINTR) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"can't poll on packet socket: %s",
pcap_strerror(errno));
return PCAP_ERROR;
- } else if (ret > 0) {
+ } else if (ret > 0 &&
+ (pollinfo.revents & (POLLHUP|POLLRDHUP|POLLERR|POLLNVAL))) {
/*
- * There's some indication on the descriptor.
- * Check for indications other than
- * "you can read on this descriptor".
+ * There's some indication other than
+ * "you can read on this descriptor" on
+ * the descriptor.
*/
-#ifdef POLLRDHUP
if (pollinfo.revents & (POLLHUP | POLLRDHUP)) {
-#else
- if (pollinfo.revents & POLLHUP) {
-#endif
snprintf(handle->errbuf,
PCAP_ERRBUF_SIZE,
"Hangup on packet socket");