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
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
#ifdef HAVE_CONFIG_H
@ -33,6 +33,7 @@ static const char rcsid[] _U_ =
#include <sys/socket.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/utsname.h>
#include <net/if.h>
@ -495,6 +496,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
#endif
u_int v;
pcap_t *p;
struct utsname osinfo;
#ifdef HAVE_DAG_API
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);
#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->setfilter_op = pcap_setfilter_bpf;
p->set_datalink_op = pcap_set_datalink_bpf;

View File

@ -29,7 +29,7 @@
#ifndef lint
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
#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;
}
/*
* "select()" and "poll()" don't (yet) work on DAG device descriptors.
*/
handle->selectable_fd = -1;
#ifdef linux
handle->md.device = (char *)device;
#else

View File

@ -38,7 +38,7 @@
#ifndef lint
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
#ifdef HAVE_CONFIG_H
@ -704,6 +704,12 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
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->setfilter_op = install_bpf_program; /* no kernel filtering */
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
* 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
@ -101,6 +101,7 @@ struct pcap {
int nonblock;
#else
int fd;
int selectable_fd;
#endif /* WIN32 */
int snapshot;
int linktype;

View File

@ -27,7 +27,7 @@
#ifndef lint
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
/*
@ -397,6 +397,12 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
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->setfilter_op = pcap_setfilter_linux;
handle->set_datalink_op = NULL; /* can't change data link type */

View File

@ -20,7 +20,7 @@
*/
#ifndef lint
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
#ifdef HAVE_CONFIG_H
@ -280,6 +280,11 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
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->setfilter_op = install_bpf_program; /* no kernel filtering */
p->set_datalink_op = NULL; /* can't change data link type */

View File

@ -24,7 +24,7 @@
#ifndef lint
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
#ifdef HAVE_CONFIG_H
@ -434,6 +434,11 @@ your system may not be properly configured; see the packetfilter(4) man page\n",
goto bad;
}
/*
* "select()" and "poll()" work on packetfilter devices.
*/
p->selectable_fd = p->fd;
p->read_op = pcap_read_pf;
p->setfilter_op = pcap_setfilter_pf;
p->set_datalink_op = NULL; /* can't change data link type */

View File

@ -25,7 +25,7 @@
#ifndef lint
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
#ifdef HAVE_CONFIG_H
@ -338,6 +338,12 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
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->setfilter_op = install_bpf_program; /* no kernel filtering */
p->set_datalink_op = NULL; /* can't change data link type */

View File

@ -20,7 +20,7 @@
*/
#ifndef lint
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
#ifdef HAVE_CONFIG_H
@ -323,6 +323,11 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
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->setfilter_op = install_bpf_program; /* no kernel filtering */
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
.\" The Regents of the University of California. All rights reserved.
@ -19,7 +19,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
.TH PCAP 3 "18 November 2003"
.TH PCAP 3 "21 November 2003"
.SH NAME
pcap \- Packet Capture library
.SH SYNOPSIS

10
pcap.c
View File

@ -33,7 +33,7 @@
#ifndef lint
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
#ifdef HAVE_CONFIG_H
@ -500,6 +500,14 @@ pcap_fileno(pcap_t *p)
#endif
}
#ifndef WIN32
int
pcap_get_selectable_fd(pcap_t *p)
{
return (p->selectable_fd);
}
#endif
void
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
* 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
@ -241,6 +241,13 @@ int pcap_setmintocopy(pcap_t *p, int size);
#define MODE_CAPT 0
#define MODE_STAT 1
#else
/*
* UN*X definitions
*/
int pcap_get_selectable_fd(pcap_t *);
#endif /* WIN32 */
#ifdef __cplusplus

View File

@ -30,7 +30,7 @@
#ifndef lint
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
#ifdef HAVE_CONFIG_H
@ -600,6 +600,12 @@ pcap_open_offline(const char *fname, char *errbuf)
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->setfilter_op = install_bpf_program;
p->set_datalink_op = NULL; /* we don't support munging link-layer headers */