resolve conflicts.

This commit is contained in:
christos 2013-12-31 17:08:14 +00:00
parent 7e05f63e56
commit 511f4361e2
13 changed files with 1445 additions and 674 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: gencode.c,v 1.5 2013/04/06 17:29:53 christos Exp $ */
/* $NetBSD: gencode.c,v 1.6 2013/12/31 17:08:23 christos Exp $ */
/*#define CHASE_CHAIN*/
/*
@ -87,7 +87,7 @@ static const char rcsid[] _U_ =
#include "pcap/sll.h"
#include "pcap/ipnet.h"
#include "arcnet.h"
#if defined(PF_PACKET) && defined(SO_ATTACH_FILTER)
#if defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER)
#include <linux/types.h>
#include <linux/if_packet.h>
#include <linux/filter.h>
@ -110,6 +110,18 @@ static const char rcsid[] _U_ =
#define ETHERMTU 1500
#ifndef IPPROTO_HOPOPTS
#define IPPROTO_HOPOPTS 0
#endif
#ifndef IPPROTO_ROUTING
#define IPPROTO_ROUTING 43
#endif
#ifndef IPPROTO_FRAGMENT
#define IPPROTO_FRAGMENT 44
#endif
#ifndef IPPROTO_DSTOPTS
#define IPPROTO_DSTOPTS 60
#endif
#ifndef IPPROTO_SCTP
#define IPPROTO_SCTP 132
#endif
@ -132,9 +144,7 @@ static u_int orig_linktype = -1U, orig_nl = -1U, label_stack_depth = -1U;
#endif
/* XXX */
#ifdef PCAP_FDDIPAD
static int pcap_fddipad;
#endif
/* VARARGS */
void
@ -264,20 +274,16 @@ static struct block *gen_gateway(const u_char *, bpf_u_int32 **, int, int);
static struct block *gen_ipfrag(void);
static struct block *gen_portatom(int, bpf_int32);
static struct block *gen_portrangeatom(int, bpf_int32, bpf_int32);
#ifdef INET6
static struct block *gen_portatom6(int, bpf_int32);
static struct block *gen_portrangeatom6(int, bpf_int32, bpf_int32);
#endif
struct block *gen_portop(int, int, int);
static struct block *gen_port(int, int, int);
struct block *gen_portrangeop(int, int, int, int);
static struct block *gen_portrange(int, int, int, int);
#ifdef INET6
struct block *gen_portop6(int, int, int);
static struct block *gen_port6(int, int, int);
struct block *gen_portrangeop6(int, int, int, int);
static struct block *gen_portrange6(int, int, int, int);
#endif
static int lookup_proto(const char *, int);
static struct block *gen_protochain(int, int, int);
static struct block *gen_proto(int, int, int);
@ -428,6 +434,15 @@ pcap_compile(pcap_t *p, struct bpf_program *program,
const char * volatile xbuf = buf;
u_int len;
/*
* If this pcap_t hasn't been activated, it doesn't have a
* link-layer type, so we can't use it.
*/
if (!p->activated) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"not-yet-activated pcap_t passed to pcap_compile");
return (-1);
}
no_optimize = 0;
n_errors = 0;
root = NULL;
@ -862,6 +877,7 @@ static u_int off_proto;
* These are offsets for the MTP2 fields.
*/
static u_int off_li;
static u_int off_li_hsl;
/*
* These are offsets for the MTP3 fields.
@ -911,9 +927,7 @@ init_linktype(p)
pcap_t *p;
{
linktype = pcap_datalink(p);
#ifdef PCAP_FDDIPAD
pcap_fddipad = p->fddipad;
#endif
/*
* Assume it's not raw ATM with a pseudo-header, for now.
@ -935,6 +949,7 @@ init_linktype(p)
* And assume we're not doing SS7.
*/
off_li = -1;
off_li_hsl = -1;
off_sio = -1;
off_opc = -1;
off_dpc = -1;
@ -1050,13 +1065,9 @@ init_linktype(p)
* XXX - should we generate code to check for SNAP?
*/
off_linktype = 13;
#ifdef PCAP_FDDIPAD
off_linktype += pcap_fddipad;
#endif
off_macpl = 13; /* FDDI MAC header length */
#ifdef PCAP_FDDIPAD
off_macpl += pcap_fddipad;
#endif
off_nl = 8; /* 802.2+SNAP */
off_nl_nosnap = 3; /* 802.2 */
return;
@ -1327,6 +1338,13 @@ init_linktype(p)
off_nl_nosnap = -1; /* no 802.2 LLC */
return;
case DLT_BACNET_MS_TP:
off_linktype = -1;
off_macpl = -1;
off_nl = -1;
off_nl_nosnap = -1;
return;
case DLT_JUNIPER_SERVICES:
off_linktype = 12;
off_macpl = -1; /* L3 proto location dep. on cookie type */
@ -1367,6 +1385,7 @@ init_linktype(p)
case DLT_MTP2:
off_li = 2;
off_li_hsl = 4;
off_sio = 3;
off_opc = 4;
off_dpc = 4;
@ -1379,6 +1398,7 @@ init_linktype(p)
case DLT_MTP2_WITH_PHDR:
off_li = 6;
off_li_hsl = 8;
off_sio = 7;
off_opc = 8;
off_dpc = 8;
@ -1391,6 +1411,7 @@ init_linktype(p)
case DLT_ERF:
off_li = 22;
off_li_hsl = 24;
off_sio = 23;
off_opc = 24;
off_dpc = 24;
@ -2835,11 +2856,9 @@ ethertype_to_ppptype(proto)
proto = PPP_IP;
break;
#ifdef INET6
case ETHERTYPE_IPV6:
proto = PPP_IPV6;
break;
#endif
case ETHERTYPE_DN:
proto = PPP_DECNET;
@ -3047,11 +3066,10 @@ gen_linktype(proto)
case ETHERTYPE_IP:
/* Check for a version number of 4. */
return gen_mcmp(OR_LINK, 0, BPF_B, 0x40, 0xF0);
#ifdef INET6
case ETHERTYPE_IPV6:
/* Check for a version number of 6. */
return gen_mcmp(OR_LINK, 0, BPF_B, 0x60, 0xF0);
#endif
default:
return gen_false(); /* always false */
@ -3075,10 +3093,8 @@ gen_linktype(proto)
/*
* Raw IPv6, so no type field.
*/
#ifdef INET6
if (proto == ETHERTYPE_IPV6)
return gen_true(); /* always true */
#endif
/* Checking for something other than IPv6; always false */
return gen_false();
@ -3184,8 +3200,7 @@ gen_linktype(proto)
* Then we run it through "htonl()", and
* generate code to compare against the result.
*/
if (bpf_pcap->sf.rfile != NULL &&
bpf_pcap->sf.swapped)
if (bpf_pcap->rfile != NULL && bpf_pcap->swapped)
proto = SWAPLONG(proto);
proto = htonl(proto);
}
@ -3200,11 +3215,9 @@ gen_linktype(proto)
if (proto == ETHERTYPE_IP)
return (gen_cmp(OR_LINK, offsetof(struct pfloghdr, af),
BPF_B, (bpf_int32)AF_INET));
#ifdef INET6
else if (proto == ETHERTYPE_IPV6)
return (gen_cmp(OR_LINK, offsetof(struct pfloghdr, af),
BPF_B, (bpf_int32)AF_INET6));
#endif /* INET6 */
else
return gen_false();
/*NOTREACHED*/
@ -3222,11 +3235,9 @@ gen_linktype(proto)
default:
return gen_false();
#ifdef INET6
case ETHERTYPE_IPV6:
return (gen_cmp(OR_LINK, off_linktype, BPF_B,
(bpf_int32)ARCTYPE_INET6));
#endif /* INET6 */
case ETHERTYPE_IP:
b0 = gen_cmp(OR_LINK, off_linktype, BPF_B,
@ -3278,13 +3289,11 @@ gen_linktype(proto)
*/
return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | 0xcc);
#ifdef INET6
case ETHERTYPE_IPV6:
/*
* Check for the special NLPID for IPv6.
*/
return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | 0x8e);
#endif
case LLCSAP_ISONS:
/*
@ -3346,6 +3355,9 @@ gen_linktype(proto)
*/
return gen_mcmp(OR_LINK, 0, BPF_W, 0x4d474300, 0xffffff00); /* compare the magic number */
case DLT_BACNET_MS_TP:
return gen_mcmp(OR_LINK, 0, BPF_W, 0x55FF0000, 0xffff0000);
case DLT_IPNET:
return gen_ipnet_linktype(proto);
@ -3631,7 +3643,7 @@ gen_hostop6(addr, mask, dir, proto, src_off, dst_off)
gen_and(b0, b1);
return b1;
}
#endif /*INET6*/
#endif
static struct block *
gen_ehostop(eaddr, dir)
@ -3700,18 +3712,10 @@ gen_fhostop(eaddr, dir)
switch (dir) {
case Q_SRC:
#ifdef PCAP_FDDIPAD
return gen_bcmp(OR_LINK, 6 + 1 + pcap_fddipad, 6, eaddr);
#else
return gen_bcmp(OR_LINK, 6 + 1, 6, eaddr);
#endif
case Q_DST:
#ifdef PCAP_FDDIPAD
return gen_bcmp(OR_LINK, 0 + 1 + pcap_fddipad, 6, eaddr);
#else
return gen_bcmp(OR_LINK, 0 + 1, 6, eaddr);
#endif
case Q_AND:
b0 = gen_fhostop(eaddr, Q_SRC);
@ -4509,13 +4513,11 @@ gen_host(addr, mask, proto, dir, type)
case Q_MOPRC:
bpf_error("MOPRC host filtering not implemented");
#ifdef INET6
case Q_IPV6:
bpf_error("'ip6' modifier applied to ip host");
case Q_ICMPV6:
bpf_error("'icmp6' modifier applied to %s", typestr);
#endif /* INET6 */
case Q_AH:
bpf_error("'ah' modifier applied to %s", typestr);
@ -4574,6 +4576,9 @@ gen_host6(addr, mask, proto, dir, type)
case Q_DEFAULT:
return gen_host6(addr, mask, Q_IPV6, dir, type);
case Q_LINK:
bpf_error("link-layer modifier applied to ip6 %s", typestr);
case Q_IP:
bpf_error("'ip' modifier applied to ip6 %s", typestr);
@ -4672,7 +4677,7 @@ gen_host6(addr, mask, proto, dir, type)
}
/* NOTREACHED */
}
#endif /*INET6*/
#endif
#ifndef INET6
static struct block *
@ -4764,26 +4769,20 @@ gen_proto_abbrev(proto)
case Q_SCTP:
b1 = gen_proto(IPPROTO_SCTP, Q_IP, Q_DEFAULT);
#ifdef INET6
b0 = gen_proto(IPPROTO_SCTP, Q_IPV6, Q_DEFAULT);
gen_or(b0, b1);
#endif
break;
case Q_TCP:
b1 = gen_proto(IPPROTO_TCP, Q_IP, Q_DEFAULT);
#ifdef INET6
b0 = gen_proto(IPPROTO_TCP, Q_IPV6, Q_DEFAULT);
gen_or(b0, b1);
#endif
break;
case Q_UDP:
b1 = gen_proto(IPPROTO_UDP, Q_IP, Q_DEFAULT);
#ifdef INET6
b0 = gen_proto(IPPROTO_UDP, Q_IPV6, Q_DEFAULT);
gen_or(b0, b1);
#endif
break;
case Q_ICMP:
@ -4811,10 +4810,8 @@ gen_proto_abbrev(proto)
case Q_PIM:
b1 = gen_proto(IPPROTO_PIM, Q_IP, Q_DEFAULT);
#ifdef INET6
b0 = gen_proto(IPPROTO_PIM, Q_IPV6, Q_DEFAULT);
gen_or(b0, b1);
#endif
break;
#ifndef IPPROTO_VRRP
@ -4876,7 +4873,6 @@ gen_proto_abbrev(proto)
b1 = gen_linktype(ETHERTYPE_MOPRC);
break;
#ifdef INET6
case Q_IPV6:
b1 = gen_linktype(ETHERTYPE_IPV6);
break;
@ -4887,17 +4883,14 @@ gen_proto_abbrev(proto)
case Q_ICMPV6:
b1 = gen_proto(IPPROTO_ICMPV6, Q_IPV6, Q_DEFAULT);
break;
#endif /* INET6 */
#ifndef IPPROTO_AH
#define IPPROTO_AH 51
#endif
case Q_AH:
b1 = gen_proto(IPPROTO_AH, Q_IP, Q_DEFAULT);
#ifdef INET6
b0 = gen_proto(IPPROTO_AH, Q_IPV6, Q_DEFAULT);
gen_or(b0, b1);
#endif
break;
#ifndef IPPROTO_ESP
@ -4905,10 +4898,8 @@ gen_proto_abbrev(proto)
#endif
case Q_ESP:
b1 = gen_proto(IPPROTO_ESP, Q_IP, Q_DEFAULT);
#ifdef INET6
b0 = gen_proto(IPPROTO_ESP, Q_IPV6, Q_DEFAULT);
gen_or(b0, b1);
#endif
break;
case Q_ISO:
@ -5041,7 +5032,6 @@ gen_portatom(off, v)
return gen_cmp(OR_TRAN_IPV4, off, BPF_H, v);
}
#ifdef INET6
static struct block *
gen_portatom6(off, v)
int off;
@ -5049,7 +5039,6 @@ gen_portatom6(off, v)
{
return gen_cmp(OR_TRAN_IPV6, off, BPF_H, v);
}
#endif/*INET6*/
struct block *
gen_portop(port, proto, dir)
@ -5141,7 +5130,6 @@ gen_port(port, ip_proto, dir)
return b1;
}
#ifdef INET6
struct block *
gen_portop6(port, proto, dir)
int port, proto, dir;
@ -5214,7 +5202,6 @@ gen_port6(port, ip_proto, dir)
gen_and(b0, b1);
return b1;
}
#endif /* INET6 */
/* gen_portrange code */
static struct block *
@ -5319,7 +5306,6 @@ gen_portrange(port1, port2, ip_proto, dir)
return b1;
}
#ifdef INET6
static struct block *
gen_portrangeatom6(off, v1, v2)
int off;
@ -5420,7 +5406,6 @@ gen_portrange6(port1, port2, ip_proto, dir)
gen_and(b0, b1);
return b1;
}
#endif /* INET6 */
static int
lookup_proto(name, proto)
@ -5555,7 +5540,7 @@ gen_protochain(v, proto, dir)
s[i]->s.k = off_macpl + off_nl;
i++;
break;
#ifdef INET6
case Q_IPV6:
b0 = gen_linktype(ETHERTYPE_IPV6);
@ -5568,7 +5553,7 @@ gen_protochain(v, proto, dir)
s[i]->s.k = 40;
i++;
break;
#endif
default:
bpf_error("unsupported proto to gen_protochain");
/*NOTREACHED*/
@ -5595,7 +5580,6 @@ gen_protochain(v, proto, dir)
fix2 = i;
i++;
#ifdef INET6
if (proto == Q_IPV6) {
int v6start, v6end, v6advance, j;
@ -5677,9 +5661,7 @@ gen_protochain(v, proto, dir)
/* fixup */
for (j = v6start; j <= v6end; j++)
s[j]->s.jt = s[v6advance];
} else
#endif
{
} else {
/* nop */
s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
s[i]->s.k = 0;
@ -5823,10 +5805,8 @@ gen_proto(v, proto, dir)
int dir;
{
struct block *b0, *b1;
#ifdef INET6
#ifndef CHASE_CHAIN
struct block *b2;
#endif
#endif
if (dir != Q_DEFAULT)
@ -5834,14 +5814,11 @@ gen_proto(v, proto, dir)
switch (proto) {
case Q_DEFAULT:
#ifdef INET6
b0 = gen_proto(v, Q_IP, dir);
b1 = gen_proto(v, Q_IPV6, dir);
gen_or(b0, b1);
return b1;
#else
/*FALLTHROUGH*/
#endif
case Q_IP:
/*
* For FDDI, RFC 1188 says that SNAP encapsulation is used,
@ -5992,7 +5969,6 @@ gen_proto(v, proto, dir)
bpf_error("'carp proto' is bogus");
/* NOTREACHED */
#ifdef INET6
case Q_IPV6:
b0 = gen_linktype(ETHERTYPE_IPV6);
#ifndef CHASE_CHAIN
@ -6013,7 +5989,6 @@ gen_proto(v, proto, dir)
case Q_ICMPV6:
bpf_error("'icmp6 proto' is bogus");
#endif /* INET6 */
case Q_AH:
bpf_error("'ah proto' is bogus");
@ -6270,13 +6245,9 @@ gen_scode(name, q)
bpf_error("illegal port number %d < 0", port);
if (port > 65535)
bpf_error("illegal port number %d > 65535", port);
#ifndef INET6
return gen_port(port, real_proto, dir);
#else
b = gen_port(port, real_proto, dir);
gen_or(gen_port6(port, real_proto, dir), b);
return b;
#endif /* INET6 */
case Q_PORTRANGE:
if (proto != Q_DEFAULT &&
@ -6320,13 +6291,9 @@ gen_scode(name, q)
if (port2 > 65535)
bpf_error("illegal port number %d > 65535", port2);
#ifndef INET6
return gen_portrange(port1, port2, real_proto, dir);
#else
b = gen_portrange(port1, port2, real_proto, dir);
gen_or(gen_portrange6(port1, port2, real_proto, dir), b);
return b;
#endif /* INET6 */
case Q_GATEWAY:
#ifndef INET6
@ -6474,16 +6441,12 @@ gen_ncode(s, v, q)
if (v > 65535)
bpf_error("illegal port number %u > 65535", v);
#ifndef INET6
return gen_port((int)v, proto, dir);
#else
{
struct block *b;
b = gen_port((int)v, proto, dir);
gen_or(gen_port6((int)v, proto, dir), b);
return b;
}
#endif /* INET6 */
case Q_PORTRANGE:
if (proto == Q_UDP)
@ -6500,16 +6463,12 @@ gen_ncode(s, v, q)
if (v > 65535)
bpf_error("illegal port number %u > 65535", v);
#ifndef INET6
return gen_portrange((int)v, (int)v, proto, dir);
#else
{
struct block *b;
b = gen_portrange((int)v, (int)v, proto, dir);
gen_or(gen_portrange6((int)v, (int)v, proto, dir), b);
return b;
}
#endif /* INET6 */
case Q_GATEWAY:
bpf_error("'gateway' requires a name");
@ -6799,9 +6758,7 @@ gen_load(proto, inst, size)
case Q_LAT:
case Q_MOPRC:
case Q_MOPDL:
#ifdef INET6
case Q_IPV6:
#endif
/*
* The offset is relative to the beginning of
* the network-layer header.
@ -6910,16 +6867,12 @@ gen_load(proto, inst, size)
gen_and(gen_proto_abbrev(proto), b = gen_ipfrag());
if (inst->b)
gen_and(inst->b, b);
#ifdef INET6
gen_and(gen_proto_abbrev(Q_IP), b);
#endif
inst->b = b;
break;
#ifdef INET6
case Q_ICMPV6:
bpf_error("IPv6 upper-layer protocol is not supported by proto[x]");
/*NOTREACHED*/
#endif
}
inst->regno = regno;
s = new_stmt(BPF_ST);
@ -7471,13 +7424,11 @@ gen_multicast(proto)
gen_and(b0, b1);
return b1;
#ifdef INET6
case Q_IPV6:
b0 = gen_linktype(ETHERTYPE_IPV6);
b1 = gen_cmp(OR_NET, 24, BPF_B, (bpf_int32)255);
gen_and(b0, b1);
return b1;
#endif /* INET6 */
}
bpf_error("link-layer multicast filters supported only on ethernet/FDDI/token ring/ARCNET/802.11/ATM LANE/Fibre Channel");
/* NOTREACHED */
@ -7586,14 +7537,14 @@ gen_inbound(dir)
* check it, otherwise give up as this link-layer type
* has nothing in the packet data.
*/
#if defined(PF_PACKET) && defined(SO_ATTACH_FILTER)
#if defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER)
/*
* We infer that this is Linux with PF_PACKET support.
* This is Linux with PF_PACKET support.
* If this is a *live* capture, we can look at
* special meta-data in the filter expression;
* if it's a savefile, we can't.
*/
if (bpf_pcap->sf.rfile != NULL) {
if (bpf_pcap->rfile != NULL) {
/* We have a FILE *, so this is a savefile */
bpf_error("inbound/outbound not supported on linktype %d when reading savefiles",
linktype);
@ -7607,12 +7558,12 @@ gen_inbound(dir)
/* to filter on inbound traffic, invert the match */
gen_not(b0);
}
#else /* defined(PF_PACKET) && defined(SO_ATTACH_FILTER) */
#else /* defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER) */
bpf_error("inbound/outbound not supported on linktype %d",
linktype);
b0 = NULL;
/* NOTREACHED */
#endif /* defined(PF_PACKET) && defined(SO_ATTACH_FILTER) */
#endif /* defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER) */
}
return (b0);
}
@ -8072,9 +8023,10 @@ gen_pppoed()
}
struct block *
gen_pppoes()
gen_pppoes(sess_num)
int sess_num;
{
struct block *b0;
struct block *b0, *b1;
/*
* Test against the PPPoE session link-layer type.
@ -8114,6 +8066,14 @@ gen_pppoes()
orig_nl = off_nl;
is_pppoes = 1;
/* If a specific session is requested, check PPPoE session id */
if (sess_num >= 0) {
b1 = gen_mcmp(OR_MACPL, orig_nl, BPF_W,
(bpf_int32)sess_num, 0x0000ffff);
gen_and(b0, b1);
b0 = b1;
}
/*
* The "network-layer" protocol is PPPoE, which has a 6-byte
* PPPoE header, followed by a PPP packet.
@ -8303,6 +8263,7 @@ gen_atmtype_abbrev(type)
* FISU, length is null
* LSSU, length is 1 or 2
* MSU, length is 3 or more
* For MTP2_HSL, sequences are on 2 bytes, and length on 9 bits
*/
struct block *
gen_mtp2type_abbrev(type)
@ -8339,6 +8300,33 @@ gen_mtp2type_abbrev(type)
b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 0, 2);
break;
case MH_FISU:
if ( (linktype != DLT_MTP2) &&
(linktype != DLT_ERF) &&
(linktype != DLT_MTP2_WITH_PHDR) )
bpf_error("'hfisu' supported only on MTP2_HSL");
/* gen_ncmp(offrel, offset, size, mask, jtype, reverse, value) */
b0 = gen_ncmp(OR_PACKET, off_li_hsl, BPF_H, 0xff80, BPF_JEQ, 0, 0);
break;
case MH_LSSU:
if ( (linktype != DLT_MTP2) &&
(linktype != DLT_ERF) &&
(linktype != DLT_MTP2_WITH_PHDR) )
bpf_error("'hlssu' supported only on MTP2_HSL");
b0 = gen_ncmp(OR_PACKET, off_li_hsl, BPF_H, 0xff80, BPF_JGT, 1, 0x0100);
b1 = gen_ncmp(OR_PACKET, off_li_hsl, BPF_H, 0xff80, BPF_JGT, 0, 0);
gen_and(b1, b0);
break;
case MH_MSU:
if ( (linktype != DLT_MTP2) &&
(linktype != DLT_ERF) &&
(linktype != DLT_MTP2_WITH_PHDR) )
bpf_error("'hmsu' supported only on MTP2_HSL");
b0 = gen_ncmp(OR_PACKET, off_li_hsl, BPF_H, 0xff80, BPF_JGT, 0, 0x0100);
break;
default:
abort();
}
@ -8354,9 +8342,17 @@ gen_mtp3field_code(mtp3field, jvalue, jtype, reverse)
{
struct block *b0;
bpf_u_int32 val1 , val2 , val3;
u_int newoff_sio=off_sio;
u_int newoff_opc=off_opc;
u_int newoff_dpc=off_dpc;
u_int newoff_sls=off_sls;
switch (mtp3field) {
case MH_SIO:
newoff_sio += 3; /* offset for MTP2_HSL */
/* FALLTHROUGH */
case M_SIO:
if (off_sio == (u_int)-1)
bpf_error("'sio' supported only on SS7");
@ -8364,10 +8360,12 @@ gen_mtp3field_code(mtp3field, jvalue, jtype, reverse)
if(jvalue > 255)
bpf_error("sio value %u too big; max value = 255",
jvalue);
b0 = gen_ncmp(OR_PACKET, off_sio, BPF_B, 0xffffffff,
b0 = gen_ncmp(OR_PACKET, newoff_sio, BPF_B, 0xffffffff,
(u_int)jtype, reverse, (u_int)jvalue);
break;
case MH_OPC:
newoff_opc+=3;
case M_OPC:
if (off_opc == (u_int)-1)
bpf_error("'opc' supported only on SS7");
@ -8384,10 +8382,14 @@ gen_mtp3field_code(mtp3field, jvalue, jtype, reverse)
val3 = jvalue & 0x00000003;
val3 = val3 <<22;
jvalue = val1 + val2 + val3;
b0 = gen_ncmp(OR_PACKET, off_opc, BPF_W, 0x00c0ff0f,
b0 = gen_ncmp(OR_PACKET, newoff_opc, BPF_W, 0x00c0ff0f,
(u_int)jtype, reverse, (u_int)jvalue);
break;
case MH_DPC:
newoff_dpc += 3;
/* FALLTHROUGH */
case M_DPC:
if (off_dpc == (u_int)-1)
bpf_error("'dpc' supported only on SS7");
@ -8402,10 +8404,12 @@ gen_mtp3field_code(mtp3field, jvalue, jtype, reverse)
val2 = jvalue & 0x00003f00;
val2 = val2 << 8;
jvalue = val1 + val2;
b0 = gen_ncmp(OR_PACKET, off_dpc, BPF_W, 0xff3f0000,
b0 = gen_ncmp(OR_PACKET, newoff_dpc, BPF_W, 0xff3f0000,
(u_int)jtype, reverse, (u_int)jvalue);
break;
case MH_SLS:
newoff_sls+=3;
case M_SLS:
if (off_sls == (u_int)-1)
bpf_error("'sls' supported only on SS7");
@ -8416,7 +8420,7 @@ gen_mtp3field_code(mtp3field, jvalue, jtype, reverse)
/* the following instruction is made to convert jvalue
* to the forme used to write sls in an ss7 message*/
jvalue = jvalue << 4;
b0 = gen_ncmp(OR_PACKET, off_sls, BPF_B, 0xf0,
b0 = gen_ncmp(OR_PACKET, newoff_sls, BPF_B, 0xf0,
(u_int)jtype,reverse, (u_int)jvalue);
break;

View File

@ -1,4 +1,4 @@
/* $NetBSD: grammar.y,v 1.3 2013/04/06 17:29:53 christos Exp $ */
/* $NetBSD: grammar.y,v 1.4 2013/12/31 17:08:23 christos Exp $ */
%{
/*
@ -169,7 +169,7 @@ yyerror(const char *msg)
/* NOTREACHED */
}
#ifndef YYBISON
#ifdef NEED_YYPARSE_WRAPPER
int yyparse(void);
int
@ -296,8 +296,9 @@ pfaction_to_num(const char *action)
%token OAM OAMF4 CONNECTMSG METACONNECT
%token VPI VCI
%token RADIO
%token FISU LSSU MSU
%token SIO OPC DPC SLS
%token FISU LSSU MSU HFISU HLSSU HMSU
%token SIO OPC DPC SLS HSIO HOPC HDPC HSLS
%type <s> ID
%type <e> EID
@ -508,7 +509,8 @@ other: pqual TK_BROADCAST { $$ = gen_broadcast($1); }
| MPLS pnum { $$ = gen_mpls($2); }
| MPLS { $$ = gen_mpls(-1); }
| PPPOED { $$ = gen_pppoed(); }
| PPPOES { $$ = gen_pppoes(); }
| PPPOES pnum { $$ = gen_pppoes($2); }
| PPPOES { $$ = gen_pppoes(-1); }
| pfvar { $$ = $1; }
| pqual p80211 { $$ = $2; }
;
@ -672,12 +674,19 @@ atmlistvalue: atmfieldvalue
mtp2type: FISU { $$ = M_FISU; }
| LSSU { $$ = M_LSSU; }
| MSU { $$ = M_MSU; }
| HFISU { $$ = MH_FISU; }
| HLSSU { $$ = MH_LSSU; }
| HMSU { $$ = MH_MSU; }
;
/* MTP3 field types quantifier */
mtp3field: SIO { $$.mtp3fieldtype = M_SIO; }
| OPC { $$.mtp3fieldtype = M_OPC; }
| DPC { $$.mtp3fieldtype = M_DPC; }
| SLS { $$.mtp3fieldtype = M_SLS; }
| HSIO { $$.mtp3fieldtype = MH_SIO; }
| HOPC { $$.mtp3fieldtype = MH_OPC; }
| HDPC { $$.mtp3fieldtype = MH_DPC; }
| HSLS { $$.mtp3fieldtype = MH_SLS; }
;
mtp3value: mtp3fieldvalue
| relop NUM { $$.b = gen_mtp3field_code($<blk>0.mtp3fieldtype, (u_int)$2, (u_int)$1, 0); }
@ -689,7 +698,11 @@ mtp3fieldvalue: NUM {
if ($$.mtp3fieldtype == M_SIO ||
$$.mtp3fieldtype == M_OPC ||
$$.mtp3fieldtype == M_DPC ||
$$.mtp3fieldtype == M_SLS )
$$.mtp3fieldtype == M_SLS ||
$$.mtp3fieldtype == MH_SIO ||
$$.mtp3fieldtype == MH_OPC ||
$$.mtp3fieldtype == MH_DPC ||
$$.mtp3fieldtype == MH_SLS)
$$.b = gen_mtp3field_code($$.mtp3fieldtype, (u_int) $1, BPF_JEQ, 0);
}
;

View File

@ -1,4 +1,4 @@
/* $NetBSD: optimize.c,v 1.5 2013/04/06 17:29:53 christos Exp $ */
/* $NetBSD: optimize.c,v 1.6 2013/12/31 17:08:23 christos Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994, 1995, 1996
@ -114,51 +114,9 @@ static int cur_mark;
static void opt_init(struct block *);
static void opt_cleanup(void);
static void make_marks(struct block *);
static void mark_code(struct block *);
static void intern_blocks(struct block *);
static int eq_slist(struct slist *, struct slist *);
static void find_levels_r(struct block *);
static void find_levels(struct block *);
static void find_dom(struct block *);
static void propedom(struct edge *);
static void find_edom(struct block *);
static void find_closure(struct block *);
static int atomuse(struct stmt *);
static int atomdef(struct stmt *);
static void compute_local_ud(struct block *);
static void find_ud(struct block *);
static void init_val(void);
static int F(int, int, int);
static inline void vstore(struct stmt *, int *, int, int);
static void opt_blk(struct block *, int);
static int use_conflict(struct block *, struct block *);
static void opt_j(struct edge *);
static void or_pullup(struct block *);
static void and_pullup(struct block *);
static void opt_blks(struct block *, int);
static inline void link_inedge(struct edge *, struct block *);
static void find_inedges(struct block *);
static void opt_root(struct block **);
static void opt_loop(struct block *, int);
static void fold_op(struct stmt *, int, int);
static inline struct slist *this_op(struct slist *);
static void opt_not(struct block *);
static void opt_peep(struct block *);
static void opt_stmt(struct stmt *, int[], int);
static void deadstmt(struct stmt *, struct stmt *[]);
static void opt_deadstores(struct block *);
static struct block *fold_edge(struct block *, struct edge *);
static inline int eq_blk(struct block *, struct block *);
static u_int slength(struct slist *);
static int count_blocks(struct block *);
static void number_blks_r(struct block *);
static u_int count_stmts(struct block *);
static int convert_code_r(struct block *);
#ifdef BDEBUG
static void opt_dump(struct block *);
#endif
@ -234,8 +192,7 @@ static uset all_edge_sets;
#endif
static void
find_levels_r(b)
struct block *b;
find_levels_r(struct block *b)
{
int level;
@ -263,8 +220,7 @@ find_levels_r(b)
* with the 'link' field of the struct block.
*/
static void
find_levels(root)
struct block *root;
find_levels(struct block *root)
{
memset((char *)levels, 0, n_blocks * sizeof(*levels));
unMarkAll();
@ -276,8 +232,7 @@ find_levels(root)
* Assumes graph has been leveled.
*/
static void
find_dom(root)
struct block *root;
find_dom(struct block *root)
{
int i;
struct block *b;
@ -307,8 +262,7 @@ find_dom(root)
}
static void
propedom(ep)
struct edge *ep;
propedom(struct edge *ep)
{
SET_INSERT(ep->edom, ep->id);
if (ep->succ) {
@ -322,8 +276,7 @@ propedom(ep)
* Assumes graph has been leveled and predecessors established.
*/
static void
find_edom(root)
struct block *root;
find_edom(struct block *root)
{
int i;
uset x;
@ -352,8 +305,7 @@ find_edom(root)
* Assumes graph has been leveled.
*/
static void
find_closure(root)
struct block *root;
find_closure(struct block *root)
{
int i;
struct block *b;
@ -383,8 +335,7 @@ find_closure(root)
* The implementation should probably change to an array access.
*/
static int
atomuse(s)
struct stmt *s;
atomuse(struct stmt *s)
{
register int c = s->code;
@ -429,8 +380,7 @@ atomuse(s)
* The implementation should probably change to an array access.
*/
static int
atomdef(s)
struct stmt *s;
atomdef(struct stmt *s)
{
if (s->code == NOP)
return -1;
@ -466,8 +416,7 @@ atomdef(s)
* register by a predecessor block of this block.
*/
static void
compute_local_ud(b)
struct block *b;
compute_local_ud(struct block *b)
{
struct slist *s;
atomset def = 0, use = 0, kill = 0;
@ -528,8 +477,7 @@ compute_local_ud(b)
* Assume graph is already leveled.
*/
static void
find_ud(root)
struct block *root;
find_ud(struct block *root)
{
int i, maxlevel;
struct block *p;
@ -584,7 +532,7 @@ struct valnode *vnode_base;
struct valnode *next_vnode;
static void
init_val()
init_val(void)
{
curval = 0;
next_vnode = vnode_base;
@ -594,9 +542,7 @@ init_val()
/* Because we really don't have an IR, this stuff is a little messy. */
static int
F(code, v0, v1)
int code;
int v0, v1;
F(int code, int v0, int v1)
{
u_int hash;
int val;
@ -627,11 +573,7 @@ F(code, v0, v1)
}
static inline void
vstore(s, valp, newval, alter)
struct stmt *s;
int *valp;
int newval;
int alter;
vstore(struct stmt *s, int *valp, int newval, int alter)
{
if (alter && *valp == newval)
s->code = NOP;
@ -639,10 +581,12 @@ vstore(s, valp, newval, alter)
*valp = newval;
}
/*
* Do constant-folding on binary operators.
* (Unary operators are handled elsewhere.)
*/
static void
fold_op(s, v0, v1)
struct stmt *s;
int v0, v1;
fold_op(struct stmt *s, int v0, int v1)
{
bpf_u_int32 a, b;
@ -684,10 +628,6 @@ fold_op(s, v0, v1)
a >>= b;
break;
case BPF_NEG:
a = -a;
break;
default:
abort();
}
@ -697,8 +637,7 @@ fold_op(s, v0, v1)
}
static inline struct slist *
this_op(s)
struct slist *s;
this_op(struct slist *s)
{
while (s != 0 && s->s.code == NOP)
s = s->next;
@ -706,8 +645,7 @@ this_op(s)
}
static void
opt_not(b)
struct block *b;
opt_not(struct block *b)
{
struct block *tmp = JT(b);
@ -716,8 +654,7 @@ opt_not(b)
}
static void
opt_peep(b)
struct block *b;
opt_peep(struct block *b)
{
struct slist *s;
struct slist *next, *last;
@ -980,10 +917,7 @@ opt_peep(b)
* evaluation and code transformations weren't folded together.
*/
static void
opt_stmt(s, val, alter)
struct stmt *s;
int val[];
int alter;
opt_stmt(struct stmt *s, int val[], int alter)
{
int op;
int v;
@ -1168,9 +1102,7 @@ opt_stmt(s, val, alter)
}
static void
deadstmt(s, last)
register struct stmt *s;
register struct stmt *last[];
deadstmt(register struct stmt *s, register struct stmt *last[])
{
register int atom;
@ -1194,8 +1126,7 @@ deadstmt(s, last)
}
static void
opt_deadstores(b)
register struct block *b;
opt_deadstores(register struct block *b)
{
register struct slist *s;
register int atom;
@ -1215,9 +1146,7 @@ opt_deadstores(b)
}
static void
opt_blk(b, do_stmts)
struct block *b;
int do_stmts;
opt_blk(struct block *b, int do_stmts)
{
struct slist *s;
struct edge *p;
@ -1321,8 +1250,7 @@ opt_blk(b, do_stmts)
* from 'b'.
*/
static int
use_conflict(b, succ)
struct block *b, *succ;
use_conflict(struct block *b, struct block *succ)
{
int atom;
atomset use = succ->out_use;
@ -1338,9 +1266,7 @@ use_conflict(b, succ)
}
static struct block *
fold_edge(child, ep)
struct block *child;
struct edge *ep;
fold_edge(struct block *child, struct edge *ep)
{
int sense;
int aval0, aval1, oval0, oval1;
@ -1392,8 +1318,7 @@ fold_edge(child, ep)
}
static void
opt_j(ep)
struct edge *ep;
opt_j(struct edge *ep)
{
register int i, k;
register struct block *target;
@ -1448,8 +1373,7 @@ opt_j(ep)
static void
or_pullup(b)
struct block *b;
or_pullup(struct block *b)
{
int val, at_top;
struct block *pull;
@ -1541,8 +1465,7 @@ or_pullup(b)
}
static void
and_pullup(b)
struct block *b;
and_pullup(struct block *b)
{
int val, at_top;
struct block *pull;
@ -1633,9 +1556,7 @@ and_pullup(b)
}
static void
opt_blks(root, do_stmts)
struct block *root;
int do_stmts;
opt_blks(struct block *root, int do_stmts)
{
int i, maxlevel;
struct block *p;
@ -1672,17 +1593,14 @@ opt_blks(root, do_stmts)
}
static inline void
link_inedge(parent, child)
struct edge *parent;
struct block *child;
link_inedge(struct edge *parent, struct block *child)
{
parent->next = child->in_edges;
child->in_edges = parent;
}
static void
find_inedges(root)
struct block *root;
find_inedges(struct block *root)
{
int i;
struct block *b;
@ -1703,8 +1621,7 @@ find_inedges(root)
}
static void
opt_root(b)
struct block **b;
opt_root(struct block **b)
{
struct slist *tmp, *s;
@ -1728,9 +1645,7 @@ opt_root(b)
}
static void
opt_loop(root, do_stmts)
struct block *root;
int do_stmts;
opt_loop(struct block *root, int do_stmts)
{
#ifdef BDEBUG
@ -1760,8 +1675,7 @@ opt_loop(root, do_stmts)
* Optimize the filter code in its dag representation.
*/
void
bpf_optimize(rootp)
struct block **rootp;
bpf_optimize(struct block **rootp)
{
struct block *root;
@ -1788,8 +1702,7 @@ bpf_optimize(rootp)
}
static void
make_marks(p)
struct block *p;
make_marks(struct block *p)
{
if (!isMarked(p)) {
Mark(p);
@ -1805,8 +1718,7 @@ make_marks(p)
* only for nodes that are alive.
*/
static void
mark_code(p)
struct block *p;
mark_code(struct block *p)
{
cur_mark += 1;
make_marks(p);
@ -1817,8 +1729,7 @@ mark_code(p)
* the accumulator.
*/
static int
eq_slist(x, y)
struct slist *x, *y;
eq_slist(struct slist *x, struct slist *y)
{
while (1) {
while (x && x->s.code == NOP)
@ -1837,8 +1748,7 @@ eq_slist(x, y)
}
static inline int
eq_blk(b0, b1)
struct block *b0, *b1;
eq_blk(struct block *b0, struct block *b1)
{
if (b0->s.code == b1->s.code &&
b0->s.k == b1->s.k &&
@ -1849,8 +1759,7 @@ eq_blk(b0, b1)
}
static void
intern_blocks(root)
struct block *root;
intern_blocks(struct block *root)
{
struct block *p;
int i, j;
@ -1893,7 +1802,7 @@ intern_blocks(root)
}
static void
opt_cleanup()
opt_cleanup(void)
{
free((void *)vnode_base);
free((void *)vmap);
@ -1907,8 +1816,7 @@ opt_cleanup()
* Return the number of stmts in 's'.
*/
static u_int
slength(s)
struct slist *s;
slength(struct slist *s)
{
u_int n = 0;
@ -1923,8 +1831,7 @@ slength(s)
* All nodes should be initially unmarked.
*/
static int
count_blocks(p)
struct block *p;
count_blocks(struct block *p)
{
if (p == 0 || isMarked(p))
return 0;
@ -1937,8 +1844,7 @@ count_blocks(p)
* the basic blocks, and entering them into the 'blocks' array.`
*/
static void
number_blks_r(p)
struct block *p;
number_blks_r(struct block *p)
{
int n;
@ -1973,8 +1879,7 @@ number_blks_r(p)
* an extra long jump if the false branch requires it (p->longjf).
*/
static u_int
count_stmts(p)
struct block *p;
count_stmts(struct block *p)
{
u_int n;
@ -1991,8 +1896,7 @@ count_stmts(p)
* from the total number of blocks and/or statements.
*/
static void
opt_init(root)
struct block *root;
opt_init(struct block *root)
{
bpf_u_int32 *p;
int i, n, max_stmts;
@ -2090,8 +1994,7 @@ int bids[1000];
* properly.
*/
static int
convert_code_r(p)
struct block *p;
convert_code_r(struct block *p)
{
struct bpf_insn *dst;
struct slist *src;
@ -2263,9 +2166,7 @@ filled:
* done with the filter program. See the pcap man page.
*/
struct bpf_insn *
icode_to_fcode(root, lenp)
struct block *root;
u_int *lenp;
icode_to_fcode(struct block *root, u_int *lenp)
{
u_int n;
struct bpf_insn *fp;
@ -2335,8 +2236,7 @@ install_bpf_program(pcap_t *p, struct bpf_program *fp)
#ifdef BDEBUG
static void
opt_dump(root)
struct block *root;
opt_dump(struct block *root)
{
struct bpf_program f;

View File

@ -1,4 +1,4 @@
/* $NetBSD: pcap-bpf.c,v 1.3 2013/04/06 17:29:53 christos Exp $ */
/* $NetBSD: pcap-bpf.c,v 1.4 2013/12/31 17:08:23 christos Exp $ */
/*
* Copyright (c) 1993, 1994, 1995, 1996, 1998
@ -127,18 +127,60 @@ static int bpf_load(char *errbuf);
#include "pcap-int.h"
#ifdef HAVE_DAG_API
#include "pcap-dag.h"
#endif /* HAVE_DAG_API */
#ifdef HAVE_SNF_API
#include "pcap-snf.h"
#endif /* HAVE_SNF_API */
#ifdef HAVE_OS_PROTO_H
#include "os-proto.h"
#endif
/*
* Later versions of NetBSD stick padding in front of FDDI frames
* to align the IP header on a 4-byte boundary.
*/
#if defined(__NetBSD__) && __NetBSD_Version__ > 106000000
#define PCAP_FDDIPAD 3
#endif
/*
* Private data for capturing on BPF devices.
*/
struct pcap_bpf {
#ifdef PCAP_FDDIPAD
int fddipad;
#endif
#ifdef HAVE_ZEROCOPY_BPF
/*
* Zero-copy read buffer -- for zero-copy BPF. 'buffer' above will
* alternative between these two actual mmap'd buffers as required.
* As there is a header on the front size of the mmap'd buffer, only
* some of the buffer is exposed to libpcap as a whole via bufsize;
* zbufsize is the true size. zbuffer tracks the current zbuf
* assocated with buffer so that it can be used to decide which the
* next buffer to read will be.
*/
u_char *zbuf1, *zbuf2, *zbuffer;
u_int zbufsize;
u_int zerocopy;
u_int interrupted;
struct timespec firstsel;
/*
* If there's currently a buffer being actively processed, then it is
* referenced here; 'buffer' is also pointed at it, but offset by the
* size of the header.
*/
struct bpf_zbuf_header *bzh;
int nonblock; /* true if in nonblocking mode */
#endif /* HAVE_ZEROCOPY_BPF */
char *device; /* device name */
int filtering_in_kernel; /* using kernel filter */
int must_do_on_close; /* stuff we must do when we close */
};
/*
* Stuff to do when we close.
*/
#define MUST_CLEAR_RFMON 0x00000001 /* clear rfmon (monitor) mode */
#ifdef BIOCGDLTLIST
# if (defined(HAVE_NET_IF_MEDIA_H) && defined(IFM_IEEE80211)) && !defined(__APPLE__)
#define HAVE_BSD_IEEE80211
@ -197,22 +239,17 @@ static int pcap_set_datalink_bpf(pcap_t *p, int dlt);
/*
* For zerocopy bpf, the setnonblock/getnonblock routines need to modify
* p->md.timeout so we don't call select(2) if the pcap handle is in non-
* blocking mode. We preserve the timeout supplied by pcap_open functions
* to make sure it does not get clobbered if the pcap handle moves between
* blocking and non-blocking mode.
* pb->nonblock so we don't call select(2) if the pcap handle is in non-
* blocking mode.
*/
static int
pcap_getnonblock_bpf(pcap_t *p, char *errbuf)
{
#ifdef HAVE_ZEROCOPY_BPF
if (p->md.zerocopy) {
/*
* Use a negative value for the timeout to represent that the
* pcap handle is in non-blocking mode.
*/
return (p->md.timeout < 0);
}
struct pcap_bpf *pb = p->priv;
if (pb->zerocopy)
return (pb->nonblock);
#endif
return (pcap_getnonblock_fd(p, errbuf));
}
@ -221,34 +258,10 @@ static int
pcap_setnonblock_bpf(pcap_t *p, int nonblock, char *errbuf)
{
#ifdef HAVE_ZEROCOPY_BPF
if (p->md.zerocopy) {
/*
* Map each value to the corresponding 2's complement, to
* preserve the timeout value provided with pcap_set_timeout.
* (from pcap-linux.c).
*/
if (nonblock) {
if (p->md.timeout >= 0) {
/*
* Timeout is non-negative, so we're not
* currently in non-blocking mode; set it
* to the 2's complement, to make it
* negative, as an indication that we're
* in non-blocking mode.
*/
p->md.timeout = p->md.timeout * -1 - 1;
}
} else {
if (p->md.timeout < 0) {
/*
* Timeout is negative, so we're currently
* in blocking mode; reverse the previous
* operation, to make the timeout non-negative
* again.
*/
p->md.timeout = (p->md.timeout + 1) * -1;
}
}
struct pcap_bpf *pb = p->priv;
if (pb->zerocopy) {
pb->nonblock = nonblock;
return (0);
}
#endif
@ -268,25 +281,26 @@ pcap_setnonblock_bpf(pcap_t *p, int nonblock, char *errbuf)
static int
pcap_next_zbuf_shm(pcap_t *p, int *cc)
{
struct pcap_bpf *pb = p->priv;
struct bpf_zbuf_header *bzh;
if (p->md.zbuffer == p->md.zbuf2 || p->md.zbuffer == NULL) {
bzh = (struct bpf_zbuf_header *)p->md.zbuf1;
if (pb->zbuffer == pb->zbuf2 || pb->zbuffer == NULL) {
bzh = (struct bpf_zbuf_header *)pb->zbuf1;
if (bzh->bzh_user_gen !=
atomic_load_acq_int(&bzh->bzh_kernel_gen)) {
p->md.bzh = bzh;
p->md.zbuffer = (u_char *)p->md.zbuf1;
p->buffer = p->md.zbuffer + sizeof(*bzh);
pb->bzh = bzh;
pb->zbuffer = (u_char *)pb->zbuf1;
p->buffer = pb->zbuffer + sizeof(*bzh);
*cc = bzh->bzh_kernel_len;
return (1);
}
} else if (p->md.zbuffer == p->md.zbuf1) {
bzh = (struct bpf_zbuf_header *)p->md.zbuf2;
} else if (pb->zbuffer == pb->zbuf1) {
bzh = (struct bpf_zbuf_header *)pb->zbuf2;
if (bzh->bzh_user_gen !=
atomic_load_acq_int(&bzh->bzh_kernel_gen)) {
p->md.bzh = bzh;
p->md.zbuffer = (u_char *)p->md.zbuf2;
p->buffer = p->md.zbuffer + sizeof(*bzh);
pb->bzh = bzh;
pb->zbuffer = (u_char *)pb->zbuf2;
p->buffer = pb->zbuffer + sizeof(*bzh);
*cc = bzh->bzh_kernel_len;
return (1);
}
@ -305,6 +319,7 @@ pcap_next_zbuf_shm(pcap_t *p, int *cc)
static int
pcap_next_zbuf(pcap_t *p, int *cc)
{
struct pcap_bpf *pb = p->priv;
struct bpf_zbuf bz;
struct timeval tv;
struct timespec cur;
@ -328,15 +343,15 @@ pcap_next_zbuf(pcap_t *p, int *cc)
* our timeout is less then or equal to zero, handle it like a
* regular timeout.
*/
tmout = p->md.timeout;
tmout = p->opt.timeout;
if (tmout)
(void) clock_gettime(CLOCK_MONOTONIC, &cur);
if (p->md.interrupted && p->md.timeout) {
expire = TSTOMILLI(&p->md.firstsel) + p->md.timeout;
if (pb->interrupted && p->opt.timeout) {
expire = TSTOMILLI(&pb->firstsel) + p->opt.timeout;
tmout = expire - TSTOMILLI(&cur);
#undef TSTOMILLI
if (tmout <= 0) {
p->md.interrupted = 0;
pb->interrupted = 0;
data = pcap_next_zbuf_shm(p, cc);
if (data)
return (data);
@ -353,7 +368,7 @@ pcap_next_zbuf(pcap_t *p, int *cc)
* the next timeout. Note that we only call select if the handle
* is in blocking mode.
*/
if (p->md.timeout >= 0) {
if (!pb->nonblock) {
FD_ZERO(&r_set);
FD_SET(p->fd, &r_set);
if (tmout != 0) {
@ -361,11 +376,11 @@ pcap_next_zbuf(pcap_t *p, int *cc)
tv.tv_usec = (tmout * 1000) % 1000000;
}
r = select(p->fd + 1, &r_set, NULL, NULL,
p->md.timeout != 0 ? &tv : NULL);
p->opt.timeout != 0 ? &tv : NULL);
if (r < 0 && errno == EINTR) {
if (!p->md.interrupted && p->md.timeout) {
p->md.interrupted = 1;
p->md.firstsel = cur;
if (!pb->interrupted && p->opt.timeout) {
pb->interrupted = 1;
pb->firstsel = cur;
}
return (0);
} else if (r < 0) {
@ -374,7 +389,7 @@ pcap_next_zbuf(pcap_t *p, int *cc)
return (PCAP_ERROR);
}
}
p->md.interrupted = 0;
pb->interrupted = 0;
/*
* Check again for data, which may exist now that we've either been
* woken up as a result of data or timed out. Try the "there's data"
@ -402,30 +417,22 @@ pcap_next_zbuf(pcap_t *p, int *cc)
static int
pcap_ack_zbuf(pcap_t *p)
{
struct pcap_bpf *pb = p->priv;
atomic_store_rel_int(&p->md.bzh->bzh_user_gen,
p->md.bzh->bzh_kernel_gen);
p->md.bzh = NULL;
atomic_store_rel_int(&pb->bzh->bzh_user_gen,
pb->bzh->bzh_kernel_gen);
pb->bzh = NULL;
p->buffer = NULL;
return (0);
}
#endif /* HAVE_ZEROCOPY_BPF */
pcap_t *
pcap_create(const char *device, char *ebuf)
pcap_create_interface(const char *device, char *ebuf)
{
pcap_t *p;
#ifdef HAVE_DAG_API
if (strstr(device, "dag"))
return (dag_create(device, ebuf));
#endif /* HAVE_DAG_API */
#ifdef HAVE_SNF_API
if (strstr(device, "snf"))
return (snf_create(device, ebuf));
#endif /* HAVE_SNF_API */
p = pcap_create_common(device, ebuf);
p = pcap_create_common(device, ebuf, sizeof (struct pcap_bpf));
if (p == NULL)
return (NULL);
@ -821,6 +828,7 @@ pcap_stats_bpf(pcap_t *p, struct pcap_stat *ps)
static int
pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
struct pcap_bpf *pb = p->priv;
int cc;
int n = 0;
register u_char *bp, *ep;
@ -856,7 +864,7 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
* buffer.
*/
#ifdef HAVE_ZEROCOPY_BPF
if (p->md.zerocopy) {
if (pb->zerocopy) {
if (p->buffer != NULL)
pcap_ack_zbuf(p);
i = pcap_next_zbuf(p, &cc);
@ -1004,7 +1012,7 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
* skipping that padding.
#endif
*/
if (p->md.use_bpf ||
if (pb->filtering_in_kernel ||
bpf_filter(p->fcode.bf_insns, datap, bhp->bh_datalen, caplen)) {
struct pcap_pkthdr pkthdr;
@ -1271,19 +1279,20 @@ bpf_load(char *errbuf)
static void
pcap_cleanup_bpf(pcap_t *p)
{
struct pcap_bpf *pb = p->priv;
#ifdef HAVE_BSD_IEEE80211
int sock;
struct ifmediareq req;
struct ifreq ifr;
#endif
if (p->md.must_do_on_close != 0) {
if (pb->must_do_on_close != 0) {
/*
* There's something we have to do when closing this
* pcap_t.
*/
#ifdef HAVE_BSD_IEEE80211
if (p->md.must_do_on_close & MUST_CLEAR_RFMON) {
if (pb->must_do_on_close & MUST_CLEAR_RFMON) {
/*
* We put the interface into rfmon mode;
* take it out of rfmon mode.
@ -1300,7 +1309,7 @@ pcap_cleanup_bpf(pcap_t *p)
strerror(errno));
} else {
memset(&req, 0, sizeof(req));
strncpy(req.ifm_name, p->md.device,
strncpy(req.ifm_name, pb->device,
sizeof(req.ifm_name));
if (ioctl(sock, SIOCGIFMEDIA, &req) < 0) {
fprintf(stderr,
@ -1315,7 +1324,7 @@ pcap_cleanup_bpf(pcap_t *p)
*/
memset(&ifr, 0, sizeof(ifr));
(void)strncpy(ifr.ifr_name,
p->md.device,
pb->device,
sizeof(ifr.ifr_name));
ifr.ifr_media =
req.ifm_current & ~IFM_IEEE80211_MONITOR;
@ -1338,11 +1347,11 @@ pcap_cleanup_bpf(pcap_t *p)
* have to take the interface out of some mode.
*/
pcap_remove_from_pcaps_to_close(p);
p->md.must_do_on_close = 0;
pb->must_do_on_close = 0;
}
#ifdef HAVE_ZEROCOPY_BPF
if (p->md.zerocopy) {
if (pb->zerocopy) {
/*
* Delete the mappings. Note that p->buffer gets
* initialized to one of the mmapped regions in
@ -1350,16 +1359,16 @@ pcap_cleanup_bpf(pcap_t *p)
* null it out so that pcap_cleanup_live_common()
* doesn't try to free it.
*/
if (p->md.zbuf1 != MAP_FAILED && p->md.zbuf1 != NULL)
(void) munmap(p->md.zbuf1, p->md.zbufsize);
if (p->md.zbuf2 != MAP_FAILED && p->md.zbuf2 != NULL)
(void) munmap(p->md.zbuf2, p->md.zbufsize);
if (pb->zbuf1 != MAP_FAILED && pb->zbuf1 != NULL)
(void) munmap(pb->zbuf1, pb->zbufsize);
if (pb->zbuf2 != MAP_FAILED && pb->zbuf2 != NULL)
(void) munmap(pb->zbuf2, pb->zbufsize);
p->buffer = NULL;
}
#endif
if (p->md.device != NULL) {
free(p->md.device);
p->md.device = NULL;
if (pb->device != NULL) {
free(pb->device);
pb->device = NULL;
}
pcap_cleanup_live_common(p);
}
@ -1474,6 +1483,7 @@ check_setif_failure(pcap_t *p, int error)
static int
pcap_activate_bpf(pcap_t *p)
{
struct pcap_bpf *pb = p->priv;
int status = 0;
int fd;
#ifdef LIFNAMSIZ
@ -1555,8 +1565,8 @@ pcap_activate_bpf(pcap_t *p)
}
#endif
p->md.device = strdup(p->opt.source);
if (p->md.device == NULL) {
pb->device = strdup(p->opt.source);
if (pb->device == NULL) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s",
pcap_strerror(errno));
status = PCAP_ERROR;
@ -1664,7 +1674,7 @@ pcap_activate_bpf(pcap_t *p)
/*
* We have zerocopy BPF; use it.
*/
p->md.zerocopy = 1;
pb->zerocopy = 1;
/*
* How to pick a buffer size: first, query the maximum buffer
@ -1694,22 +1704,22 @@ pcap_activate_bpf(pcap_t *p)
#ifndef roundup
#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) /* to any y */
#endif
p->md.zbufsize = roundup(v, getpagesize());
if (p->md.zbufsize > zbufmax)
p->md.zbufsize = zbufmax;
p->md.zbuf1 = mmap(NULL, p->md.zbufsize, PROT_READ | PROT_WRITE,
pb->zbufsize = roundup(v, getpagesize());
if (pb->zbufsize > zbufmax)
pb->zbufsize = zbufmax;
pb->zbuf1 = mmap(NULL, pb->zbufsize, PROT_READ | PROT_WRITE,
MAP_ANON, -1, 0);
p->md.zbuf2 = mmap(NULL, p->md.zbufsize, PROT_READ | PROT_WRITE,
pb->zbuf2 = mmap(NULL, pb->zbufsize, PROT_READ | PROT_WRITE,
MAP_ANON, -1, 0);
if (p->md.zbuf1 == MAP_FAILED || p->md.zbuf2 == MAP_FAILED) {
if (pb->zbuf1 == MAP_FAILED || pb->zbuf2 == MAP_FAILED) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "mmap: %s",
pcap_strerror(errno));
goto bad;
}
bzero(&bz, sizeof(bz));
bz.bz_bufa = p->md.zbuf1;
bz.bz_bufb = p->md.zbuf2;
bz.bz_buflen = p->md.zbufsize;
memset(&bz, 0, sizeof(bz)); /* bzero() deprecated, replaced with memset() */
bz.bz_bufa = pb->zbuf1;
bz.bz_bufb = pb->zbuf2;
bz.bz_buflen = pb->zbufsize;
if (ioctl(fd, BIOCSETZBUF, (caddr_t)&bz) < 0) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETZBUF: %s",
pcap_strerror(errno));
@ -1721,7 +1731,7 @@ pcap_activate_bpf(pcap_t *p)
p->opt.source, pcap_strerror(errno));
goto bad;
}
v = p->md.zbufsize - sizeof(struct bpf_zbuf_header);
v = pb->zbufsize - sizeof(struct bpf_zbuf_header);
} else
#endif
{
@ -2033,8 +2043,8 @@ pcap_activate_bpf(pcap_t *p)
if (v == DLT_FDDI)
p->fddipad = PCAP_FDDIPAD;
else
p->fddipad = 0;
#endif
p->fddipad = 0;
p->linktype = v;
#if defined(BIOCGHDRCMPLT) && defined(BIOCSHDRCMPLT)
@ -2056,9 +2066,14 @@ pcap_activate_bpf(pcap_t *p)
#endif
/* set timeout */
#ifdef HAVE_ZEROCOPY_BPF
if (p->md.timeout != 0 && !p->md.zerocopy) {
/*
* In zero-copy mode, we just use the timeout in select().
* XXX - what if we're in non-blocking mode and the *application*
* is using select() or poll() or kqueues or....?
*/
if (p->opt.timeout && !pb->zerocopy) {
#else
if (p->md.timeout) {
if (p->opt.timeout) {
#endif
/*
* XXX - is this seconds/nanoseconds in AIX?
@ -2082,8 +2097,8 @@ pcap_activate_bpf(pcap_t *p)
struct BPF_TIMEVAL bpf_to;
if (IOCPARM_LEN(BIOCSRTIMEOUT) != sizeof(struct timeval)) {
bpf_to.tv_sec = p->md.timeout / 1000;
bpf_to.tv_usec = (p->md.timeout * 1000) % 1000000;
bpf_to.tv_sec = p->opt.timeout / 1000;
bpf_to.tv_usec = (p->opt.timeout * 1000) % 1000000;
if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&bpf_to) < 0) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"BIOCSRTIMEOUT: %s", pcap_strerror(errno));
@ -2092,8 +2107,8 @@ pcap_activate_bpf(pcap_t *p)
}
} else {
#endif
to.tv_sec = p->md.timeout / 1000;
to.tv_usec = (p->md.timeout * 1000) % 1000000;
to.tv_sec = p->opt.timeout / 1000;
to.tv_usec = (p->opt.timeout * 1000) % 1000000;
if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&to) < 0) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"BIOCSRTIMEOUT: %s", pcap_strerror(errno));
@ -2105,7 +2120,6 @@ pcap_activate_bpf(pcap_t *p)
#endif
}
#ifdef _AIX
#ifdef BIOCIMMEDIATE
/*
* Darren Reed notes that
@ -2117,51 +2131,38 @@ pcap_activate_bpf(pcap_t *p)
* is reducing things to only a few packets (i.e. one every
* second or so).
*
* so we turn BIOCIMMEDIATE mode on if this is AIX.
* so we always turn BIOCIMMEDIATE mode on if this is AIX.
*
* We don't turn it on for other platforms, as that means we
* get woken up for every packet, which may not be what we want;
* in the Winter 1993 USENIX paper on BPF, they say:
* For other platforms, we don't turn immediate mode on by default,
* as that would mean we get woken up for every packet, which
* probably isn't what you want for a packet sniffer.
*
* Since a process might want to look at every packet on a
* network and the time between packets can be only a few
* microseconds, it is not possible to do a read system call
* per packet and BPF must collect the data from several
* packets and return it as a unit when the monitoring
* application does a read.
*
* which I infer is the reason for the timeout - it means we
* wait that amount of time, in the hopes that more packets
* will arrive and we'll get them all with one read.
*
* Setting BIOCIMMEDIATE mode on FreeBSD (and probably other
* BSDs) causes the timeout to be ignored.
*
* On the other hand, some platforms (e.g., Linux) don't support
* timeouts, they just hand stuff to you as soon as it arrives;
* if that doesn't cause a problem on those platforms, it may
* be OK to have BIOCIMMEDIATE mode on BSD as well.
*
* (Note, though, that applications may depend on the read
* completing, even if no packets have arrived, when the timeout
* expires, e.g. GUI applications that have to check for input
* while waiting for packets to arrive; a non-zero timeout
* prevents "select()" from working right on FreeBSD and
* possibly other BSDs, as the timer doesn't start until a
* "read()" is done, so the timer isn't in effect if the
* application is blocked on a "select()", and the "select()"
* doesn't get woken up for a BPF device until the buffer
* fills up.)
* We set immediate mode if the caller requested it by calling
* pcap_set_immediate() before calling pcap_activate().
*/
v = 1;
if (ioctl(p->fd, BIOCIMMEDIATE, &v) < 0) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCIMMEDIATE: %s",
pcap_strerror(errno));
#ifndef _AIX
if (p->opt.immediate) {
#endif /* _AIX */
v = 1;
if (ioctl(p->fd, BIOCIMMEDIATE, &v) < 0) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"BIOCIMMEDIATE: %s", pcap_strerror(errno));
status = PCAP_ERROR;
goto bad;
}
#ifndef _AIX
}
#endif /* _AIX */
#else /* BIOCIMMEDIATE */
if (p->opt.immediate) {
/*
* We don't support immediate mode. Fail.
*/
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Immediate mode not supported");
status = PCAP_ERROR;
goto bad;
}
#endif /* BIOCIMMEDIATE */
#endif /* _AIX */
#endif /* BIOCIMMEDIATE */
if (p->opt.promisc) {
/* set promiscuous mode, just warn if it fails */
@ -2180,7 +2181,7 @@ pcap_activate_bpf(pcap_t *p)
}
p->bufsize = v;
#ifdef HAVE_ZEROCOPY_BPF
if (!p->md.zerocopy) {
if (!pb->zerocopy) {
#endif
p->buffer = (u_char *)malloc(p->bufsize);
if (p->buffer == NULL) {
@ -2281,22 +2282,13 @@ pcap_activate_bpf(pcap_t *p)
return (status);
bad:
pcap_cleanup_bpf(p);
pcap_cleanup_bpf(p);
return (status);
}
int
pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
{
#ifdef HAVE_DAG_API
if (dag_platform_finddevs(alldevsp, errbuf) < 0)
return (-1);
#endif /* HAVE_DAG_API */
#ifdef HAVE_SNF_API
if (snf_platform_finddevs(alldevsp, errbuf) < 0)
return (-1);
#endif /* HAVE_SNF_API */
return (0);
}
@ -2304,6 +2296,7 @@ pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
static int
monitor_mode(pcap_t *p, int set)
{
struct pcap_bpf *pb = p->priv;
int sock;
struct ifmediareq req;
int *media_list;
@ -2441,7 +2434,7 @@ monitor_mode(pcap_t *p, int set)
return (PCAP_ERROR);
}
p->md.must_do_on_close |= MUST_CLEAR_RFMON;
pb->must_do_on_close |= MUST_CLEAR_RFMON;
/*
* Add this to the list of pcaps to close when we exit.
@ -2618,6 +2611,8 @@ remove_802_11(pcap_t *p)
static int
pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp)
{
struct pcap_bpf *pb = p->priv;
/*
* Free any user-mode filter we might happen to have installed.
*/
@ -2630,7 +2625,7 @@ pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp)
/*
* It worked.
*/
p->md.use_bpf = 1; /* filtering in the kernel */
pb->filtering_in_kernel = 1; /* filtering in the kernel */
/*
* Discard any previously-received packets, as they might
@ -2670,7 +2665,7 @@ pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp)
*/
if (install_bpf_program(p, fp) < 0)
return (-1);
p->md.use_bpf = 0; /* filtering in userland */
pb->filtering_in_kernel = 0; /* filtering in userland */
return (0);
}

View File

@ -19,7 +19,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
.TH PCAP 3PCAP "4 April 2008"
.TH PCAP 3PCAP "1 July 2013"
.SH NAME
pcap \- Packet Capture library
.SH SYNOPSIS
@ -309,6 +309,19 @@ handle, call
lists the values it returns and describes the packet formats that
correspond to those values.
.PP
Do
.B NOT
assume that the packets for a given capture or ``savefile`` will have
any given link-layer header type, such as
.B DLT_EN10MB
for Ethernet. For example, the "any" device on Linux will have a
link-layer header type of
.B DLT_LINUX_SLL
even if all devices on the system at the time the "any" device is opened
have some other data link type, such as
.B DLT_EN10MB
for Ethernet.
.PP
To obtain the
.B "FILE\ *"
corresponding to a
@ -510,20 +523,13 @@ number of bytes available from the capture, if the length of the packet
is larger than the maximum number of bytes to capture).
.RE
.PP
.BR pcap_next_ex ()
supplies that pointer through a pointer argument.
.BR pcap_next ()
is passed an argument that points to a
.I struct pcap_pkthdr
structure, and fills it in.
.PP
The callback is also supplied a
.I const u_char
pointer to the first
.B caplen
(as given in the
.I struct pcap_pkthdr
a pointer to which is passed to the callback routine)
mentioned above)
bytes of data from the packet. This won't necessarily be the entire
packet; to capture the entire packet, you will have to provide a value
for
@ -534,10 +540,28 @@ that is sufficiently large to get all of the packet's data - a value of
65535 should be sufficient on most if not all networks). When reading
from a ``savefile'', the snapshot length specified when the capture was
performed will limit the amount of packet data available.
.PP
.BR pcap_next ()
returns that pointer;
is passed an argument that points to a
.I struct pcap_pkthdr
structure, and fills it in with the time stamp and length values for the
packet. It returns a
.I const u_char
to the first
.B caplen
bytes of the packet on success, and NULL on error.
.PP
.BR pcap_next_ex ()
supplies that pointer through a pointer argument.
is passed two pointer arguments, one of which points to a
.IR struct pcap_pkthdr *
and one of which points to a
.IR "const u_char" *.
It sets the first pointer to point to a
.I struct pcap_pkthdr
structure with the time stamp and length values for the packet, and sets
the second pointer to point to the first
.B caplen
bytes of the packet.
.PP
To force the loop in
.BR pcap_dispatch ()

View File

@ -1,4 +1,4 @@
/* $NetBSD: pcap.c,v 1.3 2013/04/06 17:29:53 christos Exp $ */
/* $NetBSD: pcap.c,v 1.4 2013/12/31 17:08:23 christos Exp $ */
/*
* Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998
@ -76,17 +76,56 @@ static const char rcsid[] _U_ =
#include "pcap-int.h"
#ifdef HAVE_DAG_API
#include <dagnew.h>
#include <dagapi.h>
#include "pcap-dag.h"
#endif /* HAVE_DAG_API */
#ifdef HAVE_SEPTEL_API
#include "pcap-septel.h"
#endif /* HAVE_SEPTEL_API */
#ifdef HAVE_SNF_API
#include "pcap-snf.h"
#endif /* HAVE_SNF_API */
#ifdef PCAP_SUPPORT_USB
#include "pcap-usb-linux.h"
#endif
#ifdef PCAP_SUPPORT_BT
#include "pcap-bt-linux.h"
#endif
#ifdef PCAP_SUPPORT_CAN
#include "pcap-can-linux.h"
#endif
#ifdef PCAP_SUPPORT_CANUSB
#include "pcap-canusb-linux.h"
#endif
#ifdef PCAP_SUPPORT_NETFILTER
#include "pcap-netfilter-linux.h"
#endif
#ifdef PCAP_SUPPORT_DBUS
#include "pcap-dbus.h"
#endif
int
pcap_not_initialized(pcap_t *pcap)
pcap_not_initialized(pcap_t *pcap _U_)
{
/* this means 'not initialized' */
return (PCAP_ERROR_NOT_ACTIVATED);
}
#ifdef WIN32
Adapter *
pcap_no_adapter(pcap_t *pcap _U_)
{
return (NULL);
}
#endif
/*
* Returns 1 if rfmon mode can be set on the pcap_t, 0 if it can't,
* a PCAP_ERROR value on an error.
@ -161,7 +200,7 @@ pcap_free_tstamp_types(int *tstamp_type_list)
* packet data cannot be guaranteed to be available after the callback
* returns, so that a copy must be made.
*/
static void
void
pcap_oneshot(u_char *user, const struct pcap_pkthdr *h, const u_char *pkt)
{
struct oneshot_userdata *sp = (struct oneshot_userdata *)user;
@ -197,7 +236,7 @@ pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header,
/* Saves a pointer to the packet headers */
*pkt_header= &p->pcap_header;
if (p->sf.rfile != NULL) {
if (p->rfile != NULL) {
int status;
/* We are on an offline capture */
@ -234,6 +273,176 @@ pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header,
return (p->read_op(p, 1, p->oneshot_callback, (u_char *)&s));
}
#if defined(DAG_ONLY)
int
pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
{
return (dag_findalldevs(alldevsp, errbuf));
}
pcap_t *
pcap_create(const char *source, char *errbuf)
{
return (dag_create(source, errbuf));
}
#elif defined(SEPTEL_ONLY)
int
pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
{
return (septel_findalldevs(alldevsp, errbuf));
}
pcap_t *
pcap_create(const char *source, char *errbuf)
{
return (septel_create(source, errbuf));
}
#elif defined(SNF_ONLY)
int
pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
{
return (snf_findalldevs(alldevsp, errbuf));
}
pcap_t *
pcap_create(const char *source, char *errbuf)
{
return (snf_create(source, errbuf));
}
#else /* regular pcap */
struct capture_source_type {
int (*findalldevs_op)(pcap_if_t **, char *);
pcap_t *(*create_op)(const char *, char *, int *);
} capture_source_types[] = {
#ifdef HAVE_DAG_API
{ dag_findalldevs, dag_create },
#endif
#ifdef HAVE_SEPTEL_API
{ septel_findalldevs, septel_create },
#endif
#ifdef HAVE_SNF_API
{ snf_findalldevs, snf_create },
#endif
#ifdef PCAP_SUPPORT_BT
{ bt_findalldevs, bt_create },
#endif
#if PCAP_SUPPORT_CANUSB
{ canusb_findalldevs, canusb_create },
#endif
#ifdef PCAP_SUPPORT_CAN
{ can_findalldevs, can_create },
#endif
#ifdef PCAP_SUPPORT_USB
{ usb_findalldevs, usb_create },
#endif
#ifdef PCAP_SUPPORT_NETFILTER
{ netfilter_findalldevs, netfilter_create },
#endif
#ifdef PCAP_SUPPORT_DBUS
{ dbus_findalldevs, dbus_create },
#endif
{ NULL, NULL }
};
/*
* Get a list of all capture sources that are up and that we can open.
* Returns -1 on error, 0 otherwise.
* The list, as returned through "alldevsp", may be null if no interfaces
* were up and could be opened.
*/
int
pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
{
size_t i;
/*
* Get the list of regular interfaces first.
*/
if (pcap_findalldevs_interfaces(alldevsp, errbuf) == -1)
return (-1); /* failure */
/*
* Add any interfaces that need a platform-specific mechanism
* to find.
*/
if (pcap_platform_finddevs(alldevsp, errbuf) == -1) {
/*
* We had an error; free the list we've been
* constructing.
*/
if (*alldevsp != NULL) {
pcap_freealldevs(*alldevsp);
*alldevsp = NULL;
}
return (-1);
}
/*
* Ask each of the non-local-network-interface capture
* source types what interfaces they have.
*/
for (i = 0; capture_source_types[i].findalldevs_op != NULL; i++) {
if (capture_source_types[i].findalldevs_op(alldevsp, errbuf) == -1) {
/*
* We had an error; free the list we've been
* constructing.
*/
if (*alldevsp != NULL) {
pcap_freealldevs(*alldevsp);
*alldevsp = NULL;
}
return (-1);
}
}
return (0);
}
pcap_t *
pcap_create(const char *source, char *errbuf)
{
size_t i;
int is_theirs;
pcap_t *p;
/*
* A null source name is equivalent to the "any" device -
* which might not be supported on this platform, but
* this means that you'll get a "not supported" error
* rather than, say, a crash when we try to dereference
* the null pointer.
*/
if (source == NULL)
source = "any";
/*
* Try each of the non-local-network-interface capture
* source types until we find one that works for this
* device or run out of types.
*/
for (i = 0; capture_source_types[i].create_op != NULL; i++) {
is_theirs = 0;
p = capture_source_types[i].create_op(source, errbuf, &is_theirs);
if (is_theirs) {
/*
* The device name refers to a device of the
* type in question; either it succeeded,
* in which case p refers to a pcap_t to
* later activate for the device, or it
* failed, in which case p is null and we
* should return that to report the failure
* to create.
*/
return (p);
}
}
/*
* OK, try it as a regular network interface.
*/
return (pcap_create_interface(source, errbuf));
}
#endif
static void
initialize_ops(pcap_t *p)
{
@ -254,6 +463,7 @@ initialize_ops(pcap_t *p)
p->setbuff_op = (setbuff_op_t)pcap_not_initialized;
p->setmode_op = (setmode_op_t)pcap_not_initialized;
p->setmintocopy_op = (setmintocopy_op_t)pcap_not_initialized;
p->getadapter_op = pcap_no_adapter;
#endif
/*
@ -264,30 +474,65 @@ initialize_ops(pcap_t *p)
p->cleanup_op = pcap_cleanup_live_common;
/*
* In most cases, the standard one-short callback can
* In most cases, the standard one-shot callback can
* be used for pcap_next()/pcap_next_ex().
*/
p->oneshot_callback = pcap_oneshot;
}
pcap_t *
pcap_create_common(const char *source, char *ebuf)
static pcap_t *
pcap_alloc_pcap_t(char *ebuf, size_t size)
{
char *chunk;
pcap_t *p;
p = malloc(sizeof(*p));
if (p == NULL) {
/*
* Allocate a chunk of memory big enough for a pcap_t
* plus a structure following it of size "size". The
* structure following it is a private data structure
* for the routines that handle this pcap_t.
*/
chunk = malloc(sizeof (pcap_t) + size);
if (chunk == NULL) {
snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
pcap_strerror(errno));
return (NULL);
}
memset(p, 0, sizeof(*p));
memset(chunk, 0, sizeof (pcap_t) + size);
/*
* Get a pointer to the pcap_t at the beginning.
*/
p = (pcap_t *)chunk;
#ifndef WIN32
p->fd = -1; /* not opened yet */
p->selectable_fd = -1;
p->send_fd = -1;
#endif
if (size == 0) {
/* No private data was requested. */
p->priv = NULL;
} else {
/*
* Set the pointer to the private data; that's the structure
* of size "size" following the pcap_t.
*/
p->priv = (void *)(chunk + sizeof (pcap_t));
}
return (p);
}
pcap_t *
pcap_create_common(const char *source, char *ebuf, size_t size)
{
pcap_t *p;
p = pcap_alloc_pcap_t(ebuf, size);
if (p == NULL)
return (NULL);
p->opt.source = strdup(source);
if (p->opt.source == NULL) {
snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
@ -307,11 +552,14 @@ pcap_create_common(const char *source, char *ebuf)
initialize_ops(p);
/* put in some defaults*/
pcap_set_timeout(p, 0);
pcap_set_snaplen(p, 65535); /* max packet size */
pcap_set_snaplen(p, 65535); /* max packet size */
p->opt.timeout = 0; /* no timeout specified */
p->opt.buffer_size = 0; /* use the platform's default */
p->opt.promisc = 0;
p->opt.buffer_size = 0;
p->opt.rfmon = 0;
p->opt.immediate = 0;
p->opt.tstamp_type = -1; /* default to not setting time stamp type */
p->opt.tstamp_precision = PCAP_TSTAMP_PRECISION_MICRO;
return (p);
}
@ -358,7 +606,7 @@ pcap_set_timeout(pcap_t *p, int timeout_ms)
{
if (pcap_check_activated(p))
return (PCAP_ERROR_ACTIVATED);
p->md.timeout = timeout_ms;
p->opt.timeout = timeout_ms;
return (0);
}
@ -371,32 +619,44 @@ pcap_set_tstamp_type(pcap_t *p, int tstamp_type)
return (PCAP_ERROR_ACTIVATED);
/*
* If p->tstamp_type_count is 0, we don't support setting
* the time stamp type at all.
* If p->tstamp_type_count is 0, we only support PCAP_TSTAMP_HOST;
* the default time stamp type is PCAP_TSTAMP_HOST.
*/
if (p->tstamp_type_count == 0)
return (PCAP_ERROR_CANTSET_TSTAMP_TYPE);
/*
* Check whether we claim to support this type of time stamp.
*/
for (i = 0; i < p->tstamp_type_count; i++) {
if ((int)p->tstamp_type_list[i] == tstamp_type) {
/*
* Yes.
*/
if (p->tstamp_type_count == 0) {
if (tstamp_type == PCAP_TSTAMP_HOST) {
p->opt.tstamp_type = tstamp_type;
return (0);
}
} else {
/*
* Check whether we claim to support this type of time stamp.
*/
for (i = 0; i < p->tstamp_type_count; i++) {
if (p->tstamp_type_list[i] == (u_int)tstamp_type) {
/*
* Yes.
*/
p->opt.tstamp_type = tstamp_type;
return (0);
}
}
}
/*
* No. We support setting the time stamp type, but not to this
* particular value.
* We don't support this type of time stamp.
*/
return (PCAP_WARNING_TSTAMP_TYPE_NOTSUP);
}
int
pcap_set_immediate_mode(pcap_t *p, int immediate)
{
if (pcap_check_activated(p))
return (PCAP_ERROR_ACTIVATED);
p->opt.immediate = immediate;
return (0);
}
int
pcap_set_buffer_size(pcap_t *p, int buffer_size)
{
@ -406,6 +666,54 @@ pcap_set_buffer_size(pcap_t *p, int buffer_size)
return (0);
}
int
pcap_set_tstamp_precision(pcap_t *p, int tstamp_precision)
{
int i;
if (pcap_check_activated(p))
return (PCAP_ERROR_ACTIVATED);
/*
* If p->tstamp_precision_count is 0, we only support setting
* the time stamp precision to microsecond precision; every
* pcap module *MUST* support microsecond precision, even if
* it does so by converting the native precision to
* microseconds.
*/
if (p->tstamp_precision_count == 0) {
if (tstamp_precision == PCAP_TSTAMP_PRECISION_MICRO) {
p->opt.tstamp_precision = tstamp_precision;
return (0);
}
} else {
/*
* Check whether we claim to support this precision of
* time stamp.
*/
for (i = 0; i < p->tstamp_precision_count; i++) {
if (p->tstamp_precision_list[i] == (u_int)tstamp_precision) {
/*
* Yes.
*/
p->opt.tstamp_precision = tstamp_precision;
return (0);
}
}
}
/*
* We don't support this time stamp precision.
*/
return (PCAP_ERROR_TSTAMP_PRECISION_NOTSUP);
}
int
pcap_get_tstamp_precision(pcap_t *p)
{
return (p->opt.tstamp_precision);
}
int
pcap_activate(pcap_t *p)
{
@ -493,6 +801,27 @@ fail:
return (NULL);
}
pcap_t *
pcap_open_offline_common(char *ebuf, size_t size)
{
pcap_t *p;
p = pcap_alloc_pcap_t(ebuf, size);
if (p == NULL)
return (NULL);
p->opt.tstamp_precision = PCAP_TSTAMP_PRECISION_MICRO;
p->opt.source = strdup("(savefile)");
if (p->opt.source == NULL) {
snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
pcap_strerror(errno));
free(p);
return (NULL);
}
return (p);
}
int
pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
@ -515,7 +844,7 @@ pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
register int n;
for (;;) {
if (p->sf.rfile != NULL) {
if (p->rfile != NULL) {
/*
* 0 means EOF, so don't loop if we get 0.
*/
@ -551,18 +880,24 @@ pcap_breakloop(pcap_t *p)
int
pcap_datalink(pcap_t *p)
{
if (!p->activated)
return (PCAP_ERROR_NOT_ACTIVATED);
return (p->linktype);
}
int
pcap_datalink_ext(pcap_t *p)
{
if (!p->activated)
return (PCAP_ERROR_NOT_ACTIVATED);
return (p->linktype_ext);
}
int
pcap_list_datalinks(pcap_t *p, int **dlt_buffer)
{
if (!p->activated)
return (PCAP_ERROR_NOT_ACTIVATED);
if (p->dlt_count == 0) {
/*
* We couldn't fetch the list of DLTs, which means
@ -574,7 +909,7 @@ pcap_list_datalinks(pcap_t *p, int **dlt_buffer)
if (*dlt_buffer == NULL) {
(void)snprintf(p->errbuf, sizeof(p->errbuf),
"malloc: %s", pcap_strerror(errno));
return (-1);
return (PCAP_ERROR);
}
**dlt_buffer = p->linktype;
return (1);
@ -583,7 +918,7 @@ pcap_list_datalinks(pcap_t *p, int **dlt_buffer)
if (*dlt_buffer == NULL) {
(void)snprintf(p->errbuf, sizeof(p->errbuf),
"malloc: %s", pcap_strerror(errno));
return (-1);
return (PCAP_ERROR);
}
(void)memcpy(*dlt_buffer, p->dlt_list,
sizeof(**dlt_buffer) * p->dlt_count);
@ -811,6 +1146,7 @@ static struct dlt_choice dlt_choices[] = {
DLT_CHOICE(DLT_LINUX_IRDA, "Linux IrDA"),
DLT_CHOICE(DLT_IEEE802_11_RADIO_AVS, "802.11 plus AVS radio information header"),
DLT_CHOICE(DLT_JUNIPER_MONITOR, "Juniper Passive Monitor PIC"),
DLT_CHOICE(DLT_BACNET_MS_TP, "BACnet MS/TP"),
DLT_CHOICE(DLT_PPP_PPPD, "PPP for pppd, with direction flag"),
DLT_CHOICE(DLT_JUNIPER_PPPOE, "Juniper PPPoE"),
DLT_CHOICE(DLT_JUNIPER_PPPOE_ATM, "Juniper PPPoE/ATM"),
@ -868,6 +1204,7 @@ static struct dlt_choice dlt_choices[] = {
DLT_CHOICE(DLT_NETANALYZER, "Ethernet with Hilscher netANALYZER pseudo-header"),
DLT_CHOICE(DLT_NETANALYZER_TRANSPARENT, "Ethernet with Hilscher netANALYZER pseudo-header and with preamble and SFD"),
DLT_CHOICE(DLT_IPOIB, "RFC 4391 IP-over-Infiniband"),
DLT_CHOICE(DLT_DBUS, "D-Bus"),
DLT_CHOICE_SENTINEL
};
@ -962,31 +1299,39 @@ pcap_tstamp_type_val_to_description(int tstamp_type)
int
pcap_snapshot(pcap_t *p)
{
if (!p->activated)
return (PCAP_ERROR_NOT_ACTIVATED);
return (p->snapshot);
}
int
pcap_is_swapped(pcap_t *p)
{
return (p->sf.swapped);
if (!p->activated)
return (PCAP_ERROR_NOT_ACTIVATED);
return (p->swapped);
}
int
pcap_major_version(pcap_t *p)
{
return (p->sf.version_major);
if (!p->activated)
return (PCAP_ERROR_NOT_ACTIVATED);
return (p->version_major);
}
int
pcap_minor_version(pcap_t *p)
{
return (p->sf.version_minor);
if (!p->activated)
return (PCAP_ERROR_NOT_ACTIVATED);
return (p->version_minor);
}
FILE *
pcap_file(pcap_t *p)
{
return (p->sf.rfile);
return (p->rfile);
}
int
@ -998,7 +1343,7 @@ pcap_fileno(pcap_t *p)
if (p->adapter != NULL)
return ((int)(DWORD)p->adapter->hFile);
else
return (-1);
return (PCAP_ERROR);
#endif
}
@ -1025,7 +1370,18 @@ pcap_geterr(pcap_t *p)
int
pcap_getnonblock(pcap_t *p, char *errbuf)
{
return (p->getnonblock_op(p, errbuf));
int ret;
ret = p->getnonblock_op(p, errbuf);
if (ret == -1) {
/*
* In case somebody depended on the bug wherein
* the error message was put into p->errbuf
* by pcap_getnonblock_fd().
*/
strlcpy(p->errbuf, errbuf, PCAP_ERRBUF_SIZE);
}
return (ret);
}
/*
@ -1043,7 +1399,7 @@ pcap_getnonblock_fd(pcap_t *p, char *errbuf)
fdflags = fcntl(p->fd, F_GETFL, 0);
if (fdflags == -1) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
snprintf(errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
pcap_strerror(errno));
return (-1);
}
@ -1057,7 +1413,18 @@ pcap_getnonblock_fd(pcap_t *p, char *errbuf)
int
pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf)
{
return (p->setnonblock_op(p, nonblock, errbuf));
int ret;
ret = p->setnonblock_op(p, nonblock, errbuf);
if (ret == -1) {
/*
* In case somebody depended on the bug wherein
* the error message was put into p->errbuf
* by pcap_setnonblock_fd().
*/
strlcpy(p->errbuf, errbuf, PCAP_ERRBUF_SIZE);
}
return (ret);
}
#if !defined(WIN32) && !defined(MSDOS)
@ -1074,7 +1441,7 @@ pcap_setnonblock_fd(pcap_t *p, int nonblock, char *errbuf)
fdflags = fcntl(p->fd, F_GETFL, 0);
if (fdflags == -1) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
snprintf(errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
pcap_strerror(errno));
return (-1);
}
@ -1083,7 +1450,7 @@ pcap_setnonblock_fd(pcap_t *p, int nonblock, char *errbuf)
else
fdflags &= ~O_NONBLOCK;
if (fcntl(p->fd, F_SETFL, fdflags) == -1) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_SETFL: %s",
snprintf(errbuf, PCAP_ERRBUF_SIZE, "F_SETFL: %s",
pcap_strerror(errno));
return (-1);
}
@ -1175,6 +1542,9 @@ pcap_statustostr(int errnum)
case PCAP_ERROR_PROMISC_PERM_DENIED:
return ("You don't have permission to capture in promiscuous mode on that device");
case PCAP_ERROR_TSTAMP_PRECISION_NOTSUP:
return ("That device doesn't support that time stamp precision");
}
(void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum);
return(ebuf);
@ -1272,6 +1642,12 @@ pcap_setmintocopy(pcap_t *p, int size)
return (p->setmintocopy_op(p, size));
}
Adapter *
pcap_get_adapter(pcap_t *p)
{
return (p->getadapter_op(p));
}
static int
pcap_setmintocopy_dead(pcap_t *p, int size)
{
@ -1339,7 +1715,7 @@ pcap_do_addexit(pcap_t *p)
void
pcap_add_to_pcaps_to_close(pcap_t *p)
{
p->md.next = pcaps_to_close;
p->next = pcaps_to_close;
pcaps_to_close = p;
}
@ -1349,7 +1725,7 @@ pcap_remove_from_pcaps_to_close(pcap_t *p)
pcap_t *pc, *prevpc;
for (pc = pcaps_to_close, prevpc = NULL; pc != NULL;
prevpc = pc, pc = pc->md.next) {
prevpc = pc, pc = pc->next) {
if (pc == p) {
/*
* Found it. Remove it from the list.
@ -1358,12 +1734,12 @@ pcap_remove_from_pcaps_to_close(pcap_t *p)
/*
* It was at the head of the list.
*/
pcaps_to_close = pc->md.next;
pcaps_to_close = pc->next;
} else {
/*
* It was in the middle of the list.
*/
prevpc->md.next = pc->md.next;
prevpc->next = pc->next;
}
break;
}
@ -1387,6 +1763,11 @@ pcap_cleanup_live_common(pcap_t *p)
p->tstamp_type_list = NULL;
p->tstamp_type_count = 0;
}
if (p->tstamp_precision_list != NULL) {
free(p->tstamp_precision_list);
p->tstamp_precision_list = NULL;
p->tstamp_precision_count = 0;
}
pcap_freecode(&p->fcode);
#if !defined(WIN32) && !defined(MSDOS)
if (p->fd >= 0) {
@ -1394,7 +1775,6 @@ pcap_cleanup_live_common(pcap_t *p)
p->fd = -1;
}
p->selectable_fd = -1;
p->send_fd = -1;
#endif
}
@ -1405,16 +1785,26 @@ pcap_cleanup_dead(pcap_t *p _U_)
}
pcap_t *
pcap_open_dead(int linktype, int snaplen)
pcap_open_dead_with_tstamp_precision(int linktype, int snaplen, u_int precision)
{
pcap_t *p;
switch (precision) {
case PCAP_TSTAMP_PRECISION_MICRO:
case PCAP_TSTAMP_PRECISION_NANO:
break;
default:
return NULL;
}
p = malloc(sizeof(*p));
if (p == NULL)
return NULL;
memset (p, 0, sizeof(*p));
p->snapshot = snaplen;
p->linktype = linktype;
p->opt.tstamp_precision = precision;
p->stats_op = pcap_stats_dead;
#ifdef WIN32
p->setbuff_op = pcap_setbuff_dead;
@ -1426,6 +1816,13 @@ pcap_open_dead(int linktype, int snaplen)
return (p);
}
pcap_t *
pcap_open_dead(int linktype, int snaplen)
{
return (pcap_open_dead_with_tstamp_precision(linktype, snaplen,
PCAP_TSTAMP_PRECISION_MICRO));
}
/*
* API compatible with WinPcap's "send a packet" routine - returns -1
* on error, 0 otherwise.
@ -1466,10 +1863,10 @@ pcap_close(pcap_t *p)
* the packet doesn't pass and non-zero if the packet does pass.
*/
int
pcap_offline_filter(struct bpf_program *fp, const struct pcap_pkthdr *h,
pcap_offline_filter(const struct bpf_program *fp, const struct pcap_pkthdr *h,
const u_char *pkt)
{
struct bpf_insn *fcode = fp->bf_insns;
const struct bpf_insn *fcode = fp->bf_insns;
if (fcode != NULL)
return (bpf_filter(fcode, pkt, h->len, h->caplen));
@ -1531,6 +1928,8 @@ pcap_lib_version(void)
strlen(pcap_version_string);
full_pcap_version_string =
malloc(full_pcap_version_string_len);
if (full_pcap_version_string == NULL)
return (NULL);
sprintf(full_pcap_version_string,
pcap_version_string_fmt, wpcap_version_string,
pcap_version_string);
@ -1548,7 +1947,8 @@ pcap_lib_version(void)
strlen(packet_version_string) +
strlen(pcap_version_string);
full_pcap_version_string = malloc(full_pcap_version_string_len);
if (full_pcap_version_string == NULL)
return (NULL);
sprintf(full_pcap_version_string,
pcap_version_string_packet_dll_fmt,
wpcap_version_string, packet_version_string,
@ -1577,6 +1977,8 @@ pcap_lib_version (void)
sizeof dospfx + strlen(pcap_version_string);
full_pcap_version_string =
malloc(full_pcap_version_string_len);
if (full_pcap_version_string == NULL)
return (NULL);
strcpy(full_pcap_version_string, dospfx);
strcat(full_pcap_version_string, pcap_version_string);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: bpf.h,v 1.4 2013/04/06 17:29:53 christos Exp $ */
/* $NetBSD: bpf.h,v 1.5 2013/12/31 17:08:23 christos Exp $ */
/*-
* Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
@ -1138,7 +1138,7 @@ struct bpf_program {
#define DLT_NETANALYZER_TRANSPARENT 241
/*
* IP-over-Infiniband, as specified by RFC 4391.
* IP-over-InfiniBand, as specified by RFC 4391.
*
* Requested by Petr Sumbera <petr.sumbera@oracle.com>.
*/
@ -1180,7 +1180,56 @@ struct bpf_program {
#define DLT_PFSYNC 246
#endif
#define DLT_MATCHING_MAX 246 /* highest value in the "matching" range */
/*
* Raw InfiniBand packets, starting with the Local Routing Header.
*
* Requested by Oren Kladnitsky <orenk@mellanox.com>.
*/
#define DLT_INFINIBAND 247
/*
* SCTP, with no lower-level protocols (i.e., no IPv4 or IPv6).
*
* Requested by Michael Tuexen <Michael.Tuexen@lurchi.franken.de>.
*/
#define DLT_SCTP 248
/*
* USB packets, beginning with a USBPcap header.
*
* Requested by Tomasz Mon <desowin@gmail.com>
*/
#define DLT_USBPCAP 249
/*
* Schweitzer Engineering Laboratories "RTAC" product serial-line
* packets.
*
* Requested by Chris Bontje <chris_bontje@selinc.com>.
*/
#define DLT_RTAC_SERIAL 250
/*
* Bluetooth Low Energy air interface link-layer packets.
*
* Requested by Mike Kershaw <dragorn@kismetwireless.net>.
*/
#define DLT_BLUETOOTH_LE_LL 251
/*
* DLT type for upper-protocol layer PDU saves from wireshark.
*
* the actual contents are determined by two TAGs stored with each
* packet:
* EXP_PDU_TAG_LINKTYPE the link type (LINKTYPE_ value) of the
* original packet.
*
* EXP_PDU_TAG_PROTO_NAME the name of the wireshark dissector
* that can make sense of the data stored.
*/
#define DLT_WIRESHARK_UPPER_PDU 252
#define DLT_MATCHING_MAX 252 /* highest value in the "matching" range */
/*
* DLT and savefile link type values are split into a class and

View File

@ -1,4 +1,4 @@
/* $NetBSD: pcap.h,v 1.3 2013/04/06 17:29:53 christos Exp $ */
/* $NetBSD: pcap.h,v 1.4 2013/12/31 17:08:23 christos Exp $ */
/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
/*
@ -117,12 +117,13 @@ typedef struct pcap_addr pcap_addr_t;
* the old file header as well as files with the new file header
* (using the magic number to determine the header format).
*
* Then supply the changes as a patch at
* Then supply the changes by forking the branch at
*
* http://sourceforge.net/projects/libpcap/
* https://github.com/the-tcpdump-group/libpcap/issues
*
* so that future versions of libpcap and programs that use it (such as
* tcpdump) will be able to read your new capture file format.
* and issuing a pull request, so that future versions of libpcap and
* programs that use it (such as tcpdump) will be able to read your new
* capture file format.
*/
struct pcap_file_header {
bpf_u_int32 magic;
@ -257,6 +258,7 @@ typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,
#define PCAP_ERROR_IFACE_NOT_UP -9 /* interface isn't up */
#define PCAP_ERROR_CANTSET_TSTAMP_TYPE -10 /* this device doesn't support setting the time stamp type */
#define PCAP_ERROR_PROMISC_PERM_DENIED -11 /* you don't have permission to capture in promiscuous mode */
#define PCAP_ERROR_TSTAMP_PRECISION_NOTSUP -12 /* the requested time stamp precision is not supported */
/*
* Warning codes for the pcap API.
@ -283,7 +285,10 @@ int pcap_can_set_rfmon(pcap_t *);
int pcap_set_rfmon(pcap_t *, int);
int pcap_set_timeout(pcap_t *, int);
int pcap_set_tstamp_type(pcap_t *, int);
int pcap_set_immediate_mode(pcap_t *, int);
int pcap_set_buffer_size(pcap_t *, int);
int pcap_set_tstamp_precision(pcap_t *, int);
int pcap_get_tstamp_precision(pcap_t *);
int pcap_activate(pcap_t *);
int pcap_list_tstamp_types(pcap_t *, int **);
@ -336,18 +341,34 @@ const char *pcap_tstamp_type_val_to_description(int);
#define PCAP_TSTAMP_ADAPTER 3 /* device-provided, synced with the system clock */
#define PCAP_TSTAMP_ADAPTER_UNSYNCED 4 /* device-provided, not synced with the system clock */
/*
* Time stamp resolution types.
* Not all systems and interfaces will necessarily support all of these
* resolutions when doing live captures; all of them can be requested
* when reading a savefile.
*/
#define PCAP_TSTAMP_PRECISION_MICRO 0 /* use timestamps with microsecond precision, default */
#define PCAP_TSTAMP_PRECISION_NANO 1 /* use timestamps with nanosecond precision */
pcap_t *pcap_open_live(const char *, int, int, int, char *);
pcap_t *pcap_open_dead(int, int);
pcap_t *pcap_open_dead_with_tstamp_precision(int, int, u_int);
pcap_t *pcap_open_offline_with_tstamp_precision(const char *, u_int, char *);
pcap_t *pcap_open_offline(const char *, char *);
#if defined(WIN32)
pcap_t *pcap_hopen_offline_with_tstamp_precision(intptr_t, u_int, char *);
pcap_t *pcap_hopen_offline(intptr_t, char *);
#if !defined(LIBPCAP_EXPORTS)
#define pcap_fopen_offline_with_tstamp_precision(f,p,b) \
pcap_hopen_offline_with_tstamp_precision(_get_osfhandle(_fileno(f)), p, b)
#define pcap_fopen_offline(f,b) \
pcap_hopen_offline(_get_osfhandle(_fileno(f)), b)
#else /*LIBPCAP_EXPORTS*/
static pcap_t *pcap_fopen_offline_with_tstamp_precision(FILE *, u_int, char *);
static pcap_t *pcap_fopen_offline(FILE *, char *);
#endif
#else /*WIN32*/
pcap_t *pcap_fopen_offline_with_tstamp_precision(FILE *, u_int, char *);
pcap_t *pcap_fopen_offline(FILE *, char *);
#endif /*WIN32*/
@ -374,8 +395,8 @@ int pcap_compile(pcap_t *, struct bpf_program *, const char *, int,
int pcap_compile_nopcap(int, int, struct bpf_program *,
const char *, int, bpf_u_int32);
void pcap_freecode(struct bpf_program *);
int pcap_offline_filter(struct bpf_program *, const struct pcap_pkthdr *,
const u_char *);
int pcap_offline_filter(const struct bpf_program *,
const struct pcap_pkthdr *, const u_char *);
int pcap_datalink(pcap_t *);
int pcap_datalink_ext(pcap_t *);
int pcap_list_datalinks(pcap_t *, int **);
@ -429,6 +450,7 @@ void bpf_dump(const struct bpf_program *, int);
int pcap_setbuff(pcap_t *p, int dim);
int pcap_setmode(pcap_t *p, int mode);
int pcap_setmintocopy(pcap_t *p, int size);
Adapter *pcap_get_adapter(pcap_t *p);
#ifdef WPCAP
/* Include file with the wpcap-specific extensions */

View File

@ -19,9 +19,10 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
.TH PCAP_OPEN_OFFLINE 3PCAP "5 April 2008"
.TH PCAP_OPEN_OFFLINE 3PCAP "1 July 2013"
.SH NAME
pcap_open_offline, pcap_fopen_offline \- open a saved capture file for reading
pcap_open_offline, pcap_open_offline_with_tstamp_precision,
pcap_fopen_offline, pcap_fopen_offline_with_tstamp_precision \- open a saved capture file for reading
.SH SYNOPSIS
.nf
.ft B
@ -35,12 +36,18 @@ char errbuf[PCAP_ERRBUF_SIZE];
.LP
.ft B
pcap_t *pcap_open_offline(const char *fname, char *errbuf);
pcap_t *pcap_open_offline_with_tstamp_precision(const char *fname,
u_int precision, char *errbuf);
pcap_t *pcap_fopen_offline(FILE *fp, char *errbuf);
pcap_t *pcap_fopen_offline_with_tstamp_precision(FILE *fp,
u_int precision, char *errbuf);
.ft
.fi
.SH DESCRIPTION
.B pcap_open_offline()
is called to open a ``savefile'' for reading.
and
.B pcap_open_offline_with_tstamp_precision()
are called to open a ``savefile'' for reading.
.PP
.I fname
specifies the name of the file to open. The file can have the pcap file
@ -55,15 +62,37 @@ be read.
The name "-" in a synonym for
.BR stdin .
.PP
.B pcap_open_offline_with_tstamp_precision()
takes an additional
.I precision
argument specifying the time stamp precision desired;
if
.B PCAP_TSTAMP_PRECISION_MICRO
is specified, packet time stamps will be supplied in seconds and
microseconds,
and if
.B PCAP_TSTAMP_PRECISION_NANO
is specified, packet time stamps will be supplied in seconds and
nanoseconds. If the time stamps in the file do not have the same
precision as the requested precision, they will be scaled up or down as
necessary before being supplied.
.PP
Alternatively, you may call
.B pcap_fopen_offline()
or
.B pcap_fopen_offline_with_tstamp_precision()
to read dumped data from an existing open stream
.IR fp .
.B pcap_fopen_offline_with_tstamp_precision() takes an additional
.I precision
argument as described above.
Note that on Windows, that stream should be opened in binary mode.
.SH RETURN VALUE
.B pcap_open_offline()
.BR pcap_open_offline() ,
.BR pcap_open_offline_with_tstamp_precision() ,
.BR pcap_fopen_offline() ,
and
.B pcap_fopen_offline()
.B pcap_fopen_offline_with_tstamp_precision()
return a
.I pcap_t *
on success and

View File

@ -1,4 +1,4 @@
/* $NetBSD: scanner.l,v 1.4 2013/04/06 17:29:53 christos Exp $ */
/* $NetBSD: scanner.l,v 1.5 2013/12/31 17:08:23 christos Exp $ */
%{
/*
@ -210,20 +210,8 @@ vrrp return VRRP;
carp return CARP;
radio return RADIO;
ip6 {
#ifdef INET6
return IPV6;
#else
bpf_error("%s not supported", yytext);
#endif
}
icmp6 {
#ifdef INET6
return ICMPV6;
#else
bpf_error("%s not supported", yytext);
#endif
}
ip6 return IPV6;
icmp6 return ICMPV6;
ah return AH;
esp return ESP;
@ -327,10 +315,17 @@ fisu return FISU;
lssu return LSSU;
lsu return LSSU;
msu return MSU;
hfisu return HFISU;
hlssu return HLSSU;
hmsu return HMSU;
sio return SIO;
opc return OPC;
dpc return DPC;
sls return SLS;
hsio return HSIO;
hopc return HOPC;
hdpc return HDPC;
hsls return HSLS;
[ \r\n\t] ;
[+\-*/:\[\]!<>()&|=] return yytext[0];
@ -341,8 +336,12 @@ sls return SLS;
"<<" return LSH;
">>" return RSH;
${B} { yylval.e = pcap_ether_aton(((char *)yytext)+1);
if (yylval.e == NULL)
bpf_error("malloc");
return AID; }
{MAC} { yylval.e = pcap_ether_aton((char *)yytext);
if (yylval.e == NULL)
bpf_error("malloc");
return EID; }
{N} { yylval.i = stoi((char *)yytext); return NUM; }
({N}\.{N})|({N}\.{N}\.{N})|({N}\.{N}\.{N}\.{N}) {

View File

@ -1,4 +1,4 @@
/* $NetBSD: sf-pcap-ng.c,v 1.3 2013/04/06 17:29:53 christos Exp $ */
/* $NetBSD: sf-pcap-ng.c,v 1.4 2013/12/31 17:08:23 christos Exp $ */
/*
* Copyright (c) 1993, 1994, 1995, 1996, 1997
@ -203,6 +203,29 @@ struct block_cursor {
bpf_u_int32 block_type;
};
typedef enum {
PASS_THROUGH,
SCALE_UP,
SCALE_DOWN
} tstamp_scale_type_t;
/*
* Per-interface information.
*/
struct pcap_ng_if {
u_int tsresol; /* time stamp resolution */
u_int64_t tsoffset; /* time stamp offset */
tstamp_scale_type_t scale_type; /* how to scale */
};
struct pcap_ng_sf {
u_int user_tsresol; /* time stamp resolution requested by the user */
bpf_u_int32 ifcount; /* number of interfaces seen in this capture */
bpf_u_int32 ifaces_size; /* size of arrary below */
struct pcap_ng_if *ifaces; /* array of interface information */
};
static void pcap_ng_cleanup(pcap_t *p);
static int pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr,
u_char **data);
@ -241,7 +264,7 @@ read_block(FILE *fp, pcap_t *p, struct block_cursor *cursor, char *errbuf)
if (status <= 0)
return (status); /* error or EOF */
if (p->sf.swapped) {
if (p->swapped) {
bhdr.block_type = SWAPLONG(bhdr.block_type);
bhdr.total_length = SWAPLONG(bhdr.total_length);
}
@ -348,7 +371,7 @@ get_opthdr_from_block_data(pcap_t *p, struct block_cursor *cursor, char *errbuf)
/*
* Byte-swap it if necessary.
*/
if (p->sf.swapped) {
if (p->swapped) {
opthdr->option_code = SWAPSHORT(opthdr->option_code);
opthdr->option_length = SWAPSHORT((uint32_t)opthdr->option_length);
}
@ -483,7 +506,7 @@ process_idb_options(pcap_t *p, struct block_cursor *cursor, u_int *tsresol,
}
saw_tsoffset = 1;
memcpy(tsoffset, optvalue, sizeof(*tsoffset));
if (p->sf.swapped)
if (p->swapped)
*tsoffset = (uint64_t)SWAPLL(*tsoffset);
break;
@ -496,22 +519,151 @@ done:
return (0);
}
static int
add_interface(pcap_t *p, struct block_cursor *cursor, char *errbuf)
{
struct pcap_ng_sf *ps;
u_int tsresol;
u_int64_t tsoffset;
ps = p->priv;
/*
* Count this interface.
*/
ps->ifcount++;
/*
* Grow the array of per-interface information as necessary.
*/
if (ps->ifcount > ps->ifaces_size) {
/*
* We need to grow the array.
*/
if (ps->ifaces == NULL) {
/*
* It's currently empty.
*/
ps->ifaces_size = 1;
ps->ifaces = malloc(sizeof (struct pcap_ng_if));
} else {
/*
* It's not currently empty; double its size.
* (Perhaps overkill once we have a lot of interfaces.)
*/
ps->ifaces_size *= 2;
ps->ifaces = realloc(ps->ifaces, ps->ifaces_size * sizeof (struct pcap_ng_if));
}
if (ps->ifaces == NULL) {
/*
* We ran out of memory.
* Give up.
*/
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"out of memory for per-interface information (%u interfaces)",
ps->ifcount);
return (0);
}
}
/*
* Set the default time stamp resolution and offset.
*/
tsresol = 1000000; /* microsecond resolution */
tsoffset = 0; /* absolute timestamps */
/*
* Now look for various time stamp options, so we know
* how to interpret the time stamps for this interface.
*/
if (process_idb_options(p, cursor, &tsresol, &tsoffset, errbuf) == -1)
return (0);
ps->ifaces[ps->ifcount - 1].tsresol = tsresol;
ps->ifaces[ps->ifcount - 1].tsoffset = tsoffset;
/*
* Determine whether we're scaling up or down or not
* at all for this interface.
*/
switch (p->opt.tstamp_precision) {
case PCAP_TSTAMP_PRECISION_MICRO:
if (tsresol == 1000000) {
/*
* The resolution is 1 microsecond,
* so we don't have to do scaling.
*/
ps->ifaces[ps->ifcount - 1].scale_type = PASS_THROUGH;
} else if (tsresol > 1000000) {
/*
* The resolution is greater than
* 1 microsecond, so we have to
* scale the timestamps down.
*/
ps->ifaces[ps->ifcount - 1].scale_type = SCALE_DOWN;
} else {
/*
* The resolution is less than 1
* microsecond, so we have to scale
* the timestamps up.
*/
ps->ifaces[ps->ifcount - 1].scale_type = SCALE_UP;
}
break;
case PCAP_TSTAMP_PRECISION_NANO:
if (tsresol == 1000000000) {
/*
* The resolution is 1 nanosecond,
* so we don't have to do scaling.
*/
ps->ifaces[ps->ifcount - 1].scale_type = PASS_THROUGH;
} else if (tsresol > 1000000000) {
/*
* The resolution is greater than
* 1 nanosecond, so we have to
* scale the timestamps down.
*/
ps->ifaces[ps->ifcount - 1].scale_type = SCALE_DOWN;
} else {
/*
* The resolution is less than 1
* nanosecond, so we have to scale
* the timestamps up.
*/
ps->ifaces[ps->ifcount - 1].scale_type = SCALE_UP;
}
break;
}
return (1);
}
/*
* Check whether this is a pcap-ng savefile and, if it is, extract the
* relevant information from the header.
*/
int
pcap_ng_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
pcap_t *
pcap_ng_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
int *err)
{
size_t amt_read;
bpf_u_int32 total_length;
bpf_u_int32 byte_order_magic;
struct block_header *bhdrp;
struct section_header_block *shbp;
pcap_t *p;
int swapped = 0;
struct pcap_ng_sf *ps;
int status;
struct block_cursor cursor;
struct interface_description_block *idbp;
/*
* Assume no read errors.
*/
*err = 0;
/*
* Check whether the first 4 bytes of the file are the block
* type for a pcap-ng savefile.
@ -526,7 +678,7 @@ pcap_ng_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
* this as possibly being a pcap-ng file transferred
* between UN*X and Windows in text file format?
*/
return (0); /* nope */
return (NULL); /* nope */
}
/*
@ -546,14 +698,15 @@ pcap_ng_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"error reading dump file: %s",
pcap_strerror(errno));
return (-1); /* fail */
*err = 1;
return (NULL); /* fail */
}
/*
* Possibly a weird short text file, so just say
* "not pcap-ng".
*/
return (0);
return (NULL);
}
amt_read = fread(&byte_order_magic, 1, sizeof(byte_order_magic), fp);
if (amt_read < sizeof(byte_order_magic)) {
@ -561,14 +714,15 @@ pcap_ng_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"error reading dump file: %s",
pcap_strerror(errno));
return (-1); /* fail */
*err = 1;
return (NULL); /* fail */
}
/*
* Possibly a weird short text file, so just say
* "not pcap-ng".
*/
return (0);
return (NULL);
}
if (byte_order_magic != BYTE_ORDER_MAGIC) {
byte_order_magic = SWAPLONG(byte_order_magic);
@ -576,9 +730,9 @@ pcap_ng_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
/*
* Not a pcap-ng file.
*/
return (0);
return (NULL);
}
p->sf.swapped = 1;
swapped = 1;
total_length = SWAPLONG(total_length);
}
@ -590,9 +744,46 @@ pcap_ng_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
"Section Header Block in pcap-ng dump file has a length of %u < %lu",
total_length,
(unsigned long)(sizeof(*bhdrp) + sizeof(*shbp) + sizeof(struct block_trailer)));
return (-1);
*err = 1;
return (NULL);
}
/*
* OK, this is a good pcap-ng file.
* Allocate a pcap_t for it.
*/
p = pcap_open_offline_common(errbuf, sizeof (struct pcap_ng_sf));
if (p == NULL) {
/* Allocation failed. */
*err = 1;
return (NULL);
}
p->swapped = swapped;
ps = p->priv;
/*
* What precision does the user want?
*/
switch (precision) {
case PCAP_TSTAMP_PRECISION_MICRO:
ps->user_tsresol = 1000000;
break;
case PCAP_TSTAMP_PRECISION_NANO:
ps->user_tsresol = 1000000000;
break;
default:
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"unknown time stamp resolution %u", precision);
free(p);
*err = 1;
return (NULL);
}
p->opt.tstamp_precision = precision;
/*
* Allocate a buffer into which to read blocks. We default to
* the maximum of:
@ -611,7 +802,9 @@ pcap_ng_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
p->buffer = malloc(p->bufsize);
if (p->buffer == NULL) {
snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
return (-1);
free(p);
*err = 1;
return (NULL);
}
/*
@ -629,7 +822,7 @@ pcap_ng_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
1, errbuf) == -1)
goto fail;
if (p->sf.swapped) {
if (p->swapped) {
/*
* Byte-swap the fields we've read.
*/
@ -646,15 +839,13 @@ pcap_ng_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
shbp->major_version);
goto fail;
}
p->sf.version_major = shbp->major_version;
p->sf.version_minor = shbp->minor_version;
p->version_major = shbp->major_version;
p->version_minor = shbp->minor_version;
/*
* Set the default time stamp resolution and offset.
* Save the time stamp resolution the user requested.
*/
p->sf.tsresol = 1000000; /* microsecond resolution */
p->sf.tsscale = 1; /* multiply by 1 to scale to microseconds */
p->sf.tsoffset = 0; /* absolute timestamps */
p->opt.tstamp_precision = precision;
/*
* Now start looking for an Interface Description Block.
@ -666,7 +857,7 @@ pcap_ng_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
status = read_block(fp, p, &cursor, errbuf);
if (status == 0) {
/* EOF - no IDB in this file */
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"the capture file has no Interface Description Blocks");
goto fail;
}
@ -687,42 +878,16 @@ pcap_ng_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
/*
* Byte-swap it if necessary.
*/
if (p->sf.swapped) {
if (p->swapped) {
idbp->linktype = SWAPSHORT((uint16_t)idbp->linktype);
idbp->snaplen = SWAPLONG(idbp->snaplen);
}
/*
* Count this interface.
* Try to add this interface.
*/
p->sf.ifcount++;
/*
* Now look for various time stamp options, so
* we know how to interpret the time stamps.
*/
if (process_idb_options(p, &cursor, &p->sf.tsresol,
&p->sf.tsoffset, errbuf) == -1)
if (!add_interface(p, &cursor, errbuf))
goto fail;
/*
* Compute the scaling factor to convert the
* sub-second part of the time stamp to
* microseconds.
*/
if (p->sf.tsresol > 1000000) {
/*
* Higher than microsecond resolution;
* scale down to microseconds.
*/
p->sf.tsscale = (p->sf.tsresol / 1000000);
} else {
/*
* Lower than microsecond resolution;
* scale up to microseconds.
*/
p->sf.tsscale = (1000000 / p->sf.tsresol);
}
goto done;
case BT_EPB:
@ -733,7 +898,7 @@ pcap_ng_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
* not valid, as we don't know what link-layer
* encapsulation the packet has.
*/
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"the capture file has a packet block before any Interface Description Blocks");
goto fail;
@ -751,13 +916,26 @@ done:
p->linktype = linktype_to_dlt(idbp->linktype);
p->linktype_ext = 0;
p->sf.next_packet_op = pcap_ng_next_packet;
p->next_packet_op = pcap_ng_next_packet;
p->cleanup_op = pcap_ng_cleanup;
return (1);
return (p);
fail:
free(ps->ifaces);
free(p->buffer);
return (-1);
free(p);
*err = 1;
return (NULL);
}
static void
pcap_ng_cleanup(pcap_t *p)
{
struct pcap_ng_sf *ps = p->priv;
free(ps->ifaces);
sf_cleanup(p);
}
/*
@ -768,6 +946,7 @@ fail:
static int
pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
{
struct pcap_ng_sf *ps = p->priv;
struct block_cursor cursor;
int status;
struct enhanced_packet_block *epbp;
@ -776,9 +955,7 @@ pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
bpf_u_int32 interface_id = 0xFFFFFFFF;
struct interface_description_block *idbp;
struct section_header_block *shbp;
FILE *fp = p->sf.rfile;
u_int tsresol;
u_int64_t tsoffset;
FILE *fp = p->rfile;
u_int64_t t, sec, frac;
/*
@ -810,7 +987,7 @@ pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
/*
* Byte-swap it if necessary.
*/
if (p->sf.swapped) {
if (p->swapped) {
/* these were written in opposite byte order */
interface_id = SWAPLONG(epbp->interface_id);
hdr->caplen = SWAPLONG(epbp->caplen);
@ -845,7 +1022,7 @@ pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
/*
* Byte-swap it if necessary.
*/
if (p->sf.swapped) {
if (p->swapped) {
/* these were written in opposite byte order */
hdr->len = SWAPLONG(spbp->len);
} else
@ -875,7 +1052,7 @@ pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
/*
* Byte-swap it if necessary.
*/
if (p->sf.swapped) {
if (p->swapped) {
/* these were written in opposite byte order */
interface_id = SWAPSHORT((uint32_t)pbp->interface_id);
hdr->caplen = SWAPLONG(pbp->caplen);
@ -904,7 +1081,7 @@ pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
/*
* Byte-swap it if necessary.
*/
if (p->sf.swapped) {
if (p->swapped) {
idbp->linktype = SWAPSHORT((uint32_t)idbp->linktype);
idbp->snaplen = SWAPLONG(idbp->snaplen);
}
@ -931,37 +1108,10 @@ pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
}
/*
* Count this interface.
* Try to add this interface.
*/
p->sf.ifcount++;
/*
* Set the default time stamp resolution and offset.
*/
tsresol = 1000000; /* microsecond resolution */
tsoffset = 0; /* absolute timestamps */
/*
* Now look for various time stamp options, to
* make sure they're the same.
*
* XXX - we could, in theory, handle multiple
* different resolutions and offsets, but we
* don't do so for now.
*/
if (process_idb_options(p, &cursor, &tsresol, &tsoffset,
p->errbuf) == -1)
if (!add_interface(p, &cursor, p->errbuf))
return (-1);
if (tsresol != p->sf.tsresol) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"an interface has a time stamp resolution different from the time stamp resolution of the first interface");
return (-1);
}
if (tsoffset != p->sf.tsoffset) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"an interface has a time stamp offset different from the time stamp offset of the first interface");
return (-1);
}
break;
case BT_SHB:
@ -979,7 +1129,7 @@ pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
* the same as that of the previous section.
* We'll check for that later.
*/
if (p->sf.swapped) {
if (p->swapped) {
shbp->byte_order_magic =
SWAPLONG(shbp->byte_order_magic);
shbp->major_version =
@ -1036,7 +1186,7 @@ pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
* any IDBs, we'll fail when we see a packet
* block.)
*/
p->sf.ifcount = 0;
ps->ifcount = 0;
break;
default:
@ -1051,7 +1201,7 @@ found:
/*
* Is the interface ID an interface we know?
*/
if (interface_id >= p->sf.ifcount) {
if (interface_id >= ps->ifcount) {
/*
* Yes. Fail.
*/
@ -1064,20 +1214,52 @@ found:
/*
* Convert the time stamp to a struct timeval.
*/
sec = t / p->sf.tsresol + p->sf.tsoffset;
frac = t % p->sf.tsresol;
if (p->sf.tsresol > 1000000) {
sec = t / ps->ifaces[interface_id].tsresol + ps->ifaces[interface_id].tsoffset;
frac = t % ps->ifaces[interface_id].tsresol;
switch (ps->ifaces[interface_id].scale_type) {
case PASS_THROUGH:
/*
* Higher than microsecond resolution; scale down to
* microseconds.
* The interface resolution is what the user wants,
* so we're done.
*/
frac /= p->sf.tsscale;
} else {
break;
case SCALE_UP:
/*
* Lower than microsecond resolution; scale up to
* microseconds.
* The interface resolution is less than what the user
* wants; scale up to that resolution.
*
* XXX - if ps->ifaces[interface_id].tsresol is a power
* of 10, we could just multiply by the quotient of
* ps->ifaces[interface_id].tsresol and ps->user_tsresol,
* as we know that's an integer. That runs less risk of
* overflow.
*
* Is there something clever we could do if
* ps->ifaces[interface_id].tsresol is a power of 2?
*/
frac *= p->sf.tsscale;
frac *= ps->ifaces[interface_id].tsresol;
frac /= ps->user_tsresol;
break;
case SCALE_DOWN:
/*
* The interface resolution is greater than what the user
* wants; scale down to that resolution.
*
* XXX - if ps->ifaces[interface_id].tsresol is a power
* of 10, we could just divide by the quotient of
* ps->user_tsresol and ps->ifaces[interface_id].tsresol,
* as we know that's an integer. That runs less risk of
* overflow.
*
* Is there something clever we could do if
* ps->ifaces[interface_id].tsresol is a power of 2?
*/
frac *= ps->user_tsresol;
frac /= ps->ifaces[interface_id].tsresol;
break;
}
hdr->ts.tv_sec = sec;
hdr->ts.tv_usec = (suseconds_t)frac;
@ -1089,7 +1271,7 @@ found:
if (*data == NULL)
return (-1);
if (p->sf.swapped) {
if (p->swapped) {
/*
* Convert pseudo-headers from the byte order of
* the host on which the file was saved to our

View File

@ -1,4 +1,4 @@
/* $NetBSD: sf-pcap.c,v 1.3 2013/04/06 17:29:53 christos Exp $ */
/* $NetBSD: sf-pcap.c,v 1.4 2013/12/31 17:08:23 christos Exp $ */
/*
* Copyright (c) 1993, 1994, 1995, 1996, 1997
@ -124,26 +124,58 @@ static const char rcsid[] _U_ =
static int pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **datap);
/*
* Private data for reading pcap savefiles.
*/
typedef enum {
NOT_SWAPPED,
SWAPPED,
MAYBE_SWAPPED
} swapped_type_t;
typedef enum {
PASS_THROUGH,
SCALE_UP,
SCALE_DOWN
} tstamp_scale_type_t;
struct pcap_sf {
size_t hdrsize;
swapped_type_t lengths_swapped;
tstamp_scale_type_t scale_type;
};
/*
* Check whether this is a pcap savefile and, if it is, extract the
* relevant information from the header.
*/
int
pcap_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
pcap_t *
pcap_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
int *err)
{
struct pcap_file_header hdr;
size_t amt_read;
pcap_t *p;
int swapped = 0;
struct pcap_sf *ps;
/*
* Assume no read errors.
*/
*err = 0;
/*
* Check whether the first 4 bytes of the file are the magic
* number for a pcap savefile, or for a byte-swapped pcap
* savefile.
*/
if (magic != TCPDUMP_MAGIC && magic != KUZNETZOV_TCPDUMP_MAGIC) {
if (magic != TCPDUMP_MAGIC && magic != KUZNETZOV_TCPDUMP_MAGIC &&
magic != NSEC_TCPDUMP_MAGIC) {
magic = SWAPLONG(magic);
if (magic != TCPDUMP_MAGIC && magic != KUZNETZOV_TCPDUMP_MAGIC)
return (0); /* nope */
p->sf.swapped = 1;
if (magic != TCPDUMP_MAGIC && magic != KUZNETZOV_TCPDUMP_MAGIC &&
magic != NSEC_TCPDUMP_MAGIC)
return (NULL); /* nope */
swapped = 1;
}
/*
@ -164,13 +196,14 @@ pcap_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
(unsigned long)sizeof(hdr),
(unsigned long)amt_read);
}
return (-1);
*err = 1;
return (NULL);
}
/*
* If it's a byte-swapped capture file, byte-swap the header.
*/
if (p->sf.swapped) {
if (swapped) {
hdr.version_major = SWAPSHORT(hdr.version_major);
hdr.version_minor = SWAPSHORT(hdr.version_minor);
hdr.thiszone = SWAPLONG(hdr.thiszone);
@ -182,16 +215,81 @@ pcap_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
if (hdr.version_major < PCAP_VERSION_MAJOR) {
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"archaic pcap savefile format");
return (-1);
*err = 1;
return (NULL);
}
p->sf.version_major = hdr.version_major;
p->sf.version_minor = hdr.version_minor;
/*
* OK, this is a good pcap file.
* Allocate a pcap_t for it.
*/
p = pcap_open_offline_common(errbuf, sizeof (struct pcap_sf));
if (p == NULL) {
/* Allocation failed. */
*err = 1;
return (NULL);
}
p->swapped = swapped;
p->version_major = hdr.version_major;
p->version_minor = hdr.version_minor;
p->tzoff = hdr.thiszone;
p->snapshot = hdr.snaplen;
p->linktype = linktype_to_dlt(LT_LINKTYPE(hdr.linktype));
p->linktype_ext = LT_LINKTYPE_EXT(hdr.linktype);
p->sf.next_packet_op = pcap_next_packet;
p->next_packet_op = pcap_next_packet;
ps = p->priv;
p->opt.tstamp_precision = precision;
/*
* Will we need to scale the timestamps to match what the
* user wants?
*/
switch (precision) {
case PCAP_TSTAMP_PRECISION_MICRO:
if (magic == NSEC_TCPDUMP_MAGIC) {
/*
* The file has nanoseconds, the user
* wants microseconds; scale the
* precision down.
*/
ps->scale_type = SCALE_DOWN;
} else {
/*
* The file has microseconds, the
* user wants microseconds; nothing to do.
*/
ps->scale_type = PASS_THROUGH;
}
break;
case PCAP_TSTAMP_PRECISION_NANO:
if (magic == NSEC_TCPDUMP_MAGIC) {
/*
* The file has nanoseconds, the
* user wants nanoseconds; nothing to do.
*/
ps->scale_type = PASS_THROUGH;
} else {
/*
* The file has microoseconds, the user
* wants nanoseconds; scale the
* precision up.
*/
ps->scale_type = SCALE_UP;
}
break;
default:
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"unknown time stamp resolution %u", precision);
free(p);
*err = 1;
return (NULL);
}
/*
* We interchanged the caplen and len fields at version 2.3,
@ -207,19 +305,19 @@ pcap_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
case 2:
if (hdr.version_minor < 3)
p->sf.lengths_swapped = SWAPPED;
ps->lengths_swapped = SWAPPED;
else if (hdr.version_minor == 3)
p->sf.lengths_swapped = MAYBE_SWAPPED;
ps->lengths_swapped = MAYBE_SWAPPED;
else
p->sf.lengths_swapped = NOT_SWAPPED;
ps->lengths_swapped = NOT_SWAPPED;
break;
case 543:
p->sf.lengths_swapped = SWAPPED;
ps->lengths_swapped = SWAPPED;
break;
default:
p->sf.lengths_swapped = NOT_SWAPPED;
ps->lengths_swapped = NOT_SWAPPED;
break;
}
@ -241,7 +339,7 @@ pcap_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
* data ourselves and read from that buffer in order to
* make that work.
*/
p->sf.hdrsize = sizeof(struct pcap_sf_patched_pkthdr);
ps->hdrsize = sizeof(struct pcap_sf_patched_pkthdr);
if (p->linktype == DLT_EN10MB) {
/*
@ -267,7 +365,7 @@ pcap_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
p->snapshot += 14;
}
} else
p->sf.hdrsize = sizeof(struct pcap_sf_pkthdr);
ps->hdrsize = sizeof(struct pcap_sf_pkthdr);
/*
* Allocate a buffer for the packet data.
@ -282,10 +380,14 @@ pcap_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
p->buffer = malloc(p->bufsize);
if (p->buffer == NULL) {
snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
return (-1);
free(p);
*err = 1;
return (NULL);
}
return (1);
p->cleanup_op = sf_cleanup;
return (p);
}
/*
@ -296,8 +398,9 @@ pcap_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
static int
pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
{
struct pcap_sf *ps = p->priv;
struct pcap_sf_patched_pkthdr sf_hdr;
FILE *fp = p->sf.rfile;
FILE *fp = p->rfile;
size_t amt_read;
bpf_u_int32 t;
@ -308,8 +411,8 @@ pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
* unpatched libpcap we only read as many bytes as the regular
* header has.
*/
amt_read = fread(&sf_hdr, 1, p->sf.hdrsize, fp);
if (amt_read != p->sf.hdrsize) {
amt_read = fread(&sf_hdr, 1, ps->hdrsize, fp);
if (amt_read != ps->hdrsize) {
if (ferror(fp)) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"error reading dump file: %s",
@ -319,7 +422,7 @@ pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
if (amt_read != 0) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"truncated dump file; tried to read %lu header bytes, only got %lu",
(unsigned long)p->sf.hdrsize,
(unsigned long)ps->hdrsize,
(unsigned long)amt_read);
return (-1);
}
@ -328,7 +431,7 @@ pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
}
}
if (p->sf.swapped) {
if (p->swapped) {
/* these were written in opposite byte order */
hdr->caplen = SWAPLONG(sf_hdr.caplen);
hdr->len = SWAPLONG(sf_hdr.len);
@ -340,8 +443,34 @@ pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
hdr->ts.tv_sec = sf_hdr.ts.tv_sec;
hdr->ts.tv_usec = sf_hdr.ts.tv_usec;
}
switch (ps->scale_type) {
case PASS_THROUGH:
/*
* Just pass the time stamp through.
*/
break;
case SCALE_UP:
/*
* File has microseconds, user wants nanoseconds; convert
* it.
*/
hdr->ts.tv_usec = hdr->ts.tv_usec * 1000;
break;
case SCALE_DOWN:
/*
* File has nanoseconds, user wants microseconds; convert
* it.
*/
hdr->ts.tv_usec = hdr->ts.tv_usec / 1000;
break;
}
/* Swap the caplen and len fields, if necessary. */
switch (p->sf.lengths_swapped) {
switch (ps->lengths_swapped) {
case NOT_SWAPPED:
break;
@ -432,7 +561,7 @@ pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
}
*data = p->buffer;
if (p->sf.swapped) {
if (p->swapped) {
/*
* Convert pseudo-headers from the byte order of
* the host on which the file was saved to our
@ -454,11 +583,11 @@ pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
}
static int
sf_write_header(FILE *fp, int linktype, int thiszone, int snaplen)
sf_write_header(pcap_t *p, FILE *fp, int linktype, int thiszone, int snaplen)
{
struct pcap_file_header hdr;
hdr.magic = TCPDUMP_MAGIC;
hdr.magic = p->opt.tstamp_precision == PCAP_TSTAMP_PRECISION_NANO ? NSEC_TCPDUMP_MAGIC : TCPDUMP_MAGIC;
hdr.version_major = PCAP_VERSION_MAJOR;
hdr.version_minor = PCAP_VERSION_MINOR;
@ -509,7 +638,7 @@ pcap_setup_dump(pcap_t *p, int linktype, FILE *f, const char *fname)
else
setbuf(f, NULL);
#endif
if (sf_write_header(f, linktype, p->tzoff, p->snapshot) == -1) {
if (sf_write_header(p, f, linktype, p->tzoff, p->snapshot) == -1) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Can't write to %s: %s",
fname, pcap_strerror(errno));
if (f != stdout)

View File

@ -59,6 +59,15 @@
/* if libnl exists and is version 2.x */
/* #undef HAVE_LIBNL_2_x */
/* if libnl exists and is version 3.x */
/* #undef HAVE_LIBNL_3_x */
/* libnl has NLE_FAILURE */
/* #undef HAVE_LIBNL_NLE */
/* libnl has new-style socket api */
/* #undef HAVE_LIBNL_SOCKETS */
/* Define to 1 if you have the <limits.h> header file. */
#define HAVE_LIMITS_H 1
@ -212,6 +221,9 @@
/* path for device for USB sniffing */
/* #undef LINUX_USB_MON_DEV */
/* if we need a pcap_parse wrapper around yyparse */
/* #undef NEED_YYPARSE_WRAPPER */
/* Define to 1 if netinet/ether.h declares `ether_hostton' */
/* #undef NETINET_ETHER_H_DECLARES_ETHER_HOSTTON */
@ -251,6 +263,9 @@
/* target host supports canusb */
/* #undef PCAP_SUPPORT_CANUSB */
/* support D-Bus sniffing */
/* #undef PCAP_SUPPORT_DBUS */
/* target host supports netfilter sniffing */
/* #undef PCAP_SUPPORT_NETFILTER */
@ -260,18 +275,23 @@
/* include ACN support */
/* #undef SITA */
/* if struct sockaddr_hci has hci_channel member */
/* #undef SOCKADDR_HCI_HAS_HCI_CHANNEL */
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Enable parser debugging */
/* #undef YYDEBUG */
/* Enable large inode numbers on Mac OS X 10.5. */
#ifndef _DARWIN_USE_64_BIT_INODE
# define _DARWIN_USE_64_BIT_INODE 1
#endif
/* Number of bits in a file offset, on hosts where this is settable. */
/* #undef _FILE_OFFSET_BITS */
/* needed on HP-UX */
/* #undef _HPUX_SOURCE */
/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
/* #undef _LARGEFILE_SOURCE */
@ -281,6 +301,9 @@
/* define on AIX to get certain functions */
/* #undef _SUN */
/* define if your compiler allows __attribute__((format)) without a warning */
#define __ATTRIBUTE___FORMAT_OK 1
/* to handle Ultrix compilers that don't support const in prototypes */
/* #undef const */