diff options
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | Makefile.in | 1 | ||||
-rw-r--r-- | pcap-dag.c | 9 | ||||
-rw-r--r-- | pcap-int.h | 20 | ||||
-rw-r--r-- | pcap.c | 7 | ||||
-rw-r--r-- | pcap/pcap.h | 1 | ||||
-rw-r--r-- | pcap_get_required_select_timeout.3pcap | 84 | ||||
-rw-r--r-- | pcap_get_selectable_fd.3pcap | 88 |
8 files changed, 171 insertions, 40 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index bf0a4765..3ec8464e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1719,6 +1719,7 @@ set(MAN3PCAP_NOEXPAND pcap_fileno.3pcap pcap_findalldevs.3pcap pcap_freecode.3pcap + pcap_get_required_select_timeout.3pcap pcap_get_selectable_fd.3pcap pcap_geterr.3pcap pcap_inject.3pcap diff --git a/Makefile.in b/Makefile.in index c3d2a3bd..79840e22 100644 --- a/Makefile.in +++ b/Makefile.in @@ -187,6 +187,7 @@ MAN3PCAP_NOEXPAND = \ pcap_fileno.3pcap \ pcap_findalldevs.3pcap \ pcap_freecode.3pcap \ + pcap_get_required_select_timeout.3pcap \ pcap_get_selectable_fd.3pcap \ pcap_geterr.3pcap \ pcap_inject.3pcap \ @@ -185,6 +185,8 @@ struct pcap_dag { int dag_timeout; /* timeout specified to pcap_open_live. * Same as in linux above, introduce * generally? */ + struct timeval required_select_timeout; + /* Timeout caller must use in event loops */ }; typedef struct pcap_dag_node { @@ -798,6 +800,13 @@ static int dag_activate(pcap_t* p) goto faildetach; } + /* Use the poll time as the required select timeout for callers + * who are using select()/etc. in an event loop waiting for + * packets to arrive. + */ + pd->required_select_timeout = poll; + p->required_select_timeout = &pd->required_select_timeout; + /* * Turn a negative snapshot value (invalid), a snapshot value of * 0 (unspecified), or a value bigger than the normal maximum @@ -161,7 +161,6 @@ struct pcap { HANDLE handle; #else int fd; - int selectable_fd; #endif /* _WIN32 */ /* @@ -210,7 +209,7 @@ struct pcap { u_char *pkt; #ifdef _WIN32 - struct pcap_stat stat; /* used for pcap_stats_ex() */ + struct pcap_stat stat; /* used for pcap_stats_ex() */ #endif /* We're accepting only packets in this direction/these directions. */ @@ -221,6 +220,23 @@ struct pcap { */ int bpf_codegen_flags; +#ifndef _WIN32 + int selectable_fd; /* FD on which select()/poll()/epoll()/kevent()/etc. can be done */ + + /* + * In case there either is no selectable FD, or there is but + * it doesn't necessarily work (e.g., if it doesn't get notified + * if the packet capture timeout expires before the buffer + * fills up), this points to a timeout that should be used + * in select()/poll()/epoll()/kevent() call. The pcap_t should + * be put into non-blocking mode, and, if the timeout expires on + * the call, an attempt should be made to read packets from all + * pcap_t's with a required timeout, and the code must be + * prepared not to see any packets from the attempt. + */ + struct timeval *required_select_timeout; +#endif + /* * Placeholder for filter code if bpf not in kernel. */ @@ -2099,6 +2099,7 @@ pcap_alloc_pcap_t(char *ebuf, size_t size) #else p->fd = -1; /* not opened yet */ p->selectable_fd = -1; + p->required_select_timeout = NULL; #endif if (size == 0) { @@ -3066,6 +3067,12 @@ pcap_get_selectable_fd(pcap_t *p) { return (p->selectable_fd); } + +struct timeval * +pcap_get_required_select_timeout(pcap_t *p) +{ + return (p->required_select_timeout); +} #endif void diff --git a/pcap/pcap.h b/pcap/pcap.h index d32e2a9a..94ca2114 100644 --- a/pcap/pcap.h +++ b/pcap/pcap.h @@ -597,6 +597,7 @@ PCAP_API void bpf_dump(const struct bpf_program *, int); */ PCAP_API int pcap_get_selectable_fd(pcap_t *); + PCAP_API struct timeval *pcap_get_required_select_timeout(pcap_t *); #endif /* _WIN32/MSDOS/UN*X */ diff --git a/pcap_get_required_select_timeout.3pcap b/pcap_get_required_select_timeout.3pcap new file mode 100644 index 00000000..8ef6611a --- /dev/null +++ b/pcap_get_required_select_timeout.3pcap @@ -0,0 +1,84 @@ +.\" Copyright (c) 1994, 1996, 1997 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that: (1) source code distributions +.\" retain the above copyright notice and this paragraph in its entirety, (2) +.\" distributions including binary code include the above copyright notice and +.\" this paragraph in its entirety in the documentation or other materials +.\" provided with the distribution, and (3) all advertising materials mentioning +.\" features or use of this software display the following acknowledgement: +.\" ``This product includes software developed by the University of California, +.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of +.\" the University nor the names of its contributors may be used to endorse +.\" or promote products derived from this software without specific prior +.\" written permission. +.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED +.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +.\" +.TH PCAP_GET_REQUIRED_SELECT_TIMEOUT 3PCAP "19 January 2018" +.SH NAME +pcap_get_required_select_timeout \- get a file descriptor on which a +select() can be done for a live capture +.SH SYNOPSIS +.nf +.ft B +#include <pcap/pcap.h> +.ft +.LP +.ft B +struct timeval *pcap_get_required_select_timeout(pcap_t *p); +.ft +.fi +.SH DESCRIPTION +.B pcap_get_required_select_timeout() +returns, on UNIX, a pointer to a +.B struct timeval +containing a value that must be used as the minimum timeout in +.BR select() , +.BR poll() , +.BR epoll() , +and +.B kevent() +calls if +.B pcap_get_selectable_fd() +returns \-1. +.PP +The timeout that should be used in those calls must be no larger than +the smallest of all timeouts returned by +.B pcap_get_required_select_timeout() +for devices from which packets will be captured. +.PP +The device for which +.B pcap_get_selectable_fd() +returned \-1 must be put in non-blocking mode with +.BR pcap_setnonblock() , +and an attempt must always be made to read packets from the device +when the +.BR select() , +.BR poll() , +.BR epoll() , +or +.B kevent() +call returns. +.PP +Note that a device on which a read can be done without blocking may, +on some platforms, not have any packets to read if the packet buffer +timeout has expired. A call to +.B pcap_dispatch() +or +.B pcap_next_ex() +will return 0 in this case, but will not block. +.PP +.B pcap_get_required_select_timeout() +is not available on Windows. +.SH RETURN VALUE +A pointer to a +.B struct timeval +is returned if the timeout is required; otherwise +.B NULL +is returned. +.SH SEE ALSO +pcap(3PCAP), pcap_get_selectable_fd(3PCAP), select(2), poll(2), +epoll(2), kqueue(2) diff --git a/pcap_get_selectable_fd.3pcap b/pcap_get_selectable_fd.3pcap index aa457a23..c1c617c7 100644 --- a/pcap_get_selectable_fd.3pcap +++ b/pcap_get_selectable_fd.3pcap @@ -38,26 +38,41 @@ which one can do a .BR select() , .BR poll() , +.BR epoll() , +.BR kevent() , or other such call to wait for it to be possible to read packets without blocking, if such -a descriptor exists, or \-1, if no such descriptor exists. Some network -devices opened with +a descriptor exists, or \-1, if no such descriptor exists. +.PP +Some network devices opened with .B pcap_create() and .BR pcap_activate() , or with .BR pcap_open_live() , -do not support -.B select() -or -.B poll() -(for example, regular network devices on FreeBSD 4.3 and 4.4, and Endace -DAG devices), so \-1 is returned for those devices. +do not support those calls (for example, regular network devices on +FreeBSD 4.3 and 4.4, and Endace DAG devices), so \-1 is returned for +those devices. In that case, those calls must be given a timeout less +than or equal to the timeout returned by +.B pcap_get_required_select_timeout() +for the device for which +.B pcap_get_selectable_fd() +returned \-1, the device must be put in non-blocking mode with a call to +.BR pcap_setnonblock() , +and an attempt must always be made to read packets from the device +when the call returns. If +.B pcap_get_required_select_timeout() +returns +.BR NULL , +it is not possible to wait for packets to arrive on the device in an +event loop. .PP -Note that a descriptor on which a read can be done without blocking may, +Note that a device on which a read can be done without blocking may, on some platforms, not have any packets to read if the packet buffer timeout has expired. A call to .B pcap_dispatch() +or +.B pcap_next_ex() will return 0 in this case, but will not block. .PP Note that in: @@ -70,59 +85,55 @@ OpenBSD prior to OpenBSD 2.4; .IP Mac OS X prior to Mac OS X 10.7; .PP -.B select() +.BR select() , +.BR poll() , and -.B poll() +.B kevent() do not work correctly on BPF devices; .B pcap_get_selectable_fd() will return a file descriptor on most of those versions (the exceptions being FreeBSD 4.3 and 4.4), but a simple -.B select() -or -.B poll() -will not indicate that the descriptor is readable until a full buffer's -worth of packets is received, even if the packet timeout expires before -then. To work around this, an application that uses -.B select() +.BR select() , +.BR poll() , or -.B poll() -to wait for packets to arrive must put the +.B kevent() +call will not indicate that the descriptor is readable until a full +buffer's worth of packets is received, even if the packet timeout +expires before then. To work around this, code that uses +those calls to wait for packets to arrive must put the .B pcap_t -in non-blocking mode, and must arrange that the -.B select() -or -.B poll() +in non-blocking mode, and must arrange that the call have a timeout less than or equal to the packet buffer timeout, and must try to read packets after that timeout expires, regardless of -whether -.B select() -or -.B poll() -indicated that the file descriptor for the +whether the call indicated that the file descriptor for the .B pcap_t is ready to be read or not. (That workaround will not work in FreeBSD -4.3 and later; however, in FreeBSD 4.6 and later, -.B select() -and -.B poll() +4.3 and later; however, in FreeBSD 4.6 and later, those calls work correctly on BPF devices, so the workaround isn't necessary, although it does no harm.) .PP Note also that .B poll() +and +.B kevent() doesn't work on character special files, including BPF devices, in Mac OS X 10.4 and 10.5, so, while .B select() can be used on the descriptor returned by .BR pcap_get_selectable_fd() , .B poll() -cannot be used on it those versions of Mac OS X. Kqueues also don't -work on that descriptor. +and +.B kevent() +cannot be used on it those versions of Mac OS X. .BR poll() , -but not kqueues, work on that descriptor in Mac OS X releases prior to +but not +.BR kevent() , +works on that descriptor in Mac OS X releases prior to 10.4; .B poll() -and kqueues work on that descriptor in Mac OS X 10.6 and later. +and +.B kevent() +work on that descriptor in Mac OS X 10.6 and later. .PP .B pcap_get_selectable_fd() is not available on Windows. @@ -130,4 +141,5 @@ is not available on Windows. A selectable file descriptor is returned if one exists; otherwise, \-1 is returned. .SH SEE ALSO -pcap(3PCAP), select(2), poll(2) +pcap(3PCAP), pcap_get_required_select_timeout(3PCAP), +pcap_setnonblock(3PCAP), select(2), poll(2), epoll(2), kqueue(2) |