diff options
author | sam <sam@FreeBSD.org> | 2006-09-04 19:43:23 +0000 |
---|---|---|
committer | sam <sam@FreeBSD.org> | 2006-09-04 19:43:23 +0000 |
commit | ffd4bfbe7bca827ff32b489ba212a49c38c3f224 (patch) | |
tree | db8dd338004459feebb8546681de0f273dcd020f /contrib/libpcap/gencode.c | |
parent | bf281a32a1c59fe37a685431dd57d7e432a7f3e0 (diff) | |
download | FreeBSD-src-ffd4bfbe7bca827ff32b489ba212a49c38c3f224.zip FreeBSD-src-ffd4bfbe7bca827ff32b489ba212a49c38c3f224.tar.gz |
Import of libpcap v0.9.4
Diffstat (limited to 'contrib/libpcap/gencode.c')
-rw-r--r-- | contrib/libpcap/gencode.c | 271 |
1 files changed, 214 insertions, 57 deletions
diff --git a/contrib/libpcap/gencode.c b/contrib/libpcap/gencode.c index 33ad950..8672171 100644 --- a/contrib/libpcap/gencode.c +++ b/contrib/libpcap/gencode.c @@ -21,7 +21,7 @@ */ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.221.2.24 2005/06/20 21:52:53 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.221.2.34 2005/09/05 09:08:04 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -100,8 +100,8 @@ static const char rcsid[] _U_ = static jmp_buf top_ctx; static pcap_t *bpf_pcap; -/* Hack for updating VLAN, MPLS offsets. */ -static u_int orig_linktype = -1U, orig_nl = -1U; +/* Hack for updating VLAN, MPLS, and PPPoE offsets. */ +static u_int orig_linktype = -1U, orig_nl = -1U, label_stack_depth = -1U; /* XXX */ #ifdef PCAP_FDDIPAD @@ -205,6 +205,7 @@ static struct block *gen_thostop(const u_char *, int); static struct block *gen_wlanhostop(const u_char *, int); static struct block *gen_ipfchostop(const u_char *, int); static struct block *gen_dnhostop(bpf_u_int32, int); +static struct block *gen_mpls_linktype(int); static struct block *gen_host(bpf_u_int32, bpf_u_int32, int, int); #ifdef INET6 static struct block *gen_host6(struct in6_addr *, struct in6_addr *, int, int); @@ -778,6 +779,9 @@ init_linktype(p) off_proto = -1; off_payload = -1; + /* + * And assume we're not doing SS7. + */ off_sio = -1; off_opc = -1; off_dpc = -1; @@ -790,6 +794,7 @@ init_linktype(p) orig_linktype = -1; orig_nl = -1; + label_stack_depth = 0; reg_ll_size = -1; @@ -1113,8 +1118,12 @@ init_linktype(p) off_nl_nosnap = PFLOG_HDRLEN; /* no 802.2 LLC */ return; + case DLT_JUNIPER_MFR: case DLT_JUNIPER_MLFR: case DLT_JUNIPER_MLPPP: + case DLT_JUNIPER_PPP: + case DLT_JUNIPER_CHDLC: + case DLT_JUNIPER_FRELAY: off_linktype = 4; off_nl = 4; off_nl_nosnap = -1; /* no 802.2 LLC */ @@ -1135,6 +1144,7 @@ init_linktype(p) /* frames captured on a Juniper PPPoE service PIC * contain raw ethernet frames */ case DLT_JUNIPER_PPPOE: + case DLT_JUNIPER_ETHER: off_linktype = 16; off_nl = 18; /* Ethernet II */ off_nl_nosnap = 21; /* 802.3+802.2 */ @@ -1851,6 +1861,25 @@ gen_linktype(proto) { struct block *b0, *b1, *b2; + /* are we checking MPLS-encapsulated packets? */ + if (label_stack_depth > 0) { + switch (proto) { + case ETHERTYPE_IP: + case PPP_IP: + /* FIXME add other L3 proto IDs */ + return gen_mpls_linktype(Q_IP); + + case ETHERTYPE_IPV6: + case PPP_IPV6: + /* FIXME add other L3 proto IDs */ + return gen_mpls_linktype(Q_IPV6); + + default: + bpf_error("unsupported protocol over mpls"); + /* NOTREACHED */ + } + } + switch (linktype) { case DLT_EN10MB: @@ -2240,6 +2269,7 @@ gen_linktype(proto) /*NOTREACHED*/ break; + case DLT_JUNIPER_MFR: case DLT_JUNIPER_MLFR: case DLT_JUNIPER_MLPPP: case DLT_JUNIPER_ATM1: @@ -2250,6 +2280,10 @@ gen_linktype(proto) case DLT_JUNIPER_ES: case DLT_JUNIPER_MONITOR: case DLT_JUNIPER_SERVICES: + case DLT_JUNIPER_ETHER: + case DLT_JUNIPER_PPP: + case DLT_JUNIPER_FRELAY: + case DLT_JUNIPER_CHDLC: /* just lets verify the magic number for now - * on ATM we may have up to 6 different encapsulations on the wire * and need a lot of heuristics to figure out that the payload @@ -3034,6 +3068,40 @@ gen_dnhostop(addr, dir) return b1; } +/* + * Generate a check for IPv4 or IPv6 for MPLS-encapsulated packets; + * test the bottom-of-stack bit, and then check the version number + * field in the IP header. + */ +static struct block * +gen_mpls_linktype(proto) + int proto; +{ + struct block *b0, *b1; + + switch (proto) { + + case Q_IP: + /* match the bottom-of-stack bit */ + b0 = gen_mcmp(OR_NET, -2, BPF_B, 0x01, 0x01); + /* match the IPv4 version number */ + b1 = gen_mcmp(OR_NET, 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); + /* match the IPv4 version number */ + b1 = gen_mcmp(OR_NET, 0, BPF_B, 0x60, 0xf0); + gen_and(b0, b1); + return b1; + + default: + abort(); + } +} + static struct block * gen_host(addr, mask, proto, dir) bpf_u_int32 addr; @@ -3047,11 +3115,15 @@ gen_host(addr, mask, proto, dir) case Q_DEFAULT: b0 = gen_host(addr, mask, Q_IP, dir); - if (off_linktype != (u_int)-1) { - b1 = gen_host(addr, mask, Q_ARP, dir); - gen_or(b0, b1); - b0 = gen_host(addr, mask, Q_RARP, dir); - gen_or(b1, b0); + /* + * Only check for non-IPv4 addresses if we're not + * checking MPLS-encapsulated packets. + */ + if (label_stack_depth == 0) { + b1 = gen_host(addr, mask, Q_ARP, dir); + gen_or(b0, b1); + b0 = gen_host(addr, mask, Q_RARP, dir); + gen_or(b1, b0); } return b0; @@ -4393,6 +4465,7 @@ gen_proto(v, proto, dir) * * So we always check for ETHERTYPE_IP. */ + b0 = gen_linktype(ETHERTYPE_IP); #ifndef CHASE_CHAIN b1 = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)v); @@ -5983,6 +6056,7 @@ gen_inbound(dir) } break; + case DLT_JUNIPER_MFR: case DLT_JUNIPER_MLFR: case DLT_JUNIPER_MLPPP: case DLT_JUNIPER_ATM1: @@ -5993,6 +6067,10 @@ gen_inbound(dir) case DLT_JUNIPER_ES: case DLT_JUNIPER_MONITOR: case DLT_JUNIPER_SERVICES: + case DLT_JUNIPER_ETHER: + case DLT_JUNIPER_PPP: + case DLT_JUNIPER_FRELAY: + case DLT_JUNIPER_CHDLC: /* juniper flags (including direction) are stored * the byte after the 3-byte magic number */ if (dir) { @@ -6036,7 +6114,7 @@ gen_pf_ifname(const char *ifname) return (b0); } -/* PF firewall log matched interface */ +/* PF firewall log ruleset name */ struct block * gen_pf_ruleset(char *ruleset) { @@ -6175,7 +6253,11 @@ struct block * gen_vlan(vlan_num) int vlan_num; { - struct block *b0; + struct block *b0, *b1; + + /* can't check for VLAN-encapsulated packets inside MPLS */ + if (label_stack_depth > 0) + bpf_error("no VLAN match after MPLS"); /* * Change the offsets to point to the type and data fields within @@ -6207,30 +6289,28 @@ gen_vlan(vlan_num) * be done assuming a VLAN, even though the "or" could be viewed * as meaning "or, if this isn't a VLAN packet...". */ - orig_linktype = off_linktype; /* save original values */ - orig_nl = off_nl; + orig_linktype = off_linktype; /* save original values */ + orig_nl = off_nl; - switch (linktype) { + switch (linktype) { - case DLT_EN10MB: - off_linktype += 4; - off_nl_nosnap += 4; - off_nl += 4; - break; + case DLT_EN10MB: + off_linktype += 4; + off_nl_nosnap += 4; + off_nl += 4; + break; - 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*/ + } /* check for VLAN */ b0 = gen_cmp(OR_LINK, orig_linktype, BPF_H, (bpf_int32)ETHERTYPE_8021Q); /* If a specific VLAN is requested, check VLAN id */ if (vlan_num >= 0) { - struct block *b1; - b1 = gen_mcmp(OR_LINK, orig_nl, BPF_H, (bpf_int32)vlan_num, 0x0fff); gen_and(b0, b1); @@ -6247,7 +6327,7 @@ struct block * gen_mpls(label_num) int label_num; { - struct block *b0; + struct block *b0,*b1; /* * Change the offsets to point to the type and data fields within @@ -6258,44 +6338,46 @@ gen_mpls(label_num) * * XXX - this is a bit of a kludge. See comments in gen_vlan(). */ - orig_linktype = off_linktype; /* save original values */ orig_nl = off_nl; - 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; - - case DLT_PPP: - off_nl_nosnap += 4; - off_nl += 4; - - b0 = gen_cmp(OR_LINK, orig_linktype, BPF_H, - (bpf_int32)PPP_MPLS_UCAST); - 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", + if (label_stack_depth > 0) { + /* just match the bottom-of-stack bit clear */ + b0 = gen_mcmp(OR_LINK, orig_nl-2, BPF_B, 0, 0x01); + } else { + /* + * Indicate that we're checking MPLS-encapsulated headers, + * to make sure higher level code generators don't try to + * match against IP-related protocols such as Q_ARP, Q_RARP + * etc. + */ + switch (linktype) { + + case DLT_C_HDLC: /* fall through */ + case DLT_EN10MB: + b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, + (bpf_int32)ETHERTYPE_MPLS); + break; + + case DLT_PPP: + b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, + (bpf_int32)PPP_MPLS_UCAST); + 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*/ - break; + b0 = NULL; + /*NOTREACHED*/ + break; + } } /* If a specific MPLS label is requested, check it */ if (label_num >= 0) { - struct block *b1; - label_num = label_num << 12; /* label is shifted 12 bits on the wire */ b1 = gen_mcmp(OR_LINK, orig_nl, BPF_W, (bpf_int32)label_num, 0xfffff000); /* only compare the first 20 bits */ @@ -6303,9 +6385,84 @@ gen_mpls(label_num) b0 = b1; } + off_nl_nosnap += 4; + off_nl += 4; + label_stack_depth++; return (b0); } +/* + * Support PPPOE discovery and session. + */ +struct block * +gen_pppoed() +{ + /* check for PPPoE discovery */ + return gen_linktype((bpf_int32)ETHERTYPE_PPPOED); +} + +struct block * +gen_pppoes() +{ + struct block *b0; + + /* + * Test against the PPPoE session link-layer type. + */ + b0 = gen_linktype((bpf_int32)ETHERTYPE_PPPOES); + + /* + * Change the offsets to point to the type and data fields within + * the PPP packet. + * + * 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 PPPoE node the adjusted offsets. + * + * This would mean that "pppoes" 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 "pppoes", which might break some expressions. + * However, it would mean that "(pppoes 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 "pppoes and ..." which I suspect are the + * most common expressions involving "pppoes". "pppoes or ..." + * doesn't necessarily do what the user would really want, now, + * as all the "or ..." tests would be done assuming PPPoE, even + * though the "or" could be viewed as meaning "or, if this isn't + * a PPPoE packet...". + */ + orig_linktype = off_linktype; /* save original values */ + orig_nl = off_nl; + + /* + * The "network-layer" protocol is PPPoE, which has a 6-byte + * PPPoE header, followed by PPP payload, so we set the + * offsets to the network layer offset plus 6 bytes for + * the PPPoE header plus the values appropriate for PPP when + * encapsulated in Ethernet (which means there's no HDLC + * encapsulation). + */ + off_linktype = orig_nl + 6; + off_nl = orig_nl + 6 + 2; + off_nl_nosnap = orig_nl + 6 + 2; + + /* + * Set the link-layer type to PPP, as all subsequent tests will + * be on the encapsulated PPP header. + */ + linktype = DLT_PPP; + + return b0; +} + struct block * gen_atmfield_code(atmfield, jvalue, jtype, reverse) int atmfield; |