"pcap_dispatch()" and "pcap_loop()".
*/
#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
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);
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;
/*
#endif /* HAVE_DAG_API */
#ifdef BIOCGDLTLIST
- bzero(&bdl, sizeof(bdl));
+ memset(&bdl, 0, sizeof(bdl));
#endif
p = (pcap_t *)malloc(sizeof(*p));
#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
/*
* 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;
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;
#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
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) {
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;
* 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
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;
#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
/*
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,
*/
#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
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);
#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
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);
#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
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;
*/
#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
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 */
#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>
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;
-.\" @(#) $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.
.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);
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,
.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
.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() .
#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
* 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".
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)
{
* 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
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 *);
#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
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)