dect
/
libpcap
Archived
13
0
Fork 0

Add a "pcap_breakloop()" API to break out of the loop in

"pcap_dispatch()" and "pcap_loop()".
This commit is contained in:
guy 2003-11-04 07:05:32 +00:00
parent 4246a40e00
commit 991d444f71
14 changed files with 281 additions and 21 deletions

View File

@ -20,7 +20,7 @@
*/
#ifndef lint
static const char rcsid[] =
"@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.66 2003-07-25 05:32:02 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.67 2003-11-04 07:05:32 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -143,6 +143,18 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
register u_char *bp, *ep;
again:
/*
* Has "pcap_breakloop()" been called?
*/
if (p->break_loop) {
/*
* Yes - clear the flag that indicates that it
* has, and return -2 to indicate that we were
* told to break out of the loop.
*/
p->break_loop = 0;
return (-2);
}
cc = p->cc;
if (p->cc == 0) {
cc = read(p->fd, (char *)p->buffer, p->bufsize);
@ -211,6 +223,27 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
ep = bp + cc;
while (bp < ep) {
register int caplen, hdrlen;
/*
* Has "pcap_breakloop()" been called?
* If so, return immediately - if we haven't read any
* packets, clear the flag and return -2 to indicate
* that we were told to break out of the loop, otherwise
* leave the flag set, so that the *next* call will break
* out of the loop without having read any packets, and
* return the number of packets we've processed so far.
*/
if (p->break_loop) {
if (n == 0) {
p->break_loop = 0;
return (-2);
} else {
p->bp = bp;
p->cc = ep - bp;
return (n);
}
}
caplen = bhp->bh_caplen;
hdrlen = bhp->bh_hdrlen;
/*
@ -470,7 +503,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
#endif /* HAVE_DAG_API */
#ifdef BIOCGDLTLIST
bzero(&bdl, sizeof(bdl));
memset(&bdl, 0, sizeof(bdl));
#endif
p = (pcap_t *)malloc(sizeof(*p));

View File

@ -19,7 +19,7 @@
#ifndef lint
static const char rcsid[] =
"@(#) $Header: /tcpdump/master/libpcap/pcap-dag.c,v 1.9 2003-10-02 07:07:49 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap-dag.c,v 1.10 2003-11-04 07:05:33 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -210,8 +210,9 @@ static dag_record_t *get_next_dag_header(pcap_t *p) {
/*
* Read at most max_packets from the capture stream and call the callback
* for each of them. Returns the number of packets handled or -1 if an
* error occured. A blocking
* for each of them. Returns the number of packets handled, -1 if an
* error occured, or -2 if we were told to break out of the loop.
* A blocking
*/
static int dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) {
u_char *dp = NULL;
@ -221,6 +222,18 @@ static int dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) {
dag_record_t *header;
register unsigned long long ts;
/*
* Has "pcap_breakloop()" been called?
*/
if (p->break_loop) {
/*
* Yes - clear the flag that indicates that it has, and return -2
* to indicate that we were told to break out of the loop.
*/
p->break_loop = 0;
return -2;
}
/* Receive a single packet from the kernel */
header = get_next_dag_header(p);
dp = ((u_char *)header) + dag_record_size;

View File

@ -38,7 +38,7 @@
#ifndef lint
static const char rcsid[] =
"@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.90 2003-07-25 05:32:03 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.91 2003-11-04 07:05:33 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -207,6 +207,19 @@ pcap_read_dlpi(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
data.maxlen = p->bufsize;
data.len = 0;
do {
/*
* Has "pcap_breakloop()" been called?
*/
if (p->break_loop) {
/*
* Yes - clear the flag that indicates
* that it has, and return -2 to
* indicate that we were told to
* break out of the loop.
*/
p->break_loop = 0;
return (-2);
}
if (getmsg(p->fd, &ctl, &data, &flags) < 0) {
/* Don't choke when we get ptraced */
if (errno == EINTR) {
@ -229,6 +242,25 @@ pcap_read_dlpi(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
n = 0;
#ifdef HAVE_SYS_BUFMOD_H
while (bp < ep) {
/*
* Has "pcap_breakloop()" been called?
* If so, return immediately - if we haven't read any
* packets, clear the flag and return -2 to indicate
* that we were told to break out of the loop, otherwise
* leave the flag set, so that the *next* call will break
* out of the loop without having read any packets, and
* return the number of packets we've processed so far.
*/
if (p->break_loop) {
if (n == 0) {
p->break_loop = 0;
return (-2);
} else {
p->bp = bp;
p->cc = ep - bp;
return (n);
}
}
#ifdef LBL_ALIGN
if ((long)bp & 3) {
sbp = &sbhdr;

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.54 2003-10-24 23:55:06 guy Exp $ (LBL)
* @(#) $Header: /tcpdump/master/libpcap/pcap-int.h,v 1.55 2003-11-04 07:05:34 guy Exp $ (LBL)
*/
#ifndef pcap_int_h
@ -106,6 +106,8 @@ struct pcap {
int tzoff; /* timezone offset */
int offset; /* offset for proper alignment */
int break_loop; /* flag set to force break from packet-reading loop */
struct pcap_sf sf;
struct pcap_md md;

View File

@ -27,7 +27,7 @@
#ifndef lint
static const char rcsid[] =
"@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.96 2003-10-06 07:04:55 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.97 2003-11-04 07:05:34 guy Exp $ (LBL)";
#endif
/*
@ -462,6 +462,18 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
bp = handle->buffer + handle->offset;
do {
/*
* Has "pcap_breakloop()" been called?
*/
if (p->break_loop) {
/*
* Yes - clear the flag that indicates that it
* has, and return -2 as an indication that we
* were told to break out of the loop.
*/
p->break_loop = 0;
return -2;
}
fromlen = sizeof(from);
packet_len = recvfrom(
handle->fd, bp + offset,

View File

@ -20,7 +20,7 @@
*/
#ifndef lint
static const char rcsid[] =
"@(#) $Header: /tcpdump/master/libpcap/pcap-nit.c,v 1.49 2003-07-25 05:32:04 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap-nit.c,v 1.50 2003-11-04 07:05:35 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -126,6 +126,26 @@ pcap_read_nit(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
n = 0;
ep = bp + cc;
while (bp < ep) {
/*
* Has "pcap_breakloop()" been called?
* If so, return immediately - if we haven't read any
* packets, clear the flag and return -2 to indicate
* that we were told to break out of the loop, otherwise
* leave the flag set, so that the *next* call will break
* out of the loop without having read any packets, and
* return the number of packets we've processed so far.
*/
if (p->break_loop) {
if (n == 0) {
p->break_loop = 0;
return (-2);
} else {
p->cc = ep - bp;
p->bp = bp;
return (n);
}
}
nh = (struct nit_hdr *)bp;
cp = bp + sizeof(*nh);

View File

@ -24,7 +24,7 @@
#ifndef lint
static const char rcsid[] =
"@(#) $Header: /tcpdump/master/libpcap/pcap-pf.c,v 1.78 2003-07-25 05:32:05 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap-pf.c,v 1.79 2003-11-04 07:05:36 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -135,6 +135,25 @@ pcap_read_pf(pcap_t *pc, int cnt, pcap_handler callback, u_char *user)
pad = 0;
#endif
while (cc > 0) {
/*
* Has "pcap_breakloop()" been called?
* If so, return immediately - if we haven't read any
* packets, clear the flag and return -2 to indicate
* that we were told to break out of the loop, otherwise
* leave the flag set, so that the *next* call will break
* out of the loop without having read any packets, and
* return the number of packets we've processed so far.
*/
if (pc->break_loop) {
if (n == 0) {
pc->break_loop = 0;
return (-2);
} else {
pc->cc = cc;
pc->bp = bp;
return (n);
}
}
if (cc < sizeof(*sp)) {
snprintf(pc->errbuf, sizeof(pc->errbuf),
"pf short read (%d)", cc);

View File

@ -25,7 +25,7 @@
#ifndef lint
static const char rcsid[] =
"@(#) $Header: /tcpdump/master/libpcap/pcap-snit.c,v 1.65 2003-07-25 05:32:05 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap-snit.c,v 1.66 2003-11-04 07:05:36 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -141,6 +141,26 @@ pcap_read_snit(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
n = 0;
ep = bp + cc;
while (bp < ep) {
/*
* Has "pcap_breakloop()" been called?
* If so, return immediately - if we haven't read any
* packets, clear the flag and return -2 to indicate
* that we were told to break out of the loop, otherwise
* leave the flag set, so that the *next* call will break
* out of the loop without having read any packets, and
* return the number of packets we've processed so far.
*/
if (p->break_loop) {
if (n == 0) {
p->break_loop = 0;
return (-2);
} else {
p->bp = bp;
p->cc = ep - bp;
return (n);
}
}
++p->md.stat.ps_recv;
cp = bp;

View File

@ -20,7 +20,7 @@
*/
#ifndef lint
static const char rcsid[] =
"@(#) $Header: /tcpdump/master/libpcap/pcap-snoop.c,v 1.44 2003-07-25 05:32:05 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap-snoop.c,v 1.45 2003-11-04 07:05:37 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -68,13 +68,25 @@ pcap_read_snoop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
register u_char *cp;
again:
/*
* Has "pcap_breakloop()" been called?
*/
if (p->break_loop) {
/*
* Yes - clear the flag that indicates that it
* has, and return -2 to indicate that we were
* told to break out of the loop.
*/
p->break_loop = 0;
return (-2);
}
cc = read(p->fd, (char *)p->buffer, p->bufsize);
if (cc < 0) {
/* Don't choke when we get ptraced */
switch (errno) {
case EINTR:
goto again;
goto again;
case EWOULDBLOCK:
return (0); /* XXX */

View File

@ -32,7 +32,7 @@
#ifndef lint
static const char rcsid[] =
"@(#) $Header: /tcpdump/master/libpcap/pcap-win32.c,v 1.14 2003-09-22 11:48:40 risso Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap-win32.c,v 1.15 2003-11-04 07:05:37 guy Exp $ (LBL)";
#endif
#include <pcap-int.h>
@ -119,6 +119,27 @@ pcap_read_win32(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
ep = bp + cc;
while (bp < ep) {
register int caplen, hdrlen;
/*
* Has "pcap_breakloop()" been called?
* If so, return immediately - if we haven't read any
* packets, clear the flag and return -2 to indicate
* that we were told to break out of the loop, otherwise
* leave the flag set, so that the *next* call will break
* out of the loop without having read any packets, and
* return the number of packets we've processed so far.
*/
if (p->break_loop) {
if (n == 0) {
p->break_loop = 0;
return (-2);
} else {
p->bp = bp;
p->cc = ep - bp;
return (n);
}
}
caplen = bhp->bh_caplen;
hdrlen = bhp->bh_hdrlen;

56
pcap.3
View File

@ -1,4 +1,4 @@
.\" @(#) $Header: /tcpdump/master/libpcap/Attic/pcap.3,v 1.49 2003-10-10 00:27:45 guy Exp $
.\" @(#) $Header: /tcpdump/master/libpcap/Attic/pcap.3,v 1.50 2003-11-04 07:05:38 guy Exp $
.\"
.\" Copyright (c) 1994, 1996, 1997
.\" The Regents of the University of California. All rights reserved.
@ -84,6 +84,10 @@ const u_char **pkt_data)
.ft
.LP
.ft B
void pcap_breakloop(pcap_t *)
.ft
.LP
.ft B
int pcap_datalink(pcap_t *p)
int pcap_list_datalinks(pcap_t *p, int **dlt_buf);
int pcap_set_datalink(pcap_t *p, int dlt);
@ -455,6 +459,9 @@ an error in which case
or
.B pcap_geterr()
may be used to display the error text.
A return of \-2 indicates that the loop terminated due to a call to
.B pcap_breakloop()
before any packets were processed.
.PP
.BR NOTE :
when reading a live capture,
@ -489,10 +496,12 @@ A negative
.I cnt
causes
.B pcap_loop()
to loop forever (or at least until an error occurs). A negative number
is returned on an error; 0 is returned if
to loop forever (or at least until an error occurs). \-1 is returned on
an error; 0 is returned if
.I cnt
is exhausted.
is exhausted; \-2 is returned if the loop terminated due to a call to
.B pcap_breakloop()
before any packets were processed.
.PP
.B pcap_next()
reads the next packet (by calling
@ -541,6 +550,45 @@ pointer pointed to by the
.I pkt_data
argument is set to point to the data in the packet.
.PP
.B pcap_breakloop()
sets a flag that will force
.B pcap_dispatch()
or
.B pcap_loop()
to return rather than looping; they will return the number of packets
that have been processed so far, or \-2 if no packets have been
processed so far.
.PP
This routine is safe to use inside a signal handler on UNIX or a console
control handler on Windows, as it merely sets a flag that is checked
within the loop.
.PP
The flag is checked in loops reading packets from the OS - a signal by
itself will not necessarily terminate those loops - as well as in loops
processing a set of packets returned by the OS. Note that
.B pcap_next()
will, on some platforms, loop reading packets from the OS; that loop
will not necessarily be terminated by a signal, so
.B pcap_breakloop()
should be used to terminate packet processing even if
.B pcap_next()
is being used.
.PP
.B pcap_breakloop()
does not guarantee that no further packets will be processed by
.B pcap_dispatch()
or
.B pcap_loop()
after it is called; at most one more packet might be processed.
.PP
If \-2 is returned from
.B pcap_dispatch()
or
.BR pcap_loop() ,
the flag is cleared, so a subsequent call will resume reading packets.
If a positive number is returned, the flag is not cleared, so a
subsequent call will return \-2 and clear the flag.
.PP
.B pcap_dump()
outputs a packet to the ``savefile'' opened with
.BR pcap_dump_open() .

12
pcap.c
View File

@ -33,7 +33,7 @@
#ifndef lint
static const char rcsid[] =
"@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.62 2003-10-31 21:49:18 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.63 2003-11-04 07:05:39 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -189,6 +189,7 @@ pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header,
* Return codes for pcap_read() are:
* - 0: timeout
* - -1: error
* - -2: loop was broken out of with pcap_breakloop()
* - >1: OK
* The first one ('0') conflicts with the return code of 0 from
* pcap_offline_read() meaning "end of file".
@ -196,6 +197,15 @@ pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header,
return (p->read_op(p, 1, pcap_fakecallback, (u_char *)&s));
}
/*
* Force the loop in "pcap_read()" or "pcap_read_offline()" to terminate.
*/
void
pcap_breakloop(pcap_t *p)
{
p->break_loop = 1;
}
int
pcap_datalink(pcap_t *p)
{

3
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.44 2003-04-10 06:08:06 guy Exp $ (LBL)
* @(#) $Header: /tcpdump/master/libpcap/pcap.h,v 1.45 2003-11-04 07:05:39 guy Exp $ (LBL)
*/
#ifndef lib_pcap_h
@ -178,6 +178,7 @@ int pcap_dispatch(pcap_t *, int, pcap_handler, u_char *);
const u_char*
pcap_next(pcap_t *, struct pcap_pkthdr *);
int pcap_next_ex(pcap_t *, struct pcap_pkthdr **, const u_char **);
void pcap_breakloop(pcap_t *);
int pcap_stats(pcap_t *, struct pcap_stat *);
int pcap_setfilter(pcap_t *, struct bpf_program *);
int pcap_getnonblock(pcap_t *, char *);

View File

@ -30,7 +30,7 @@
#ifndef lint
static const char rcsid[] =
"@(#) $Header: /tcpdump/master/libpcap/savefile.c,v 1.91 2003-11-04 01:49:08 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/savefile.c,v 1.92 2003-11-04 07:05:40 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -742,6 +742,23 @@ pcap_offline_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
while (status == 0) {
struct pcap_pkthdr h;
/*
* Has "pcap_breakloop()" been called?
* If so, return immediately - if we haven't read any
* packets, clear the flag and return -2 to indicate
* that we were told to break out of the loop, otherwise
* leave the flag set, so that the *next* call will break
* out of the loop without having read any packets, and
* return the number of packets we've processed so far.
*/
if (p->break_loop) {
if (n == 0) {
p->break_loop = 0;
return (-2);
} else
return (n);
}
status = sf_next_packet(p, &h, p->buffer, p->bufsize);
if (status) {
if (status == 1)