static struct block *root;
+/*
+ * Absolute offsets, which are offsets from the beginning of the raw
+ * packet data, are, in the general case, the sum of a variable value
+ * and a constant value; the variable value may be absent, in which
+ * case the offset is only the constant value, and the constant value
+ * may be zero, in which case the offset is only the variable value.
+ *
+ * bpf_abs_offset is a structure containing all that information:
+ *
+ * is_variable is 1 if there's a variable part.
+ *
+ * constant_part is the constant part of the value, possibly zero;
+ *
+ * if is_variable is 1, reg is the register number for a register
+ * containing the variable value if the register has been assigned,
+ * and -1 otherwise.
+ */
+typedef struct {
+ int is_variable;
+ u_int constant_part;
+ int reg;
+} bpf_abs_offset;
+
/*
* Value passed to gen_load_a() to indicate what the offset argument
* is relative to the beginning of.
*/
enum e_offrel {
- OR_PACKET, /* full packet data */
- OR_LINKHDR, /* link-layer header */
- OR_PREVLINKHDR, /* previous link-layer header */
- OR_LLC, /* 802.2 LLC header */
- OR_LINKPL, /* link-layer payload */
- OR_MPLSPL, /* MPLS payload */
- OR_NET, /* network-layer header */
- OR_NET_NOSNAP, /* network-layer header, with no SNAP header at the link layer */
- OR_TRAN_IPV4, /* transport-layer header, with IPv4 network layer */
- OR_TRAN_IPV6 /* transport-layer header, with IPv6 network layer */
+ OR_PACKET, /* full packet data */
+ OR_LINKHDR, /* link-layer header */
+ OR_PREVLINKHDR, /* previous link-layer header */
+ OR_LLC, /* 802.2 LLC header */
+ OR_PREVMPLSHDR, /* previous MPLS header */
+ OR_LINKTYPE, /* link-layer type */
+ OR_LINKPL, /* link-layer payload */
+ OR_LINKPL_NOSNAP, /* link-layer payload, with no SNAP header at the link layer */
+ OR_TRAN_IPV4, /* transport-layer header, with IPv4 network layer */
+ OR_TRAN_IPV6 /* transport-layer header, with IPv6 network layer */
};
#ifdef INET6
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_linkhdrrel(u_int, u_int);
-static struct slist *gen_load_prevlinkhdrrel(u_int, u_int);
-static struct slist *gen_load_linkplrel(u_int, u_int);
+static struct slist *gen_load_absoffsetrel(bpf_abs_offset *, u_int, u_int);
static struct slist *gen_load_a(enum e_offrel, u_int, u_int);
static struct slist *gen_loadx_iphdrlen(void);
static struct block *gen_uncond(int);
static struct slist *gen_load_radiotap_llprefixlen(void);
static struct slist *gen_load_ppi_llprefixlen(void);
static void insert_compute_vloffsets(struct block *);
-static struct slist *gen_llprefixlen(void);
-static struct slist *gen_prevlinkhdrprefixlen(void);
-static struct slist *gen_off_linkpl(void);
+static struct slist *gen_abs_offset_varpart(bpf_abs_offset *);
static int ethertype_to_ppptype(int);
static struct block *gen_linktype(int);
static struct block *gen_snap(bpf_u_int32, bpf_u_int32);
*/
/*
- * The offset of the beginning of the link-layer payload, from the beginning
- * of the raw packet data, is, in the general case, the sum of a variable
- * value and a constant value; the variable value may be absent, in which
- * case the offset is only the constant value, and the constant value may
- * be zero, in which case the offset is only the variable value.
- *
- * off_linkhdr_constant_part is the constant value.
- *
- * reg_off_linkhdr is the register number for a register containing the
- * variable value, and -1 otherwise.
- *
- * off_linkhdr_is_variable is 1 if there's a variable part.
+ * Absolute offset of the beginning of the link-layer header.
*/
-static u_int off_linkhdr_constant_part;
-static int reg_off_linkhdr;
-static int off_linkhdr_is_variable;
+static bpf_abs_offset off_linkhdr;
/*
* If we're checking a link-layer header for a packet encapsulated in
* previous layers' link-layer header from the beginning of the raw
* packet data.
*/
-static u_int off_prevlinkhdr_constant_part;
-static int reg_off_prevlinkhdr;
-static int off_prevlinkhdr_is_variable;
+static bpf_abs_offset off_prevlinkhdr;
/*
* This is the equivalent information for the outermost layers' link-layer
* header.
*/
-static u_int off_outermostlinkhdr_constant_part;
-static int reg_off_outermostlinkhdr;
-static int off_outermostlinkhdr_is_variable;
+static bpf_abs_offset off_outermostlinkhdr;
/*
- * The offset of the beginning of the link-layer payload, from the beginning
- * of the raw packet data, is, in the general case, the sum of a variable
- * value and a constant value; the variable value may be absent, in which
- * case the offset is only the constant value, and the constant value may
- * be zero, in which case the offset is only the variable value.
- *
- * off_linkpl_constant_part is the constant value.
- *
- * reg_off_linkpl is the register number for a register containing the
- * variable value, and -1 otherwise.
- *
- * off_linkpl_is_variable is 1 if there's a variable part.
+ * "Push" the current value of the link-layer header type and link-layer
+ * header offset onto a "stack", and set a new value. (It's not a
+ * full-blown stack; we keep only the top two items.)
+ */
+#define PUSH_LINKHDR(new_linktype, new_is_variable, new_constant_part, new_reg) \
+{ \
+ prevlinktype = new_linktype; \
+ off_prevlinkhdr = off_linkhdr; \
+ linktype = new_linktype; \
+ off_linkhdr.is_variable = new_is_variable; \
+ off_linkhdr.constant_part = new_constant_part; \
+ off_linkhdr.reg = new_reg; \
+}
+
+/*
+ * Absolute offset of the beginning of the link-layer payload.
*/
-static u_int off_linkpl_constant_part;
-static int off_linkpl_is_variable;
-static int reg_off_linkpl;
+static bpf_abs_offset off_linkpl;
/*
* "off_linktype" is the offset to information in the link-layer header
- * giving the packet type. This offset is relative to the beginning
- * of the link-layer header - i.e., it doesn't include off_linkhdr_constant_part - so
- * loads with an offset that includes "off_linktype" should use
- * OR_LINKHDR.
+ * giving the packet type. This is an absolute offset from the beginning
+ * of the packet.
*
* For Ethernet, it's the offset of the Ethernet type field; this
* means that it must have a value that skips VLAN tags.
*
* For Linux cooked sockets, it's the offset of the type field.
*
- * It's set to -1 for no encapsulation, in which case, IP is assumed.
+ * off_linktype.constant_part is set to -1 for no encapsulation,
+ * in which case, IP is assumed.
*/
-static u_int off_linktype;
+static bpf_abs_offset off_linktype;
/*
* TRUE if the link layer includes an ATM pseudo-header.
/*
* These are offsets to the beginning of the network-layer header.
* They are relative to the beginning of the link-layer payload (i.e.,
- * they don't include off_linkhdr_constant_part or off_linkpl_constant_part).
+ * they don't include off_linkhdr.constant_part or off_linkpl.constant_part).
*
* If the link layer never uses 802.2 LLC:
*
* We start out with only one link-layer header.
*/
outermostlinktype = pcap_datalink(p);
- off_outermostlinkhdr_constant_part = 0;
- off_outermostlinkhdr_is_variable = 0;
- reg_off_outermostlinkhdr = -1;
+ off_outermostlinkhdr.constant_part = 0;
+ off_outermostlinkhdr.is_variable = 0;
+ off_outermostlinkhdr.reg = -1;
prevlinktype = outermostlinktype;
- off_prevlinkhdr_constant_part = 0;
- off_prevlinkhdr_is_variable = 0;
- reg_off_prevlinkhdr = -1;
+ off_prevlinkhdr.constant_part = 0;
+ off_prevlinkhdr.is_variable = 0;
+ off_prevlinkhdr.reg = -1;
linktype = outermostlinktype;
- off_linkhdr_constant_part = 0;
- off_linkhdr_is_variable = 0;
- reg_off_linkhdr = -1;
+ off_linkhdr.constant_part = 0;
+ off_linkhdr.is_variable = 0;
+ off_linkhdr.reg = -1;
/*
* XXX
*/
- off_linkpl_constant_part = 0;
- off_linkpl_is_variable = 0;
- reg_off_linkpl = -1;
+ off_linkpl.constant_part = 0;
+ off_linkpl.is_variable = 0;
+ off_linkpl.reg = -1;
+
+ off_linktype.constant_part = 0;
+ off_linktype.is_variable = 0;
+ off_linktype.reg = -1;
/*
* Assume it's not raw ATM with a pseudo-header, for now.
switch (linktype) {
case DLT_ARCNET:
- off_linktype = 2;
- off_linkpl_constant_part = 6;
+ off_linktype.constant_part = 2;
+ off_linkpl.constant_part = 6;
off_nl = 0; /* XXX in reality, variable! */
off_nl_nosnap = 0; /* no 802.2 LLC */
- return;
+ break;
case DLT_ARCNET_LINUX:
- off_linktype = 4;
- off_linkpl_constant_part = 8;
+ off_linktype.constant_part = 4;
+ off_linkpl.constant_part = 8;
off_nl = 0; /* XXX in reality, variable! */
off_nl_nosnap = 0; /* no 802.2 LLC */
- return;
+ break;
case DLT_EN10MB:
- off_linktype = 12;
- off_linkpl_constant_part = 14; /* Ethernet header length */
+ off_linktype.constant_part = 12;
+ off_linkpl.constant_part = 14; /* Ethernet header length */
off_nl = 0; /* Ethernet II */
off_nl_nosnap = 3; /* 802.3+802.2 */
- return;
+ break;
case DLT_SLIP:
/*
* SLIP doesn't have a link level type. The 16 byte
* header is hacked into our SLIP driver.
*/
- off_linktype = -1;
- off_linkpl_constant_part = 16;
+ off_linktype.constant_part = -1;
+ off_linkpl.constant_part = 16;
off_nl = 0;
off_nl_nosnap = 0; /* no 802.2 LLC */
- return;
+ break;
case DLT_SLIP_BSDOS:
/* XXX this may be the same as the DLT_PPP_BSDOS case */
- off_linktype = -1;
+ off_linktype.constant_part = -1;
/* XXX end */
- off_linkpl_constant_part = 24;
+ off_linkpl.constant_part = 24;
off_nl = 0;
off_nl_nosnap = 0; /* no 802.2 LLC */
- return;
+ break;
case DLT_NULL:
case DLT_LOOP:
- off_linktype = 0;
- off_linkpl_constant_part = 4;
+ off_linktype.constant_part = 0;
+ off_linkpl.constant_part = 4;
off_nl = 0;
off_nl_nosnap = 0; /* no 802.2 LLC */
- return;
+ break;
case DLT_ENC:
- off_linktype = 0;
- off_linkpl_constant_part = 12;
+ off_linktype.constant_part = 0;
+ off_linkpl.constant_part = 12;
off_nl = 0;
off_nl_nosnap = 0; /* no 802.2 LLC */
- return;
+ break;
case DLT_PPP:
case DLT_PPP_PPPD:
case DLT_C_HDLC: /* BSD/OS Cisco HDLC */
case DLT_PPP_SERIAL: /* NetBSD sync/async serial PPP */
- off_linktype = 2; /* skip HDLC-like framing */
- off_linkpl_constant_part = 4; /* skip HDLC-like framing and protocol field */
+ off_linktype.constant_part = 2; /* skip HDLC-like framing */
+ off_linkpl.constant_part = 4; /* skip HDLC-like framing and protocol field */
off_nl = 0;
off_nl_nosnap = 0; /* no 802.2 LLC */
- return;
+ break;
case DLT_PPP_ETHER:
/*
* This does no include the Ethernet header, and
* only covers session state.
*/
- off_linktype = 6;
- off_linkpl_constant_part = 8;
+ off_linktype.constant_part = 6;
+ off_linkpl.constant_part = 8;
off_nl = 0;
off_nl_nosnap = 0; /* no 802.2 LLC */
- return;
+ break;
case DLT_PPP_BSDOS:
- off_linktype = 5;
- off_linkpl_constant_part = 24;
+ off_linktype.constant_part = 5;
+ off_linkpl.constant_part = 24;
off_nl = 0;
off_nl_nosnap = 0; /* no 802.2 LLC */
- return;
+ break;
case DLT_FDDI:
/*
* is being used and pick out the encapsulated Ethernet type.
* XXX - should we generate code to check for SNAP?
*/
- off_linktype = 13;
- off_linktype += pcap_fddipad;
- off_linkpl_constant_part = 13; /* FDDI MAC header length */
- off_linkpl_constant_part += pcap_fddipad;
+ off_linktype.constant_part = 13;
+ off_linktype.constant_part += pcap_fddipad;
+ off_linkpl.constant_part = 13; /* FDDI MAC header length */
+ off_linkpl.constant_part += pcap_fddipad;
off_nl = 8; /* 802.2+SNAP */
off_nl_nosnap = 3; /* 802.2 */
- return;
+ break;
case DLT_IEEE802:
/*
* the 16-bit value at an offset of 14 (shifted right
* 8 - figure out which byte that is).
*/
- off_linktype = 14;
- off_linkpl_constant_part = 14; /* Token Ring MAC header length */
+ off_linktype.constant_part = 14;
+ off_linkpl.constant_part = 14; /* Token Ring MAC header length */
off_nl = 8; /* 802.2+SNAP */
off_nl_nosnap = 3; /* 802.2 */
- return;
+ break;
- case DLT_IEEE802_11:
case DLT_PRISM_HEADER:
case DLT_IEEE802_11_RADIO_AVS:
case DLT_IEEE802_11_RADIO:
+ off_linkhdr.is_variable = 1;
+ /* Fall through, 802.11 doesn't have a variable link
+ * prefix but is otherwise the same. */
+
+ case DLT_IEEE802_11:
/*
* 802.11 doesn't really have a link-level type field.
- * We set "off_linktype" to the offset of the LLC header.
+ * We set "off_linktype.constant_part" to the offset of
+ * the LLC header.
*
* To check for Ethernet types, we assume that SSAP = SNAP
* is being used and pick out the encapsulated Ethernet type.
* header or an AVS header, so, in practice, it's
* variable-length.
*/
- off_linktype = 24;
- off_linkpl_constant_part = 0; /* link-layer header is variable-length */
- off_linkpl_is_variable = 1;
+ off_linktype.constant_part = 24;
+ off_linkpl.constant_part = 0; /* link-layer header is variable-length */
+ off_linkpl.is_variable = 1;
off_nl = 8; /* 802.2+SNAP */
off_nl_nosnap = 3; /* 802.2 */
- return;
+ break;
case DLT_PPI:
/*
* the encapsulated DLT should be DLT_IEEE802_11) we
* generate code to check for this too.
*/
- off_linktype = 24;
- off_linkpl_constant_part = 0; /* link-layer header is variable-length */
- off_linkpl_is_variable = 1;
+ off_linktype.constant_part = 24;
+ off_linkpl.constant_part = 0; /* link-layer header is variable-length */
+ off_linkpl.is_variable = 1;
+ off_linkhdr.is_variable = 1;
off_nl = 8; /* 802.2+SNAP */
off_nl_nosnap = 3; /* 802.2 */
- return;
+ break;
case DLT_ATM_RFC1483:
case DLT_ATM_CLIP: /* Linux ATM defines this */
* or "pppoa and tcp port 80" and have it check for
* PPPo{A,E} and a PPP protocol of IP and....
*/
- off_linktype = 0;
- off_linkpl_constant_part = 0; /* packet begins with LLC header */
+ off_linktype.constant_part = 0;
+ off_linkpl.constant_part = 0; /* packet begins with LLC header */
off_nl = 8; /* 802.2+SNAP */
off_nl_nosnap = 3; /* 802.2 */
- return;
+ break;
case DLT_SUNATM:
/*
off_vci = SUNATM_VCI_POS;
off_proto = PROTO_POS;
off_payload = SUNATM_PKT_BEGIN_POS;
- off_linktype = off_payload;
- off_linkpl_constant_part = off_payload; /* if LLC-encapsulated */
+ off_linktype.constant_part = off_payload;
+ off_linkpl.constant_part = off_payload; /* if LLC-encapsulated */
off_nl = 8; /* 802.2+SNAP */
off_nl_nosnap = 3; /* 802.2 */
- return;
+ break;
case DLT_RAW:
case DLT_IPV4:
case DLT_IPV6:
- off_linktype = -1;
- off_linkpl_constant_part = 0;
+ off_linktype.constant_part = -1;
+ off_linkpl.constant_part = 0;
off_nl = 0;
off_nl_nosnap = 0; /* no 802.2 LLC */
- return;
+ break;
case DLT_LINUX_SLL: /* fake header for Linux cooked socket */
- off_linktype = 14;
- off_linkpl_constant_part = 16;
+ off_linktype.constant_part = 14;
+ off_linkpl.constant_part = 16;
off_nl = 0;
off_nl_nosnap = 0; /* no 802.2 LLC */
- return;
+ break;
case DLT_LTALK:
/*
* but really it just indicates whether there is a "short" or
* "long" DDP packet following.
*/
- off_linktype = -1;
- off_linkpl_constant_part = 0;
+ off_linktype.constant_part = -1;
+ off_linkpl.constant_part = 0;
off_nl = 0;
off_nl_nosnap = 0; /* no 802.2 LLC */
- return;
+ break;
case DLT_IP_OVER_FC:
/*
* XXX - should we generate code to check for SNAP? RFC
* 2625 says SNAP should be used.
*/
- off_linktype = 16;
- off_linkpl_constant_part = 16;
+ off_linktype.constant_part = 16;
+ off_linkpl.constant_part = 16;
off_nl = 8; /* 802.2+SNAP */
off_nl_nosnap = 3; /* 802.2 */
- return;
+ break;
case DLT_FRELAY:
/*
* XXX - we should set this to handle SNAP-encapsulated
* frames (NLPID of 0x80).
*/
- off_linktype = -1;
- off_linkpl_constant_part = 0;
+ off_linktype.constant_part = -1;
+ off_linkpl.constant_part = 0;
off_nl = 0;
off_nl_nosnap = 0; /* no 802.2 LLC */
- return;
+ break;
/*
* the only BPF-interesting FRF.16 frames are non-control frames;
* so lets start with offset 4 for now and increments later on (FIXME);
*/
case DLT_MFR:
- off_linktype = -1;
- off_linkpl_constant_part = 0;
+ off_linktype.constant_part = -1;
+ off_linkpl.constant_part = 0;
off_nl = 4;
off_nl_nosnap = 0; /* XXX - for now -> no 802.2 LLC */
- return;
+ break;
case DLT_APPLE_IP_OVER_IEEE1394:
- off_linktype = 16;
- off_linkpl_constant_part = 18;
+ off_linktype.constant_part = 16;
+ off_linkpl.constant_part = 18;
off_nl = 0;
off_nl_nosnap = 0; /* no 802.2 LLC */
- return;
+ break;
case DLT_SYMANTEC_FIREWALL:
- off_linktype = 6;
- off_linkpl_constant_part = 44;
+ off_linktype.constant_part = 6;
+ off_linkpl.constant_part = 44;
off_nl = 0; /* Ethernet II */
off_nl_nosnap = 0; /* XXX - what does it do with 802.3 packets? */
- return;
+ break;
#ifdef HAVE_NET_PFVAR_H
case DLT_PFLOG:
- off_linktype = 0;
- off_linkpl_constant_part = PFLOG_HDRLEN;
+ off_linktype.constant_part = 0;
+ off_linkpl.constant_part = PFLOG_HDRLEN;
off_nl = 0;
off_nl_nosnap = 0; /* no 802.2 LLC */
- return;
+ break;
#endif
case DLT_JUNIPER_MFR:
case DLT_JUNIPER_PPP:
case DLT_JUNIPER_CHDLC:
case DLT_JUNIPER_FRELAY:
- off_linktype = 4;
- off_linkpl_constant_part = 4;
+ off_linktype.constant_part = 4;
+ off_linkpl.constant_part = 4;
off_nl = 0;
off_nl_nosnap = -1; /* no 802.2 LLC */
- return;
+ break;
case DLT_JUNIPER_ATM1:
- off_linktype = 4; /* in reality variable between 4-8 */
- off_linkpl_constant_part = 4; /* in reality variable between 4-8 */
+ off_linktype.constant_part = 4; /* in reality variable between 4-8 */
+ off_linkpl.constant_part = 4; /* in reality variable between 4-8 */
off_nl = 0;
off_nl_nosnap = 10;
- return;
+ break;
case DLT_JUNIPER_ATM2:
- off_linktype = 8; /* in reality variable between 8-12 */
- off_linkpl_constant_part = 8; /* in reality variable between 8-12 */
+ off_linktype.constant_part = 8; /* in reality variable between 8-12 */
+ off_linkpl.constant_part = 8; /* in reality variable between 8-12 */
off_nl = 0;
off_nl_nosnap = 10;
- return;
+ break;
/* frames captured on a Juniper PPPoE service PIC
* contain raw ethernet frames */
case DLT_JUNIPER_PPPOE:
case DLT_JUNIPER_ETHER:
- off_linkpl_constant_part = 14;
- off_linktype = 16;
+ off_linkpl.constant_part = 14;
+ off_linktype.constant_part = 16;
off_nl = 18; /* Ethernet II */
off_nl_nosnap = 21; /* 802.3+802.2 */
- return;
+ break;
case DLT_JUNIPER_PPPOE_ATM:
- off_linktype = 4;
- off_linkpl_constant_part = 6;
+ off_linktype.constant_part = 4;
+ off_linkpl.constant_part = 6;
off_nl = 0;
off_nl_nosnap = -1; /* no 802.2 LLC */
- return;
+ break;
case DLT_JUNIPER_GGSN:
- off_linktype = 6;
- off_linkpl_constant_part = 12;
+ off_linktype.constant_part = 6;
+ off_linkpl.constant_part = 12;
off_nl = 0;
off_nl_nosnap = -1; /* no 802.2 LLC */
- return;
+ break;
case DLT_JUNIPER_ES:
- off_linktype = 6;
- off_linkpl_constant_part = -1; /* not really a network layer but raw IP addresses */
+ off_linktype.constant_part = 6;
+ off_linkpl.constant_part = -1; /* not really a network layer but raw IP addresses */
off_nl = -1; /* not really a network layer but raw IP addresses */
off_nl_nosnap = -1; /* no 802.2 LLC */
- return;
+ break;
case DLT_JUNIPER_MONITOR:
- off_linktype = 12;
- off_linkpl_constant_part = 12;
+ off_linktype.constant_part = 12;
+ off_linkpl.constant_part = 12;
off_nl = 0; /* raw IP/IP6 header */
off_nl_nosnap = -1; /* no 802.2 LLC */
- return;
+ break;
case DLT_BACNET_MS_TP:
- off_linktype = -1;
- off_linkpl_constant_part = -1;
+ off_linktype.constant_part = -1;
+ off_linkpl.constant_part = -1;
off_nl = -1;
off_nl_nosnap = -1;
- return;
+ break;
case DLT_JUNIPER_SERVICES:
- off_linktype = 12;
- off_linkpl_constant_part = -1; /* L3 proto location dep. on cookie type */
+ off_linktype.constant_part = 12;
+ off_linkpl.constant_part = -1; /* L3 proto location dep. on cookie type */
off_nl = -1; /* L3 proto location dep. on cookie type */
off_nl_nosnap = -1; /* no 802.2 LLC */
- return;
+ break;
case DLT_JUNIPER_VP:
- off_linktype = 18;
- off_linkpl_constant_part = -1;
+ off_linktype.constant_part = 18;
+ off_linkpl.constant_part = -1;
off_nl = -1;
off_nl_nosnap = -1;
- return;
+ break;
case DLT_JUNIPER_ST:
- off_linktype = 18;
- off_linkpl_constant_part = -1;
+ off_linktype.constant_part = 18;
+ off_linkpl.constant_part = -1;
off_nl = -1;
off_nl_nosnap = -1;
- return;
+ break;
case DLT_JUNIPER_ISM:
- off_linktype = 8;
- off_linkpl_constant_part = -1;
+ off_linktype.constant_part = 8;
+ off_linkpl.constant_part = -1;
off_nl = -1;
off_nl_nosnap = -1;
- return;
+ break;
case DLT_JUNIPER_VS:
case DLT_JUNIPER_SRX_E2E:
case DLT_JUNIPER_FIBRECHANNEL:
case DLT_JUNIPER_ATM_CEMIC:
- off_linktype = 8;
- off_linkpl_constant_part = -1;
+ off_linktype.constant_part = 8;
+ off_linkpl.constant_part = -1;
off_nl = -1;
off_nl_nosnap = -1;
- return;
+ break;
case DLT_MTP2:
off_li = 2;
off_opc = 4;
off_dpc = 4;
off_sls = 7;
- off_linktype = -1;
- off_linkpl_constant_part = -1;
+ off_linktype.constant_part = -1;
+ off_linkpl.constant_part = -1;
off_nl = -1;
off_nl_nosnap = -1;
- return;
+ break;
case DLT_MTP2_WITH_PHDR:
off_li = 6;
off_opc = 8;
off_dpc = 8;
off_sls = 11;
- off_linktype = -1;
- off_linkpl_constant_part = -1;
+ off_linktype.constant_part = -1;
+ off_linkpl.constant_part = -1;
off_nl = -1;
off_nl_nosnap = -1;
- return;
+ break;
case DLT_ERF:
off_li = 22;
off_opc = 24;
off_dpc = 24;
off_sls = 27;
- off_linktype = -1;
- off_linkpl_constant_part = -1;
+ off_linktype.constant_part = -1;
+ off_linkpl.constant_part = -1;
off_nl = -1;
off_nl_nosnap = -1;
- return;
+ break;
case DLT_PFSYNC:
- off_linktype = -1;
- off_linkpl_constant_part = 4;
+ off_linktype.constant_part = -1;
+ off_linkpl.constant_part = 4;
off_nl = 0;
off_nl_nosnap = 0;
- return;
+ break;
case DLT_AX25_KISS:
/*
* Currently, only raw "link[N:M]" filtering is supported.
*/
- off_linktype = -1; /* variable, min 15, max 71 steps of 7 */
- off_linkpl_constant_part = -1;
+ off_linktype.constant_part = -1; /* variable, min 15, max 71 steps of 7 */
+ off_linkpl.constant_part = -1;
off_nl = -1; /* variable, min 16, max 71 steps of 7 */
off_nl_nosnap = -1; /* no 802.2 LLC */
- return;
+ break;
case DLT_IPNET:
- off_linktype = 1;
- off_linkpl_constant_part = 24; /* ipnet header length */
+ off_linktype.constant_part = 1;
+ off_linkpl.constant_part = 24; /* ipnet header length */
off_nl = 0;
off_nl_nosnap = -1;
- return;
+ break;
case DLT_NETANALYZER:
- off_linkhdr_constant_part = 4; /* Ethernet header is past 4-byte pseudo-header */
- off_linktype = 12;
- off_linkpl_constant_part = off_linkhdr_constant_part + 14; /* pseudo-header+Ethernet header length */
+ off_linkhdr.constant_part = 4; /* Ethernet header is past 4-byte pseudo-header */
+ off_linktype.constant_part = off_linkhdr.constant_part + 12;
+ off_linkpl.constant_part = off_linkhdr.constant_part + 14; /* pseudo-header+Ethernet header length */
off_nl = 0; /* Ethernet II */
off_nl_nosnap = 3; /* 802.3+802.2 */
- return;
+ break;
case DLT_NETANALYZER_TRANSPARENT:
- off_linkhdr_constant_part = 12; /* MAC header is past 4-byte pseudo-header, preamble, and SFD */
- off_linktype = 12;
- off_linkpl_constant_part = off_linkhdr_constant_part + 14; /* pseudo-header+preamble+SFD+Ethernet header length */
+ off_linkhdr.constant_part = 12; /* MAC header is past 4-byte pseudo-header, preamble, and SFD */
+ off_linktype.constant_part = off_linkhdr.constant_part + 12;
+ off_linkpl.constant_part = off_linkhdr.constant_part + 14; /* pseudo-header+preamble+SFD+Ethernet header length */
off_nl = 0; /* Ethernet II */
off_nl_nosnap = 3; /* 802.3+802.2 */
- return;
+ break;
default:
/*
*/
if (linktype >= DLT_MATCHING_MIN &&
linktype <= DLT_MATCHING_MAX) {
- off_linktype = -1;
- off_linkpl_constant_part = -1;
+ off_linktype.constant_part = -1;
+ off_linkpl.constant_part = -1;
off_nl = -1;
off_nl_nosnap = -1;
- return;
+ } else {
+ bpf_error("unknown data link type %d", linktype);
}
-
+ break;
}
- bpf_error("unknown data link type %d", linktype);
- /* NOTREACHED */
-}
-/*
- * 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_linkhdrrel(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.
- *
- * Otherwise, the length of the prefix preceding the link-layer
- * header is "off_linkhdr_constant_part".
- */
- 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.
- * do an indirect load, to use the X register as an offset.
- */
- s2 = new_stmt(BPF_LD|BPF_IND|size);
- s2->s.k = off_linkhdr_constant_part + offset;
- sappend(s, s2);
- } else {
- /*
- * There is no variable-length header preceding the
- * link-layer header; add in off_linkhdr_constant_part, which, if
- * there's a fixed-length header preceding the
- * link-layer header, is the length of that header.
- */
- s = new_stmt(BPF_LD|BPF_ABS|size);
- s->s.k = off_linkhdr_constant_part + offset;
- }
- return s;
+ off_outermostlinkhdr = off_prevlinkhdr = off_linkhdr;
}
/*
- * Load a value relative to the beginning of the previous link-layer header,
- * if we're also looking at an inner link-layer header encapsulated
- * within other protocol layers.
- *
- * 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.
+ * Load a value relative to the specified absolute offset.
*/
static struct slist *
-gen_load_prevlinkhdrrel(offset, size)
- u_int offset, size;
+gen_load_absoffsetrel(bpf_abs_offset *abs_offset, u_int offset, u_int size)
{
struct slist *s, *s2;
- s = gen_prevlinkhdrprefixlen();
+ s = gen_abs_offset_varpart(abs_offset);
/*
* 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.
- *
- * Otherwise, the length of the prefix preceding the link-layer
- * header is "off_prevlinkhdr_constant_part".
- */
- 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.
- * do an indirect load, to use the X register as an offset.
- */
- s2 = new_stmt(BPF_LD|BPF_IND|size);
- s2->s.k = off_prevlinkhdr_constant_part + offset;
- sappend(s, s2);
- } else {
- /*
- * There is no variable-length header preceding the
- * link-layer header; add in off_prevlinkhdr_constant_part, which,
- * if there's a fixed-length header preceding the
- * link-layer header, is the length of that header.
- */
- s = new_stmt(BPF_LD|BPF_ABS|size);
- s->s.k = off_prevlinkhdr_constant_part + offset;
- }
- return s;
-}
-
-/*
- * Load a value relative to the beginning of the link-layer payload.
- */
-static struct slist *
-gen_load_linkplrel(offset, size)
- u_int offset, size;
-{
- struct slist *s, *s2;
-
- s = gen_off_linkpl();
-
- /*
- * If s is non-null, the offset of the link-layer payload is
- * variable, and s points to a list of instructions that
- * arrange that the X register contains the variable part
- * of that offset. The sum of that variable part and
- * off_linkpl_constant_part is the offset.
+ * contains the variable part of the absolute offset, so we
+ * generate a load relative to that, with an offset of
+ * abs_offset->constant_part + offset.
*
- * Otherwise, the offset of the link-layer payload is constant,
- * and is in off_linkpl_constant_part.
+ * Otherwise, we can do an absolute load with an offset of
+ * abs_offset->constant_part + offset.
*/
if (s != NULL) {
/*
- * The variable part of the offset of the link-layer payload
- * is in the X register. Do an indirect load, to use the X
- * register as part of the offset of the load.
+ * "s" points to a list of statements that puts the
+ * variable part of the absolute offset into the X register.
+ * Do an indirect load, to use the X register as an offset.
*/
s2 = new_stmt(BPF_LD|BPF_IND|size);
- s2->s.k = off_linkpl_constant_part + offset;
+ s2->s.k = abs_offset->constant_part + offset;
sappend(s, s2);
} else {
/*
- * The offset of the link-layer payload is constant,
- * and is in off_linkpl_constant_part; load the value
- * at that offset plus the specified offset.
+ * There is no variable part of the absolute offset, so
+ * just do an absolute load.
*/
s = new_stmt(BPF_LD|BPF_ABS|size);
- s->s.k = off_linkpl_constant_part + offset;
+ s->s.k = abs_offset->constant_part + offset;
}
return s;
}
break;
case OR_LINKHDR:
- s = gen_load_linkhdrrel(offset, size);
+ s = gen_load_absoffsetrel(&off_linkhdr, offset, size);
break;
case OR_PREVLINKHDR:
- s = gen_load_prevlinkhdrrel(offset, size);
+ s = gen_load_absoffsetrel(&off_prevlinkhdr, offset, size);
break;
case OR_LLC:
+ s = gen_load_absoffsetrel(&off_linkpl, offset, size);
+ break;
+
+ case OR_PREVMPLSHDR:
+ s = gen_load_absoffsetrel(&off_linkpl, off_nl - 4 + offset, size);
+ break;
+
case OR_LINKPL:
- case OR_MPLSPL:
- s = gen_load_linkplrel(offset, size);
+ s = gen_load_absoffsetrel(&off_linkpl, off_nl + offset, size);
break;
- case OR_NET:
- s = gen_load_linkplrel(off_nl + offset, size);
+ case OR_LINKPL_NOSNAP:
+ s = gen_load_absoffsetrel(&off_linkpl, off_nl_nosnap + offset, size);
break;
- case OR_NET_NOSNAP:
- s = gen_load_linkplrel(off_nl_nosnap + offset, size);
+ case OR_LINKTYPE:
+ s = gen_load_absoffsetrel(&off_linktype, offset, size);
break;
case OR_TRAN_IPV4:
* part in the offset of the load.
*/
s2 = new_stmt(BPF_LD|BPF_IND|size);
- s2->s.k = off_linkpl_constant_part + off_nl + offset;
+ s2->s.k = off_linkpl.constant_part + off_nl + offset;
sappend(s, s2);
break;
case OR_TRAN_IPV6:
- s = gen_load_linkplrel(off_nl + 40 + offset, size);
+ s = gen_load_absoffsetrel(&off_linkpl, off_nl + 40 + offset, size);
break;
default:
{
struct slist *s, *s2;
- s = gen_off_linkpl();
+ s = gen_abs_offset_varpart(&off_linkpl);
if (s != NULL) {
/*
* The offset of the link-layer payload has a variable
* the value from the X register.
*/
s2 = new_stmt(BPF_LD|BPF_IND|BPF_B);
- s2->s.k = off_nl;
+ s2->s.k = off_linkpl.constant_part + off_nl;
sappend(s, s2);
s2 = new_stmt(BPF_ALU|BPF_AND|BPF_K);
s2->s.k = 0xf;
* mode. Load the length of the IPv4 header, which
* is at an offset of off_nl from the beginning of
* the link-layer payload, and thus at an offset of
- * off_linkpl_constant_part + off_nl from the beginning
+ * off_linkpl.constant_part + off_nl from the beginning
* of the raw packet data, using that addressing mode.
*/
s = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
- s->s.k = off_linkpl_constant_part + off_nl;
+ s->s.k = off_linkpl.constant_part + off_nl;
}
return s;
}
* DSAP, as we do for other types <= ETHERMTU
* (i.e., other SAP values)?
*/
- b0 = gen_cmp_gt(OR_LINKHDR, off_linktype, BPF_H, ETHERMTU);
+ b0 = gen_cmp_gt(OR_LINKTYPE, 0, BPF_H, ETHERMTU);
gen_not(b0);
b1 = gen_cmp(OR_LLC, 0, BPF_H, (bpf_int32)
((proto << 8) | proto));
* Now we generate code to check for 802.3
* frames in general.
*/
- b0 = gen_cmp_gt(OR_LINKHDR, off_linktype, BPF_H, ETHERMTU);
+ b0 = gen_cmp_gt(OR_LINKTYPE, 0, BPF_H, ETHERMTU);
gen_not(b0);
/*
* do that before checking for the other frame
* types.
*/
- b0 = gen_cmp(OR_LINKHDR, off_linktype, BPF_H,
- (bpf_int32)ETHERTYPE_IPX);
+ b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)ETHERTYPE_IPX);
gen_or(b0, b1);
return b1;
* we check for an Ethernet type field less than
* 1500, which means it's an 802.3 length field.
*/
- b0 = gen_cmp_gt(OR_LINKHDR, off_linktype, BPF_H, ETHERMTU);
+ b0 = gen_cmp_gt(OR_LINKTYPE, 0, BPF_H, ETHERMTU);
gen_not(b0);
/*
* phase 1?); we just check for the Ethernet
* protocol type.
*/
- b0 = gen_cmp(OR_LINKHDR, off_linktype, BPF_H, (bpf_int32)proto);
+ b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
gen_or(b0, b1);
return b1;
* a length field, <= ETHERMTU) and
* then check the DSAP.
*/
- b0 = gen_cmp_gt(OR_LINKHDR, off_linktype, BPF_H, ETHERMTU);
+ b0 = gen_cmp_gt(OR_LINKTYPE, 0, BPF_H, ETHERMTU);
gen_not(b0);
- b1 = gen_cmp(OR_LINKHDR, off_linktype + 2, BPF_B,
- (bpf_int32)proto);
+ b1 = gen_cmp(OR_LINKTYPE, 2, BPF_B, (bpf_int32)proto);
gen_and(b0, b1);
return b1;
} else {
* will fail and the frame won't match,
* which is what we want).
*/
- return gen_cmp(OR_LINKHDR, off_linktype, BPF_H,
+ return gen_cmp(OR_LINKTYPE, 0, BPF_H,
(bpf_int32)proto);
}
}
switch (proto) {
case ETHERTYPE_IP:
- return gen_cmp(OR_LINKHDR, off_linktype, BPF_B,
- (bpf_int32)IPH_AF_INET);
+ return gen_cmp(OR_LINKTYPE, 0, BPF_B, (bpf_int32)IPH_AF_INET);
/* NOTREACHED */
case ETHERTYPE_IPV6:
- return gen_cmp(OR_LINKHDR, off_linktype, BPF_B,
+ return gen_cmp(OR_LINKTYPE, 0, BPF_B,
(bpf_int32)IPH_AF_INET6);
/* NOTREACHED */
* DSAP, as we do for other types <= ETHERMTU
* (i.e., other SAP values)?
*/
- b0 = gen_cmp(OR_LINKHDR, off_linktype, BPF_H, LINUX_SLL_P_802_2);
+ b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
b1 = gen_cmp(OR_LLC, 0, BPF_H, (bpf_int32)
((proto << 8) | proto));
gen_and(b0, b1);
b0 = gen_cmp(OR_LLC, 0, BPF_B, (bpf_int32)LLCSAP_IPX);
b1 = gen_snap(0x000000, ETHERTYPE_IPX);
gen_or(b0, b1);
- b0 = gen_cmp(OR_LINKHDR, off_linktype, BPF_H, LINUX_SLL_P_802_2);
+ b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
gen_and(b0, b1);
/*
* Now check for 802.3 frames and OR that with
* the previous test.
*/
- b0 = gen_cmp(OR_LINKHDR, off_linktype, BPF_H, LINUX_SLL_P_802_3);
+ b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_3);
gen_or(b0, b1);
/*
* do that before checking for the other frame
* types.
*/
- b0 = gen_cmp(OR_LINKHDR, off_linktype, BPF_H,
- (bpf_int32)ETHERTYPE_IPX);
+ b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)ETHERTYPE_IPX);
gen_or(b0, b1);
return b1;
* we check for the 802.2 protocol type in the
* "Ethernet type" field.
*/
- b0 = gen_cmp(OR_LINKHDR, off_linktype, BPF_H, LINUX_SLL_P_802_2);
+ b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
/*
* 802.2-encapsulated ETHERTYPE_ATALK packets are
* phase 1?); we just check for the Ethernet
* protocol type.
*/
- b0 = gen_cmp(OR_LINKHDR, off_linktype, BPF_H, (bpf_int32)proto);
+ b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
gen_or(b0, b1);
return b1;
* in the "Ethernet type" field, and
* then check the DSAP.
*/
- b0 = gen_cmp(OR_LINKHDR, off_linktype, BPF_H,
- LINUX_SLL_P_802_2);
- b1 = gen_cmp(OR_LINKHDR, off_linkpl_constant_part, BPF_B,
+ b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
+ b1 = gen_cmp(OR_LINKHDR, off_linkpl.constant_part, BPF_B,
(bpf_int32)proto);
gen_and(b0, b1);
return b1;
* will fail and the frame won't match,
* which is what we want).
*/
- return gen_cmp(OR_LINKHDR, off_linktype, BPF_H,
- (bpf_int32)proto);
+ return gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
}
}
}
* but no known software generates headers that aren't 144
* bytes long.
*/
- if (reg_off_linkhdr != -1) {
+ if (off_linkhdr.reg != -1) {
/*
* Load the cookie.
*/
* loading the length of the AVS header.
*/
s2 = new_stmt(BPF_ST);
- s2->s.k = reg_off_linkhdr;
+ s2->s.k = off_linkhdr.reg;
sappend(s1, s2);
sjcommon->s.jf = s2;
* generated uses that prefix, so we don't need to generate any
* code to load it.)
*/
- if (reg_off_linkhdr != -1) {
+ if (off_linkhdr.reg != -1) {
/*
* The 4 bytes at an offset of 4 from the beginning of
* the AVS header are the length of the AVS header.
* it.
*/
s2 = new_stmt(BPF_ST);
- s2->s.k = reg_off_linkhdr;
+ s2->s.k = off_linkhdr.reg;
sappend(s1, s2);
/*
* generated uses that prefix, so we don't need to generate any
* code to load it.)
*/
- if (reg_off_linkhdr != -1) {
+ if (off_linkhdr.reg != -1) {
/*
* The 2 bytes at offsets of 2 and 3 from the beginning
* of the radiotap header are the length of the radiotap
* it.
*/
s2 = new_stmt(BPF_ST);
- s2->s.k = reg_off_linkhdr;
+ s2->s.k = off_linkhdr.reg;
sappend(s1, s2);
/*
* into the register assigned to hold that length, if one has
* been assigned.
*/
- if (reg_off_linkhdr != -1) {
+ if (off_linkhdr.reg != -1) {
/*
* The 2 bytes at offsets of 2 and 3 from the beginning
* of the radiotap header are the length of the radiotap
* it.
*/
s2 = new_stmt(BPF_ST);
- s2->s.k = reg_off_linkhdr;
+ s2->s.k = off_linkhdr.reg;
sappend(s1, s2);
/*
struct slist *sjset_tsft_datapad, *sjset_notsft_datapad;
struct slist *s_roundup;
- if (reg_off_linkpl == -1) {
+ if (off_linkpl.reg == -1) {
/*
* No register has been assigned to the offset of
* the link-layer payload, which means nobody needs
* header.
*
* Otherwise, the length of the prefix preceding the link-layer
- * header is "off_outermostlinkhdr_constant_part".
+ * header is "off_outermostlinkhdr.constant_part".
*/
if (s == NULL) {
/*
*
* Load the length of the fixed-length prefix preceding
* the link-layer header (if any) into the X register,
- * and store it in the reg_off_linkpl register.
- * That length is off_outermostlinkhdr_constant_part.
+ * and store it in the off_linkpl.reg register.
+ * That length is off_outermostlinkhdr.constant_part.
*/
s = new_stmt(BPF_LDX|BPF_IMM);
- s->s.k = off_outermostlinkhdr_constant_part;
+ s->s.k = off_outermostlinkhdr.constant_part;
}
/*
* The X register contains the offset of the beginning of the
* link-layer header; add 24, which is the minimum length
* of the MAC header for a data frame, to that, and store it
- * in reg_off_linkpl, and then load the Frame Control field,
+ * in off_linkpl.reg, and then load the Frame Control field,
* which is at the offset in the X register, with an indexed load.
*/
s2 = new_stmt(BPF_MISC|BPF_TXA);
s2->s.k = 24;
sappend(s, s2);
s2 = new_stmt(BPF_ST);
- s2->s.k = reg_off_linkpl;
+ s2->s.k = off_linkpl.reg;
sappend(s, s2);
s2 = new_stmt(BPF_LD|BPF_IND|BPF_B);
sappend(s, sjset_qos);
/*
- * If it's set, add 2 to reg_off_linkpl, to skip the QoS
+ * If it's set, add 2 to off_linkpl.reg, to skip the QoS
* field.
* Otherwise, go to the first statement of the rest of the
* program.
*/
sjset_qos->s.jt = s2 = new_stmt(BPF_LD|BPF_MEM);
- s2->s.k = reg_off_linkpl;
+ s2->s.k = off_linkpl.reg;
sappend(s, s2);
s2 = new_stmt(BPF_ALU|BPF_ADD|BPF_IMM);
s2->s.k = 2;
sappend(s, s2);
s2 = new_stmt(BPF_ST);
- s2->s.k = reg_off_linkpl;
+ s2->s.k = off_linkpl.reg;
sappend(s, s2);
/*
* ANDing with ~3.
*/
s_roundup = new_stmt(BPF_LD|BPF_MEM);
- s_roundup->s.k = reg_off_linkpl;
+ s_roundup->s.k = off_linkpl.reg;
sappend(s, s_roundup);
s2 = new_stmt(BPF_ALU|BPF_ADD|BPF_IMM);
s2->s.k = 3;
s2->s.k = ~3;
sappend(s, s2);
s2 = new_stmt(BPF_ST);
- s2->s.k = reg_off_linkpl;
+ s2->s.k = off_linkpl.reg;
sappend(s, s2);
sjset_tsft_datapad->s.jt = s_roundup;
{
struct slist *s;
+ /* There is an implicit dependency between the link
+ * payload and link header since the payload computation
+ * includes the variable part of the header. Therefore,
+ * if nobody else has allocated a register for the link
+ * header and we need it, do it now. */
+ if (off_linkpl.reg != -1 && off_linkhdr.is_variable &&
+ off_linkhdr.reg == -1)
+ off_linkhdr.reg = alloc_reg();
+
/*
* For link-layer types that have a variable-length header
* preceding the link-layer header, generate code to load
}
/*
- * Generate code to load the register containing the variable part of
- * the offset of the link-layer header into the X register; if no
- * register for that offset has been allocated, allocate it first.
+ * Take an absolute offset, and:
+ *
+ * if it has no variable part, return NULL;
+ *
+ * if it has a variable part, generate code to load the register
+ * containing that variable part into the X register, returning
+ * a pointer to that code - if no register for that offset has
+ * been allocated, allocate it first.
+ *
* (The code to set that register will be generated later, but will
* be placed earlier in the code sequence.)
*/
static struct slist *
-gen_llprefixlen(void)
-{
- struct slist *s;
-
- if (off_linkhdr_is_variable) {
- if (reg_off_linkhdr == -1) {
- /*
- * We haven't yet assigned a register for the
- * variable part of the offset of the link-layer
- * header; allocate one.
- */
- reg_off_linkhdr = alloc_reg();
- }
-
- /*
- * Load the register containing the variable part of the
- * offset of the link-layer header into the X register.
- */
- s = new_stmt(BPF_LDX|BPF_MEM);
- s->s.k = reg_off_linkhdr;
- return s;
- } else {
- /*
- * That offset isn't variable, there's no variable part,
- * so we don't need to generate any code.
- */
- return NULL;
- }
-}
-
-/*
- * Generate code to compute the previous 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_prevlinkhdrprefixlen(void)
+gen_abs_offset_varpart(bpf_abs_offset *off)
{
struct slist *s;
- if (off_prevlinkhdr_is_variable) {
- if (reg_off_prevlinkhdr == -1) {
+ if (off->is_variable) {
+ if (off->reg == -1) {
/*
* We haven't yet assigned a register for the
* variable part of the offset of the link-layer
* header; allocate one.
*/
- reg_off_prevlinkhdr = alloc_reg();
+ off->reg = alloc_reg();
}
/*
* offset of the link-layer header into the X register.
*/
s = new_stmt(BPF_LDX|BPF_MEM);
- s->s.k = reg_off_prevlinkhdr;
- return s;
- } else {
- /*
- * That offset isn't variable, there's no variable part,
- * so we don't need to generate any code.
- */
- return NULL;
- }
-}
-
-/*
- * Generate code to load the register containing the variable part of
- * the offset of the link-layer payload into the X register; if no
- * register for that offset has been allocated, allocate it first.
- * (The code to set that register will be generated later, but will
- * be placed earlier in the code sequence.)
- */
-static struct slist *
-gen_off_linkpl(void)
-{
- struct slist *s;
-
- if (off_linkpl_is_variable) {
- if (reg_off_linkpl == -1) {
- /*
- * We haven't yet assigned a register for the
- * variable part of the offset of the link-layer
- * payload; allocate one.
- */
- reg_off_linkpl = alloc_reg();
- }
-
- /*
- * Load the register containing the variable part of the
- * offset of the link-layer payload into the X register.
- */
- s = new_stmt(BPF_LDX|BPF_MEM);
- s->s.k = reg_off_linkpl;
+ s->s.k = off->reg;
return s;
} else {
/*
/* fall through */
default:
- return gen_cmp(OR_LINKHDR, off_linktype, BPF_H,
- (bpf_int32)proto);
+ return gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
/*NOTREACHED*/
break;
}
* map them to the corresponding PPP protocol types.
*/
proto = ethertype_to_ppptype(proto);
- return gen_cmp(OR_LINKHDR, off_linktype, BPF_H, (bpf_int32)proto);
+ return gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
/*NOTREACHED*/
break;
* Also check for Van Jacobson-compressed IP.
* XXX - do this for other forms of PPP?
*/
- b0 = gen_cmp(OR_LINKHDR, off_linktype, BPF_H, PPP_IP);
- b1 = gen_cmp(OR_LINKHDR, off_linktype, BPF_H, PPP_VJC);
+ b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, PPP_IP);
+ b1 = gen_cmp(OR_LINKTYPE, 0, BPF_H, PPP_VJC);
gen_or(b0, b1);
- b0 = gen_cmp(OR_LINKHDR, off_linktype, BPF_H, PPP_VJNC);
+ b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, PPP_VJNC);
gen_or(b1, b0);
return b0;
default:
proto = ethertype_to_ppptype(proto);
- return gen_cmp(OR_LINKHDR, off_linktype, BPF_H,
+ return gen_cmp(OR_LINKTYPE, 0, BPF_H,
(bpf_int32)proto);
}
/*NOTREACHED*/
return gen_false();
case ETHERTYPE_IPV6:
- return (gen_cmp(OR_LINKHDR, off_linktype, BPF_B,
+ return (gen_cmp(OR_LINKTYPE, 0, BPF_B,
(bpf_int32)ARCTYPE_INET6));
case ETHERTYPE_IP:
- b0 = gen_cmp(OR_LINKHDR, off_linktype, BPF_B,
+ b0 = gen_cmp(OR_LINKTYPE, 0, BPF_B,
(bpf_int32)ARCTYPE_IP);
- b1 = gen_cmp(OR_LINKHDR, off_linktype, BPF_B,
+ b1 = gen_cmp(OR_LINKTYPE, 0, BPF_B,
(bpf_int32)ARCTYPE_IP_OLD);
gen_or(b0, b1);
return (b1);
case ETHERTYPE_ARP:
- b0 = gen_cmp(OR_LINKHDR, off_linktype, BPF_B,
+ b0 = gen_cmp(OR_LINKTYPE, 0, BPF_B,
(bpf_int32)ARCTYPE_ARP);
- b1 = gen_cmp(OR_LINKHDR, off_linktype, BPF_B,
+ b1 = gen_cmp(OR_LINKTYPE, 0, BPF_B,
(bpf_int32)ARCTYPE_ARP_OLD);
gen_or(b0, b1);
return (b1);
case ETHERTYPE_REVARP:
- return (gen_cmp(OR_LINKHDR, off_linktype, BPF_B,
+ return (gen_cmp(OR_LINKTYPE, 0, BPF_B,
(bpf_int32)ARCTYPE_REVARP));
case ETHERTYPE_ATALK:
- return (gen_cmp(OR_LINKHDR, off_linktype, BPF_B,
+ return (gen_cmp(OR_LINKTYPE, 0, BPF_B,
(bpf_int32)ARCTYPE_ATALK));
}
/*NOTREACHED*/
/*
* Does this link-layer header type have a field
* indicating the type of the next protocol? If
- * so, off_linktype will be the offset of that
+ * so, off_linktype.constant_part will be the offset of that
* field in the packet; if not, it will be -1.
*/
- if (off_linktype != (u_int)-1) {
+ if (off_linktype.constant_part != (u_int)-1) {
/*
* Yes; assume it's an Ethernet type. (If
* it's not, it needs to be handled specially
* above.)
*/
- return gen_cmp(OR_LINKHDR, off_linktype, BPF_H, (bpf_int32)proto);
+ return gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
} else {
/*
* No; report an error.
* We check for an Ethernet type field less than
* 1500, which means it's an 802.3 length field.
*/
- b0 = gen_cmp_gt(OR_LINKHDR, off_linktype, BPF_H, ETHERMTU);
+ b0 = gen_cmp_gt(OR_LINKTYPE, 0, BPF_H, ETHERMTU);
gen_not(b0);
/*
abort();
}
b0 = gen_linktype(proto);
- b1 = gen_mcmp(OR_NET, offset, BPF_W, (bpf_int32)addr, mask);
+ b1 = gen_mcmp(OR_LINKPL, offset, BPF_W, (bpf_int32)addr, mask);
gen_and(b0, b1);
return b1;
}
/* this order is important */
a = (u_int32_t *)addr;
m = (u_int32_t *)mask;
- 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]));
+ b1 = gen_mcmp(OR_LINKPL, offset + 12, BPF_W, ntohl(a[3]), ntohl(m[3]));
+ b0 = gen_mcmp(OR_LINKPL, offset + 8, BPF_W, ntohl(a[2]), ntohl(m[2]));
gen_and(b0, b1);
- b0 = gen_mcmp(OR_NET, offset + 4, BPF_W, ntohl(a[1]), ntohl(m[1]));
+ b0 = gen_mcmp(OR_LINKPL, offset + 4, BPF_W, ntohl(a[1]), ntohl(m[1]));
gen_and(b0, b1);
- b0 = gen_mcmp(OR_NET, offset + 0, BPF_W, ntohl(a[0]), ntohl(m[0]));
+ b0 = gen_mcmp(OR_LINKPL, offset + 0, BPF_W, ntohl(a[0]), ntohl(m[0]));
gen_and(b0, b1);
b0 = gen_linktype(proto);
gen_and(b0, b1);
}
b0 = gen_linktype(ETHERTYPE_DN);
/* Check for pad = 1, long header case */
- tmp = gen_mcmp(OR_NET, 2, BPF_H,
+ tmp = gen_mcmp(OR_LINKPL, 2, BPF_H,
(bpf_int32)ntohs(0x0681), (bpf_int32)ntohs(0x07FF));
- b1 = gen_cmp(OR_NET, 2 + 1 + offset_lh,
+ b1 = gen_cmp(OR_LINKPL, 2 + 1 + offset_lh,
BPF_H, (bpf_int32)ntohs((u_short)addr));
gen_and(tmp, b1);
/* Check for pad = 0, long header case */
- 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((u_short)addr));
+ tmp = gen_mcmp(OR_LINKPL, 2, BPF_B, (bpf_int32)0x06, (bpf_int32)0x7);
+ b2 = gen_cmp(OR_LINKPL, 2 + offset_lh, BPF_H, (bpf_int32)ntohs((u_short)addr));
gen_and(tmp, b2);
gen_or(b2, b1);
/* Check for pad = 1, short header case */
- tmp = gen_mcmp(OR_NET, 2, BPF_H,
+ tmp = gen_mcmp(OR_LINKPL, 2, BPF_H,
(bpf_int32)ntohs(0x0281), (bpf_int32)ntohs(0x07FF));
- b2 = gen_cmp(OR_NET, 2 + 1 + offset_sh, BPF_H, (bpf_int32)ntohs((u_short)addr));
+ b2 = gen_cmp(OR_LINKPL, 2 + 1 + offset_sh, BPF_H, (bpf_int32)ntohs((u_short)addr));
gen_and(tmp, b2);
gen_or(b2, b1);
/* Check for pad = 0, short header case */
- 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((u_short)addr));
+ tmp = gen_mcmp(OR_LINKPL, 2, BPF_B, (bpf_int32)0x02, (bpf_int32)0x7);
+ b2 = gen_cmp(OR_LINKPL, 2 + offset_sh, BPF_H, (bpf_int32)ntohs((u_short)addr));
gen_and(tmp, b2);
gen_or(b2, b1);
case Q_IP:
/* match the bottom-of-stack bit */
- b0 = gen_mcmp(OR_NET, -2, BPF_B, 0x01, 0x01);
+ b0 = gen_mcmp(OR_LINKPL, -2, BPF_B, 0x01, 0x01);
/* match the IPv4 version number */
- b1 = gen_mcmp(OR_NET, 0, BPF_B, 0x40, 0xf0);
+ b1 = gen_mcmp(OR_LINKPL, 0, BPF_B, 0x40, 0xf0);
gen_and(b0, b1);
return b1;
case Q_IPV6:
/* match the bottom-of-stack bit */
- b0 = gen_mcmp(OR_NET, -2, BPF_B, 0x01, 0x01);
+ b0 = gen_mcmp(OR_LINKPL, -2, BPF_B, 0x01, 0x01);
/* match the IPv4 version number */
- b1 = gen_mcmp(OR_NET, 0, BPF_B, 0x60, 0xf0);
+ b1 = gen_mcmp(OR_LINKPL, 0, BPF_B, 0x60, 0xf0);
gen_and(b0, b1);
return b1;
struct block *b;
/* not IPv4 frag other than the first frag */
- s = gen_load_a(OR_NET, 6, BPF_H);
+ s = gen_load_a(OR_LINKPL, 6, BPF_H);
b = new_block(JMP(BPF_JSET));
b->s.k = 0x1fff;
b->stmts = s;
struct block *b0, *b1, *tmp;
/* ip proto 'proto' and not a fragment other than the first fragment */
- tmp = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)proto);
+ tmp = gen_cmp(OR_LINKPL, 9, BPF_B, (bpf_int32)proto);
b0 = gen_ipfrag();
gen_and(tmp, b0);
/* ip6 proto 'proto' */
/* XXX - catch the first fragment of a fragmented packet? */
- b0 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)proto);
+ b0 = gen_cmp(OR_LINKPL, 6, BPF_B, (bpf_int32)proto);
switch (dir) {
case Q_SRC:
struct block *b0, *b1, *tmp;
/* ip proto 'proto' and not a fragment other than the first fragment */
- tmp = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)proto);
+ tmp = gen_cmp(OR_LINKPL, 9, BPF_B, (bpf_int32)proto);
b0 = gen_ipfrag();
gen_and(tmp, b0);
/* ip6 proto 'proto' */
/* XXX - catch the first fragment of a fragmented packet? */
- b0 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)proto);
+ b0 = gen_cmp(OR_LINKPL, 6, BPF_B, (bpf_int32)proto);
switch (dir) {
case Q_SRC:
* branches, and backward branch support is unlikely to appear
* in kernel BPF engines.)
*/
- switch (linktype) {
-
- case DLT_IEEE802_11:
- case DLT_PRISM_HEADER:
- case DLT_IEEE802_11_RADIO_AVS:
- case DLT_IEEE802_11_RADIO:
- case DLT_PPI:
- bpf_error("'protochain' not supported with 802.11");
- }
+ if (off_linkpl.is_variable)
+ bpf_error("'protochain' not supported with variable length headers");
no_optimize = 1; /*this code is not compatible with optimzer yet */
/* A = ip->ip_p */
s[i] = new_stmt(BPF_LD|BPF_ABS|BPF_B);
- s[i]->s.k = off_linkpl_constant_part + off_nl + 9;
+ s[i]->s.k = off_linkpl.constant_part + off_nl + 9;
i++;
/* X = ip->ip_hl << 2 */
s[i] = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
- s[i]->s.k = off_linkpl_constant_part + off_nl;
+ s[i]->s.k = off_linkpl.constant_part + off_nl;
i++;
break;
/* A = ip6->ip_nxt */
s[i] = new_stmt(BPF_LD|BPF_ABS|BPF_B);
- s[i]->s.k = off_linkpl_constant_part + off_nl + 6;
+ s[i]->s.k = off_linkpl.constant_part + off_nl + 6;
i++;
/* X = sizeof(struct ip6_hdr) */
s[i] = new_stmt(BPF_LDX|BPF_IMM);
*/
/* A = P[X + packet head] */
s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
- s[i]->s.k = off_linkpl_constant_part + off_nl;
+ s[i]->s.k = off_linkpl.constant_part + off_nl;
i++;
/* MEM[reg2] = A */
s[i] = new_stmt(BPF_ST);
i++;
/* A = P[X + packet head + 1]; */
s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
- s[i]->s.k = off_linkpl_constant_part + off_nl + 1;
+ s[i]->s.k = off_linkpl.constant_part + off_nl + 1;
i++;
/* A += 1 */
s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
i++;
/* A = P[X + packet head]; */
s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
- s[i]->s.k = off_linkpl_constant_part + off_nl;
+ s[i]->s.k = off_linkpl.constant_part + off_nl;
i++;
/* MEM[reg2] = A */
s[i] = new_stmt(BPF_ST);
i++;
/* A = P[X + packet head] */
s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
- s[i]->s.k = off_linkpl_constant_part + off_nl;
+ s[i]->s.k = off_linkpl.constant_part + off_nl;
i++;
/* A += 2 */
s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
*/
b0 = gen_linktype(ETHERTYPE_IP);
#ifndef CHASE_CHAIN
- b1 = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)v);
+ b1 = gen_cmp(OR_LINKPL, 9, BPF_B, (bpf_int32)v);
#else
b1 = gen_protochain(v, Q_IP);
#endif
*/
b0 = gen_linktype(LLCSAP_ISONS<<8 | LLCSAP_ISONS);
/* OSI in C-HDLC is stuffed with a fudge byte */
- b1 = gen_cmp(OR_NET_NOSNAP, 1, BPF_B, (long)v);
+ b1 = gen_cmp(OR_LINKPL_NOSNAP, 1, BPF_B, (long)v);
gen_and(b0, b1);
return b1;
default:
b0 = gen_linktype(LLCSAP_ISONS);
- b1 = gen_cmp(OR_NET_NOSNAP, 0, BPF_B, (long)v);
+ b1 = gen_cmp(OR_LINKPL_NOSNAP, 0, BPF_B, (long)v);
gen_and(b0, b1);
return b1;
}
* 4 is the offset of the PDU type relative to the IS-IS
* header.
*/
- b1 = gen_cmp(OR_NET_NOSNAP, 4, BPF_B, (long)v);
+ b1 = gen_cmp(OR_LINKPL_NOSNAP, 4, BPF_B, (long)v);
gen_and(b0, b1);
return b1;
* Also check for a fragment header before the final
* header.
*/
- b2 = gen_cmp(OR_NET, 6, BPF_B, IPPROTO_FRAGMENT);
- b1 = gen_cmp(OR_NET, 40, BPF_B, (bpf_int32)v);
+ b2 = gen_cmp(OR_LINKPL, 6, BPF_B, IPPROTO_FRAGMENT);
+ b1 = gen_cmp(OR_LINKPL, 40, BPF_B, (bpf_int32)v);
gen_and(b2, b1);
- b2 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)v);
+ b2 = gen_cmp(OR_LINKPL, 6, BPF_B, (bpf_int32)v);
gen_or(b2, b1);
#else
b1 = gen_protochain(v, Q_IPV6);
if (alist == NULL || *alist == NULL)
bpf_error("unknown host '%s'", name);
tproto = proto;
- if (off_linktype == (u_int)-1 && tproto == Q_DEFAULT)
+ if (off_linktype.constant_part == (u_int)-1 &&
+ tproto == Q_DEFAULT)
tproto = Q_IP;
b = gen_host(**alist++, 0xffffffff, tproto, dir, q.addr);
while (*alist) {
ai = res;
b = tmp = NULL;
tproto = tproto6 = proto;
- if (off_linktype == -1 && tproto == Q_DEFAULT) {
+ if (off_linktype.constant_part == -1 &&
+ tproto == Q_DEFAULT) {
tproto = Q_IP;
tproto6 = Q_IPV6;
}
* frame, so that 0 refers, for Ethernet LANE, to
* the beginning of the destination address?
*/
- s = gen_llprefixlen();
+ s = gen_abs_offset_varpart(&off_linkhdr);
/*
* If "s" is non-null, it has code to arrange that the
* into the X register and then added to the index).
*/
tmp = new_stmt(BPF_LD|BPF_IND|size);
- tmp->s.k = off_linkhdr_constant_part;
+ tmp->s.k = off_linkhdr.constant_part;
sappend(s, tmp);
sappend(inst->s, s);
break;
* XXX - are there any cases where we want
* off_nl_nosnap?
*/
- s = gen_off_linkpl();
+ s = gen_abs_offset_varpart(&off_linkpl);
/*
* If "s" is non-null, it has code to arrange that the
* start of the link-layer payload.
*/
tmp = new_stmt(BPF_LD|BPF_IND|size);
- tmp->s.k = off_linkpl_constant_part + off_nl;
+ tmp->s.k = off_linkpl.constant_part + off_nl;
sappend(s, tmp);
sappend(inst->s, s);
sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
sappend(s, new_stmt(BPF_MISC|BPF_TAX));
sappend(s, tmp = new_stmt(BPF_LD|BPF_IND|size));
- tmp->s.k = off_linkpl_constant_part + off_nl;
+ tmp->s.k = off_linkpl.constant_part + off_nl;
sappend(inst->s, s);
/*
bpf_error("netmask not known, so 'ip broadcast' not supported");
b0 = gen_linktype(ETHERTYPE_IP);
hostmask = ~netmask;
- b1 = gen_mcmp(OR_NET, 16, BPF_W, (bpf_int32)0, hostmask);
- b2 = gen_mcmp(OR_NET, 16, BPF_W,
+ b1 = gen_mcmp(OR_LINKPL, 16, BPF_W, (bpf_int32)0, hostmask);
+ b2 = gen_mcmp(OR_LINKPL, 16, BPF_W,
(bpf_int32)(~0 & hostmask), hostmask);
gen_or(b1, b2);
gen_and(b0, b2);
case Q_IP:
b0 = gen_linktype(ETHERTYPE_IP);
- b1 = gen_cmp_ge(OR_NET, 16, BPF_B, (bpf_int32)224);
+ b1 = gen_cmp_ge(OR_LINKPL, 16, BPF_B, (bpf_int32)224);
gen_and(b0, b1);
return b1;
case Q_IPV6:
b0 = gen_linktype(ETHERTYPE_IPV6);
- b1 = gen_cmp(OR_NET, 24, BPF_B, (bpf_int32)255);
+ b1 = gen_cmp(OR_LINKPL, 24, BPF_B, (bpf_int32)255);
gen_and(b0, b1);
return b1;
}
* The payload follows the full header, including the
* VLAN tags, so skip past this VLAN tag.
*/
- off_linkpl_constant_part += 4;
+ off_linkpl.constant_part += 4;
/*
* The link-layer type information follows the VLAN tags, so
* skip past this VLAN tag.
*/
- off_linktype += 4;
+ off_linktype.constant_part += 4;
return b0;
}
case DLT_NETANALYZER:
case DLT_NETANALYZER_TRANSPARENT:
#if defined(SKF_AD_VLAN_TAG) && defined(SKF_AD_VLAN_TAG_PRESENT)
- if (vlan_stack_depth == 0) {
+ /* Verify that this is the outer part of the packet and
+ * not encapsulated somehow. */
+ if (vlan_stack_depth == 0 && !off_linkhdr.is_variable &&
+ off_linkhdr.constant_part ==
+ off_outermostlinkhdr.constant_part) {
/*
* Do we need special VLAN handling?
*/
#endif
b0 = gen_vlan_no_bpf_extensions(vlan_num);
break;
+
+ case DLT_IEEE802_11:
+ case DLT_PRISM_HEADER:
+ case DLT_IEEE802_11_RADIO_AVS:
+ case DLT_IEEE802_11_RADIO:
+ b0 = gen_vlan_no_bpf_extensions(vlan_num);
+ break;
+
default:
bpf_error("no VLAN support for data link type %d",
linktype);
if (label_stack_depth > 0) {
/* just match the bottom-of-stack bit clear */
- b0 = gen_mcmp(OR_MPLSPL, off_nl-2, BPF_B, 0, 0x01);
+ b0 = gen_mcmp(OR_PREVMPLSHDR, 2, BPF_B, 0, 0x01);
} else {
/*
* We're not in an MPLS stack yet, so check the link-layer
/* If a specific MPLS label is requested, check it */
if (label_num >= 0) {
label_num = label_num << 12; /* label is shifted 12 bits on the wire */
- b1 = gen_mcmp(OR_MPLSPL, off_nl, BPF_W, (bpf_int32)label_num,
+ b1 = gen_mcmp(OR_LINKPL, 0, BPF_W, (bpf_int32)label_num,
0xfffff000); /* only compare the first 20 bits */
gen_and(b0, b1);
b0 = b1;
/* If a specific session is requested, check PPPoE session id */
if (sess_num >= 0) {
- b1 = gen_mcmp(OR_LINKPL, off_nl, BPF_W,
+ b1 = gen_mcmp(OR_LINKPL, 0, BPF_W,
(bpf_int32)sess_num, 0x0000ffff);
gen_and(b0, b1);
b0 = b1;
* link-layer payload, including any 802.2 LLC header, so
* it's 6 bytes past off_nl.
*/
- prevlinktype = linktype;
- off_prevlinkhdr_constant_part = off_linkhdr_constant_part;
- off_prevlinkhdr_is_variable = off_linkhdr_is_variable;
- reg_off_prevlinkhdr = reg_off_linkhdr;
-
- linktype = DLT_PPP;
- off_linkhdr_constant_part = off_linkpl_constant_part + off_nl + 6; /* 6 bytes past the PPPoE header */
- reg_off_linkhdr = reg_off_linkpl;
- off_linkhdr_is_variable = off_linkpl_is_variable;
+ PUSH_LINKHDR(DLT_PPP, off_linkpl.is_variable,
+ off_linkpl.constant_part + off_nl + 6, /* 6 bytes past the PPPoE header */
+ off_linkpl.reg);
- off_linktype = 0;
- off_linkpl_constant_part = off_linkhdr_constant_part + 2;
+ off_linktype = off_linkhdr;
+ off_linkpl.constant_part = off_linkhdr.constant_part + 2;
off_nl = 0;
off_nl_nosnap = 0; /* no 802.2 LLC */
*
* We assume LANE means Ethernet, not Token Ring.
*/
- prevlinktype = linktype;
- off_prevlinkhdr_constant_part = off_linkhdr_constant_part;
- off_prevlinkhdr_is_variable = off_linkhdr_is_variable;
- reg_off_prevlinkhdr = reg_off_linkhdr;
- linktype = DLT_EN10MB;
- off_linkhdr_constant_part = off_payload + 2; /* Ethernet header */
- off_linktype = 12;
- off_linkpl_constant_part = off_linkhdr_constant_part + 14; /* Ethernet */
+ PUSH_LINKHDR(DLT_EN10MB, 0,
+ off_payload + 2, /* Ethernet header */
+ -1);
+ off_linktype.constant_part = off_linkhdr.constant_part + 12;
+ off_linkpl.constant_part = off_linkhdr.constant_part + 14; /* Ethernet */
off_nl = 0; /* Ethernet II */
off_nl_nosnap = 3; /* 802.3+802.2 */
break;