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:
parent
2c618b93a0
commit
c98ffbcabf
58
pcap-bpf.c
58
pcap-bpf.c
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
4
pcap.3
|
@ -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
10
pcap.c
|
@ -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
9
pcap.h
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
Reference in New Issue