22c22
< * $FreeBSD: head/contrib/libpcap/gencode.c 146771 2005-05-29 18:09:04Z sam $
---
> * $FreeBSD: head/contrib/libpcap/gencode.c 147897 2005-07-11 03:43:25Z sam $
26c26
< "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.221 2005/03/27 22:10:23 guy Exp $ (LBL)";
---
> "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.221.2.24 2005/06/20 21:52:53 guy Exp $ (LBL)";
107c107
< static u_int orig_linktype = -1U, orig_nl = -1U, orig_nl_nosnap = -1U;
---
> static u_int orig_linktype = -1U, orig_nl = -1U;
117d116
<
137a137,149
> * Value passed to gen_load_a() to indicate what the offset argument
> * is relative to.
> */
> enum e_offrel {
> OR_PACKET, /* relative to the beginning of the packet */
> OR_LINK, /* relative to the link-layer header */
> OR_NET, /* relative to the network-layer header */
> OR_NET_NOSNAP, /* relative to the network-layer header, with no SNAP header at the link layer */
> OR_TRAN_IPV4, /* relative to the transport-layer header, with IPv4 network layer */
> OR_TRAN_IPV6 /* relative to the transport-layer header, with IPv6 network layer */
> };
>
> /*
164,169c176,188
< static struct block *gen_cmp(u_int, u_int, bpf_int32);
< static struct block *gen_cmp_gt(u_int, u_int, bpf_int32);
< static struct block *gen_mcmp(u_int, u_int, bpf_int32, bpf_u_int32);
< static struct block *gen_bcmp(u_int, u_int, const u_char *);
< static struct block *gen_ncmp(bpf_u_int32, bpf_u_int32, bpf_u_int32,
< bpf_u_int32, bpf_u_int32, int);
---
> static struct block *gen_cmp(enum e_offrel, u_int, u_int, bpf_int32);
> static struct block *gen_cmp_gt(enum e_offrel, u_int, u_int, bpf_int32);
> static struct block *gen_cmp_ge(enum e_offrel, u_int, u_int, bpf_int32);
> static struct block *gen_cmp_lt(enum e_offrel, u_int, u_int, bpf_int32);
> static struct block *gen_cmp_le(enum e_offrel, u_int, u_int, bpf_int32);
> static struct block *gen_mcmp(enum e_offrel, u_int, u_int, bpf_int32,
> bpf_u_int32);
> static struct block *gen_bcmp(enum e_offrel, u_int, u_int, const u_char *);
> static struct block *gen_ncmp(enum e_offrel, bpf_u_int32, bpf_u_int32,
> bpf_u_int32, bpf_u_int32, int, bpf_int32);
> static struct slist *gen_load_llrel(u_int, u_int);
> static struct slist *gen_load_a(enum e_offrel, u_int, u_int);
> static struct slist *gen_loadx_iphdrlen(void);
174a194,196
> static void insert_radiotap_load_llprefixlen(struct block *);
> static void insert_load_llprefixlen(struct block *);
> static struct slist *gen_llprefixlen(void);
177c199
< static struct block *gen_llc(int);
---
> static struct block *gen_llc_linktype(int);
188c210
< static struct block *gen_dnhostop(bpf_u_int32, int, u_int);
---
> static struct block *gen_dnhostop(bpf_u_int32, int);
197a220
> static struct block *gen_portrangeatom(int, bpf_int32, bpf_int32);
199a223
> static struct block *gen_portrangeatom6(int, bpf_int32, bpf_int32);
202a227,228
> struct block *gen_portrangeop(int, int, int, int);
> static struct block *gen_portrange(int, int, int, int);
205a232,233
> struct block *gen_portrangeop6(int, int, int, int);
> static struct block *gen_portrange6(int, int, int, int);
456a485,501
>
> /*
> * Insert before the statements of the first (root) block any
> * statements needed to load the lengths of any variable-length
> * headers into registers.
> *
> * XXX - a fancier strategy would be to insert those before the
> * statements of all blocks that use those lengths and that
> * have no predecessors that use them, so that we only compute
> * the lengths if we need them. There might be even better
> * approaches than that. However, as we're currently only
> * handling variable-length radiotap headers, and as all
> * filtering expressions other than raw link[M:N] tests
> * require the length of that header, doing more for that
> * header length isn't really worth the effort.
> */
> insert_load_llprefixlen(root);
490c535,536
< gen_cmp(offset, size, v)
---
> gen_cmp(offrel, offset, size, v)
> enum e_offrel offrel;
494,495c540,541
< struct slist *s;
< struct block *b;
---
> return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JEQ, 0, v);
> }
497,498c543,550
< s = new_stmt(BPF_LD|BPF_ABS|size);
< s->s.k = offset;
---
> static struct block *
> gen_cmp_gt(offrel, offset, size, v)
> enum e_offrel offrel;
> u_int offset, size;
> bpf_int32 v;
> {
> return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGT, 0, v);
> }
500,504c552,558
< b = new_block(JMP(BPF_JEQ));
< b->stmts = s;
< b->s.k = v;
<
< return b;
---
> static struct block *
> gen_cmp_ge(offrel, offset, size, v)
> enum e_offrel offrel;
> u_int offset, size;
> bpf_int32 v;
> {
> return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGE, 0, v);
508c562,563
< gen_cmp_gt(offset, size, v)
---
> gen_cmp_lt(offrel, offset, size, v)
> enum e_offrel offrel;
512,513c567,568
< struct slist *s;
< struct block *b;
---
> return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGE, 1, v);
> }
515,522c570,576
< s = new_stmt(BPF_LD|BPF_ABS|size);
< s->s.k = offset;
<
< b = new_block(JMP(BPF_JGT));
< b->stmts = s;
< b->s.k = v;
<
< return b;
---
> static struct block *
> gen_cmp_le(offrel, offset, size, v)
> enum e_offrel offrel;
> u_int offset, size;
> bpf_int32 v;
> {
> return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGT, 1, v);
526c580,581
< gen_mcmp(offset, size, v, mask)
---
> gen_mcmp(offrel, offset, size, v, mask)
> enum e_offrel offrel;
531,539c586
< struct block *b = gen_cmp(offset, size, v);
< struct slist *s;
<
< if (mask != 0xffffffff) {
< s = new_stmt(BPF_ALU|BPF_AND|BPF_K);
< s->s.k = mask;
< b->stmts->next = s;
< }
< return b;
---
> return gen_ncmp(offrel, offset, size, mask, BPF_JEQ, 0, v);
543c590,591
< gen_bcmp(offset, size, v)
---
> gen_bcmp(offrel, offset, size, v)
> enum e_offrel offrel;
555c603
< tmp = gen_cmp(offset + size - 4, BPF_W, w);
---
> tmp = gen_cmp(offrel, offset + size - 4, BPF_W, w);
565c613
< tmp = gen_cmp(offset + size - 2, BPF_H, w);
---
> tmp = gen_cmp(offrel, offset + size - 2, BPF_H, w);
572c620
< tmp = gen_cmp(offset, BPF_B, (bpf_int32)v[0]);
---
> tmp = gen_cmp(offrel, offset, BPF_B, (bpf_int32)v[0]);
579a628,633
> /*
> * AND the field of size "size" at offset "offset" relative to the header
> * specified by "offrel" with "mask", and compare it with the value "v"
> * with the test specified by "jtype"; if "reverse" is true, the test
> * should test the opposite of "jtype".
> */
581,582c635,638
< gen_ncmp(datasize, offset, mask, jtype, jvalue, reverse)
< bpf_u_int32 datasize, offset, mask, jtype, jvalue;
---
> gen_ncmp(offrel, offset, size, mask, jtype, reverse, v)
> enum e_offrel offrel;
> bpf_int32 v;
> bpf_u_int32 offset, size, mask, jtype;
585c641
< struct slist *s;
---
> struct slist *s, *s2;
588,589c644
< s = new_stmt(BPF_LD|datasize|BPF_ABS);
< s->s.k = offset;
---
> s = gen_load_a(offrel, offset, size);
592,593c647,649
< s->next = new_stmt(BPF_ALU|BPF_AND|BPF_K);
< s->next->s.k = mask;
---
> s2 = new_stmt(BPF_ALU|BPF_AND|BPF_K);
> s2->s.k = mask;
> sappend(s, s2);
598c654
< b->s.k = jvalue;
---
> b->s.k = v;
606c662,668
< * layer. These variables give the necessary offsets.
---
> * layer. These variables give the necessary offsets from the beginning
> * of the packet data.
> *
> * If the link layer has variable_length headers, the offsets are offsets
> * from the end of the link-link-layer header, and "reg_ll_size" is
> * the register number for a register containing the length of the
> * link-layer header. Otherwise, "reg_ll_size" is -1.
607a670
> static int reg_ll_size;
609a673,678
> * This is the offset of the beginning of the link-layer header.
> * It's usually 0, except for 802.11 with a fixed-length radio header.
> */
> static u_int off_ll;
>
> /*
654a724,731
> * These are offsets for the MTP3 fields.
> */
> static u_int off_sio;
> static u_int off_opc;
> static u_int off_dpc;
> static u_int off_sls;
>
> /*
706a784,793
> off_sio = -1;
> off_opc = -1;
> off_dpc = -1;
> off_sls = -1;
>
> /*
> * Also assume it's not 802.11 with a fixed-length radio header.
> */
> off_ll = 0;
>
709d795
< orig_nl_nosnap = -1;
710a797,798
> reg_ll_size = -1;
>
867a956
> off_ll = 144;
887a977
> off_ll = 64;
899,909c989,992
< * XXX - same variable-length header problem, only
< * even *more* so; this header is also variable-length,
< * with the length being the 16-bit number at an offset
< * of 2 from the beginning of the radio header, and it's
< * device-dependent (different devices might supply
< * different amounts of information), so we can't even
< * assume a fixed length for the current version of the
< * header.
< *
< * Therefore, currently, only raw "link[N:M]" filtering is
< * supported.
---
> * The radiotap header is variable length, and we
> * generate code to compute its length and store it
> * in a register. These offsets are relative to the
> * beginning of the 802.11 header.
911,913c994,996
< off_linktype = -1;
< off_nl = -1;
< off_nl_nosnap = -1;
---
> off_linktype = 24;
> off_nl = 32; /* 802.11+802.2+SNAP */
> off_nl_nosnap = 27; /* 802.11+802.2 */
920a1004,1010
> *
> * XXX - what about ISO PDUs, e.g. CLNP, ISIS, ESIS,
> * or PPP with the PPP NLPID (e.g., PPPoA)? The
> * latter would presumably be treated the way PPPoE
> * should be, so you can do "pppoe and udp port 2049"
> * or "pppoa and tcp port 80" and have it check for
> * PPPo{A,E} and a PPP protocol of IP and....
995c1085
< off_nl_nosnap = 0; /* no 802.2 LLC */
---
> off_nl_nosnap = 18; /* no 802.2 LLC */
1024c1114
< /* XXX read from header? */
---
> /* XXX read this from pf.h? */
1026c1116
< off_nl_nosnap = PFLOG_HDRLEN;
---
> off_nl_nosnap = PFLOG_HDRLEN; /* no 802.2 LLC */
1033c1123
< off_nl_nosnap = -1;
---
> off_nl_nosnap = -1; /* no 802.2 LLC */
1047a1138,1185
> /* frames captured on a Juniper PPPoE service PIC
> * contain raw ethernet frames */
> case DLT_JUNIPER_PPPOE:
> off_linktype = 16;
> off_nl = 18; /* Ethernet II */
> off_nl_nosnap = 21; /* 802.3+802.2 */
> return;
>
> case DLT_JUNIPER_PPPOE_ATM:
> off_linktype = 4;
> off_nl = 6;
> off_nl_nosnap = -1; /* no 802.2 LLC */
> return;
>
> case DLT_JUNIPER_GGSN:
> off_linktype = 6;
> off_nl = 12;
> off_nl_nosnap = -1; /* no 802.2 LLC */
> return;
>
> case DLT_JUNIPER_ES:
> off_linktype = 6;
> off_nl = -1; /* not really a network layer but raw IP adresses */
> off_nl_nosnap = -1; /* no 802.2 LLC */
> return;
>
> case DLT_JUNIPER_MONITOR:
> off_linktype = 12;
> off_nl = 12; /* raw IP/IP6 header */
> off_nl_nosnap = -1; /* no 802.2 LLC */
> return;
>
> case DLT_JUNIPER_SERVICES:
> off_linktype = 12;
> off_nl = -1; /* L3 proto location dep. on cookie type */
> off_nl_nosnap = -1; /* no 802.2 LLC */
> return;
>
> case DLT_MTP2:
> off_sio = 3;
> off_opc = 4;
> off_dpc = 4;
> off_sls = 7;
> off_linktype = -1;
> off_nl = -1;
> off_nl_nosnap = -1;
> return;
>
1054a1193,1201
>
> case DLT_LINUX_LAPD:
> /*
> * Currently, only raw "link[N:M]" filtering is supported.
> */
> off_linktype = -1;
> off_nl = -1;
> off_nl_nosnap = -1;
> return;
1059a1207,1344
> /*
> * Load a value relative to the beginning of the link-layer header.
> * The link-layer header doesn't necessarily begin at the beginning
> * of the packet data; there might be a variable-length prefix containing
> * radio information.
> */
> static struct slist *
> gen_load_llrel(offset, size)
> u_int offset, size;
> {
> struct slist *s, *s2;
>
> s = gen_llprefixlen();
>
> /*
> * If "s" is non-null, it has code to arrange that the X register
> * contains the length of the prefix preceding the link-layer
> * header.
> */
> if (s != NULL) {
> s2 = new_stmt(BPF_LD|BPF_IND|size);
> s2->s.k = offset;
> sappend(s, s2);
> } else {
> s = new_stmt(BPF_LD|BPF_ABS|size);
> s->s.k = offset;
> }
> return s;
> }
>
> /*
> * Load a value relative to the beginning of the specified header.
> */
> static struct slist *
> gen_load_a(offrel, offset, size)
> enum e_offrel offrel;
> u_int offset, size;
> {
> struct slist *s, *s2;
>
> switch (offrel) {
>
> case OR_PACKET:
> s = gen_load_llrel(offset, size);
> break;
>
> case OR_LINK:
> s = gen_load_llrel(off_ll + offset, size);
> break;
>
> case OR_NET:
> s = gen_load_llrel(off_nl + offset, size);
> break;
>
> case OR_NET_NOSNAP:
> s = gen_load_llrel(off_nl_nosnap + offset, size);
> break;
>
> case OR_TRAN_IPV4:
> /*
> * Load the X register with the length of the IPv4 header,
> * in bytes.
> */
> s = gen_loadx_iphdrlen();
>
> /*
> * Load the item at {length of the link-layer header} +
> * {length of the IPv4 header} + {specified offset}.
> */
> s2 = new_stmt(BPF_LD|BPF_IND|size);
> s2->s.k = off_nl + offset;
> sappend(s, s2);
> break;
>
> case OR_TRAN_IPV6:
> s = gen_load_llrel(off_nl + 40 + offset, size);
> break;
>
> default:
> abort();
> return NULL;
> }
> return s;
> }
>
> /*
> * Generate code to load into the X register the sum of the length of
> * the IPv4 header and any variable-length header preceding the link-layer
> * header.
> */
> static struct slist *
> gen_loadx_iphdrlen()
> {
> struct slist *s, *s2;
>
> s = gen_llprefixlen();
> if (s != NULL) {
> /*
> * There's a variable-length prefix preceding the
> * link-layer header. "s" points to a list of statements
> * that put the length of that prefix into the X register.
> * The 4*([k]&0xf) addressing mode can't be used, as we
> * don't have a constant offset, so we have to load the
> * value in question into the A register and add to it
> * the value from the X register.
> */
> s2 = new_stmt(BPF_LD|BPF_IND|BPF_B);
> s2->s.k = off_nl;
> sappend(s, s2);
> s2 = new_stmt(BPF_ALU|BPF_AND|BPF_K);
> s2->s.k = 0xf;
> sappend(s, s2);
> s2 = new_stmt(BPF_ALU|BPF_LSH|BPF_K);
> s2->s.k = 2;
> sappend(s, s2);
>
> /*
> * The A register now contains the length of the
> * IP header. We need to add to it the length
> * of the prefix preceding the link-layer
> * header, which is still in the X register, and
> * move the result into the X register.
> */
> sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
> sappend(s, new_stmt(BPF_MISC|BPF_TAX));
> } else {
> /*
> * There is no variable-length header preceding the
> * link-layer header; if there's a fixed-length
> * header preceding it, its length is included in
> * the off_ variables, so it doesn't need to be added.
> */
> s = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
> s->s.k = off_nl;
> }
> return s;
> }
>
1094a1380,1388
> /*
> * Generate code to match a particular packet type.
> *
> * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
> * value, if <= ETHERMTU. We use that to determine whether to
> * match the type/length field or to check the type/length field for
> * a value <= ETHERMTU to see whether it's a type field and then do
> * the appropriate test.
> */
1104,1116d1397
< /*
< * OSI protocols always use 802.2 encapsulation.
< * XXX - should we check both the DSAP and the
< * SSAP, like this, or should we check just the
< * DSAP?
< */
< b0 = gen_cmp_gt(off_linktype, BPF_H, ETHERMTU);
< gen_not(b0);
< b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32)
< ((LLCSAP_ISONS << 8) | LLCSAP_ISONS));
< gen_and(b0, b1);
< return b1;
<
1118,1124d1398
< b0 = gen_cmp_gt(off_linktype, BPF_H, ETHERMTU);
< gen_not(b0);
< b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32)
< ((LLCSAP_IP << 8) | LLCSAP_IP));
< gen_and(b0, b1);
< return b1;
<
1127c1401,1406
< * NetBEUI always uses 802.2 encapsulation.
---
> * OSI protocols and NetBEUI always use 802.2 encapsulation,
> * so we check the DSAP and SSAP.
> *
> * LLCSAP_IP checks for IP-over-802.2, rather
> * than IP-over-Ethernet or IP-over-SNAP.
> *
1130c1409,1410
< * DSAP?
---
> * DSAP, as we do for other types <= ETHERMTU
> * (i.e., other SAP values)?
1132c1412
< b0 = gen_cmp_gt(off_linktype, BPF_H, ETHERMTU);
---
> b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU);
1134,1135c1414,1415
< b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32)
< ((LLCSAP_NETBEUI << 8) | LLCSAP_NETBEUI));
---
> b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_H, (bpf_int32)
> ((proto << 8) | proto));
1172,1173c1452,1455
< b0 = gen_cmp(off_linktype + 2, BPF_B, (bpf_int32)LLCSAP_IPX);
< b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32)0xFFFF);
---
> b0 = gen_cmp(OR_LINK, off_linktype + 2, BPF_B,
> (bpf_int32)LLCSAP_IPX);
> b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_H,
> (bpf_int32)0xFFFF);
1187c1469
< b0 = gen_cmp_gt(off_linktype, BPF_H, ETHERMTU);
---
> b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU);
1203c1485,1486
< b0 = gen_cmp(off_linktype, BPF_H, (bpf_int32)ETHERTYPE_IPX);
---
> b0 = gen_cmp(OR_LINK, off_linktype, BPF_H,
> (bpf_int32)ETHERTYPE_IPX);
1219c1502
< b0 = gen_cmp_gt(off_linktype, BPF_H, ETHERMTU);
---
> b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU);
1244c1527
< b0 = gen_cmp(off_linktype, BPF_H, (bpf_int32)proto);
---
> b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto);
1259c1542
< b0 = gen_cmp_gt(off_linktype, BPF_H, ETHERMTU);
---
> b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU);
1261c1544,1545
< b1 = gen_cmp(off_linktype + 2, BPF_B, (bpf_int32)proto);
---
> b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_B,
> (bpf_int32)proto);
1274c1558,1559
< return gen_cmp(off_linktype, BPF_H, (bpf_int32)proto);
---
> return gen_cmp(OR_LINK, off_linktype, BPF_H,
> (bpf_int32)proto);
1278a1564,1571
> /*
> * Generate code to match a particular packet type.
> *
> * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
> * value, if <= ETHERMTU. We use that to determine whether to
> * match the type field or to check the type field for the special
> * LINUX_SLL_P_802_2 value and then do the appropriate test.
> */
1287,1293d1579
< case LLCSAP_IP:
< b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2);
< b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32)
< ((LLCSAP_IP << 8) | LLCSAP_IP));
< gen_and(b0, b1);
< return b1;
<
1294a1581,1582
> case LLCSAP_IP:
> case LLCSAP_NETBEUI:
1296c1584,1589
< * OSI protocols always use 802.2 encapsulation.
---
> * OSI protocols and NetBEUI always use 802.2 encapsulation,
> * so we check the DSAP and SSAP.
> *
> * LLCSAP_IP checks for IP-over-802.2, rather
> * than IP-over-Ethernet or IP-over-SNAP.
> *
1299c1592,1593
< * DSAP?
---
> * DSAP, as we do for other types <= ETHERMTU
> * (i.e., other SAP values)?
1301,1303c1595,1597
< b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2);
< b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32)
< ((LLCSAP_ISONS << 8) | LLCSAP_ISONS));
---
> b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2);
> b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_H, (bpf_int32)
> ((proto << 8) | proto));
1307,1319d1600
< case LLCSAP_NETBEUI:
< /*
< * NetBEUI always uses 802.2 encapsulation.
< * XXX - should we check both the DSAP and the
< * LSAP, like this, or should we check just the
< * DSAP?
< */
< b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2);
< b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32)
< ((LLCSAP_NETBEUI << 8) | LLCSAP_NETBEUI));
< gen_and(b0, b1);
< return b1;
<
1346c1627
< b0 = gen_cmp(off_linktype + 2, BPF_B,
---
> b0 = gen_cmp(OR_LINK, off_linktype + 2, BPF_B,
1351c1632
< b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2);
---
> b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2);
1358c1639
< b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_3);
---
> b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_3);
1366c1647
< b0 = gen_cmp(off_linktype, BPF_H,
---
> b0 = gen_cmp(OR_LINK, off_linktype, BPF_H,
1383c1664
< b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2);
---
> b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2);
1409c1690
< b0 = gen_cmp(off_linktype, BPF_H, (bpf_int32)proto);
---
> b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto);
1423c1704
< b0 = gen_cmp(off_linktype, BPF_H,
---
> b0 = gen_cmp(OR_LINK, off_linktype, BPF_H,
1425c1706
< b1 = gen_cmp(off_linktype + 2, BPF_B,
---
> b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_B,
1439c1720
< return gen_cmp(off_linktype, BPF_H,
---
> return gen_cmp(OR_LINK, off_linktype, BPF_H,
1444a1726,1850
> static void
> insert_radiotap_load_llprefixlen(b)
> struct block *b;
> {
> struct slist *s1, *s2;
>
> /*
> * Prepend to the statements in this block code to load the
> * length of the radiotap header into the register assigned
> * to hold that length, if one has been assigned.
> */
> if (reg_ll_size != -1) {
> /*
> * The 2 bytes at offsets of 2 and 3 from the beginning
> * of the radiotap header are the length of the radiotap
> * header; unfortunately, it's little-endian, so we have
> * to load it a byte at a time and construct the value.
> */
>
> /*
> * Load the high-order byte, at an offset of 3, shift it
> * left a byte, and put the result in the X register.
> */
> s1 = new_stmt(BPF_LD|BPF_B|BPF_ABS);
> s1->s.k = 3;
> s2 = new_stmt(BPF_ALU|BPF_LSH|BPF_K);
> sappend(s1, s2);
> s2->s.k = 8;
> s2 = new_stmt(BPF_MISC|BPF_TAX);
> sappend(s1, s2);
>
> /*
> * Load the next byte, at an offset of 2, and OR the
> * value from the X register into it.
> */
> s2 = new_stmt(BPF_LD|BPF_B|BPF_ABS);
> sappend(s1, s2);
> s2->s.k = 2;
> s2 = new_stmt(BPF_ALU|BPF_OR|BPF_X);
> sappend(s1, s2);
>
> /*
> * Now allocate a register to hold that value and store
> * it.
> */
> s2 = new_stmt(BPF_ST);
> s2->s.k = reg_ll_size;
> sappend(s1, s2);
>
> /*
> * Now move it into the X register.
> */
> s2 = new_stmt(BPF_MISC|BPF_TAX);
> sappend(s1, s2);
>
> /*
> * Now append all the existing statements in this
> * block to these statements.
> */
> sappend(s1, b->stmts);
> b->stmts = s1;
> }
> }
>
>
> static void
> insert_load_llprefixlen(b)
> struct block *b;
> {
> switch (linktype) {
>
> case DLT_IEEE802_11_RADIO:
> insert_radiotap_load_llprefixlen(b);
> }
> }
>
>
> static struct slist *
> gen_radiotap_llprefixlen(void)
> {
> struct slist *s;
>
> if (reg_ll_size == -1) {
> /*
> * We haven't yet assigned a register for the length
> * of the radiotap header; allocate one.
> */
> reg_ll_size = alloc_reg();
> }
>
> /*
> * Load the register containing the radiotap length
> * into the X register.
> */
> s = new_stmt(BPF_LDX|BPF_MEM);
> s->s.k = reg_ll_size;
> return s;
> }
>
> /*
> * Generate code to compute the link-layer header length, if necessary,
> * putting it into the X register, and to return either a pointer to a
> * "struct slist" for the list of statements in that code, or NULL if
> * no code is necessary.
> */
> static struct slist *
> gen_llprefixlen(void)
> {
> switch (linktype) {
>
> case DLT_IEEE802_11_RADIO:
> return gen_radiotap_llprefixlen();
>
> default:
> return NULL;
> }
> }
>
> /*
> * Generate code to match a particular packet type by matching the
> * link-layer type field or fields in the 802.2 LLC header.
> *
> * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
> * value, if <= ETHERMTU.
> */
1466c1872,1873
< return gen_cmp(off_linktype, BPF_H, (bpf_int32)proto);
---
> return gen_cmp(OR_LINK, off_linktype, BPF_H,
> (bpf_int32)proto);
1472,1474d1878
< case DLT_IEEE802_11:
< case DLT_PRISM_HEADER:
< case DLT_IEEE802_11_RADIO:
1476a1881,1884
> case DLT_IEEE802_11:
> case DLT_IEEE802_11_RADIO_AVS:
> case DLT_IEEE802_11_RADIO:
> case DLT_PRISM_HEADER:
1480c1888
< return gen_llc(proto);
---
> return gen_llc_linktype(proto);
1498c1906,1907
< b0 = gen_cmp(SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00);
---
> b0 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H,
> 0xFF00);
1513c1922
< b1 = gen_llc(proto);
---
> b1 = gen_llc_linktype(proto);
1516a1926,1927
> /*NOTREACHED*/
> break;
1606,1607c2017,2018
< b0 = gen_cmp(off_linktype, BPF_H, PPP_IP);
< b1 = gen_cmp(off_linktype, BPF_H, PPP_VJC);
---
> b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_IP);
> b1 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_VJC);
1609c2020
< b0 = gen_cmp(off_linktype, BPF_H, PPP_VJNC);
---
> b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_VJNC);
1715c2126
< return (gen_cmp(0, BPF_W, (bpf_int32)proto));
---
> return (gen_cmp(OR_LINK, 0, BPF_W, (bpf_int32)proto));
1723,1724c2134,2135
< return (gen_cmp(offsetof(struct pfloghdr, af), BPF_B,
< (bpf_int32)AF_INET));
---
> return (gen_cmp(OR_LINK, offsetof(struct pfloghdr, af),
> BPF_B, (bpf_int32)AF_INET));
1727,1728c2138,2139
< return (gen_cmp(offsetof(struct pfloghdr, af), BPF_B,
< (bpf_int32)AF_INET6));
---
> return (gen_cmp(OR_LINK, offsetof(struct pfloghdr, af),
> BPF_B, (bpf_int32)AF_INET6));
1748c2159
< return (gen_cmp(off_linktype, BPF_B,
---
> return (gen_cmp(OR_LINK, off_linktype, BPF_B,
1753c2164
< b0 = gen_cmp(off_linktype, BPF_B,
---
> b0 = gen_cmp(OR_LINK, off_linktype, BPF_B,
1755c2166
< b1 = gen_cmp(off_linktype, BPF_B,
---
> b1 = gen_cmp(OR_LINK, off_linktype, BPF_B,
1761c2172
< b0 = gen_cmp(off_linktype, BPF_B,
---
> b0 = gen_cmp(OR_LINK, off_linktype, BPF_B,
1763c2174
< b1 = gen_cmp(off_linktype, BPF_B,
---
> b1 = gen_cmp(OR_LINK, off_linktype, BPF_B,
1769c2180
< return (gen_cmp(off_linktype, BPF_B,
---
> return (gen_cmp(OR_LINK, off_linktype, BPF_B,
1773c2184
< return (gen_cmp(off_linktype, BPF_B,
---
> return (gen_cmp(OR_LINK, off_linktype, BPF_B,
1800c2211
< return gen_cmp(2, BPF_H, (0x03<<8) | 0xcc);
---
> return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | 0xcc);
1807c2218
< return gen_cmp(2, BPF_H, (0x03<<8) | 0x8e);
---
> return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | 0x8e);
1822,1824c2233,2235
< b0 = gen_cmp(2, BPF_H, (0x03<<8) | ISO8473_CLNP);
< b1 = gen_cmp(2, BPF_H, (0x03<<8) | ISO9542_ESIS);
< b2 = gen_cmp(2, BPF_H, (0x03<<8) | ISO10589_ISIS);
---
> b0 = gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | ISO8473_CLNP);
> b1 = gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | ISO9542_ESIS);
> b2 = gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | ISO10589_ISIS);
1838a2250,2255
> case DLT_JUNIPER_PPPOE:
> case DLT_JUNIPER_PPPOE_ATM:
> case DLT_JUNIPER_GGSN:
> case DLT_JUNIPER_ES:
> case DLT_JUNIPER_MONITOR:
> case DLT_JUNIPER_SERVICES:
1846c2263
< return gen_mcmp(0, BPF_W, 0x4d474300, 0xffffff00); /* compare the magic number */
---
> return gen_mcmp(OR_LINK, 0, BPF_W, 0x4d474300, 0xffffff00); /* compare the magic number */
1852a2270,2272
>
> case DLT_LINUX_LAPD:
> bpf_error("LAPD link-layer type filtering not implemented");
1877c2297
< return gen_cmp(off_linktype, BPF_H, (bpf_int32)proto);
---
> return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto);
1903c2323
< return gen_bcmp(offset, 8, snapblock);
---
> return gen_bcmp(OR_LINK, offset, 8, snapblock);
1907c2327,2336
< * Check for a given protocol value assuming an 802.2 LLC header.
---
> * Generate code to match a particular packet type, for link-layer types
> * using 802.2 LLC headers.
> *
> * This is *NOT* used for Ethernet; "gen_ether_linktype()" is used
> * for that - it handles the D/I/X Ethernet vs. 802.3+802.2 issues.
> *
> * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
> * value, if <= ETHERMTU. We use that to determine whether to
> * match the DSAP or both DSAP and LSAP or to check the OUI and
> * protocol ID in a SNAP header.
1910c2339
< gen_llc(proto)
---
> gen_llc_linktype(proto)
1919,1921d2347
< return gen_cmp(off_linktype, BPF_H, (long)
< ((LLCSAP_IP << 8) | LLCSAP_IP));
<
1923,1925d2348
< return gen_cmp(off_linktype, BPF_H, (long)
< ((LLCSAP_ISONS << 8) | LLCSAP_ISONS));
<
1927,1928c2350,2357
< return gen_cmp(off_linktype, BPF_H, (long)
< ((LLCSAP_NETBEUI << 8) | LLCSAP_NETBEUI));
---
> /*
> * XXX - should we check both the DSAP and the
> * SSAP, like this, or should we check just the
> * DSAP, as we do for other types <= ETHERMTU
> * (i.e., other SAP values)?
> */
> return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_u_int32)
> ((proto << 8) | proto));
1935c2364,2365
< return gen_cmp(off_linktype, BPF_B, (bpf_int32)LLCSAP_IPX);
---
> return gen_cmp(OR_LINK, off_linktype, BPF_B,
> (bpf_int32)LLCSAP_IPX);
1959c2389,2390
< return gen_cmp(off_linktype, BPF_B, (bpf_int32)proto);
---
> return gen_cmp(OR_LINK, off_linktype, BPF_B,
> (bpf_int32)proto);
1981c2412,2413
< return gen_cmp(off_linktype+6, BPF_H, (bpf_int32)proto);
---
> return gen_cmp(OR_LINK, off_linktype+6, BPF_H,
> (bpf_int32)proto);
2023c2455
< b1 = gen_mcmp(offset, BPF_W, (bpf_int32)addr, mask);
---
> b1 = gen_mcmp(OR_NET, offset, BPF_W, (bpf_int32)addr, mask);
2069,2070c2501,2502
< b1 = gen_mcmp(offset + 12, BPF_W, ntohl(a[3]), ntohl(m[3]));
< b0 = gen_mcmp(offset + 8, BPF_W, ntohl(a[2]), ntohl(m[2]));
---
> b1 = gen_mcmp(OR_NET, offset + 12, BPF_W, ntohl(a[3]), ntohl(m[3]));
> b0 = gen_mcmp(OR_NET, offset + 8, BPF_W, ntohl(a[2]), ntohl(m[2]));
2072c2504
< b0 = gen_mcmp(offset + 4, BPF_W, ntohl(a[1]), ntohl(m[1]));
---
> b0 = gen_mcmp(OR_NET, offset + 4, BPF_W, ntohl(a[1]), ntohl(m[1]));
2074c2506
< b0 = gen_mcmp(offset + 0, BPF_W, ntohl(a[0]), ntohl(m[0]));
---
> b0 = gen_mcmp(OR_NET, offset + 0, BPF_W, ntohl(a[0]), ntohl(m[0]));
2091c2523
< return gen_bcmp(off_mac + 6, 6, eaddr);
---
> return gen_bcmp(OR_LINK, off_mac + 6, 6, eaddr);
2094c2526
< return gen_bcmp(off_mac + 0, 6, eaddr);
---
> return gen_bcmp(OR_LINK, off_mac + 0, 6, eaddr);
2126c2558
< return gen_bcmp(6 + 1 + pcap_fddipad, 6, eaddr);
---
> return gen_bcmp(OR_LINK, 6 + 1 + pcap_fddipad, 6, eaddr);
2128c2560
< return gen_bcmp(6 + 1, 6, eaddr);
---
> return gen_bcmp(OR_LINK, 6 + 1, 6, eaddr);
2133c2565
< return gen_bcmp(0 + 1 + pcap_fddipad, 6, eaddr);
---
> return gen_bcmp(OR_LINK, 0 + 1 + pcap_fddipad, 6, eaddr);
2135c2567
< return gen_bcmp(0 + 1, 6, eaddr);
---
> return gen_bcmp(OR_LINK, 0 + 1, 6, eaddr);
2167c2599
< return gen_bcmp(8, 6, eaddr);
---
> return gen_bcmp(OR_LINK, 8, 6, eaddr);
2170c2602
< return gen_bcmp(2, 6, eaddr);
---
> return gen_bcmp(OR_LINK, 2, 6, eaddr);
2227,2228c2659
< s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
< s->s.k = 1;
---
> s = gen_load_a(OR_LINK, 1, BPF_B);
2236c2667
< b0 = gen_bcmp(24, 6, eaddr);
---
> b0 = gen_bcmp(OR_LINK, 24, 6, eaddr);
2243,2244c2674
< s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
< s->s.k = 1;
---
> s = gen_load_a(OR_LINK, 1, BPF_B);
2253c2683
< b1 = gen_bcmp(16, 6, eaddr);
---
> b1 = gen_bcmp(OR_LINK, 16, 6, eaddr);
2267,2268c2697
< s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
< s->s.k = 1;
---
> s = gen_load_a(OR_LINK, 1, BPF_B);
2277,2278c2706
< s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
< s->s.k = 1;
---
> s = gen_load_a(OR_LINK, 1, BPF_B);
2287c2715
< b1 = gen_bcmp(10, 6, eaddr);
---
> b1 = gen_bcmp(OR_LINK, 10, 6, eaddr);
2301,2302c2729
< s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
< s->s.k = 0;
---
> gen_load_a(OR_LINK, 0, BPF_B);
2317,2318c2744
< s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
< s->s.k = 0;
---
> s = gen_load_a(OR_LINK, 0, BPF_B);
2327c2753
< b1 = gen_bcmp(10, 6, eaddr);
---
> b1 = gen_bcmp(OR_LINK, 10, 6, eaddr);
2345,2346c2771
< s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
< s->s.k = 0;
---
> s = gen_load_a(OR_LINK, 0, BPF_B);
2381,2382c2806
< s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
< s->s.k = 1;
---
> s = gen_load_a(OR_LINK, 1, BPF_B);
2390c2814
< b0 = gen_bcmp(16, 6, eaddr);
---
> b0 = gen_bcmp(OR_LINK, 16, 6, eaddr);
2397,2398c2821
< s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
< s->s.k = 1;
---
> s = gen_load_a(OR_LINK, 1, BPF_B);
2407c2830
< b1 = gen_bcmp(4, 6, eaddr);
---
> b1 = gen_bcmp(OR_LINK, 4, 6, eaddr);
2420,2421c2843
< s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
< s->s.k = 0;
---
> s = gen_load_a(OR_LINK, 0, BPF_B);
2436,2437c2858
< s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
< s->s.k = 0;
---
> s = gen_load_a(OR_LINK, 0, BPF_B);
2446c2867
< b1 = gen_bcmp(4, 6, eaddr);
---
> b1 = gen_bcmp(OR_LINK, 4, 6, eaddr);
2464,2465c2885
< s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
< s->s.k = 0;
---
> s = gen_load_a(OR_LINK, 0, BPF_B);
2509c2929
< return gen_bcmp(10, 6, eaddr);
---
> return gen_bcmp(OR_LINK, 10, 6, eaddr);
2512c2932
< return gen_bcmp(2, 6, eaddr);
---
> return gen_bcmp(OR_LINK, 2, 6, eaddr);
2550c2970
< gen_dnhostop(addr, dir, base_off)
---
> gen_dnhostop(addr, dir)
2553d2972
< u_int base_off;
2573,2574c2992,2993
< b0 = gen_dnhostop(addr, Q_SRC, base_off);
< b1 = gen_dnhostop(addr, Q_DST, base_off);
---
> b0 = gen_dnhostop(addr, Q_SRC);
> b1 = gen_dnhostop(addr, Q_DST);
2581,2582c3000,3001
< b0 = gen_dnhostop(addr, Q_SRC, base_off);
< b1 = gen_dnhostop(addr, Q_DST, base_off);
---
> b0 = gen_dnhostop(addr, Q_SRC);
> b1 = gen_dnhostop(addr, Q_DST);
2594c3013
< tmp = gen_mcmp(base_off + 2, BPF_H,
---
> tmp = gen_mcmp(OR_NET, 2, BPF_H,
2596c3015
< b1 = gen_cmp(base_off + 2 + 1 + offset_lh,
---
> b1 = gen_cmp(OR_NET, 2 + 1 + offset_lh,
2600,2601c3019,3020
< tmp = gen_mcmp(base_off + 2, BPF_B, (bpf_int32)0x06, (bpf_int32)0x7);
< b2 = gen_cmp(base_off + 2 + offset_lh, BPF_H, (bpf_int32)ntohs(addr));
---
> tmp = gen_mcmp(OR_NET, 2, BPF_B, (bpf_int32)0x06, (bpf_int32)0x7);
> b2 = gen_cmp(OR_NET, 2 + offset_lh, BPF_H, (bpf_int32)ntohs(addr));
2605c3024
< tmp = gen_mcmp(base_off + 2, BPF_H,
---
> tmp = gen_mcmp(OR_NET, 2, BPF_H,
2607,2608c3026
< b2 = gen_cmp(base_off + 2 + 1 + offset_sh,
< BPF_H, (bpf_int32)ntohs(addr));
---
> b2 = gen_cmp(OR_NET, 2 + 1 + offset_sh, BPF_H, (bpf_int32)ntohs(addr));
2612,2613c3030,3031
< tmp = gen_mcmp(base_off + 2, BPF_B, (bpf_int32)0x02, (bpf_int32)0x7);
< b2 = gen_cmp(base_off + 2 + offset_sh, BPF_H, (bpf_int32)ntohs(addr));
---
> tmp = gen_mcmp(OR_NET, 2, BPF_B, (bpf_int32)0x02, (bpf_int32)0x7);
> b2 = gen_cmp(OR_NET, 2 + offset_sh, BPF_H, (bpf_int32)ntohs(addr));
2644,2645c3062
< return gen_hostop(addr, mask, dir, ETHERTYPE_IP,
< off_nl + 12, off_nl + 16);
---
> return gen_hostop(addr, mask, dir, ETHERTYPE_IP, 12, 16);
2648,2649c3065
< return gen_hostop(addr, mask, dir, ETHERTYPE_REVARP,
< off_nl + 14, off_nl + 24);
---
> return gen_hostop(addr, mask, dir, ETHERTYPE_REVARP, 14, 24);
2652,2653c3068
< return gen_hostop(addr, mask, dir, ETHERTYPE_ARP,
< off_nl + 14, off_nl + 24);
---
> return gen_hostop(addr, mask, dir, ETHERTYPE_ARP, 14, 24);
2686c3101
< return gen_dnhostop(addr, dir, off_nl);
---
> return gen_dnhostop(addr, dir);
2734a3150,3152
> case Q_RADIO:
> bpf_error("'radio' modifier applied to host");
>
2809,2810c3227
< return gen_hostop6(addr, mask, dir, ETHERTYPE_IPV6,
< off_nl + 8, off_nl + 24);
---
> return gen_hostop6(addr, mask, dir, ETHERTYPE_IPV6, 8, 24);
2841a3259,3261
> case Q_RADIO:
> bpf_error("'radio' modifier applied to host");
>
2873c3293,3296
< else if (linktype == DLT_IEEE802_11)
---
> else if (linktype == DLT_IEEE802_11 ||
> linktype == DLT_IEEE802_11_RADIO_AVS ||
> linktype == DLT_IEEE802_11_RADIO ||
> linktype == DLT_PRISM_HEADER)
2881c3304,3305
< b1 = gen_cmp(SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00);
---
> b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H,
> 0xFF00);
3147a3572,3574
> case Q_RADIO:
> bpf_error("'radio' is not a valid protocol type");
>
3161,3162c3588
< s = new_stmt(BPF_LD|BPF_H|BPF_ABS);
< s->s.k = off_nl + 6;
---
> s = gen_load_a(OR_NET, 6, BPF_H);
3170a3597,3605
> /*
> * Generate a comparison to a port value in the transport-layer header
> * at the specified offset from the beginning of that header.
> *
> * XXX - this handles a variable-length prefix preceding the link-layer
> * header, such as the radiotap or AVS radio prefix, but doesn't handle
> * variable-length link-layer headers (such as Token Ring or 802.11
> * headers).
> */
3176,3189c3611
< struct slist *s;
< struct block *b;
<
< s = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
< s->s.k = off_nl;
<
< s->next = new_stmt(BPF_LD|BPF_IND|BPF_H);
< s->next->s.k = off_nl + off;
<
< b = new_block(JMP(BPF_JEQ));
< b->stmts = s;
< b->s.k = v;
<
< return b;
---
> return gen_cmp(OR_TRAN_IPV4, off, BPF_H, v);
3198c3620
< return gen_cmp(off_nl + 40 + off, BPF_H, v);
---
> return gen_cmp(OR_TRAN_IPV6, off, BPF_H, v);
3209c3631
< tmp = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)proto);
---
> tmp = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)proto);
3299,3300c3721,3722
< /* ip proto 'proto' */
< b0 = gen_cmp(off_nl + 6, BPF_B, (bpf_int32)proto);
---
> /* ip6 proto 'proto' */
> b0 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)proto);
3340c3762
< /* ether proto ip */
---
> /* link proto ip6 */
3365a3788,3992
> /* gen_portrange code */
> static struct block *
> gen_portrangeatom(off, v1, v2)
> int off;
> bpf_int32 v1, v2;
> {
> struct block *b1, *b2;
>
> if (v1 > v2) {
> /*
> * Reverse the order of the ports, so v1 is the lower one.
> */
> bpf_int32 vtemp;
>
> vtemp = v1;
> v1 = v2;
> v2 = vtemp;
> }
>
> b1 = gen_cmp_ge(OR_TRAN_IPV4, off, BPF_H, v1);
> b2 = gen_cmp_le(OR_TRAN_IPV4, off, BPF_H, v2);
>
> gen_and(b1, b2);
>
> return b2;
> }
>
> struct block *
> gen_portrangeop(port1, port2, proto, dir)
> int port1, port2;
> int proto;
> int dir;
> {
> struct block *b0, *b1, *tmp;
>
> /* ip proto 'proto' */
> tmp = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)proto);
> b0 = gen_ipfrag();
> gen_and(tmp, b0);
>
> switch (dir) {
> case Q_SRC:
> b1 = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2);
> break;
>
> case Q_DST:
> b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2);
> break;
>
> case Q_OR:
> case Q_DEFAULT:
> tmp = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2);
> b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2);
> gen_or(tmp, b1);
> break;
>
> case Q_AND:
> tmp = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2);
> b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2);
> gen_and(tmp, b1);
> break;
>
> default:
> abort();
> }
> gen_and(b0, b1);
>
> return b1;
> }
>
> static struct block *
> gen_portrange(port1, port2, ip_proto, dir)
> int port1, port2;
> int ip_proto;
> int dir;
> {
> struct block *b0, *b1, *tmp;
>
> /* link proto ip */
> b0 = gen_linktype(ETHERTYPE_IP);
>
> switch (ip_proto) {
> case IPPROTO_UDP:
> case IPPROTO_TCP:
> case IPPROTO_SCTP:
> b1 = gen_portrangeop(port1, port2, ip_proto, dir);
> break;
>
> case PROTO_UNDEF:
> tmp = gen_portrangeop(port1, port2, IPPROTO_TCP, dir);
> b1 = gen_portrangeop(port1, port2, IPPROTO_UDP, dir);
> gen_or(tmp, b1);
> tmp = gen_portrangeop(port1, port2, IPPROTO_SCTP, dir);
> gen_or(tmp, b1);
> break;
>
> default:
> abort();
> }
> gen_and(b0, b1);
> return b1;
> }
>
> #ifdef INET6
> static struct block *
> gen_portrangeatom6(off, v1, v2)
> int off;
> bpf_int32 v1, v2;
> {
> struct block *b1, *b2;
>
> if (v1 > v2) {
> /*
> * Reverse the order of the ports, so v1 is the lower one.
> */
> bpf_int32 vtemp;
>
> vtemp = v1;
> v1 = v2;
> v2 = vtemp;
> }
>
> b1 = gen_cmp_ge(OR_TRAN_IPV6, off, BPF_H, v1);
> b2 = gen_cmp_le(OR_TRAN_IPV6, off, BPF_H, v2);
>
> gen_and(b1, b2);
>
> return b2;
> }
>
> struct block *
> gen_portrangeop6(port1, port2, proto, dir)
> int port1, port2;
> int proto;
> int dir;
> {
> struct block *b0, *b1, *tmp;
>
> /* ip6 proto 'proto' */
> b0 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)proto);
>
> switch (dir) {
> case Q_SRC:
> b1 = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2);
> break;
>
> case Q_DST:
> b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2);
> break;
>
> case Q_OR:
> case Q_DEFAULT:
> tmp = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2);
> b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2);
> gen_or(tmp, b1);
> break;
>
> case Q_AND:
> tmp = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2);
> b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2);
> gen_and(tmp, b1);
> break;
>
> default:
> abort();
> }
> gen_and(b0, b1);
>
> return b1;
> }
>
> static struct block *
> gen_portrange6(port1, port2, ip_proto, dir)
> int port1, port2;
> int ip_proto;
> int dir;
> {
> struct block *b0, *b1, *tmp;
>
> /* link proto ip6 */
> b0 = gen_linktype(ETHERTYPE_IPV6);
>
> switch (ip_proto) {
> case IPPROTO_UDP:
> case IPPROTO_TCP:
> case IPPROTO_SCTP:
> b1 = gen_portrangeop6(port1, port2, ip_proto, dir);
> break;
>
> case PROTO_UNDEF:
> tmp = gen_portrangeop6(port1, port2, IPPROTO_TCP, dir);
> b1 = gen_portrangeop6(port1, port2, IPPROTO_UDP, dir);
> gen_or(tmp, b1);
> tmp = gen_portrangeop6(port1, port2, IPPROTO_SCTP, dir);
> gen_or(tmp, b1);
> break;
>
> default:
> abort();
> }
> gen_and(b0, b1);
> return b1;
> }
> #endif /* INET6 */
>
3453a4081,4093
> /*
> * We don't handle variable-length radiotap here headers yet.
> * We might want to add BPF instructions to do the protochain
> * work, to simplify that and, on platforms that have a BPF
> * interpreter with the new instructions, let the filtering
> * be done in the kernel. (We already require a modified BPF
> * engine to do the protochain stuff, to support backward
> * branches, and backward branch support is unlikely to appear
> * in kernel BPF engines.)
> */
> if (linktype == DLT_IEEE802_11_RADIO)
> bpf_error("'protochain' not supported with radiotap headers");
>
3457c4097
< * s[0] is a dummy entry to protect other BPF insn from damaged
---
> * s[0] is a dummy entry to protect other BPF insn from damage
3712a4353,4361
> /*
> * Generate code that checks whether the packet is a packet for protocol
> * <proto> and whether the type field in that protocol's header has
> * the value <v>, e.g. if <proto> is Q_IP, it checks whether it's an
> * IP packet and checks the protocol number in the IP header against <v>.
> *
> * If <proto> is Q_DEFAULT, i.e. just "proto" was specified, it checks
> * against Q_IP and Q_IPV6.
> */
3752c4401
< b1 = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)v);
---
> b1 = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)v);
3781c4430
< return gen_cmp(2, BPF_H, (0x03<<8) | v);
---
> return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | v);
3792c4441
< b1 = gen_cmp(off_nl_nosnap+1, BPF_B, (long)v);
---
> b1 = gen_cmp(OR_NET_NOSNAP, 1, BPF_B, (long)v);
3798c4447
< b1 = gen_cmp(off_nl_nosnap, BPF_B, (long)v);
---
> b1 = gen_cmp(OR_NET_NOSNAP, 0, BPF_B, (long)v);
3809c4458
< b1 = gen_cmp(off_nl_nosnap+4, BPF_B, (long)v);
---
> b1 = gen_cmp(OR_NET_NOSNAP, 4, BPF_B, (long)v);
3884c4533
< b1 = gen_cmp(off_nl + 6, BPF_B, (bpf_int32)v);
---
> b1 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)v);
3909a4559,4561
> case Q_RADIO:
> bpf_error("'radio proto' is bogus");
>
3937a4590
> int port1, port2;
3985a4639,4641
> case DLT_IEEE802_11_RADIO_AVS:
> case DLT_IEEE802_11_RADIO:
> case DLT_PRISM_HEADER:
4012,4013c4668,4669
< tmp = gen_cmp(SUNATM_PKT_BEGIN_POS, BPF_H,
< 0xFF00);
---
> tmp = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS,
> BPF_H, 0xFF00);
4144a4801,4844
> case Q_PORTRANGE:
> if (proto != Q_DEFAULT &&
> proto != Q_UDP && proto != Q_TCP && proto != Q_SCTP)
> bpf_error("illegal qualifier of 'portrange'");
> if (pcap_nametoportrange(name, &port1, &port2, &real_proto) == 0)
> bpf_error("unknown port in range '%s'", name);
> if (proto == Q_UDP) {
> if (real_proto == IPPROTO_TCP)
> bpf_error("port in range '%s' is tcp", name);
> else if (real_proto == IPPROTO_SCTP)
> bpf_error("port in range '%s' is sctp", name);
> else
> /* override PROTO_UNDEF */
> real_proto = IPPROTO_UDP;
> }
> if (proto == Q_TCP) {
> if (real_proto == IPPROTO_UDP)
> bpf_error("port in range '%s' is udp", name);
> else if (real_proto == IPPROTO_SCTP)
> bpf_error("port in range '%s' is sctp", name);
> else
> /* override PROTO_UNDEF */
> real_proto = IPPROTO_TCP;
> }
> if (proto == Q_SCTP) {
> if (real_proto == IPPROTO_UDP)
> bpf_error("port in range '%s' is udp", name);
> else if (real_proto == IPPROTO_TCP)
> bpf_error("port in range '%s' is tcp", name);
> else
> /* override PROTO_UNDEF */
> real_proto = IPPROTO_SCTP;
> }
> #ifndef INET6
> return gen_portrange(port1, port2, real_proto, dir);
> #else
> {
> struct block *b;
> b = gen_portrange(port1, port2, real_proto, dir);
> gen_or(gen_portrange6(port1, port2, real_proto, dir), b);
> return b;
> }
> #endif /* INET6 */
>
4291a4992,5014
> case Q_PORTRANGE:
> if (proto == Q_UDP)
> proto = IPPROTO_UDP;
> else if (proto == Q_TCP)
> proto = IPPROTO_TCP;
> else if (proto == Q_SCTP)
> proto = IPPROTO_SCTP;
> else if (proto == Q_DEFAULT)
> proto = PROTO_UNDEF;
> else
> bpf_error("illegal qualifier of 'portrange'");
>
> #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 */
>
4386c5109,5112
< if (linktype == DLT_IEEE802_11)
---
> if (linktype == DLT_IEEE802_11 ||
> linktype == DLT_IEEE802_11_RADIO_AVS ||
> linktype == DLT_IEEE802_11_RADIO ||
> linktype == DLT_PRISM_HEADER)
4394c5120,5121
< tmp = gen_cmp(SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00);
---
> tmp = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H,
> 0xFF00);
4446a5174,5180
> /*
> * Modify "index" to use the value stored into its register as an
> * offset relative to the beginning of the header for the protocol
> * "proto", and allocate a register and put an item "size" bytes long
> * (1, 2, or 4) at that offset into that register, making it the register
> * for "index".
> */
4478a5213,5237
> case Q_RADIO:
> /*
> * The offset is relative to the beginning of the packet
> * data, if we have a radio header. (If we don't, this
> * is an error.)
> */
> if (linktype != DLT_IEEE802_11_RADIO_AVS &&
> linktype != DLT_IEEE802_11_RADIO &&
> linktype != DLT_PRISM_HEADER)
> bpf_error("radio information not present in capture");
>
> /*
> * Load into the X register the offset computed into the
> * register specifed by "index".
> */
> s = xfer_to_x(index);
>
> /*
> * Load the item at that offset.
> */
> tmp = new_stmt(BPF_LD|BPF_IND|size);
> sappend(s, tmp);
> sappend(index->s, s);
> break;
>
4480a5240,5242
> * The offset is relative to the beginning of
> * the link-layer header.
> *
4488c5250,5274
< s = xfer_to_x(index);
---
> s = gen_llprefixlen();
>
> /*
> * If "s" is non-null, it has code to arrange that the
> * X register contains the length of the prefix preceding
> * the link-layer header. Add to it the offset computed
> * into the register specified by "index", and move that
> * into the X register. Otherwise, just load into the X
> * register the offset computed into the register specifed
> * by "index".
> */
> if (s != NULL) {
> sappend(s, xfer_to_a(index));
> sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
> sappend(s, new_stmt(BPF_MISC|BPF_TAX));
> } else
> s = xfer_to_x(index);
>
> /*
> * Load the item at the sum of the offset we've put in the
> * X register and the offset of the start of the link
> * layer header (which is 0 if the radio header is
> * variable-length; that header length is what we put
> * into the X register and then added to the index).
> */
4489a5276
> tmp->s.k = off_ll;
4506,4507c5293,5321
< /* XXX Note that we assume a fixed link header here. */
< s = xfer_to_x(index);
---
> /*
> * The offset is relative to the beginning of
> * the network-layer header.
> * XXX - are there any cases where we want
> * off_nl_nosnap?
> */
> s = gen_llprefixlen();
>
> /*
> * If "s" is non-null, it has code to arrange that the
> * X register contains the length of the prefix preceding
> * the link-layer header. Add to it the offset computed
> * into the register specified by "index", and move that
> * into the X register. Otherwise, just load into the X
> * register the offset computed into the register specifed
> * by "index".
> */
> if (s != NULL) {
> sappend(s, xfer_to_a(index));
> sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
> sappend(s, new_stmt(BPF_MISC|BPF_TAX));
> } else
> s = xfer_to_x(index);
>
> /*
> * Load the item at the sum of the offset we've put in the
> * X register and the offset of the start of the network
> * layer header.
> */
4512a5327,5330
> /*
> * Do the computation only if the packet contains
> * the protocol in question.
> */
4527,4528c5345,5367
< s = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
< s->s.k = off_nl;
---
> /*
> * The offset is relative to the beginning of
> * the transport-layer header.
> * XXX - are there any cases where we want
> * off_nl_nosnap?
> * XXX - we should, if we're built with
> * IPv6 support, generate code to load either
> * IPv4, IPv6, or both, as appropriate.
> */
> s = gen_loadx_iphdrlen();
>
> /*
> * The X register now contains the sum of the offset
> * of the beginning of the link-layer header and
> * the length of the network-layer header. Load
> * into the A register the offset relative to
> * the beginning of the transport layer header,
> * add the X register to that, move that to the
> * X register, and load with an offset from the
> * X register equal to the offset of the network
> * layer header relative to the beginning of
> * the link-layer header.
> */
4535a5375,5380
> /*
> * Do the computation only if the packet contains
> * the protocol in question - which is true only
> * if this is an IP datagram and is the first or
> * only fragment of that datagram.
> */
4760a5606,5615
> /*
> * This is for "byte {idx} {op} {val}"; "idx" is treated as relative to
> * the beginning of the link-layer header.
> * XXX - that means you can't test values in the radiotap header, but
> * as that header is difficult if not impossible to parse generally
> * without a loop, that might not be a severe problem. A new keyword
> * "radio" could be added for that, although what you'd really want
> * would be a way of testing particular radio header values, which
> * would generate code appropriate to the radio header in question.
> */
4773c5628
< return gen_cmp((u_int)idx, BPF_B, (bpf_int32)val);
---
> return gen_cmp(OR_LINK, (u_int)idx, BPF_B, (bpf_int32)val);
4776,4778c5631
< b = gen_cmp((u_int)idx, BPF_B, (bpf_int32)val);
< b->s.code = JMP(BPF_JGE);
< gen_not(b);
---
> b = gen_cmp_lt(OR_LINK, (u_int)idx, BPF_B, (bpf_int32)val);
4782,4783c5635
< b = gen_cmp((u_int)idx, BPF_B, (bpf_int32)val);
< b->s.code = JMP(BPF_JGT);
---
> b = gen_cmp_gt(OR_LINK, (u_int)idx, BPF_B, (bpf_int32)val);
4824c5676,5679
< if (linktype == DLT_IEEE802_11)
---
> if (linktype == DLT_IEEE802_11 ||
> linktype == DLT_IEEE802_11_RADIO_AVS ||
> linktype == DLT_IEEE802_11_RADIO ||
> linktype == DLT_PRISM_HEADER)
4834c5689,5690
< b1 = gen_cmp(SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00);
---
> b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H,
> 0xFF00);
4850,4851c5706,5707
< b1 = gen_mcmp(off_nl + 16, BPF_W, (bpf_int32)0, hostmask);
< b2 = gen_mcmp(off_nl + 16, BPF_W,
---
> b1 = gen_mcmp(OR_NET, 16, BPF_W, (bpf_int32)0, hostmask);
> b2 = gen_mcmp(OR_NET, 16, BPF_W,
4873,4874c5729
< s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
< s->s.k = offset;
---
> s = gen_load_a(OR_LINK, offset, BPF_B);
4916c5771,5774
< if (linktype == DLT_IEEE802_11) {
---
> if (linktype == DLT_IEEE802_11 ||
> linktype == DLT_IEEE802_11_RADIO_AVS ||
> linktype == DLT_IEEE802_11_RADIO ||
> linktype == DLT_PRISM_HEADER) {
4938,4939c5796
< s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
< s->s.k = 1;
---
> s = gen_load_a(OR_LINK, 1, BPF_B);
4954,4955c5811
< s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
< s->s.k = 1;
---
> s = gen_load_a(OR_LINK, 1, BPF_B);
4977,4978c5833
< s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
< s->s.k = 0;
---
> s = gen_load_a(OR_LINK, 0, BPF_B);
4993,4994c5848
< s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
< s->s.k = 0;
---
> s = gen_load_a(OR_LINK, 0, BPF_B);
5021,5022c5875
< s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
< s->s.k = 0;
---
> s = gen_load_a(OR_LINK, 0, BPF_B);
5047c5900,5901
< b1 = gen_cmp(SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00);
---
> b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H,
> 0xFF00);
5061,5062c5915
< b1 = gen_cmp(off_nl + 16, BPF_B, (bpf_int32)224);
< b1->s.code = JMP(BPF_JGE);
---
> b1 = gen_cmp_ge(OR_NET, 16, BPF_B, (bpf_int32)224);
5069c5922
< b1 = gen_cmp(off_nl + 24, BPF_B, (bpf_int32)255);
---
> b1 = gen_cmp(OR_NET, 24, BPF_B, (bpf_int32)255);
5105c5958
< b0 = gen_cmp(0, BPF_H, LINUX_SLL_OUTGOING);
---
> b0 = gen_cmp(OR_LINK, 0, BPF_H, LINUX_SLL_OUTGOING);
5117c5970
< b0 = gen_cmp(0, BPF_H, LINUX_SLL_HOST);
---
> b0 = gen_cmp(OR_LINK, 0, BPF_H, LINUX_SLL_HOST);
5122c5975
< b0 = gen_cmp(offsetof(struct pfloghdr, dir), BPF_B,
---
> b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, dir), BPF_B,
5129c5982
< b0 = gen_cmp(0, BPF_B, PPP_PPPD_OUT);
---
> b0 = gen_cmp(OR_LINK, 0, BPF_B, PPP_PPPD_OUT);
5132c5985
< b0 = gen_cmp(0, BPF_B, PPP_PPPD_IN);
---
> b0 = gen_cmp(OR_LINK, 0, BPF_B, PPP_PPPD_IN);
5139a5993,5998
> case DLT_JUNIPER_PPPOE:
> case DLT_JUNIPER_PPPOE_ATM:
> case DLT_JUNIPER_GGSN:
> case DLT_JUNIPER_ES:
> case DLT_JUNIPER_MONITOR:
> case DLT_JUNIPER_SERVICES:
5144c6003
< b0 = gen_mcmp(3, BPF_B, 0, 0x01);
---
> b0 = gen_mcmp(OR_LINK, 3, BPF_B, 0, 0x01);
5147c6006
< b0 = gen_mcmp(3, BPF_B, 1, 0x01);
---
> b0 = gen_mcmp(OR_LINK, 3, BPF_B, 1, 0x01);
5179c6038
< b0 = gen_bcmp(off, strlen(ifname), (const u_char *)ifname);
---
> b0 = gen_bcmp(OR_LINK, off, strlen(ifname), (const u_char *)ifname);
5198c6057
< b0 = gen_bcmp(offsetof(struct pfloghdr, ruleset),
---
> b0 = gen_bcmp(OR_LINK, offsetof(struct pfloghdr, ruleset),
5210c6069
< b0 = gen_cmp(offsetof(struct pfloghdr, rulenr), BPF_W,
---
> b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, rulenr), BPF_W,
5231c6090
< b0 = gen_cmp(offsetof(struct pfloghdr, subrulenr), BPF_W,
---
> b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, subrulenr), BPF_W,
5243c6102
< b0 = gen_cmp(offsetof(struct pfloghdr, reason), BPF_B,
---
> b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, reason), BPF_B,
5260c6119
< b0 = gen_cmp(offsetof(struct pfloghdr, action), BPF_B,
---
> b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, action), BPF_B,
5293c6152
< return gen_bcmp(0, 1, eaddr);
---
> return gen_bcmp(OR_LINK, 0, 1, eaddr);
5296c6155
< return gen_bcmp(1, 1, eaddr);
---
> return gen_bcmp(OR_LINK, 1, 1, eaddr);
5326c6185,6211
< * the VLAN packet. This is somewhat of a kludge.
---
> * the VLAN packet. Just increment the offsets, so that we
> * can support a hierarchy, e.g. "vlan 300 && vlan 200" to
> * capture VLAN 200 encapsulated within VLAN 100.
> *
> * XXX - this is a bit of a kludge. If we were to split the
> * compiler into a parser that parses an expression and
> * generates an expression tree, and a code generator that
> * takes an expression tree (which could come from our
> * parser or from some other parser) and generates BPF code,
> * we could perhaps make the offsets parameters of routines
> * and, in the handler for an "AND" node, pass to subnodes
> * other than the VLAN node the adjusted offsets.
> *
> * This would mean that "vlan" would, instead of changing the
> * behavior of *all* tests after it, change only the behavior
> * of tests ANDed with it. That would change the documented
> * semantics of "vlan", which might break some expressions.
> * However, it would mean that "(vlan and ip) or ip" would check
> * both for VLAN-encapsulated IP and IP-over-Ethernet, rather than
> * checking only for VLAN-encapsulated IP, so that could still
> * be considered worth doing; it wouldn't break expressions
> * that are of the form "vlan and ..." or "vlan N and ...",
> * which I suspect are the most common expressions involving
> * "vlan". "vlan or ..." doesn't necessarily do what the user
> * would really want, now, as all the "or ..." tests would
> * be done assuming a VLAN, even though the "or" could be viewed
> * as meaning "or, if this isn't a VLAN packet...".
5328,5331c6213,6214
< if (orig_nl == (u_int)-1) {
< orig_linktype = off_linktype; /* save original values */
< orig_nl = off_nl;
< orig_nl_nosnap = off_nl_nosnap;
---
> orig_linktype = off_linktype; /* save original values */
> orig_nl = off_nl;
5333c6216
< switch (linktype) {
---
> switch (linktype) {
5335,5339c6218,6222
< case DLT_EN10MB:
< off_linktype = 16;
< off_nl_nosnap = 18;
< off_nl = 18;
< break;
---
> case DLT_EN10MB:
> off_linktype += 4;
> off_nl_nosnap += 4;
> off_nl += 4;
> break;
5341,5346c6224,6228
< default:
< bpf_error("no VLAN support for data link type %d",
< linktype);
< /*NOTREACHED*/
< }
< }
---
> default:
> bpf_error("no VLAN support for data link type %d",
> linktype);
> /*NOTREACHED*/
> }
5349c6231
< b0 = gen_cmp(orig_linktype, BPF_H, (bpf_int32)ETHERTYPE_8021Q);
---
> b0 = gen_cmp(OR_LINK, orig_linktype, BPF_H, (bpf_int32)ETHERTYPE_8021Q);
5355c6237,6238
< b1 = gen_mcmp(orig_nl, BPF_H, (bpf_int32)vlan_num, 0x0fff);
---
> b1 = gen_mcmp(OR_LINK, orig_nl, BPF_H, (bpf_int32)vlan_num,
> 0x0fff);
5374c6257,6262
< * the MPLS packet. This is somewhat of a kludge.
---
> * the MPLS packet. Just increment the offsets, so that we
> * can support a hierarchy, e.g. "mpls 100000 && mpls 1024" to
> * capture packets with an outer label of 100000 and an inner
> * label of 1024.
> *
> * XXX - this is a bit of a kludge. See comments in gen_vlan().
5376,5379c6264,6265
< if (orig_nl == (u_int)-1) {
< orig_linktype = off_linktype; /* save original values */
< orig_nl = off_nl;
< orig_nl_nosnap = off_nl_nosnap;
---
> orig_linktype = off_linktype; /* save original values */
> orig_nl = off_nl;
5381c6267,6276
< switch (linktype) {
---
> switch (linktype) {
>
> case DLT_C_HDLC: /* fall through */
> case DLT_EN10MB:
> off_nl_nosnap += 4;
> off_nl += 4;
>
> b0 = gen_cmp(OR_LINK, orig_linktype, BPF_H,
> (bpf_int32)ETHERTYPE_MPLS);
> break;
5383,5386c6278,6280
< case DLT_EN10MB:
< off_linktype = 16;
< off_nl_nosnap = 18;
< off_nl = 18;
---
> case DLT_PPP:
> off_nl_nosnap += 4;
> off_nl += 4;
5388,5389c6282,6284
< b0 = gen_cmp(orig_linktype, BPF_H, (bpf_int32)ETHERTYPE_MPLS);
< break;
---
> b0 = gen_cmp(OR_LINK, orig_linktype, BPF_H,
> (bpf_int32)PPP_MPLS_UCAST);
> break;
5391,5394c6286,6288
< case DLT_PPP:
< off_linktype = 6;
< off_nl_nosnap = 8;
< off_nl = 8;
---
> /* FIXME add other DLT_s ...
> * for Frame-Relay/and ATM this may get messy due to SNAP headers
> * leave it for now */
5396,5397c6290,6296
< b0 = gen_cmp(orig_linktype, BPF_H, (bpf_int32)PPP_MPLS_UCAST);
< break;
---
> default:
> bpf_error("no MPLS support for data link type %d",
> linktype);
> b0 = NULL;
> /*NOTREACHED*/
> break;
> }
5399,5422d6297
< case DLT_C_HDLC:
< off_linktype = 6;
< off_nl_nosnap = 8;
< off_nl = 8;
<
< b0 = gen_cmp(orig_linktype, BPF_H, (bpf_int32)ETHERTYPE_MPLS);
< break;
<
< /* FIXME add other DLT_s ...
< * for Frame-Relay/and ATM this may get messy due to SNAP headers
< * leave it for now */
<
< default:
< bpf_error("no MPLS support for data link type %d",
< linktype);
< b0 = NULL;
< /*NOTREACHED*/
< }
< } else {
< bpf_error("'mpls' can't be combined with 'vlan' or another 'mpls'");
< b0 = NULL;
< /*NOTREACHED*/
< }
<
5428c6303,6304
< b1 = gen_mcmp(orig_nl, BPF_W, (bpf_int32)label_num, 0xfffff000); /* only compare the first 20 bits */
---
> b1 = gen_mcmp(OR_LINK, orig_nl, BPF_W, (bpf_int32)label_num,
> 0xfffff000); /* only compare the first 20 bits */
5439c6315
< bpf_u_int32 jvalue;
---
> bpf_int32 jvalue;
5452,5453c6328,6329
< b0 = gen_ncmp(BPF_B, off_vpi, 0xffffffff, (u_int)jtype,
< (u_int)jvalue, reverse);
---
> b0 = gen_ncmp(OR_LINK, off_vpi, BPF_B, 0xffffffff, jtype,
> reverse, jvalue);
5461,5462c6337,6338
< b0 = gen_ncmp(BPF_H, off_vci, 0xffffffff, (u_int)jtype,
< (u_int)jvalue, reverse);
---
> b0 = gen_ncmp(OR_LINK, off_vci, BPF_H, 0xffffffff, jtype,
> reverse, jvalue);
5468,5469c6344,6345
< b0 = gen_ncmp(BPF_B, off_proto, 0x0f, (u_int)jtype,
< (u_int)jvalue, reverse);
---
> b0 = gen_ncmp(OR_LINK, off_proto, BPF_B, 0x0f, jtype,
> reverse, jvalue);
5475,5476c6351,6352
< b0 = gen_ncmp(BPF_B, off_payload + MSG_TYPE_POS, 0xffffffff,
< (u_int)jtype, (u_int)jvalue, reverse);
---
> b0 = gen_ncmp(OR_LINK, off_payload + MSG_TYPE_POS, BPF_B,
> 0xffffffff, jtype, reverse, jvalue);
5484,5485c6360,6361
< b0 = gen_ncmp(BPF_B, off_proto, 0xffffffff, (u_int)jtype,
< (u_int)jvalue, reverse);
---
> b0 = gen_ncmp(OR_LINK, off_proto, BPF_B, 0xffffffff,
> jtype, reverse, jvalue);
5594a6471,6479
> struct block *
> gen_mtp3field_code(mtp3field, jvalue, jtype, reverse)
> int mtp3field;
> bpf_u_int32 jvalue;
> bpf_u_int32 jtype;
> int reverse;
> {
> struct block *b0;
> bpf_u_int32 val1 , val2 , val3;
5595a6481,6551
> switch (mtp3field) {
>
> case M_SIO:
> if (off_sio == (u_int)-1)
> bpf_error("'sio' supported only on SS7");
> /* sio coded on 1 byte so max value 255 */
> if(jvalue > 255)
> bpf_error("sio value %u too big; max value = 255",
> jvalue);
> b0 = gen_ncmp(OR_PACKET, off_sio, BPF_B, 0xffffffff,
> (u_int)jtype, reverse, (u_int)jvalue);
> break;
>
> case M_OPC:
> if (off_opc == (u_int)-1)
> bpf_error("'opc' supported only on SS7");
> /* opc coded on 14 bits so max value 16383 */
> if (jvalue > 16383)
> bpf_error("opc value %u too big; max value = 16383",
> jvalue);
> /* the following instructions are made to convert jvalue
> * to the form used to write opc in an ss7 message*/
> val1 = jvalue & 0x00003c00;
> val1 = val1 >>10;
> val2 = jvalue & 0x000003fc;
> val2 = val2 <<6;
> val3 = jvalue & 0x00000003;
> val3 = val3 <<22;
> jvalue = val1 + val2 + val3;
> b0 = gen_ncmp(OR_PACKET, off_opc, BPF_W, 0x00c0ff0f,
> (u_int)jtype, reverse, (u_int)jvalue);
> break;
>
> case M_DPC:
> if (off_dpc == (u_int)-1)
> bpf_error("'dpc' supported only on SS7");
> /* dpc coded on 14 bits so max value 16383 */
> if (jvalue > 16383)
> bpf_error("dpc value %u too big; max value = 16383",
> jvalue);
> /* the following instructions are made to convert jvalue
> * to the forme used to write dpc in an ss7 message*/
> val1 = jvalue & 0x000000ff;
> val1 = val1 << 24;
> val2 = jvalue & 0x00003f00;
> val2 = val2 << 8;
> jvalue = val1 + val2;
> b0 = gen_ncmp(OR_PACKET, off_dpc, BPF_W, 0xff3f0000,
> (u_int)jtype, reverse, (u_int)jvalue);
> break;
>
> case M_SLS:
> if (off_sls == (u_int)-1)
> bpf_error("'sls' supported only on SS7");
> /* sls coded on 4 bits so max value 15 */
> if (jvalue > 15)
> bpf_error("sls value %u too big; max value = 15",
> jvalue);
> /* 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,
> (u_int)jtype,reverse, (u_int)jvalue);
> break;
>
> default:
> abort();
> }
> return b0;
> }
>
< * $FreeBSD: head/contrib/libpcap/gencode.c 146771 2005-05-29 18:09:04Z sam $
---
> * $FreeBSD: head/contrib/libpcap/gencode.c 147897 2005-07-11 03:43:25Z sam $
26c26
< "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.221 2005/03/27 22:10:23 guy Exp $ (LBL)";
---
> "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.221.2.24 2005/06/20 21:52:53 guy Exp $ (LBL)";
107c107
< static u_int orig_linktype = -1U, orig_nl = -1U, orig_nl_nosnap = -1U;
---
> static u_int orig_linktype = -1U, orig_nl = -1U;
117d116
<
137a137,149
> * Value passed to gen_load_a() to indicate what the offset argument
> * is relative to.
> */
> enum e_offrel {
> OR_PACKET, /* relative to the beginning of the packet */
> OR_LINK, /* relative to the link-layer header */
> OR_NET, /* relative to the network-layer header */
> OR_NET_NOSNAP, /* relative to the network-layer header, with no SNAP header at the link layer */
> OR_TRAN_IPV4, /* relative to the transport-layer header, with IPv4 network layer */
> OR_TRAN_IPV6 /* relative to the transport-layer header, with IPv6 network layer */
> };
>
> /*
164,169c176,188
< static struct block *gen_cmp(u_int, u_int, bpf_int32);
< static struct block *gen_cmp_gt(u_int, u_int, bpf_int32);
< static struct block *gen_mcmp(u_int, u_int, bpf_int32, bpf_u_int32);
< static struct block *gen_bcmp(u_int, u_int, const u_char *);
< static struct block *gen_ncmp(bpf_u_int32, bpf_u_int32, bpf_u_int32,
< bpf_u_int32, bpf_u_int32, int);
---
> static struct block *gen_cmp(enum e_offrel, u_int, u_int, bpf_int32);
> static struct block *gen_cmp_gt(enum e_offrel, u_int, u_int, bpf_int32);
> static struct block *gen_cmp_ge(enum e_offrel, u_int, u_int, bpf_int32);
> static struct block *gen_cmp_lt(enum e_offrel, u_int, u_int, bpf_int32);
> static struct block *gen_cmp_le(enum e_offrel, u_int, u_int, bpf_int32);
> static struct block *gen_mcmp(enum e_offrel, u_int, u_int, bpf_int32,
> bpf_u_int32);
> static struct block *gen_bcmp(enum e_offrel, u_int, u_int, const u_char *);
> static struct block *gen_ncmp(enum e_offrel, bpf_u_int32, bpf_u_int32,
> bpf_u_int32, bpf_u_int32, int, bpf_int32);
> static struct slist *gen_load_llrel(u_int, u_int);
> static struct slist *gen_load_a(enum e_offrel, u_int, u_int);
> static struct slist *gen_loadx_iphdrlen(void);
174a194,196
> static void insert_radiotap_load_llprefixlen(struct block *);
> static void insert_load_llprefixlen(struct block *);
> static struct slist *gen_llprefixlen(void);
177c199
< static struct block *gen_llc(int);
---
> static struct block *gen_llc_linktype(int);
188c210
< static struct block *gen_dnhostop(bpf_u_int32, int, u_int);
---
> static struct block *gen_dnhostop(bpf_u_int32, int);
197a220
> static struct block *gen_portrangeatom(int, bpf_int32, bpf_int32);
199a223
> static struct block *gen_portrangeatom6(int, bpf_int32, bpf_int32);
202a227,228
> struct block *gen_portrangeop(int, int, int, int);
> static struct block *gen_portrange(int, int, int, int);
205a232,233
> struct block *gen_portrangeop6(int, int, int, int);
> static struct block *gen_portrange6(int, int, int, int);
456a485,501
>
> /*
> * Insert before the statements of the first (root) block any
> * statements needed to load the lengths of any variable-length
> * headers into registers.
> *
> * XXX - a fancier strategy would be to insert those before the
> * statements of all blocks that use those lengths and that
> * have no predecessors that use them, so that we only compute
> * the lengths if we need them. There might be even better
> * approaches than that. However, as we're currently only
> * handling variable-length radiotap headers, and as all
> * filtering expressions other than raw link[M:N] tests
> * require the length of that header, doing more for that
> * header length isn't really worth the effort.
> */
> insert_load_llprefixlen(root);
490c535,536
< gen_cmp(offset, size, v)
---
> gen_cmp(offrel, offset, size, v)
> enum e_offrel offrel;
494,495c540,541
< struct slist *s;
< struct block *b;
---
> return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JEQ, 0, v);
> }
497,498c543,550
< s = new_stmt(BPF_LD|BPF_ABS|size);
< s->s.k = offset;
---
> static struct block *
> gen_cmp_gt(offrel, offset, size, v)
> enum e_offrel offrel;
> u_int offset, size;
> bpf_int32 v;
> {
> return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGT, 0, v);
> }
500,504c552,558
< b = new_block(JMP(BPF_JEQ));
< b->stmts = s;
< b->s.k = v;
<
< return b;
---
> static struct block *
> gen_cmp_ge(offrel, offset, size, v)
> enum e_offrel offrel;
> u_int offset, size;
> bpf_int32 v;
> {
> return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGE, 0, v);
508c562,563
< gen_cmp_gt(offset, size, v)
---
> gen_cmp_lt(offrel, offset, size, v)
> enum e_offrel offrel;
512,513c567,568
< struct slist *s;
< struct block *b;
---
> return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGE, 1, v);
> }
515,522c570,576
< s = new_stmt(BPF_LD|BPF_ABS|size);
< s->s.k = offset;
<
< b = new_block(JMP(BPF_JGT));
< b->stmts = s;
< b->s.k = v;
<
< return b;
---
> static struct block *
> gen_cmp_le(offrel, offset, size, v)
> enum e_offrel offrel;
> u_int offset, size;
> bpf_int32 v;
> {
> return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGT, 1, v);
526c580,581
< gen_mcmp(offset, size, v, mask)
---
> gen_mcmp(offrel, offset, size, v, mask)
> enum e_offrel offrel;
531,539c586
< struct block *b = gen_cmp(offset, size, v);
< struct slist *s;
<
< if (mask != 0xffffffff) {
< s = new_stmt(BPF_ALU|BPF_AND|BPF_K);
< s->s.k = mask;
< b->stmts->next = s;
< }
< return b;
---
> return gen_ncmp(offrel, offset, size, mask, BPF_JEQ, 0, v);
543c590,591
< gen_bcmp(offset, size, v)
---
> gen_bcmp(offrel, offset, size, v)
> enum e_offrel offrel;
555c603
< tmp = gen_cmp(offset + size - 4, BPF_W, w);
---
> tmp = gen_cmp(offrel, offset + size - 4, BPF_W, w);
565c613
< tmp = gen_cmp(offset + size - 2, BPF_H, w);
---
> tmp = gen_cmp(offrel, offset + size - 2, BPF_H, w);
572c620
< tmp = gen_cmp(offset, BPF_B, (bpf_int32)v[0]);
---
> tmp = gen_cmp(offrel, offset, BPF_B, (bpf_int32)v[0]);
579a628,633
> /*
> * AND the field of size "size" at offset "offset" relative to the header
> * specified by "offrel" with "mask", and compare it with the value "v"
> * with the test specified by "jtype"; if "reverse" is true, the test
> * should test the opposite of "jtype".
> */
581,582c635,638
< gen_ncmp(datasize, offset, mask, jtype, jvalue, reverse)
< bpf_u_int32 datasize, offset, mask, jtype, jvalue;
---
> gen_ncmp(offrel, offset, size, mask, jtype, reverse, v)
> enum e_offrel offrel;
> bpf_int32 v;
> bpf_u_int32 offset, size, mask, jtype;
585c641
< struct slist *s;
---
> struct slist *s, *s2;
588,589c644
< s = new_stmt(BPF_LD|datasize|BPF_ABS);
< s->s.k = offset;
---
> s = gen_load_a(offrel, offset, size);
592,593c647,649
< s->next = new_stmt(BPF_ALU|BPF_AND|BPF_K);
< s->next->s.k = mask;
---
> s2 = new_stmt(BPF_ALU|BPF_AND|BPF_K);
> s2->s.k = mask;
> sappend(s, s2);
598c654
< b->s.k = jvalue;
---
> b->s.k = v;
606c662,668
< * layer. These variables give the necessary offsets.
---
> * layer. These variables give the necessary offsets from the beginning
> * of the packet data.
> *
> * If the link layer has variable_length headers, the offsets are offsets
> * from the end of the link-link-layer header, and "reg_ll_size" is
> * the register number for a register containing the length of the
> * link-layer header. Otherwise, "reg_ll_size" is -1.
607a670
> static int reg_ll_size;
609a673,678
> * This is the offset of the beginning of the link-layer header.
> * It's usually 0, except for 802.11 with a fixed-length radio header.
> */
> static u_int off_ll;
>
> /*
654a724,731
> * These are offsets for the MTP3 fields.
> */
> static u_int off_sio;
> static u_int off_opc;
> static u_int off_dpc;
> static u_int off_sls;
>
> /*
706a784,793
> off_sio = -1;
> off_opc = -1;
> off_dpc = -1;
> off_sls = -1;
>
> /*
> * Also assume it's not 802.11 with a fixed-length radio header.
> */
> off_ll = 0;
>
709d795
< orig_nl_nosnap = -1;
710a797,798
> reg_ll_size = -1;
>
867a956
> off_ll = 144;
887a977
> off_ll = 64;
899,909c989,992
< * XXX - same variable-length header problem, only
< * even *more* so; this header is also variable-length,
< * with the length being the 16-bit number at an offset
< * of 2 from the beginning of the radio header, and it's
< * device-dependent (different devices might supply
< * different amounts of information), so we can't even
< * assume a fixed length for the current version of the
< * header.
< *
< * Therefore, currently, only raw "link[N:M]" filtering is
< * supported.
---
> * The radiotap header is variable length, and we
> * generate code to compute its length and store it
> * in a register. These offsets are relative to the
> * beginning of the 802.11 header.
911,913c994,996
< off_linktype = -1;
< off_nl = -1;
< off_nl_nosnap = -1;
---
> off_linktype = 24;
> off_nl = 32; /* 802.11+802.2+SNAP */
> off_nl_nosnap = 27; /* 802.11+802.2 */
920a1004,1010
> *
> * XXX - what about ISO PDUs, e.g. CLNP, ISIS, ESIS,
> * or PPP with the PPP NLPID (e.g., PPPoA)? The
> * latter would presumably be treated the way PPPoE
> * should be, so you can do "pppoe and udp port 2049"
> * or "pppoa and tcp port 80" and have it check for
> * PPPo{A,E} and a PPP protocol of IP and....
995c1085
< off_nl_nosnap = 0; /* no 802.2 LLC */
---
> off_nl_nosnap = 18; /* no 802.2 LLC */
1024c1114
< /* XXX read from header? */
---
> /* XXX read this from pf.h? */
1026c1116
< off_nl_nosnap = PFLOG_HDRLEN;
---
> off_nl_nosnap = PFLOG_HDRLEN; /* no 802.2 LLC */
1033c1123
< off_nl_nosnap = -1;
---
> off_nl_nosnap = -1; /* no 802.2 LLC */
1047a1138,1185
> /* frames captured on a Juniper PPPoE service PIC
> * contain raw ethernet frames */
> case DLT_JUNIPER_PPPOE:
> off_linktype = 16;
> off_nl = 18; /* Ethernet II */
> off_nl_nosnap = 21; /* 802.3+802.2 */
> return;
>
> case DLT_JUNIPER_PPPOE_ATM:
> off_linktype = 4;
> off_nl = 6;
> off_nl_nosnap = -1; /* no 802.2 LLC */
> return;
>
> case DLT_JUNIPER_GGSN:
> off_linktype = 6;
> off_nl = 12;
> off_nl_nosnap = -1; /* no 802.2 LLC */
> return;
>
> case DLT_JUNIPER_ES:
> off_linktype = 6;
> off_nl = -1; /* not really a network layer but raw IP adresses */
> off_nl_nosnap = -1; /* no 802.2 LLC */
> return;
>
> case DLT_JUNIPER_MONITOR:
> off_linktype = 12;
> off_nl = 12; /* raw IP/IP6 header */
> off_nl_nosnap = -1; /* no 802.2 LLC */
> return;
>
> case DLT_JUNIPER_SERVICES:
> off_linktype = 12;
> off_nl = -1; /* L3 proto location dep. on cookie type */
> off_nl_nosnap = -1; /* no 802.2 LLC */
> return;
>
> case DLT_MTP2:
> off_sio = 3;
> off_opc = 4;
> off_dpc = 4;
> off_sls = 7;
> off_linktype = -1;
> off_nl = -1;
> off_nl_nosnap = -1;
> return;
>
1054a1193,1201
>
> case DLT_LINUX_LAPD:
> /*
> * Currently, only raw "link[N:M]" filtering is supported.
> */
> off_linktype = -1;
> off_nl = -1;
> off_nl_nosnap = -1;
> return;
1059a1207,1344
> /*
> * Load a value relative to the beginning of the link-layer header.
> * The link-layer header doesn't necessarily begin at the beginning
> * of the packet data; there might be a variable-length prefix containing
> * radio information.
> */
> static struct slist *
> gen_load_llrel(offset, size)
> u_int offset, size;
> {
> struct slist *s, *s2;
>
> s = gen_llprefixlen();
>
> /*
> * If "s" is non-null, it has code to arrange that the X register
> * contains the length of the prefix preceding the link-layer
> * header.
> */
> if (s != NULL) {
> s2 = new_stmt(BPF_LD|BPF_IND|size);
> s2->s.k = offset;
> sappend(s, s2);
> } else {
> s = new_stmt(BPF_LD|BPF_ABS|size);
> s->s.k = offset;
> }
> return s;
> }
>
> /*
> * Load a value relative to the beginning of the specified header.
> */
> static struct slist *
> gen_load_a(offrel, offset, size)
> enum e_offrel offrel;
> u_int offset, size;
> {
> struct slist *s, *s2;
>
> switch (offrel) {
>
> case OR_PACKET:
> s = gen_load_llrel(offset, size);
> break;
>
> case OR_LINK:
> s = gen_load_llrel(off_ll + offset, size);
> break;
>
> case OR_NET:
> s = gen_load_llrel(off_nl + offset, size);
> break;
>
> case OR_NET_NOSNAP:
> s = gen_load_llrel(off_nl_nosnap + offset, size);
> break;
>
> case OR_TRAN_IPV4:
> /*
> * Load the X register with the length of the IPv4 header,
> * in bytes.
> */
> s = gen_loadx_iphdrlen();
>
> /*
> * Load the item at {length of the link-layer header} +
> * {length of the IPv4 header} + {specified offset}.
> */
> s2 = new_stmt(BPF_LD|BPF_IND|size);
> s2->s.k = off_nl + offset;
> sappend(s, s2);
> break;
>
> case OR_TRAN_IPV6:
> s = gen_load_llrel(off_nl + 40 + offset, size);
> break;
>
> default:
> abort();
> return NULL;
> }
> return s;
> }
>
> /*
> * Generate code to load into the X register the sum of the length of
> * the IPv4 header and any variable-length header preceding the link-layer
> * header.
> */
> static struct slist *
> gen_loadx_iphdrlen()
> {
> struct slist *s, *s2;
>
> s = gen_llprefixlen();
> if (s != NULL) {
> /*
> * There's a variable-length prefix preceding the
> * link-layer header. "s" points to a list of statements
> * that put the length of that prefix into the X register.
> * The 4*([k]&0xf) addressing mode can't be used, as we
> * don't have a constant offset, so we have to load the
> * value in question into the A register and add to it
> * the value from the X register.
> */
> s2 = new_stmt(BPF_LD|BPF_IND|BPF_B);
> s2->s.k = off_nl;
> sappend(s, s2);
> s2 = new_stmt(BPF_ALU|BPF_AND|BPF_K);
> s2->s.k = 0xf;
> sappend(s, s2);
> s2 = new_stmt(BPF_ALU|BPF_LSH|BPF_K);
> s2->s.k = 2;
> sappend(s, s2);
>
> /*
> * The A register now contains the length of the
> * IP header. We need to add to it the length
> * of the prefix preceding the link-layer
> * header, which is still in the X register, and
> * move the result into the X register.
> */
> sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
> sappend(s, new_stmt(BPF_MISC|BPF_TAX));
> } else {
> /*
> * There is no variable-length header preceding the
> * link-layer header; if there's a fixed-length
> * header preceding it, its length is included in
> * the off_ variables, so it doesn't need to be added.
> */
> s = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
> s->s.k = off_nl;
> }
> return s;
> }
>
1094a1380,1388
> /*
> * Generate code to match a particular packet type.
> *
> * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
> * value, if <= ETHERMTU. We use that to determine whether to
> * match the type/length field or to check the type/length field for
> * a value <= ETHERMTU to see whether it's a type field and then do
> * the appropriate test.
> */
1104,1116d1397
< /*
< * OSI protocols always use 802.2 encapsulation.
< * XXX - should we check both the DSAP and the
< * SSAP, like this, or should we check just the
< * DSAP?
< */
< b0 = gen_cmp_gt(off_linktype, BPF_H, ETHERMTU);
< gen_not(b0);
< b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32)
< ((LLCSAP_ISONS << 8) | LLCSAP_ISONS));
< gen_and(b0, b1);
< return b1;
<
1118,1124d1398
< b0 = gen_cmp_gt(off_linktype, BPF_H, ETHERMTU);
< gen_not(b0);
< b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32)
< ((LLCSAP_IP << 8) | LLCSAP_IP));
< gen_and(b0, b1);
< return b1;
<
1127c1401,1406
< * NetBEUI always uses 802.2 encapsulation.
---
> * OSI protocols and NetBEUI always use 802.2 encapsulation,
> * so we check the DSAP and SSAP.
> *
> * LLCSAP_IP checks for IP-over-802.2, rather
> * than IP-over-Ethernet or IP-over-SNAP.
> *
1130c1409,1410
< * DSAP?
---
> * DSAP, as we do for other types <= ETHERMTU
> * (i.e., other SAP values)?
1132c1412
< b0 = gen_cmp_gt(off_linktype, BPF_H, ETHERMTU);
---
> b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU);
1134,1135c1414,1415
< b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32)
< ((LLCSAP_NETBEUI << 8) | LLCSAP_NETBEUI));
---
> b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_H, (bpf_int32)
> ((proto << 8) | proto));
1172,1173c1452,1455
< b0 = gen_cmp(off_linktype + 2, BPF_B, (bpf_int32)LLCSAP_IPX);
< b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32)0xFFFF);
---
> b0 = gen_cmp(OR_LINK, off_linktype + 2, BPF_B,
> (bpf_int32)LLCSAP_IPX);
> b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_H,
> (bpf_int32)0xFFFF);
1187c1469
< b0 = gen_cmp_gt(off_linktype, BPF_H, ETHERMTU);
---
> b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU);
1203c1485,1486
< b0 = gen_cmp(off_linktype, BPF_H, (bpf_int32)ETHERTYPE_IPX);
---
> b0 = gen_cmp(OR_LINK, off_linktype, BPF_H,
> (bpf_int32)ETHERTYPE_IPX);
1219c1502
< b0 = gen_cmp_gt(off_linktype, BPF_H, ETHERMTU);
---
> b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU);
1244c1527
< b0 = gen_cmp(off_linktype, BPF_H, (bpf_int32)proto);
---
> b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto);
1259c1542
< b0 = gen_cmp_gt(off_linktype, BPF_H, ETHERMTU);
---
> b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU);
1261c1544,1545
< b1 = gen_cmp(off_linktype + 2, BPF_B, (bpf_int32)proto);
---
> b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_B,
> (bpf_int32)proto);
1274c1558,1559
< return gen_cmp(off_linktype, BPF_H, (bpf_int32)proto);
---
> return gen_cmp(OR_LINK, off_linktype, BPF_H,
> (bpf_int32)proto);
1278a1564,1571
> /*
> * Generate code to match a particular packet type.
> *
> * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
> * value, if <= ETHERMTU. We use that to determine whether to
> * match the type field or to check the type field for the special
> * LINUX_SLL_P_802_2 value and then do the appropriate test.
> */
1287,1293d1579
< case LLCSAP_IP:
< b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2);
< b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32)
< ((LLCSAP_IP << 8) | LLCSAP_IP));
< gen_and(b0, b1);
< return b1;
<
1294a1581,1582
> case LLCSAP_IP:
> case LLCSAP_NETBEUI:
1296c1584,1589
< * OSI protocols always use 802.2 encapsulation.
---
> * OSI protocols and NetBEUI always use 802.2 encapsulation,
> * so we check the DSAP and SSAP.
> *
> * LLCSAP_IP checks for IP-over-802.2, rather
> * than IP-over-Ethernet or IP-over-SNAP.
> *
1299c1592,1593
< * DSAP?
---
> * DSAP, as we do for other types <= ETHERMTU
> * (i.e., other SAP values)?
1301,1303c1595,1597
< b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2);
< b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32)
< ((LLCSAP_ISONS << 8) | LLCSAP_ISONS));
---
> b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2);
> b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_H, (bpf_int32)
> ((proto << 8) | proto));
1307,1319d1600
< case LLCSAP_NETBEUI:
< /*
< * NetBEUI always uses 802.2 encapsulation.
< * XXX - should we check both the DSAP and the
< * LSAP, like this, or should we check just the
< * DSAP?
< */
< b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2);
< b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32)
< ((LLCSAP_NETBEUI << 8) | LLCSAP_NETBEUI));
< gen_and(b0, b1);
< return b1;
<
1346c1627
< b0 = gen_cmp(off_linktype + 2, BPF_B,
---
> b0 = gen_cmp(OR_LINK, off_linktype + 2, BPF_B,
1351c1632
< b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2);
---
> b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2);
1358c1639
< b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_3);
---
> b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_3);
1366c1647
< b0 = gen_cmp(off_linktype, BPF_H,
---
> b0 = gen_cmp(OR_LINK, off_linktype, BPF_H,
1383c1664
< b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2);
---
> b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2);
1409c1690
< b0 = gen_cmp(off_linktype, BPF_H, (bpf_int32)proto);
---
> b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto);
1423c1704
< b0 = gen_cmp(off_linktype, BPF_H,
---
> b0 = gen_cmp(OR_LINK, off_linktype, BPF_H,
1425c1706
< b1 = gen_cmp(off_linktype + 2, BPF_B,
---
> b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_B,
1439c1720
< return gen_cmp(off_linktype, BPF_H,
---
> return gen_cmp(OR_LINK, off_linktype, BPF_H,
1444a1726,1850
> static void
> insert_radiotap_load_llprefixlen(b)
> struct block *b;
> {
> struct slist *s1, *s2;
>
> /*
> * Prepend to the statements in this block code to load the
> * length of the radiotap header into the register assigned
> * to hold that length, if one has been assigned.
> */
> if (reg_ll_size != -1) {
> /*
> * The 2 bytes at offsets of 2 and 3 from the beginning
> * of the radiotap header are the length of the radiotap
> * header; unfortunately, it's little-endian, so we have
> * to load it a byte at a time and construct the value.
> */
>
> /*
> * Load the high-order byte, at an offset of 3, shift it
> * left a byte, and put the result in the X register.
> */
> s1 = new_stmt(BPF_LD|BPF_B|BPF_ABS);
> s1->s.k = 3;
> s2 = new_stmt(BPF_ALU|BPF_LSH|BPF_K);
> sappend(s1, s2);
> s2->s.k = 8;
> s2 = new_stmt(BPF_MISC|BPF_TAX);
> sappend(s1, s2);
>
> /*
> * Load the next byte, at an offset of 2, and OR the
> * value from the X register into it.
> */
> s2 = new_stmt(BPF_LD|BPF_B|BPF_ABS);
> sappend(s1, s2);
> s2->s.k = 2;
> s2 = new_stmt(BPF_ALU|BPF_OR|BPF_X);
> sappend(s1, s2);
>
> /*
> * Now allocate a register to hold that value and store
> * it.
> */
> s2 = new_stmt(BPF_ST);
> s2->s.k = reg_ll_size;
> sappend(s1, s2);
>
> /*
> * Now move it into the X register.
> */
> s2 = new_stmt(BPF_MISC|BPF_TAX);
> sappend(s1, s2);
>
> /*
> * Now append all the existing statements in this
> * block to these statements.
> */
> sappend(s1, b->stmts);
> b->stmts = s1;
> }
> }
>
>
> static void
> insert_load_llprefixlen(b)
> struct block *b;
> {
> switch (linktype) {
>
> case DLT_IEEE802_11_RADIO:
> insert_radiotap_load_llprefixlen(b);
> }
> }
>
>
> static struct slist *
> gen_radiotap_llprefixlen(void)
> {
> struct slist *s;
>
> if (reg_ll_size == -1) {
> /*
> * We haven't yet assigned a register for the length
> * of the radiotap header; allocate one.
> */
> reg_ll_size = alloc_reg();
> }
>
> /*
> * Load the register containing the radiotap length
> * into the X register.
> */
> s = new_stmt(BPF_LDX|BPF_MEM);
> s->s.k = reg_ll_size;
> return s;
> }
>
> /*
> * Generate code to compute the link-layer header length, if necessary,
> * putting it into the X register, and to return either a pointer to a
> * "struct slist" for the list of statements in that code, or NULL if
> * no code is necessary.
> */
> static struct slist *
> gen_llprefixlen(void)
> {
> switch (linktype) {
>
> case DLT_IEEE802_11_RADIO:
> return gen_radiotap_llprefixlen();
>
> default:
> return NULL;
> }
> }
>
> /*
> * Generate code to match a particular packet type by matching the
> * link-layer type field or fields in the 802.2 LLC header.
> *
> * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
> * value, if <= ETHERMTU.
> */
1466c1872,1873
< return gen_cmp(off_linktype, BPF_H, (bpf_int32)proto);
---
> return gen_cmp(OR_LINK, off_linktype, BPF_H,
> (bpf_int32)proto);
1472,1474d1878
< case DLT_IEEE802_11:
< case DLT_PRISM_HEADER:
< case DLT_IEEE802_11_RADIO:
1476a1881,1884
> case DLT_IEEE802_11:
> case DLT_IEEE802_11_RADIO_AVS:
> case DLT_IEEE802_11_RADIO:
> case DLT_PRISM_HEADER:
1480c1888
< return gen_llc(proto);
---
> return gen_llc_linktype(proto);
1498c1906,1907
< b0 = gen_cmp(SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00);
---
> b0 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H,
> 0xFF00);
1513c1922
< b1 = gen_llc(proto);
---
> b1 = gen_llc_linktype(proto);
1516a1926,1927
> /*NOTREACHED*/
> break;
1606,1607c2017,2018
< b0 = gen_cmp(off_linktype, BPF_H, PPP_IP);
< b1 = gen_cmp(off_linktype, BPF_H, PPP_VJC);
---
> b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_IP);
> b1 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_VJC);
1609c2020
< b0 = gen_cmp(off_linktype, BPF_H, PPP_VJNC);
---
> b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_VJNC);
1715c2126
< return (gen_cmp(0, BPF_W, (bpf_int32)proto));
---
> return (gen_cmp(OR_LINK, 0, BPF_W, (bpf_int32)proto));
1723,1724c2134,2135
< return (gen_cmp(offsetof(struct pfloghdr, af), BPF_B,
< (bpf_int32)AF_INET));
---
> return (gen_cmp(OR_LINK, offsetof(struct pfloghdr, af),
> BPF_B, (bpf_int32)AF_INET));
1727,1728c2138,2139
< return (gen_cmp(offsetof(struct pfloghdr, af), BPF_B,
< (bpf_int32)AF_INET6));
---
> return (gen_cmp(OR_LINK, offsetof(struct pfloghdr, af),
> BPF_B, (bpf_int32)AF_INET6));
1748c2159
< return (gen_cmp(off_linktype, BPF_B,
---
> return (gen_cmp(OR_LINK, off_linktype, BPF_B,
1753c2164
< b0 = gen_cmp(off_linktype, BPF_B,
---
> b0 = gen_cmp(OR_LINK, off_linktype, BPF_B,
1755c2166
< b1 = gen_cmp(off_linktype, BPF_B,
---
> b1 = gen_cmp(OR_LINK, off_linktype, BPF_B,
1761c2172
< b0 = gen_cmp(off_linktype, BPF_B,
---
> b0 = gen_cmp(OR_LINK, off_linktype, BPF_B,
1763c2174
< b1 = gen_cmp(off_linktype, BPF_B,
---
> b1 = gen_cmp(OR_LINK, off_linktype, BPF_B,
1769c2180
< return (gen_cmp(off_linktype, BPF_B,
---
> return (gen_cmp(OR_LINK, off_linktype, BPF_B,
1773c2184
< return (gen_cmp(off_linktype, BPF_B,
---
> return (gen_cmp(OR_LINK, off_linktype, BPF_B,
1800c2211
< return gen_cmp(2, BPF_H, (0x03<<8) | 0xcc);
---
> return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | 0xcc);
1807c2218
< return gen_cmp(2, BPF_H, (0x03<<8) | 0x8e);
---
> return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | 0x8e);
1822,1824c2233,2235
< b0 = gen_cmp(2, BPF_H, (0x03<<8) | ISO8473_CLNP);
< b1 = gen_cmp(2, BPF_H, (0x03<<8) | ISO9542_ESIS);
< b2 = gen_cmp(2, BPF_H, (0x03<<8) | ISO10589_ISIS);
---
> b0 = gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | ISO8473_CLNP);
> b1 = gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | ISO9542_ESIS);
> b2 = gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | ISO10589_ISIS);
1838a2250,2255
> case DLT_JUNIPER_PPPOE:
> case DLT_JUNIPER_PPPOE_ATM:
> case DLT_JUNIPER_GGSN:
> case DLT_JUNIPER_ES:
> case DLT_JUNIPER_MONITOR:
> case DLT_JUNIPER_SERVICES:
1846c2263
< return gen_mcmp(0, BPF_W, 0x4d474300, 0xffffff00); /* compare the magic number */
---
> return gen_mcmp(OR_LINK, 0, BPF_W, 0x4d474300, 0xffffff00); /* compare the magic number */
1852a2270,2272
>
> case DLT_LINUX_LAPD:
> bpf_error("LAPD link-layer type filtering not implemented");
1877c2297
< return gen_cmp(off_linktype, BPF_H, (bpf_int32)proto);
---
> return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto);
1903c2323
< return gen_bcmp(offset, 8, snapblock);
---
> return gen_bcmp(OR_LINK, offset, 8, snapblock);
1907c2327,2336
< * Check for a given protocol value assuming an 802.2 LLC header.
---
> * Generate code to match a particular packet type, for link-layer types
> * using 802.2 LLC headers.
> *
> * This is *NOT* used for Ethernet; "gen_ether_linktype()" is used
> * for that - it handles the D/I/X Ethernet vs. 802.3+802.2 issues.
> *
> * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
> * value, if <= ETHERMTU. We use that to determine whether to
> * match the DSAP or both DSAP and LSAP or to check the OUI and
> * protocol ID in a SNAP header.
1910c2339
< gen_llc(proto)
---
> gen_llc_linktype(proto)
1919,1921d2347
< return gen_cmp(off_linktype, BPF_H, (long)
< ((LLCSAP_IP << 8) | LLCSAP_IP));
<
1923,1925d2348
< return gen_cmp(off_linktype, BPF_H, (long)
< ((LLCSAP_ISONS << 8) | LLCSAP_ISONS));
<
1927,1928c2350,2357
< return gen_cmp(off_linktype, BPF_H, (long)
< ((LLCSAP_NETBEUI << 8) | LLCSAP_NETBEUI));
---
> /*
> * XXX - should we check both the DSAP and the
> * SSAP, like this, or should we check just the
> * DSAP, as we do for other types <= ETHERMTU
> * (i.e., other SAP values)?
> */
> return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_u_int32)
> ((proto << 8) | proto));
1935c2364,2365
< return gen_cmp(off_linktype, BPF_B, (bpf_int32)LLCSAP_IPX);
---
> return gen_cmp(OR_LINK, off_linktype, BPF_B,
> (bpf_int32)LLCSAP_IPX);
1959c2389,2390
< return gen_cmp(off_linktype, BPF_B, (bpf_int32)proto);
---
> return gen_cmp(OR_LINK, off_linktype, BPF_B,
> (bpf_int32)proto);
1981c2412,2413
< return gen_cmp(off_linktype+6, BPF_H, (bpf_int32)proto);
---
> return gen_cmp(OR_LINK, off_linktype+6, BPF_H,
> (bpf_int32)proto);
2023c2455
< b1 = gen_mcmp(offset, BPF_W, (bpf_int32)addr, mask);
---
> b1 = gen_mcmp(OR_NET, offset, BPF_W, (bpf_int32)addr, mask);
2069,2070c2501,2502
< b1 = gen_mcmp(offset + 12, BPF_W, ntohl(a[3]), ntohl(m[3]));
< b0 = gen_mcmp(offset + 8, BPF_W, ntohl(a[2]), ntohl(m[2]));
---
> b1 = gen_mcmp(OR_NET, offset + 12, BPF_W, ntohl(a[3]), ntohl(m[3]));
> b0 = gen_mcmp(OR_NET, offset + 8, BPF_W, ntohl(a[2]), ntohl(m[2]));
2072c2504
< b0 = gen_mcmp(offset + 4, BPF_W, ntohl(a[1]), ntohl(m[1]));
---
> b0 = gen_mcmp(OR_NET, offset + 4, BPF_W, ntohl(a[1]), ntohl(m[1]));
2074c2506
< b0 = gen_mcmp(offset + 0, BPF_W, ntohl(a[0]), ntohl(m[0]));
---
> b0 = gen_mcmp(OR_NET, offset + 0, BPF_W, ntohl(a[0]), ntohl(m[0]));
2091c2523
< return gen_bcmp(off_mac + 6, 6, eaddr);
---
> return gen_bcmp(OR_LINK, off_mac + 6, 6, eaddr);
2094c2526
< return gen_bcmp(off_mac + 0, 6, eaddr);
---
> return gen_bcmp(OR_LINK, off_mac + 0, 6, eaddr);
2126c2558
< return gen_bcmp(6 + 1 + pcap_fddipad, 6, eaddr);
---
> return gen_bcmp(OR_LINK, 6 + 1 + pcap_fddipad, 6, eaddr);
2128c2560
< return gen_bcmp(6 + 1, 6, eaddr);
---
> return gen_bcmp(OR_LINK, 6 + 1, 6, eaddr);
2133c2565
< return gen_bcmp(0 + 1 + pcap_fddipad, 6, eaddr);
---
> return gen_bcmp(OR_LINK, 0 + 1 + pcap_fddipad, 6, eaddr);
2135c2567
< return gen_bcmp(0 + 1, 6, eaddr);
---
> return gen_bcmp(OR_LINK, 0 + 1, 6, eaddr);
2167c2599
< return gen_bcmp(8, 6, eaddr);
---
> return gen_bcmp(OR_LINK, 8, 6, eaddr);
2170c2602
< return gen_bcmp(2, 6, eaddr);
---
> return gen_bcmp(OR_LINK, 2, 6, eaddr);
2227,2228c2659
< s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
< s->s.k = 1;
---
> s = gen_load_a(OR_LINK, 1, BPF_B);
2236c2667
< b0 = gen_bcmp(24, 6, eaddr);
---
> b0 = gen_bcmp(OR_LINK, 24, 6, eaddr);
2243,2244c2674
< s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
< s->s.k = 1;
---
> s = gen_load_a(OR_LINK, 1, BPF_B);
2253c2683
< b1 = gen_bcmp(16, 6, eaddr);
---
> b1 = gen_bcmp(OR_LINK, 16, 6, eaddr);
2267,2268c2697
< s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
< s->s.k = 1;
---
> s = gen_load_a(OR_LINK, 1, BPF_B);
2277,2278c2706
< s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
< s->s.k = 1;
---
> s = gen_load_a(OR_LINK, 1, BPF_B);
2287c2715
< b1 = gen_bcmp(10, 6, eaddr);
---
> b1 = gen_bcmp(OR_LINK, 10, 6, eaddr);
2301,2302c2729
< s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
< s->s.k = 0;
---
> gen_load_a(OR_LINK, 0, BPF_B);
2317,2318c2744
< s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
< s->s.k = 0;
---
> s = gen_load_a(OR_LINK, 0, BPF_B);
2327c2753
< b1 = gen_bcmp(10, 6, eaddr);
---
> b1 = gen_bcmp(OR_LINK, 10, 6, eaddr);
2345,2346c2771
< s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
< s->s.k = 0;
---
> s = gen_load_a(OR_LINK, 0, BPF_B);
2381,2382c2806
< s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
< s->s.k = 1;
---
> s = gen_load_a(OR_LINK, 1, BPF_B);
2390c2814
< b0 = gen_bcmp(16, 6, eaddr);
---
> b0 = gen_bcmp(OR_LINK, 16, 6, eaddr);
2397,2398c2821
< s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
< s->s.k = 1;
---
> s = gen_load_a(OR_LINK, 1, BPF_B);
2407c2830
< b1 = gen_bcmp(4, 6, eaddr);
---
> b1 = gen_bcmp(OR_LINK, 4, 6, eaddr);
2420,2421c2843
< s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
< s->s.k = 0;
---
> s = gen_load_a(OR_LINK, 0, BPF_B);
2436,2437c2858
< s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
< s->s.k = 0;
---
> s = gen_load_a(OR_LINK, 0, BPF_B);
2446c2867
< b1 = gen_bcmp(4, 6, eaddr);
---
> b1 = gen_bcmp(OR_LINK, 4, 6, eaddr);
2464,2465c2885
< s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
< s->s.k = 0;
---
> s = gen_load_a(OR_LINK, 0, BPF_B);
2509c2929
< return gen_bcmp(10, 6, eaddr);
---
> return gen_bcmp(OR_LINK, 10, 6, eaddr);
2512c2932
< return gen_bcmp(2, 6, eaddr);
---
> return gen_bcmp(OR_LINK, 2, 6, eaddr);
2550c2970
< gen_dnhostop(addr, dir, base_off)
---
> gen_dnhostop(addr, dir)
2553d2972
< u_int base_off;
2573,2574c2992,2993
< b0 = gen_dnhostop(addr, Q_SRC, base_off);
< b1 = gen_dnhostop(addr, Q_DST, base_off);
---
> b0 = gen_dnhostop(addr, Q_SRC);
> b1 = gen_dnhostop(addr, Q_DST);
2581,2582c3000,3001
< b0 = gen_dnhostop(addr, Q_SRC, base_off);
< b1 = gen_dnhostop(addr, Q_DST, base_off);
---
> b0 = gen_dnhostop(addr, Q_SRC);
> b1 = gen_dnhostop(addr, Q_DST);
2594c3013
< tmp = gen_mcmp(base_off + 2, BPF_H,
---
> tmp = gen_mcmp(OR_NET, 2, BPF_H,
2596c3015
< b1 = gen_cmp(base_off + 2 + 1 + offset_lh,
---
> b1 = gen_cmp(OR_NET, 2 + 1 + offset_lh,
2600,2601c3019,3020
< tmp = gen_mcmp(base_off + 2, BPF_B, (bpf_int32)0x06, (bpf_int32)0x7);
< b2 = gen_cmp(base_off + 2 + offset_lh, BPF_H, (bpf_int32)ntohs(addr));
---
> tmp = gen_mcmp(OR_NET, 2, BPF_B, (bpf_int32)0x06, (bpf_int32)0x7);
> b2 = gen_cmp(OR_NET, 2 + offset_lh, BPF_H, (bpf_int32)ntohs(addr));
2605c3024
< tmp = gen_mcmp(base_off + 2, BPF_H,
---
> tmp = gen_mcmp(OR_NET, 2, BPF_H,
2607,2608c3026
< b2 = gen_cmp(base_off + 2 + 1 + offset_sh,
< BPF_H, (bpf_int32)ntohs(addr));
---
> b2 = gen_cmp(OR_NET, 2 + 1 + offset_sh, BPF_H, (bpf_int32)ntohs(addr));
2612,2613c3030,3031
< tmp = gen_mcmp(base_off + 2, BPF_B, (bpf_int32)0x02, (bpf_int32)0x7);
< b2 = gen_cmp(base_off + 2 + offset_sh, BPF_H, (bpf_int32)ntohs(addr));
---
> tmp = gen_mcmp(OR_NET, 2, BPF_B, (bpf_int32)0x02, (bpf_int32)0x7);
> b2 = gen_cmp(OR_NET, 2 + offset_sh, BPF_H, (bpf_int32)ntohs(addr));
2644,2645c3062
< return gen_hostop(addr, mask, dir, ETHERTYPE_IP,
< off_nl + 12, off_nl + 16);
---
> return gen_hostop(addr, mask, dir, ETHERTYPE_IP, 12, 16);
2648,2649c3065
< return gen_hostop(addr, mask, dir, ETHERTYPE_REVARP,
< off_nl + 14, off_nl + 24);
---
> return gen_hostop(addr, mask, dir, ETHERTYPE_REVARP, 14, 24);
2652,2653c3068
< return gen_hostop(addr, mask, dir, ETHERTYPE_ARP,
< off_nl + 14, off_nl + 24);
---
> return gen_hostop(addr, mask, dir, ETHERTYPE_ARP, 14, 24);
2686c3101
< return gen_dnhostop(addr, dir, off_nl);
---
> return gen_dnhostop(addr, dir);
2734a3150,3152
> case Q_RADIO:
> bpf_error("'radio' modifier applied to host");
>
2809,2810c3227
< return gen_hostop6(addr, mask, dir, ETHERTYPE_IPV6,
< off_nl + 8, off_nl + 24);
---
> return gen_hostop6(addr, mask, dir, ETHERTYPE_IPV6, 8, 24);
2841a3259,3261
> case Q_RADIO:
> bpf_error("'radio' modifier applied to host");
>
2873c3293,3296
< else if (linktype == DLT_IEEE802_11)
---
> else if (linktype == DLT_IEEE802_11 ||
> linktype == DLT_IEEE802_11_RADIO_AVS ||
> linktype == DLT_IEEE802_11_RADIO ||
> linktype == DLT_PRISM_HEADER)
2881c3304,3305
< b1 = gen_cmp(SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00);
---
> b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H,
> 0xFF00);
3147a3572,3574
> case Q_RADIO:
> bpf_error("'radio' is not a valid protocol type");
>
3161,3162c3588
< s = new_stmt(BPF_LD|BPF_H|BPF_ABS);
< s->s.k = off_nl + 6;
---
> s = gen_load_a(OR_NET, 6, BPF_H);
3170a3597,3605
> /*
> * Generate a comparison to a port value in the transport-layer header
> * at the specified offset from the beginning of that header.
> *
> * XXX - this handles a variable-length prefix preceding the link-layer
> * header, such as the radiotap or AVS radio prefix, but doesn't handle
> * variable-length link-layer headers (such as Token Ring or 802.11
> * headers).
> */
3176,3189c3611
< struct slist *s;
< struct block *b;
<
< s = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
< s->s.k = off_nl;
<
< s->next = new_stmt(BPF_LD|BPF_IND|BPF_H);
< s->next->s.k = off_nl + off;
<
< b = new_block(JMP(BPF_JEQ));
< b->stmts = s;
< b->s.k = v;
<
< return b;
---
> return gen_cmp(OR_TRAN_IPV4, off, BPF_H, v);
3198c3620
< return gen_cmp(off_nl + 40 + off, BPF_H, v);
---
> return gen_cmp(OR_TRAN_IPV6, off, BPF_H, v);
3209c3631
< tmp = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)proto);
---
> tmp = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)proto);
3299,3300c3721,3722
< /* ip proto 'proto' */
< b0 = gen_cmp(off_nl + 6, BPF_B, (bpf_int32)proto);
---
> /* ip6 proto 'proto' */
> b0 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)proto);
3340c3762
< /* ether proto ip */
---
> /* link proto ip6 */
3365a3788,3992
> /* gen_portrange code */
> static struct block *
> gen_portrangeatom(off, v1, v2)
> int off;
> bpf_int32 v1, v2;
> {
> struct block *b1, *b2;
>
> if (v1 > v2) {
> /*
> * Reverse the order of the ports, so v1 is the lower one.
> */
> bpf_int32 vtemp;
>
> vtemp = v1;
> v1 = v2;
> v2 = vtemp;
> }
>
> b1 = gen_cmp_ge(OR_TRAN_IPV4, off, BPF_H, v1);
> b2 = gen_cmp_le(OR_TRAN_IPV4, off, BPF_H, v2);
>
> gen_and(b1, b2);
>
> return b2;
> }
>
> struct block *
> gen_portrangeop(port1, port2, proto, dir)
> int port1, port2;
> int proto;
> int dir;
> {
> struct block *b0, *b1, *tmp;
>
> /* ip proto 'proto' */
> tmp = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)proto);
> b0 = gen_ipfrag();
> gen_and(tmp, b0);
>
> switch (dir) {
> case Q_SRC:
> b1 = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2);
> break;
>
> case Q_DST:
> b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2);
> break;
>
> case Q_OR:
> case Q_DEFAULT:
> tmp = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2);
> b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2);
> gen_or(tmp, b1);
> break;
>
> case Q_AND:
> tmp = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2);
> b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2);
> gen_and(tmp, b1);
> break;
>
> default:
> abort();
> }
> gen_and(b0, b1);
>
> return b1;
> }
>
> static struct block *
> gen_portrange(port1, port2, ip_proto, dir)
> int port1, port2;
> int ip_proto;
> int dir;
> {
> struct block *b0, *b1, *tmp;
>
> /* link proto ip */
> b0 = gen_linktype(ETHERTYPE_IP);
>
> switch (ip_proto) {
> case IPPROTO_UDP:
> case IPPROTO_TCP:
> case IPPROTO_SCTP:
> b1 = gen_portrangeop(port1, port2, ip_proto, dir);
> break;
>
> case PROTO_UNDEF:
> tmp = gen_portrangeop(port1, port2, IPPROTO_TCP, dir);
> b1 = gen_portrangeop(port1, port2, IPPROTO_UDP, dir);
> gen_or(tmp, b1);
> tmp = gen_portrangeop(port1, port2, IPPROTO_SCTP, dir);
> gen_or(tmp, b1);
> break;
>
> default:
> abort();
> }
> gen_and(b0, b1);
> return b1;
> }
>
> #ifdef INET6
> static struct block *
> gen_portrangeatom6(off, v1, v2)
> int off;
> bpf_int32 v1, v2;
> {
> struct block *b1, *b2;
>
> if (v1 > v2) {
> /*
> * Reverse the order of the ports, so v1 is the lower one.
> */
> bpf_int32 vtemp;
>
> vtemp = v1;
> v1 = v2;
> v2 = vtemp;
> }
>
> b1 = gen_cmp_ge(OR_TRAN_IPV6, off, BPF_H, v1);
> b2 = gen_cmp_le(OR_TRAN_IPV6, off, BPF_H, v2);
>
> gen_and(b1, b2);
>
> return b2;
> }
>
> struct block *
> gen_portrangeop6(port1, port2, proto, dir)
> int port1, port2;
> int proto;
> int dir;
> {
> struct block *b0, *b1, *tmp;
>
> /* ip6 proto 'proto' */
> b0 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)proto);
>
> switch (dir) {
> case Q_SRC:
> b1 = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2);
> break;
>
> case Q_DST:
> b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2);
> break;
>
> case Q_OR:
> case Q_DEFAULT:
> tmp = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2);
> b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2);
> gen_or(tmp, b1);
> break;
>
> case Q_AND:
> tmp = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2);
> b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2);
> gen_and(tmp, b1);
> break;
>
> default:
> abort();
> }
> gen_and(b0, b1);
>
> return b1;
> }
>
> static struct block *
> gen_portrange6(port1, port2, ip_proto, dir)
> int port1, port2;
> int ip_proto;
> int dir;
> {
> struct block *b0, *b1, *tmp;
>
> /* link proto ip6 */
> b0 = gen_linktype(ETHERTYPE_IPV6);
>
> switch (ip_proto) {
> case IPPROTO_UDP:
> case IPPROTO_TCP:
> case IPPROTO_SCTP:
> b1 = gen_portrangeop6(port1, port2, ip_proto, dir);
> break;
>
> case PROTO_UNDEF:
> tmp = gen_portrangeop6(port1, port2, IPPROTO_TCP, dir);
> b1 = gen_portrangeop6(port1, port2, IPPROTO_UDP, dir);
> gen_or(tmp, b1);
> tmp = gen_portrangeop6(port1, port2, IPPROTO_SCTP, dir);
> gen_or(tmp, b1);
> break;
>
> default:
> abort();
> }
> gen_and(b0, b1);
> return b1;
> }
> #endif /* INET6 */
>
3453a4081,4093
> /*
> * We don't handle variable-length radiotap here headers yet.
> * We might want to add BPF instructions to do the protochain
> * work, to simplify that and, on platforms that have a BPF
> * interpreter with the new instructions, let the filtering
> * be done in the kernel. (We already require a modified BPF
> * engine to do the protochain stuff, to support backward
> * branches, and backward branch support is unlikely to appear
> * in kernel BPF engines.)
> */
> if (linktype == DLT_IEEE802_11_RADIO)
> bpf_error("'protochain' not supported with radiotap headers");
>
3457c4097
< * s[0] is a dummy entry to protect other BPF insn from damaged
---
> * s[0] is a dummy entry to protect other BPF insn from damage
3712a4353,4361
> /*
> * Generate code that checks whether the packet is a packet for protocol
> * <proto> and whether the type field in that protocol's header has
> * the value <v>, e.g. if <proto> is Q_IP, it checks whether it's an
> * IP packet and checks the protocol number in the IP header against <v>.
> *
> * If <proto> is Q_DEFAULT, i.e. just "proto" was specified, it checks
> * against Q_IP and Q_IPV6.
> */
3752c4401
< b1 = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)v);
---
> b1 = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)v);
3781c4430
< return gen_cmp(2, BPF_H, (0x03<<8) | v);
---
> return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | v);
3792c4441
< b1 = gen_cmp(off_nl_nosnap+1, BPF_B, (long)v);
---
> b1 = gen_cmp(OR_NET_NOSNAP, 1, BPF_B, (long)v);
3798c4447
< b1 = gen_cmp(off_nl_nosnap, BPF_B, (long)v);
---
> b1 = gen_cmp(OR_NET_NOSNAP, 0, BPF_B, (long)v);
3809c4458
< b1 = gen_cmp(off_nl_nosnap+4, BPF_B, (long)v);
---
> b1 = gen_cmp(OR_NET_NOSNAP, 4, BPF_B, (long)v);
3884c4533
< b1 = gen_cmp(off_nl + 6, BPF_B, (bpf_int32)v);
---
> b1 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)v);
3909a4559,4561
> case Q_RADIO:
> bpf_error("'radio proto' is bogus");
>
3937a4590
> int port1, port2;
3985a4639,4641
> case DLT_IEEE802_11_RADIO_AVS:
> case DLT_IEEE802_11_RADIO:
> case DLT_PRISM_HEADER:
4012,4013c4668,4669
< tmp = gen_cmp(SUNATM_PKT_BEGIN_POS, BPF_H,
< 0xFF00);
---
> tmp = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS,
> BPF_H, 0xFF00);
4144a4801,4844
> case Q_PORTRANGE:
> if (proto != Q_DEFAULT &&
> proto != Q_UDP && proto != Q_TCP && proto != Q_SCTP)
> bpf_error("illegal qualifier of 'portrange'");
> if (pcap_nametoportrange(name, &port1, &port2, &real_proto) == 0)
> bpf_error("unknown port in range '%s'", name);
> if (proto == Q_UDP) {
> if (real_proto == IPPROTO_TCP)
> bpf_error("port in range '%s' is tcp", name);
> else if (real_proto == IPPROTO_SCTP)
> bpf_error("port in range '%s' is sctp", name);
> else
> /* override PROTO_UNDEF */
> real_proto = IPPROTO_UDP;
> }
> if (proto == Q_TCP) {
> if (real_proto == IPPROTO_UDP)
> bpf_error("port in range '%s' is udp", name);
> else if (real_proto == IPPROTO_SCTP)
> bpf_error("port in range '%s' is sctp", name);
> else
> /* override PROTO_UNDEF */
> real_proto = IPPROTO_TCP;
> }
> if (proto == Q_SCTP) {
> if (real_proto == IPPROTO_UDP)
> bpf_error("port in range '%s' is udp", name);
> else if (real_proto == IPPROTO_TCP)
> bpf_error("port in range '%s' is tcp", name);
> else
> /* override PROTO_UNDEF */
> real_proto = IPPROTO_SCTP;
> }
> #ifndef INET6
> return gen_portrange(port1, port2, real_proto, dir);
> #else
> {
> struct block *b;
> b = gen_portrange(port1, port2, real_proto, dir);
> gen_or(gen_portrange6(port1, port2, real_proto, dir), b);
> return b;
> }
> #endif /* INET6 */
>
4291a4992,5014
> case Q_PORTRANGE:
> if (proto == Q_UDP)
> proto = IPPROTO_UDP;
> else if (proto == Q_TCP)
> proto = IPPROTO_TCP;
> else if (proto == Q_SCTP)
> proto = IPPROTO_SCTP;
> else if (proto == Q_DEFAULT)
> proto = PROTO_UNDEF;
> else
> bpf_error("illegal qualifier of 'portrange'");
>
> #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 */
>
4386c5109,5112
< if (linktype == DLT_IEEE802_11)
---
> if (linktype == DLT_IEEE802_11 ||
> linktype == DLT_IEEE802_11_RADIO_AVS ||
> linktype == DLT_IEEE802_11_RADIO ||
> linktype == DLT_PRISM_HEADER)
4394c5120,5121
< tmp = gen_cmp(SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00);
---
> tmp = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H,
> 0xFF00);
4446a5174,5180
> /*
> * Modify "index" to use the value stored into its register as an
> * offset relative to the beginning of the header for the protocol
> * "proto", and allocate a register and put an item "size" bytes long
> * (1, 2, or 4) at that offset into that register, making it the register
> * for "index".
> */
4478a5213,5237
> case Q_RADIO:
> /*
> * The offset is relative to the beginning of the packet
> * data, if we have a radio header. (If we don't, this
> * is an error.)
> */
> if (linktype != DLT_IEEE802_11_RADIO_AVS &&
> linktype != DLT_IEEE802_11_RADIO &&
> linktype != DLT_PRISM_HEADER)
> bpf_error("radio information not present in capture");
>
> /*
> * Load into the X register the offset computed into the
> * register specifed by "index".
> */
> s = xfer_to_x(index);
>
> /*
> * Load the item at that offset.
> */
> tmp = new_stmt(BPF_LD|BPF_IND|size);
> sappend(s, tmp);
> sappend(index->s, s);
> break;
>
4480a5240,5242
> * The offset is relative to the beginning of
> * the link-layer header.
> *
4488c5250,5274
< s = xfer_to_x(index);
---
> s = gen_llprefixlen();
>
> /*
> * If "s" is non-null, it has code to arrange that the
> * X register contains the length of the prefix preceding
> * the link-layer header. Add to it the offset computed
> * into the register specified by "index", and move that
> * into the X register. Otherwise, just load into the X
> * register the offset computed into the register specifed
> * by "index".
> */
> if (s != NULL) {
> sappend(s, xfer_to_a(index));
> sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
> sappend(s, new_stmt(BPF_MISC|BPF_TAX));
> } else
> s = xfer_to_x(index);
>
> /*
> * Load the item at the sum of the offset we've put in the
> * X register and the offset of the start of the link
> * layer header (which is 0 if the radio header is
> * variable-length; that header length is what we put
> * into the X register and then added to the index).
> */
4489a5276
> tmp->s.k = off_ll;
4506,4507c5293,5321
< /* XXX Note that we assume a fixed link header here. */
< s = xfer_to_x(index);
---
> /*
> * The offset is relative to the beginning of
> * the network-layer header.
> * XXX - are there any cases where we want
> * off_nl_nosnap?
> */
> s = gen_llprefixlen();
>
> /*
> * If "s" is non-null, it has code to arrange that the
> * X register contains the length of the prefix preceding
> * the link-layer header. Add to it the offset computed
> * into the register specified by "index", and move that
> * into the X register. Otherwise, just load into the X
> * register the offset computed into the register specifed
> * by "index".
> */
> if (s != NULL) {
> sappend(s, xfer_to_a(index));
> sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
> sappend(s, new_stmt(BPF_MISC|BPF_TAX));
> } else
> s = xfer_to_x(index);
>
> /*
> * Load the item at the sum of the offset we've put in the
> * X register and the offset of the start of the network
> * layer header.
> */
4512a5327,5330
> /*
> * Do the computation only if the packet contains
> * the protocol in question.
> */
4527,4528c5345,5367
< s = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
< s->s.k = off_nl;
---
> /*
> * The offset is relative to the beginning of
> * the transport-layer header.
> * XXX - are there any cases where we want
> * off_nl_nosnap?
> * XXX - we should, if we're built with
> * IPv6 support, generate code to load either
> * IPv4, IPv6, or both, as appropriate.
> */
> s = gen_loadx_iphdrlen();
>
> /*
> * The X register now contains the sum of the offset
> * of the beginning of the link-layer header and
> * the length of the network-layer header. Load
> * into the A register the offset relative to
> * the beginning of the transport layer header,
> * add the X register to that, move that to the
> * X register, and load with an offset from the
> * X register equal to the offset of the network
> * layer header relative to the beginning of
> * the link-layer header.
> */
4535a5375,5380
> /*
> * Do the computation only if the packet contains
> * the protocol in question - which is true only
> * if this is an IP datagram and is the first or
> * only fragment of that datagram.
> */
4760a5606,5615
> /*
> * This is for "byte {idx} {op} {val}"; "idx" is treated as relative to
> * the beginning of the link-layer header.
> * XXX - that means you can't test values in the radiotap header, but
> * as that header is difficult if not impossible to parse generally
> * without a loop, that might not be a severe problem. A new keyword
> * "radio" could be added for that, although what you'd really want
> * would be a way of testing particular radio header values, which
> * would generate code appropriate to the radio header in question.
> */
4773c5628
< return gen_cmp((u_int)idx, BPF_B, (bpf_int32)val);
---
> return gen_cmp(OR_LINK, (u_int)idx, BPF_B, (bpf_int32)val);
4776,4778c5631
< b = gen_cmp((u_int)idx, BPF_B, (bpf_int32)val);
< b->s.code = JMP(BPF_JGE);
< gen_not(b);
---
> b = gen_cmp_lt(OR_LINK, (u_int)idx, BPF_B, (bpf_int32)val);
4782,4783c5635
< b = gen_cmp((u_int)idx, BPF_B, (bpf_int32)val);
< b->s.code = JMP(BPF_JGT);
---
> b = gen_cmp_gt(OR_LINK, (u_int)idx, BPF_B, (bpf_int32)val);
4824c5676,5679
< if (linktype == DLT_IEEE802_11)
---
> if (linktype == DLT_IEEE802_11 ||
> linktype == DLT_IEEE802_11_RADIO_AVS ||
> linktype == DLT_IEEE802_11_RADIO ||
> linktype == DLT_PRISM_HEADER)
4834c5689,5690
< b1 = gen_cmp(SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00);
---
> b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H,
> 0xFF00);
4850,4851c5706,5707
< b1 = gen_mcmp(off_nl + 16, BPF_W, (bpf_int32)0, hostmask);
< b2 = gen_mcmp(off_nl + 16, BPF_W,
---
> b1 = gen_mcmp(OR_NET, 16, BPF_W, (bpf_int32)0, hostmask);
> b2 = gen_mcmp(OR_NET, 16, BPF_W,
4873,4874c5729
< s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
< s->s.k = offset;
---
> s = gen_load_a(OR_LINK, offset, BPF_B);
4916c5771,5774
< if (linktype == DLT_IEEE802_11) {
---
> if (linktype == DLT_IEEE802_11 ||
> linktype == DLT_IEEE802_11_RADIO_AVS ||
> linktype == DLT_IEEE802_11_RADIO ||
> linktype == DLT_PRISM_HEADER) {
4938,4939c5796
< s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
< s->s.k = 1;
---
> s = gen_load_a(OR_LINK, 1, BPF_B);
4954,4955c5811
< s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
< s->s.k = 1;
---
> s = gen_load_a(OR_LINK, 1, BPF_B);
4977,4978c5833
< s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
< s->s.k = 0;
---
> s = gen_load_a(OR_LINK, 0, BPF_B);
4993,4994c5848
< s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
< s->s.k = 0;
---
> s = gen_load_a(OR_LINK, 0, BPF_B);
5021,5022c5875
< s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
< s->s.k = 0;
---
> s = gen_load_a(OR_LINK, 0, BPF_B);
5047c5900,5901
< b1 = gen_cmp(SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00);
---
> b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H,
> 0xFF00);
5061,5062c5915
< b1 = gen_cmp(off_nl + 16, BPF_B, (bpf_int32)224);
< b1->s.code = JMP(BPF_JGE);
---
> b1 = gen_cmp_ge(OR_NET, 16, BPF_B, (bpf_int32)224);
5069c5922
< b1 = gen_cmp(off_nl + 24, BPF_B, (bpf_int32)255);
---
> b1 = gen_cmp(OR_NET, 24, BPF_B, (bpf_int32)255);
5105c5958
< b0 = gen_cmp(0, BPF_H, LINUX_SLL_OUTGOING);
---
> b0 = gen_cmp(OR_LINK, 0, BPF_H, LINUX_SLL_OUTGOING);
5117c5970
< b0 = gen_cmp(0, BPF_H, LINUX_SLL_HOST);
---
> b0 = gen_cmp(OR_LINK, 0, BPF_H, LINUX_SLL_HOST);
5122c5975
< b0 = gen_cmp(offsetof(struct pfloghdr, dir), BPF_B,
---
> b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, dir), BPF_B,
5129c5982
< b0 = gen_cmp(0, BPF_B, PPP_PPPD_OUT);
---
> b0 = gen_cmp(OR_LINK, 0, BPF_B, PPP_PPPD_OUT);
5132c5985
< b0 = gen_cmp(0, BPF_B, PPP_PPPD_IN);
---
> b0 = gen_cmp(OR_LINK, 0, BPF_B, PPP_PPPD_IN);
5139a5993,5998
> case DLT_JUNIPER_PPPOE:
> case DLT_JUNIPER_PPPOE_ATM:
> case DLT_JUNIPER_GGSN:
> case DLT_JUNIPER_ES:
> case DLT_JUNIPER_MONITOR:
> case DLT_JUNIPER_SERVICES:
5144c6003
< b0 = gen_mcmp(3, BPF_B, 0, 0x01);
---
> b0 = gen_mcmp(OR_LINK, 3, BPF_B, 0, 0x01);
5147c6006
< b0 = gen_mcmp(3, BPF_B, 1, 0x01);
---
> b0 = gen_mcmp(OR_LINK, 3, BPF_B, 1, 0x01);
5179c6038
< b0 = gen_bcmp(off, strlen(ifname), (const u_char *)ifname);
---
> b0 = gen_bcmp(OR_LINK, off, strlen(ifname), (const u_char *)ifname);
5198c6057
< b0 = gen_bcmp(offsetof(struct pfloghdr, ruleset),
---
> b0 = gen_bcmp(OR_LINK, offsetof(struct pfloghdr, ruleset),
5210c6069
< b0 = gen_cmp(offsetof(struct pfloghdr, rulenr), BPF_W,
---
> b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, rulenr), BPF_W,
5231c6090
< b0 = gen_cmp(offsetof(struct pfloghdr, subrulenr), BPF_W,
---
> b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, subrulenr), BPF_W,
5243c6102
< b0 = gen_cmp(offsetof(struct pfloghdr, reason), BPF_B,
---
> b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, reason), BPF_B,
5260c6119
< b0 = gen_cmp(offsetof(struct pfloghdr, action), BPF_B,
---
> b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, action), BPF_B,
5293c6152
< return gen_bcmp(0, 1, eaddr);
---
> return gen_bcmp(OR_LINK, 0, 1, eaddr);
5296c6155
< return gen_bcmp(1, 1, eaddr);
---
> return gen_bcmp(OR_LINK, 1, 1, eaddr);
5326c6185,6211
< * the VLAN packet. This is somewhat of a kludge.
---
> * the VLAN packet. Just increment the offsets, so that we
> * can support a hierarchy, e.g. "vlan 300 && vlan 200" to
> * capture VLAN 200 encapsulated within VLAN 100.
> *
> * XXX - this is a bit of a kludge. If we were to split the
> * compiler into a parser that parses an expression and
> * generates an expression tree, and a code generator that
> * takes an expression tree (which could come from our
> * parser or from some other parser) and generates BPF code,
> * we could perhaps make the offsets parameters of routines
> * and, in the handler for an "AND" node, pass to subnodes
> * other than the VLAN node the adjusted offsets.
> *
> * This would mean that "vlan" would, instead of changing the
> * behavior of *all* tests after it, change only the behavior
> * of tests ANDed with it. That would change the documented
> * semantics of "vlan", which might break some expressions.
> * However, it would mean that "(vlan and ip) or ip" would check
> * both for VLAN-encapsulated IP and IP-over-Ethernet, rather than
> * checking only for VLAN-encapsulated IP, so that could still
> * be considered worth doing; it wouldn't break expressions
> * that are of the form "vlan and ..." or "vlan N and ...",
> * which I suspect are the most common expressions involving
> * "vlan". "vlan or ..." doesn't necessarily do what the user
> * would really want, now, as all the "or ..." tests would
> * be done assuming a VLAN, even though the "or" could be viewed
> * as meaning "or, if this isn't a VLAN packet...".
5328,5331c6213,6214
< if (orig_nl == (u_int)-1) {
< orig_linktype = off_linktype; /* save original values */
< orig_nl = off_nl;
< orig_nl_nosnap = off_nl_nosnap;
---
> orig_linktype = off_linktype; /* save original values */
> orig_nl = off_nl;
5333c6216
< switch (linktype) {
---
> switch (linktype) {
5335,5339c6218,6222
< case DLT_EN10MB:
< off_linktype = 16;
< off_nl_nosnap = 18;
< off_nl = 18;
< break;
---
> case DLT_EN10MB:
> off_linktype += 4;
> off_nl_nosnap += 4;
> off_nl += 4;
> break;
5341,5346c6224,6228
< default:
< bpf_error("no VLAN support for data link type %d",
< linktype);
< /*NOTREACHED*/
< }
< }
---
> default:
> bpf_error("no VLAN support for data link type %d",
> linktype);
> /*NOTREACHED*/
> }
5349c6231
< b0 = gen_cmp(orig_linktype, BPF_H, (bpf_int32)ETHERTYPE_8021Q);
---
> b0 = gen_cmp(OR_LINK, orig_linktype, BPF_H, (bpf_int32)ETHERTYPE_8021Q);
5355c6237,6238
< b1 = gen_mcmp(orig_nl, BPF_H, (bpf_int32)vlan_num, 0x0fff);
---
> b1 = gen_mcmp(OR_LINK, orig_nl, BPF_H, (bpf_int32)vlan_num,
> 0x0fff);
5374c6257,6262
< * the MPLS packet. This is somewhat of a kludge.
---
> * the MPLS packet. Just increment the offsets, so that we
> * can support a hierarchy, e.g. "mpls 100000 && mpls 1024" to
> * capture packets with an outer label of 100000 and an inner
> * label of 1024.
> *
> * XXX - this is a bit of a kludge. See comments in gen_vlan().
5376,5379c6264,6265
< if (orig_nl == (u_int)-1) {
< orig_linktype = off_linktype; /* save original values */
< orig_nl = off_nl;
< orig_nl_nosnap = off_nl_nosnap;
---
> orig_linktype = off_linktype; /* save original values */
> orig_nl = off_nl;
5381c6267,6276
< switch (linktype) {
---
> switch (linktype) {
>
> case DLT_C_HDLC: /* fall through */
> case DLT_EN10MB:
> off_nl_nosnap += 4;
> off_nl += 4;
>
> b0 = gen_cmp(OR_LINK, orig_linktype, BPF_H,
> (bpf_int32)ETHERTYPE_MPLS);
> break;
5383,5386c6278,6280
< case DLT_EN10MB:
< off_linktype = 16;
< off_nl_nosnap = 18;
< off_nl = 18;
---
> case DLT_PPP:
> off_nl_nosnap += 4;
> off_nl += 4;
5388,5389c6282,6284
< b0 = gen_cmp(orig_linktype, BPF_H, (bpf_int32)ETHERTYPE_MPLS);
< break;
---
> b0 = gen_cmp(OR_LINK, orig_linktype, BPF_H,
> (bpf_int32)PPP_MPLS_UCAST);
> break;
5391,5394c6286,6288
< case DLT_PPP:
< off_linktype = 6;
< off_nl_nosnap = 8;
< off_nl = 8;
---
> /* FIXME add other DLT_s ...
> * for Frame-Relay/and ATM this may get messy due to SNAP headers
> * leave it for now */
5396,5397c6290,6296
< b0 = gen_cmp(orig_linktype, BPF_H, (bpf_int32)PPP_MPLS_UCAST);
< break;
---
> default:
> bpf_error("no MPLS support for data link type %d",
> linktype);
> b0 = NULL;
> /*NOTREACHED*/
> break;
> }
5399,5422d6297
< case DLT_C_HDLC:
< off_linktype = 6;
< off_nl_nosnap = 8;
< off_nl = 8;
<
< b0 = gen_cmp(orig_linktype, BPF_H, (bpf_int32)ETHERTYPE_MPLS);
< break;
<
< /* FIXME add other DLT_s ...
< * for Frame-Relay/and ATM this may get messy due to SNAP headers
< * leave it for now */
<
< default:
< bpf_error("no MPLS support for data link type %d",
< linktype);
< b0 = NULL;
< /*NOTREACHED*/
< }
< } else {
< bpf_error("'mpls' can't be combined with 'vlan' or another 'mpls'");
< b0 = NULL;
< /*NOTREACHED*/
< }
<
5428c6303,6304
< b1 = gen_mcmp(orig_nl, BPF_W, (bpf_int32)label_num, 0xfffff000); /* only compare the first 20 bits */
---
> b1 = gen_mcmp(OR_LINK, orig_nl, BPF_W, (bpf_int32)label_num,
> 0xfffff000); /* only compare the first 20 bits */
5439c6315
< bpf_u_int32 jvalue;
---
> bpf_int32 jvalue;
5452,5453c6328,6329
< b0 = gen_ncmp(BPF_B, off_vpi, 0xffffffff, (u_int)jtype,
< (u_int)jvalue, reverse);
---
> b0 = gen_ncmp(OR_LINK, off_vpi, BPF_B, 0xffffffff, jtype,
> reverse, jvalue);
5461,5462c6337,6338
< b0 = gen_ncmp(BPF_H, off_vci, 0xffffffff, (u_int)jtype,
< (u_int)jvalue, reverse);
---
> b0 = gen_ncmp(OR_LINK, off_vci, BPF_H, 0xffffffff, jtype,
> reverse, jvalue);
5468,5469c6344,6345
< b0 = gen_ncmp(BPF_B, off_proto, 0x0f, (u_int)jtype,
< (u_int)jvalue, reverse);
---
> b0 = gen_ncmp(OR_LINK, off_proto, BPF_B, 0x0f, jtype,
> reverse, jvalue);
5475,5476c6351,6352
< b0 = gen_ncmp(BPF_B, off_payload + MSG_TYPE_POS, 0xffffffff,
< (u_int)jtype, (u_int)jvalue, reverse);
---
> b0 = gen_ncmp(OR_LINK, off_payload + MSG_TYPE_POS, BPF_B,
> 0xffffffff, jtype, reverse, jvalue);
5484,5485c6360,6361
< b0 = gen_ncmp(BPF_B, off_proto, 0xffffffff, (u_int)jtype,
< (u_int)jvalue, reverse);
---
> b0 = gen_ncmp(OR_LINK, off_proto, BPF_B, 0xffffffff,
> jtype, reverse, jvalue);
5594a6471,6479
> struct block *
> gen_mtp3field_code(mtp3field, jvalue, jtype, reverse)
> int mtp3field;
> bpf_u_int32 jvalue;
> bpf_u_int32 jtype;
> int reverse;
> {
> struct block *b0;
> bpf_u_int32 val1 , val2 , val3;
5595a6481,6551
> switch (mtp3field) {
>
> case M_SIO:
> if (off_sio == (u_int)-1)
> bpf_error("'sio' supported only on SS7");
> /* sio coded on 1 byte so max value 255 */
> if(jvalue > 255)
> bpf_error("sio value %u too big; max value = 255",
> jvalue);
> b0 = gen_ncmp(OR_PACKET, off_sio, BPF_B, 0xffffffff,
> (u_int)jtype, reverse, (u_int)jvalue);
> break;
>
> case M_OPC:
> if (off_opc == (u_int)-1)
> bpf_error("'opc' supported only on SS7");
> /* opc coded on 14 bits so max value 16383 */
> if (jvalue > 16383)
> bpf_error("opc value %u too big; max value = 16383",
> jvalue);
> /* the following instructions are made to convert jvalue
> * to the form used to write opc in an ss7 message*/
> val1 = jvalue & 0x00003c00;
> val1 = val1 >>10;
> val2 = jvalue & 0x000003fc;
> val2 = val2 <<6;
> val3 = jvalue & 0x00000003;
> val3 = val3 <<22;
> jvalue = val1 + val2 + val3;
> b0 = gen_ncmp(OR_PACKET, off_opc, BPF_W, 0x00c0ff0f,
> (u_int)jtype, reverse, (u_int)jvalue);
> break;
>
> case M_DPC:
> if (off_dpc == (u_int)-1)
> bpf_error("'dpc' supported only on SS7");
> /* dpc coded on 14 bits so max value 16383 */
> if (jvalue > 16383)
> bpf_error("dpc value %u too big; max value = 16383",
> jvalue);
> /* the following instructions are made to convert jvalue
> * to the forme used to write dpc in an ss7 message*/
> val1 = jvalue & 0x000000ff;
> val1 = val1 << 24;
> val2 = jvalue & 0x00003f00;
> val2 = val2 << 8;
> jvalue = val1 + val2;
> b0 = gen_ncmp(OR_PACKET, off_dpc, BPF_W, 0xff3f0000,
> (u_int)jtype, reverse, (u_int)jvalue);
> break;
>
> case M_SLS:
> if (off_sls == (u_int)-1)
> bpf_error("'sls' supported only on SS7");
> /* sls coded on 4 bits so max value 15 */
> if (jvalue > 15)
> bpf_error("sls value %u too big; max value = 15",
> jvalue);
> /* 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,
> (u_int)jtype,reverse, (u_int)jvalue);
> break;
>
> default:
> abort();
> }
> return b0;
> }
>