Add APIs to put a "pcap_t" into or out of non-blocking mode, and to get
the current state of non-blocking mode; this allows us to implement, for example, memory-mapped capture devices, where "pcap_read()" uses "select()" or "poll()" to wait for packets to arrive, and hide that implementation detail from applications using this API ("pcap_setnonblock()" would set or clear a non-blocking mode flag in the "pcap_t", and the "select()" or "poll()" would not be done if the "pcap_t" is in non-blocking mode).
This commit is contained in:
parent
b0ea1152b6
commit
a82f1618b8
35
pcap.3
35
pcap.3
|
@ -1,4 +1,4 @@
|
||||||
.\" @(#) $Header: /tcpdump/master/libpcap/Attic/pcap.3,v 1.27 2001-10-28 03:54:57 guy Exp $
|
.\" @(#) $Header: /tcpdump/master/libpcap/Attic/pcap.3,v 1.28 2001-12-09 05:10:02 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.
|
||||||
|
@ -76,6 +76,11 @@ u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h)
|
||||||
.ft
|
.ft
|
||||||
.LP
|
.LP
|
||||||
.ft B
|
.ft B
|
||||||
|
int pcap_setnonblock(pcap_t *, int nonblock, char *errbuf);
|
||||||
|
int pcap_getnonblock(pcap_t *p, char *errbuf);
|
||||||
|
.ft
|
||||||
|
.LP
|
||||||
|
.ft B
|
||||||
int pcap_datalink(pcap_t *p)
|
int pcap_datalink(pcap_t *p)
|
||||||
int pcap_snapshot(pcap_t *p)
|
int pcap_snapshot(pcap_t *p)
|
||||||
int pcap_is_swapped(pcap_t *p)
|
int pcap_is_swapped(pcap_t *p)
|
||||||
|
@ -481,6 +486,34 @@ when that BPF program is no longer needed, for example after it
|
||||||
has been made the filter program for a pcap structure by a call to
|
has been made the filter program for a pcap structure by a call to
|
||||||
.BR pcap_setfilter() .
|
.BR pcap_setfilter() .
|
||||||
.PP
|
.PP
|
||||||
|
.B pcap_setnonblock()
|
||||||
|
puts a capture descriptor, opened with
|
||||||
|
.BR pcap_open_live() ,
|
||||||
|
into ``non-blocking'' mode, or takes it out of ``non-blocking'' mode,
|
||||||
|
depending on whether the
|
||||||
|
.I nonblock
|
||||||
|
argument is non-zero or zero. It has no effect on ``savefiles''.
|
||||||
|
If there is an error, \-1 is returned and
|
||||||
|
.I errbuf
|
||||||
|
is filled in with an appropriate error message.
|
||||||
|
In
|
||||||
|
``non-blocking'' mode, an attempt to read from the capture descriptor
|
||||||
|
with
|
||||||
|
.B pcap_dispatch()
|
||||||
|
will, if no packets are currently available to be read, return 0
|
||||||
|
immediately rather than blocking waiting for packets to arrive.
|
||||||
|
.B pcap_loop()
|
||||||
|
and
|
||||||
|
.B pcap_next()
|
||||||
|
will not work in ``non-blocking'' mode.
|
||||||
|
.PP
|
||||||
|
.B pcap_getnonblock()
|
||||||
|
returns the current ``non-blocking'' state of the capture descriptor; it
|
||||||
|
always returns 0 on ``savefiles''.
|
||||||
|
If there is an error, \-1 is returned and
|
||||||
|
.I errbuf
|
||||||
|
is filled in with an appropriate error message.
|
||||||
|
.PP
|
||||||
.B pcap_datalink()
|
.B pcap_datalink()
|
||||||
returns the link layer type; link layer types it can return include:
|
returns the link layer type; link layer types it can return include:
|
||||||
.PP
|
.PP
|
||||||
|
|
63
pcap.c
63
pcap.c
|
@ -33,7 +33,7 @@
|
||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static const char rcsid[] =
|
static const char rcsid[] =
|
||||||
"@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.36 2000-12-16 10:43:31 guy Exp $ (LBL)";
|
"@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.37 2001-12-09 05:10:03 guy Exp $ (LBL)";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
|
@ -46,6 +46,8 @@ static const char rcsid[] =
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
#ifdef HAVE_OS_PROTO_H
|
#ifdef HAVE_OS_PROTO_H
|
||||||
#include "os-proto.h"
|
#include "os-proto.h"
|
||||||
|
@ -168,6 +170,65 @@ pcap_geterr(pcap_t *p)
|
||||||
return (p->errbuf);
|
return (p->errbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: in the future, these may need to call platform-dependent routines,
|
||||||
|
* e.g. on platforms with memory-mapped packet-capture mechanisms where
|
||||||
|
* "pcap_read()" uses "select()" or "poll()" to wait for packets to arrive.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
pcap_getnonblock(pcap_t *p, char *errbuf)
|
||||||
|
{
|
||||||
|
int fdflags;
|
||||||
|
|
||||||
|
if (p->sf.rfile != NULL) {
|
||||||
|
/*
|
||||||
|
* This is a savefile, not a live capture file, so
|
||||||
|
* never say it's in non-blocking mode.
|
||||||
|
*/
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
fdflags = fcntl(p->fd, F_GETFL, 0);
|
||||||
|
if (fdflags == -1) {
|
||||||
|
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
|
||||||
|
pcap_strerror(errno));
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
if (fdflags & O_NONBLOCK)
|
||||||
|
return (1);
|
||||||
|
else
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf)
|
||||||
|
{
|
||||||
|
int fdflags;
|
||||||
|
|
||||||
|
if (p->sf.rfile != NULL) {
|
||||||
|
/*
|
||||||
|
* This is a savefile, not a live capture file, so
|
||||||
|
* ignore requests to put it in non-blocking mode.
|
||||||
|
*/
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
fdflags = fcntl(p->fd, F_GETFL, 0);
|
||||||
|
if (fdflags == -1) {
|
||||||
|
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
|
||||||
|
pcap_strerror(errno));
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
if (nonblock)
|
||||||
|
fdflags |= O_NONBLOCK;
|
||||||
|
else
|
||||||
|
fdflags &= ~O_NONBLOCK;
|
||||||
|
if (fcntl(p->fd, F_SETFL, fdflags) == -1) {
|
||||||
|
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_SETFL: %s",
|
||||||
|
pcap_strerror(errno));
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
return (fdflags);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Not all systems have strerror().
|
* Not all systems have strerror().
|
||||||
*/
|
*/
|
||||||
|
|
4
pcap.h
4
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.33 2001-10-28 02:31:50 guy Exp $ (LBL)
|
* @(#) $Header: /tcpdump/master/libpcap/pcap.h,v 1.34 2001-12-09 05:10:03 guy Exp $ (LBL)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lib_pcap_h
|
#ifndef lib_pcap_h
|
||||||
|
@ -170,6 +170,8 @@ const u_char*
|
||||||
pcap_next(pcap_t *, struct pcap_pkthdr *);
|
pcap_next(pcap_t *, struct pcap_pkthdr *);
|
||||||
int pcap_stats(pcap_t *, struct pcap_stat *);
|
int pcap_stats(pcap_t *, struct pcap_stat *);
|
||||||
int pcap_setfilter(pcap_t *, struct bpf_program *);
|
int pcap_setfilter(pcap_t *, struct bpf_program *);
|
||||||
|
int pcap_getnonblock(pcap_t *, char *);
|
||||||
|
int pcap_setnonblock(pcap_t *, int, char *);
|
||||||
void pcap_perror(pcap_t *, char *);
|
void pcap_perror(pcap_t *, char *);
|
||||||
char *pcap_strerror(int);
|
char *pcap_strerror(int);
|
||||||
char *pcap_geterr(pcap_t *);
|
char *pcap_geterr(pcap_t *);
|
||||||
|
|
Reference in New Issue