dect
/
libpcap
Archived
13
0
Fork 0

Add a "pcap_get_selectable_fd()" API to get an FD on which you can do a

"select()" or "poll()" - or -1 if that won't work.
This commit is contained in:
guy 2003-11-21 10:19:33 +00:00
parent 2c618b93a0
commit c98ffbcabf
13 changed files with 130 additions and 14 deletions

View File

@ -20,7 +20,7 @@
*/ */
#ifndef lint #ifndef lint
static const char rcsid[] _U_ = static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.69 2003-11-20 02:02:38 guy Exp $ (LBL)"; "@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.70 2003-11-21 10:19:33 guy Exp $ (LBL)";
#endif #endif
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
@ -33,6 +33,7 @@ static const char rcsid[] _U_ =
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/file.h> #include <sys/file.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/utsname.h>
#include <net/if.h> #include <net/if.h>
@ -495,6 +496,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
#endif #endif
u_int v; u_int v;
pcap_t *p; pcap_t *p;
struct utsname osinfo;
#ifdef HAVE_DAG_API #ifdef HAVE_DAG_API
if (strstr(device, "dag")) { if (strstr(device, "dag")) {
@ -760,6 +762,60 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
memset(p->buffer, 0x0, p->bufsize); memset(p->buffer, 0x0, p->bufsize);
#endif #endif
/*
* On most BPF platforms, either you can do a "select()" or
* "poll()" on a BPF file descriptor and it works correctly,
* or you can do it and it will return "readable" if the
* hold buffer is full but not if the timeout expires *and*
* a non-blocking read will, if the hold buffer is empty
* but the store buffer isn't empty, rotate the buffers
* and return what packets are available.
*
* In the latter case, the fact that a non-blocking read
* will give you the available packets means you can work
* around the failure of "select()" and "poll()" to wake up
* and return "readable" when the timeout expires by using
* the timeout as the "select()" or "poll()" timeout, putting
* the BPF descriptor into non-blocking mode, and read from
* it regardless of whether "select()" reports it as readable
* or not.
*
* However, in FreeBSD 4.3 and 4.4, "select()" and "poll()"
* won't wake up and return "readable" if the timer expires
* and non-blocking reads return EWOULDBLOCK if the hold
* buffer is empty, even if the store buffer is non-empty.
*
* This means the workaround in question won't work.
*
* Therefore, on FreeBSD 4.3 and 4.4, we set "p->selectable_fd"
* to -1, which means "sorry, you can't use 'select()' or 'poll()'
* here". On all other BPF platforms, we set it to the FD for
* the BPF device; in NetBSD, OpenBSD, and Darwin, a non-blocking
* read will, if the hold buffer is empty and the store buffer
* isn't empty, rotate the buffers and return what packets are
* there (and in sufficiently recent versions of OpenBSD
* "select()" and "poll()" should work correctly).
*
* XXX - what about AIX?
*/
if (uname(&osinfo) == 0) {
/*
* We can check what OS this is.
*/
if (strcmp(osinfo.sysname, "FreeBSD") == 0 &&
(strcmp(osinfo.release, "4.3") == 0 ||
strcmp(osinfo.release, "4.4") == 0))
p->selectable_fd = -1;
else
p->selectable_fd = p->fd;
} else {
/*
* We can't find out what OS this is, so assume we can
* do a "select()" or "poll()".
*/
p->selectable_fd = p->fd;
}
p->read_op = pcap_read_bpf; p->read_op = pcap_read_bpf;
p->setfilter_op = pcap_setfilter_bpf; p->setfilter_op = pcap_setfilter_bpf;
p->set_datalink_op = pcap_set_datalink_bpf; p->set_datalink_op = pcap_set_datalink_bpf;

View File

@ -29,7 +29,7 @@
#ifndef lint #ifndef lint
static const char rcsid[] _U_ = static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/libpcap/pcap-dag.c,v 1.13 2003-11-20 02:02:38 guy Exp $ (LBL)"; "@(#) $Header: /tcpdump/master/libpcap/pcap-dag.c,v 1.14 2003-11-21 10:19:33 guy Exp $ (LBL)";
#endif #endif
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
@ -469,6 +469,11 @@ pcap_t *dag_open_live(const char *device, int snaplen, int promisc, int to_ms, c
goto fail; goto fail;
} }
/*
* "select()" and "poll()" don't (yet) work on DAG device descriptors.
*/
handle->selectable_fd = -1;
#ifdef linux #ifdef linux
handle->md.device = (char *)device; handle->md.device = (char *)device;
#else #else

View File

@ -38,7 +38,7 @@
#ifndef lint #ifndef lint
static const char rcsid[] _U_ = static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.93 2003-11-20 02:02:38 guy Exp $ (LBL)"; "@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.94 2003-11-21 10:19:34 guy Exp $ (LBL)";
#endif #endif
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
@ -704,6 +704,12 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
goto bad; goto bad;
} }
/*
* "p->fd" is an FD for a STREAMS device, so "select()" and
* "poll()" should work on it.
*/
p->selectable_fd = p->fd;
p->read_op = pcap_read_dlpi; p->read_op = pcap_read_dlpi;
p->setfilter_op = install_bpf_program; /* no kernel filtering */ p->setfilter_op = install_bpf_program; /* no kernel filtering */
p->set_datalink_op = NULL; /* can't change data link type */ p->set_datalink_op = NULL; /* can't change data link type */

View File

@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* @(#) $Header: /tcpdump/master/libpcap/pcap-int.h,v 1.57 2003-11-20 02:02:39 guy Exp $ (LBL) * @(#) $Header: /tcpdump/master/libpcap/pcap-int.h,v 1.58 2003-11-21 10:19:34 guy Exp $ (LBL)
*/ */
#ifndef pcap_int_h #ifndef pcap_int_h
@ -101,6 +101,7 @@ struct pcap {
int nonblock; int nonblock;
#else #else
int fd; int fd;
int selectable_fd;
#endif /* WIN32 */ #endif /* WIN32 */
int snapshot; int snapshot;
int linktype; int linktype;

View File

@ -27,7 +27,7 @@
#ifndef lint #ifndef lint
static const char rcsid[] _U_ = static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.101 2003-11-20 02:02:39 guy Exp $ (LBL)"; "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.102 2003-11-21 10:19:34 guy Exp $ (LBL)";
#endif #endif
/* /*
@ -397,6 +397,12 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
return NULL; return NULL;
} }
/*
* "handle->fd" is a socket, so "select()" and "poll()"
* should work on it.
*/
handle->selectable_fd = handle->fd;
handle->read_op = pcap_read_linux; handle->read_op = pcap_read_linux;
handle->setfilter_op = pcap_setfilter_linux; handle->setfilter_op = pcap_setfilter_linux;
handle->set_datalink_op = NULL; /* can't change data link type */ handle->set_datalink_op = NULL; /* can't change data link type */

View File

@ -20,7 +20,7 @@
*/ */
#ifndef lint #ifndef lint
static const char rcsid[] _U_ = static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/libpcap/pcap-nit.c,v 1.52 2003-11-20 02:02:40 guy Exp $ (LBL)"; "@(#) $Header: /tcpdump/master/libpcap/pcap-nit.c,v 1.53 2003-11-21 10:19:35 guy Exp $ (LBL)";
#endif #endif
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
@ -280,6 +280,11 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
goto bad; goto bad;
} }
/*
* "handle->fd" is a socket, so "select()" should work on it.
*/
p->selectable_fd = p->fd;
p->read_op = pcap_read_nit; p->read_op = pcap_read_nit;
p->setfilter_op = install_bpf_program; /* no kernel filtering */ p->setfilter_op = install_bpf_program; /* no kernel filtering */
p->set_datalink_op = NULL; /* can't change data link type */ p->set_datalink_op = NULL; /* can't change data link type */

View File

@ -24,7 +24,7 @@
#ifndef lint #ifndef lint
static const char rcsid[] _U_ = static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/libpcap/pcap-pf.c,v 1.81 2003-11-20 02:02:40 guy Exp $ (LBL)"; "@(#) $Header: /tcpdump/master/libpcap/pcap-pf.c,v 1.82 2003-11-21 10:19:35 guy Exp $ (LBL)";
#endif #endif
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
@ -434,6 +434,11 @@ your system may not be properly configured; see the packetfilter(4) man page\n",
goto bad; goto bad;
} }
/*
* "select()" and "poll()" work on packetfilter devices.
*/
p->selectable_fd = p->fd;
p->read_op = pcap_read_pf; p->read_op = pcap_read_pf;
p->setfilter_op = pcap_setfilter_pf; p->setfilter_op = pcap_setfilter_pf;
p->set_datalink_op = NULL; /* can't change data link type */ p->set_datalink_op = NULL; /* can't change data link type */

View File

@ -25,7 +25,7 @@
#ifndef lint #ifndef lint
static const char rcsid[] _U_ = static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/libpcap/pcap-snit.c,v 1.68 2003-11-20 02:02:40 guy Exp $ (LBL)"; "@(#) $Header: /tcpdump/master/libpcap/pcap-snit.c,v 1.69 2003-11-21 10:19:35 guy Exp $ (LBL)";
#endif #endif
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
@ -338,6 +338,12 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
goto bad; goto bad;
} }
/*
* "p->fd" is an FD for a STREAMS device, so "select()" and
* "poll()" should work on it.
*/
p->selectable_fd = p->fd;
p->read_op = pcap_read_snit; p->read_op = pcap_read_snit;
p->setfilter_op = install_bpf_program; /* no kernel filtering */ p->setfilter_op = install_bpf_program; /* no kernel filtering */
p->set_datalink_op = NULL; /* can't change data link type */ p->set_datalink_op = NULL; /* can't change data link type */

View File

@ -20,7 +20,7 @@
*/ */
#ifndef lint #ifndef lint
static const char rcsid[] _U_ = static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/libpcap/pcap-snoop.c,v 1.48 2003-11-20 02:02:40 guy Exp $ (LBL)"; "@(#) $Header: /tcpdump/master/libpcap/pcap-snoop.c,v 1.49 2003-11-21 10:19:35 guy Exp $ (LBL)";
#endif #endif
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
@ -323,6 +323,11 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
goto bad; goto bad;
} }
/*
* "handle->fd" is a socket, so "select()" should work on it.
*/
p->selectable_fd = p->fd;
p->read_op = pcap_read_snoop; p->read_op = pcap_read_snoop;
p->setfilter_op = install_bpf_program; /* no kernel filtering */ p->setfilter_op = install_bpf_program; /* no kernel filtering */
p->set_datalink_op = NULL; /* can't change data link type */ p->set_datalink_op = NULL; /* can't change data link type */

4
pcap.3
View File

@ -1,4 +1,4 @@
.\" @(#) $Header: /tcpdump/master/libpcap/Attic/pcap.3,v 1.54 2003-11-18 22:14:24 guy Exp $ .\" @(#) $Header: /tcpdump/master/libpcap/Attic/pcap.3,v 1.55 2003-11-21 10:19:36 guy Exp $
.\" .\"
.\" Copyright (c) 1994, 1996, 1997 .\" Copyright (c) 1994, 1996, 1997
.\" The Regents of the University of California. All rights reserved. .\" The Regents of the University of California. All rights reserved.
@ -19,7 +19,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\" .\"
.TH PCAP 3 "18 November 2003" .TH PCAP 3 "21 November 2003"
.SH NAME .SH NAME
pcap \- Packet Capture library pcap \- Packet Capture library
.SH SYNOPSIS .SH SYNOPSIS

10
pcap.c
View File

@ -33,7 +33,7 @@
#ifndef lint #ifndef lint
static const char rcsid[] _U_ = static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.68 2003-11-20 02:02:41 guy Exp $ (LBL)"; "@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.69 2003-11-21 10:19:36 guy Exp $ (LBL)";
#endif #endif
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
@ -500,6 +500,14 @@ pcap_fileno(pcap_t *p)
#endif #endif
} }
#ifndef WIN32
int
pcap_get_selectable_fd(pcap_t *p)
{
return (p->selectable_fd);
}
#endif
void void
pcap_perror(pcap_t *p, char *prefix) pcap_perror(pcap_t *p, char *prefix)
{ {

9
pcap.h
View File

@ -31,7 +31,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* @(#) $Header: /tcpdump/master/libpcap/pcap.h,v 1.47 2003-11-18 22:14:25 guy Exp $ (LBL) * @(#) $Header: /tcpdump/master/libpcap/pcap.h,v 1.48 2003-11-21 10:19:36 guy Exp $ (LBL)
*/ */
#ifndef lib_pcap_h #ifndef lib_pcap_h
@ -241,6 +241,13 @@ int pcap_setmintocopy(pcap_t *p, int size);
#define MODE_CAPT 0 #define MODE_CAPT 0
#define MODE_STAT 1 #define MODE_STAT 1
#else
/*
* UN*X definitions
*/
int pcap_get_selectable_fd(pcap_t *);
#endif /* WIN32 */ #endif /* WIN32 */
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -30,7 +30,7 @@
#ifndef lint #ifndef lint
static const char rcsid[] _U_ = static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/libpcap/savefile.c,v 1.97 2003-11-20 02:02:41 guy Exp $ (LBL)"; "@(#) $Header: /tcpdump/master/libpcap/savefile.c,v 1.98 2003-11-21 10:19:37 guy Exp $ (LBL)";
#endif #endif
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
@ -600,6 +600,12 @@ pcap_open_offline(const char *fname, char *errbuf)
break; break;
} }
/*
* You can do "select()" and "poll()" on plain files on most
* platforms, and should be able to do so on pipes.
*/
p->selectable_fd = fileno(fp);
p->read_op = pcap_offline_read; p->read_op = pcap_offline_read;
p->setfilter_op = install_bpf_program; p->setfilter_op = install_bpf_program;
p->set_datalink_op = NULL; /* we don't support munging link-layer headers */ p->set_datalink_op = NULL; /* we don't support munging link-layer headers */