summaryrefslogtreecommitdiffstats
path: root/contrib/libpcap/pcap-pf.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/libpcap/pcap-pf.c')
-rw-r--r--contrib/libpcap/pcap-pf.c81
1 files changed, 43 insertions, 38 deletions
diff --git a/contrib/libpcap/pcap-pf.c b/contrib/libpcap/pcap-pf.c
index 84c6d54..96a4a50 100644
--- a/contrib/libpcap/pcap-pf.c
+++ b/contrib/libpcap/pcap-pf.c
@@ -22,11 +22,6 @@
* Extraction/creation by Jeffrey Mogul, DECWRL
*/
-#ifndef lint
-static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/pcap-pf.c,v 1.97 2008-04-14 20:40:58 guy Exp $ (LBL)";
-#endif
-
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -74,6 +69,24 @@ struct rtentry;
#include "os-proto.h"
#endif
+/*
+ * FDDI packets are padded to make everything line up on a nice boundary.
+ */
+#define PCAP_FDDIPAD 3
+
+/*
+ * Private data for capturing on Ultrix and DEC OSF/1^WDigital UNIX^W^W
+ * Tru64 UNIX packetfilter devices.
+ */
+struct pcap_pf {
+ int filtering_in_kernel; /* using kernel filter */
+ u_long TotPkts; /* can't oflow for 79 hrs on ether */
+ u_long TotAccepted; /* count accepted by filter */
+ u_long TotDrops; /* count of dropped packets */
+ long TotMissed; /* missed by i/f during this run */
+ long OrigMissed; /* missed by i/f before this run */
+};
+
static int pcap_setfilter_pf(pcap_t *, struct bpf_program *);
/*
@@ -87,15 +100,14 @@ static int pcap_setfilter_pf(pcap_t *, struct bpf_program *);
static int
pcap_read_pf(pcap_t *pc, int cnt, pcap_handler callback, u_char *user)
{
+ struct pcap_pf *pf = pc->priv;
register u_char *p, *bp;
register int cc, n, buflen, inc;
register struct enstamp *sp;
#ifdef LBL_ALIGN
struct enstamp stamp;
#endif
-#ifdef PCAP_FDDIPAD
register int pad;
-#endif
again:
cc = pc->cc;
@@ -126,9 +138,7 @@ pcap_read_pf(pcap_t *pc, int cnt, pcap_handler callback, u_char *user)
* Loop through each packet.
*/
n = 0;
-#ifdef PCAP_FDDIPAD
pad = pc->fddipad;
-#endif
while (cc > 0) {
/*
* Has "pcap_breakloop()" been called?
@@ -177,42 +187,34 @@ pcap_read_pf(pcap_t *pc, int cnt, pcap_handler callback, u_char *user)
inc = ENALIGN(buflen + sp->ens_stamplen);
cc -= inc;
bp += inc;
- pc->md.TotPkts++;
- pc->md.TotDrops += sp->ens_dropped;
- pc->md.TotMissed = sp->ens_ifoverflows;
- if (pc->md.OrigMissed < 0)
- pc->md.OrigMissed = pc->md.TotMissed;
+ pf->TotPkts++;
+ pf->TotDrops += sp->ens_dropped;
+ pf->TotMissed = sp->ens_ifoverflows;
+ if (pf->OrigMissed < 0)
+ pf->OrigMissed = pf->TotMissed;
/*
* Short-circuit evaluation: if using BPF filter
* in kernel, no need to do it now - we already know
* the packet passed the filter.
*
-#ifdef PCAP_FDDIPAD
* Note: the filter code was generated assuming
* that pc->fddipad was the amount of padding
* before the header, as that's what's required
* in the kernel, so we run the filter before
* skipping that padding.
-#endif
*/
- if (pc->md.use_bpf ||
+ if (pf->filtering_in_kernel ||
bpf_filter(pc->fcode.bf_insns, p, sp->ens_count, buflen)) {
struct pcap_pkthdr h;
- pc->md.TotAccepted++;
+ pf->TotAccepted++;
h.ts = sp->ens_tstamp;
-#ifdef PCAP_FDDIPAD
h.len = sp->ens_count - pad;
-#else
- h.len = sp->ens_count;
-#endif
-#ifdef PCAP_FDDIPAD
p += pad;
buflen -= pad;
-#endif
h.caplen = buflen;
(*callback)(user, &h, p);
- if (++n >= cnt && cnt > 0) {
+ if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt)) {
pc->cc = cc;
pc->bp = bp;
return (n);
@@ -240,6 +242,7 @@ pcap_inject_pf(pcap_t *p, const void *buf, size_t size)
static int
pcap_stats_pf(pcap_t *p, struct pcap_stat *ps)
{
+ struct pcap_pf *pf = p->priv;
/*
* If packet filtering is being done in the kernel:
@@ -277,9 +280,9 @@ pcap_stats_pf(pcap_t *p, struct pcap_stat *ps)
* the kernel by libpcap, but they may include packets not
* yet read from libpcap by the application.
*/
- ps->ps_recv = p->md.TotAccepted;
- ps->ps_drop = p->md.TotDrops;
- ps->ps_ifdrop = p->md.TotMissed - p->md.OrigMissed;
+ ps->ps_recv = pf->TotAccepted;
+ ps->ps_drop = pf->TotDrops;
+ ps->ps_ifdrop = pf->TotMissed - pf->OrigMissed;
return (0);
}
@@ -294,6 +297,7 @@ pcap_stats_pf(pcap_t *p, struct pcap_stat *ps)
static int
pcap_activate_pf(pcap_t *p)
{
+ struct pcap_pf *pf = p->priv;
short enmode;
int backlog = -1; /* request the most */
struct enfilter Filter;
@@ -327,8 +331,10 @@ your system may not be properly configured; see the packetfilter(4) man page\n",
p->opt.source, pcap_strerror(errno));
goto bad;
}
- p->md.OrigMissed = -1;
- enmode = ENTSTAMP|ENBATCH|ENNONEXCL;
+ pf->OrigMissed = -1;
+ enmode = ENTSTAMP|ENNONEXCL;
+ if (!p->opt.immediate)
+ enmode |= ENBATCH;
if (p->opt.promisc)
enmode |= ENPROMISC;
if (ioctl(p->fd, EIOCMBIS, (caddr_t)&enmode) < 0) {
@@ -436,7 +442,6 @@ your system may not be properly configured; see the packetfilter(4) man page\n",
goto bad;
}
/* set truncation */
-#ifdef PCAP_FDDIPAD
if (p->linktype == DLT_FDDI) {
p->fddipad = PCAP_FDDIPAD;
@@ -444,7 +449,6 @@ your system may not be properly configured; see the packetfilter(4) man page\n",
p->snapshot += PCAP_FDDIPAD;
} else
p->fddipad = 0;
-#endif
if (ioctl(p->fd, EIOCTRUNCATE, (caddr_t)&p->snapshot) < 0) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCTRUNCATE: %s",
pcap_strerror(errno));
@@ -460,10 +464,10 @@ your system may not be properly configured; see the packetfilter(4) man page\n",
goto bad;
}
- if (p->md.timeout != 0) {
+ if (p->opt.timeout != 0) {
struct timeval timeout;
- timeout.tv_sec = p->md.timeout / 1000;
- timeout.tv_usec = (p->md.timeout * 1000) % 1000000;
+ timeout.tv_sec = p->opt.timeout / 1000;
+ timeout.tv_usec = (p->opt.timeout * 1000) % 1000000;
if (ioctl(p->fd, EIOCSRTIMEOUT, (caddr_t)&timeout) < 0) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCSRTIMEOUT: %s",
pcap_strerror(errno));
@@ -503,7 +507,7 @@ pcap_create_interface(const char *device, char *ebuf)
{
pcap_t *p;
- p = pcap_create_common(device, ebuf);
+ p = pcap_create_common(device, ebuf, sizeof (struct pcap_pf));
if (p == NULL)
return (NULL);
@@ -520,6 +524,7 @@ pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
static int
pcap_setfilter_pf(pcap_t *p, struct bpf_program *fp)
{
+ struct pcap_pf *pf = p->priv;
struct bpf_version bv;
/*
@@ -561,7 +566,7 @@ pcap_setfilter_pf(pcap_t *p, struct bpf_program *fp)
* a window to annoy the user.
*/
fprintf(stderr, "tcpdump: Using kernel BPF filter\n");
- p->md.use_bpf = 1;
+ pf->filtering_in_kernel = 1;
/*
* Discard any previously-received packets,
@@ -599,6 +604,6 @@ pcap_setfilter_pf(pcap_t *p, struct bpf_program *fp)
* a warning of some sort.
*/
fprintf(stderr, "tcpdump: Filtering in user process\n");
- p->md.use_bpf = 0;
+ pf->filtering_in_kernel = 0;
return (0);
}
OpenPOWER on IntegriCloud