"select()" or "poll()" - or -1 if that won't work.
*/
#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
#include <sys/socket.h>
#include <sys/file.h>
#include <sys/ioctl.h>
+#include <sys/utsname.h>
#include <net/if.h>
#endif
u_int v;
pcap_t *p;
+ struct utsname osinfo;
#ifdef HAVE_DAG_API
if (strstr(device, "dag")) {
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;
#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
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
#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
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 */
* 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
int nonblock;
#else
int fd;
+ int selectable_fd;
#endif /* WIN32 */
int snapshot;
int linktype;
#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
/*
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 */
*/
#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
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 */
#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
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 */
#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
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 */
*/
#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
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 */
-.\" @(#) $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.
.\" 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
#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
#endif
}
+#ifndef WIN32
+int
+pcap_get_selectable_fd(pcap_t *p)
+{
+ return (p->selectable_fd);
+}
+#endif
+
void
pcap_perror(pcap_t *p, char *prefix)
{
* 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
#define MODE_CAPT 0
#define MODE_STAT 1
+#else
+/*
+ * UN*X definitions
+ */
+
+int pcap_get_selectable_fd(pcap_t *);
+
#endif /* WIN32 */
#ifdef __cplusplus
#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
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 */