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
|
#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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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
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
|
.\" 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
10
pcap.c
|
@ -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
9
pcap.h
|
@ -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
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
Reference in New Issue