*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.221.2.8 2005-04-25 18:59:20 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.221.2.9 2005-05-01 00:38:34 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
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 slist *gen_load_llrel(u_int, u_int);
+static struct slist *gen_load_nlrel(u_int, u_int);
+static struct slist *gen_load_ipv4tlrel(u_int, u_int);
static struct block *gen_uncond(int);
static inline struct block *gen_true(void);
static inline struct block *gen_false(void);
struct slist *s;
struct block *b;
- s = new_stmt(BPF_LD|BPF_ABS|size);
- s->s.k = offset;
+ s = gen_load_llrel(offset, size);
b = new_block(JMP(BPF_JEQ));
b->stmts = s;
struct slist *s;
struct block *b;
- s = new_stmt(BPF_LD|BPF_ABS|size);
- s->s.k = offset;
+ s = gen_load_llrel(offset, size);
b = new_block(JMP(BPF_JGT));
b->stmts = s;
/* NOTREACHED */
}
+/*
+ * Load a value relative to the beginning of the link-layer header.
+ */
+static struct slist *
+gen_load_llrel(offset, size)
+ u_int offset, size;
+{
+ struct slist *s;
+
+ s = new_stmt(BPF_LD|BPF_ABS|size);
+ s->s.k = offset;
+ return s;
+}
+
+/*
+ * Load a value relative to the beginning of the network-layer header.
+ */
+static struct slist *
+gen_load_nlrel(offset, size)
+ u_int offset, size;
+{
+ return gen_load_llrel(off_nl + offset, size);
+}
+
+/*
+ * Load a value relative to the beginning of the transport-layer header,
+ * where the network-layer header is an IPv4 header. (This doesn't handle
+ * AH headers.)
+ */
+static struct slist *
+gen_load_ipv4tlrel(offset, size)
+ u_int offset, size;
+{
+ struct slist *s;
+
+ /*
+ * Load the X register with the length of the IPv4 header,
+ * in bytes.
+ */
+ s = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
+ s->s.k = off_nl;
+
+ /*
+ * Load the item at {length of the link-layer header} + {length
+ * of the IPv4 header} + {specified offset}.
+ */
+ s->next = new_stmt(BPF_LD|BPF_IND|size);
+ s->next->s.k = off_nl + offset;
+
+ return s;
+}
+
static struct block *
gen_uncond(rsense)
int rsense;
*
* First, check for To DS set, i.e. check "link[1] & 0x01".
*/
- s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
- s->s.k = 1;
+ s = gen_load_llrel(1, BPF_B);
b1 = new_block(JMP(BPF_JSET));
b1->s.k = 0x01; /* To DS */
b1->stmts = s;
* Now, check for To DS not set, i.e. check
* "!(link[1] & 0x01)".
*/
- s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
- s->s.k = 1;
+ s = gen_load_llrel(1, BPF_B);
b2 = new_block(JMP(BPF_JSET));
b2->s.k = 0x01; /* To DS */
b2->stmts = s;
* Now check for From DS being set, and AND that with
* the ORed-together checks.
*/
- s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
- s->s.k = 1;
+ s = gen_load_llrel(1, BPF_B);
b1 = new_block(JMP(BPF_JSET));
b1->s.k = 0x02; /* From DS */
b1->stmts = s;
/*
* Now check for data frames with From DS not set.
*/
- s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
- s->s.k = 1;
+ s = gen_load_llrel(1, BPF_B);
b2 = new_block(JMP(BPF_JSET));
b2->s.k = 0x02; /* From DS */
b2->stmts = s;
* Now check for a data frame.
* I.e, check "link[0] & 0x08".
*/
- s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
- s->s.k = 0;
+ gen_load_llrel(0, BPF_B);
b1 = new_block(JMP(BPF_JSET));
b1->s.k = 0x08;
b1->stmts = s;
* is a management frame.
* I.e, check "!(link[0] & 0x08)".
*/
- s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
- s->s.k = 0;
+ s = gen_load_llrel(0, BPF_B);
b2 = new_block(JMP(BPF_JSET));
b2->s.k = 0x08;
b2->stmts = s;
*
* I.e., check "!(link[0] & 0x04)".
*/
- s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
- s->s.k = 0;
+ s = gen_load_llrel(0, BPF_B);
b1 = new_block(JMP(BPF_JSET));
b1->s.k = 0x04;
b1->stmts = s;
*
* First, check for To DS set, i.e. "link[1] & 0x01".
*/
- s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
- s->s.k = 1;
+ s = gen_load_llrel(1, BPF_B);
b1 = new_block(JMP(BPF_JSET));
b1->s.k = 0x01; /* To DS */
b1->stmts = s;
* Now, check for To DS not set, i.e. check
* "!(link[1] & 0x01)".
*/
- s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
- s->s.k = 1;
+ s = gen_load_llrel(1, BPF_B);
b2 = new_block(JMP(BPF_JSET));
b2->s.k = 0x01; /* To DS */
b2->stmts = s;
* Now check for a data frame.
* I.e, check "link[0] & 0x08".
*/
- s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
- s->s.k = 0;
+ s = gen_load_llrel(0, BPF_B);
b1 = new_block(JMP(BPF_JSET));
b1->s.k = 0x08;
b1->stmts = s;
* is a management frame.
* I.e, check "!(link[0] & 0x08)".
*/
- s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
- s->s.k = 0;
+ s = gen_load_llrel(0, BPF_B);
b2 = new_block(JMP(BPF_JSET));
b2->s.k = 0x08;
b2->stmts = s;
*
* I.e., check "!(link[0] & 0x04)".
*/
- s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
- s->s.k = 0;
+ s = gen_load_llrel(0, BPF_B);
b1 = new_block(JMP(BPF_JSET));
b1->s.k = 0x04;
b1->stmts = s;
struct block *b;
/* not ip frag */
- s = new_stmt(BPF_LD|BPF_H|BPF_ABS);
- s->s.k = off_nl + 6;
+ s = gen_load_nlrel(6, BPF_H);
b = new_block(JMP(BPF_JSET));
b->s.k = 0x1fff;
b->stmts = s;
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;
+ s = gen_load_ipv4tlrel(off, BPF_H);
b = new_block(JMP(BPF_JEQ));
b->stmts = s;
v1 = v2;
v2 = vtemp;
}
- s1 = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
- s1->s.k = off_nl;
- s1->next = new_stmt(BPF_LD|BPF_IND|BPF_H);
- s1->next->s.k = off_nl + off;
+ s1 = gen_load_ipv4tlrel(off, BPF_H);
b1 = new_block(JMP(BPF_JGE));
b1->stmts = s1;
b1->s.k = v1;
- s2 = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
- s2->s.k = off_nl;
-
- s2->next = new_stmt(BPF_LD|BPF_IND|BPF_H);
- s2->next->s.k = off_nl + off;
+ s2 = gen_load_ipv4tlrel(off, BPF_H);
b2 = new_block(JMP(BPF_JGT));
gen_not(b2);
v2 = vtemp;
}
- s1 = new_stmt(BPF_LD|BPF_ABS|BPF_H);
- s1->s.k = off_nl + 40 + off;
+ s1 = gen_load_nlrel(40 + off, BPF_H);
b1 = new_block(JMP(BPF_JGE));
b1->stmts = s1;
b1->s.k = v1;
- s2 = new_stmt(BPF_LD|BPF_ABS|BPF_H);
- s2->s.k = off_nl + 40 + off;
+ s2 = gen_load_nlrel(40 + off, BPF_H);
b2 = new_block(JMP(BPF_JGT));
gen_not(b2);
register struct slist *s;
/* link[offset] & 1 != 0 */
- s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
- s->s.k = offset;
+ s = gen_load_llrel(offset, BPF_B);
b0 = new_block(JMP(BPF_JSET));
b0->s.k = 1;
b0->stmts = s;
*
* First, check for To DS set, i.e. "link[1] & 0x01".
*/
- s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
- s->s.k = 1;
+ s = gen_load_llrel(1, BPF_B);
b1 = new_block(JMP(BPF_JSET));
b1->s.k = 0x01; /* To DS */
b1->stmts = s;
* Now, check for To DS not set, i.e. check
* "!(link[1] & 0x01)".
*/
- s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
- s->s.k = 1;
+ s = gen_load_llrel(1, BPF_B);
b2 = new_block(JMP(BPF_JSET));
b2->s.k = 0x01; /* To DS */
b2->stmts = s;
* Now check for a data frame.
* I.e, check "link[0] & 0x08".
*/
- s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
- s->s.k = 0;
+ s = gen_load_llrel(0, BPF_B);
b1 = new_block(JMP(BPF_JSET));
b1->s.k = 0x08;
b1->stmts = s;
* is a management frame.
* I.e, check "!(link[0] & 0x08)".
*/
- s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
- s->s.k = 0;
+ s = gen_load_llrel(0, BPF_B);
b2 = new_block(JMP(BPF_JSET));
b2->s.k = 0x08;
b2->stmts = s;
*
* I.e., check "!(link[0] & 0x04)".
*/
- s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
- s->s.k = 0;
+ s = gen_load_llrel(0, BPF_B);
b1 = new_block(JMP(BPF_JSET));
b1->s.k = 0x04;
b1->stmts = s;