dect
/
libpcap
Archived
13
0
Fork 0

When we're processing MPLS-encapsulated packets, don't set off_linktype

to -1, set a "we're doing MPLS" flag, and check that flag rather than
checking for an off_linktype of -1; off_linktype can be -1 for reasons
having nothing to do with MPLS (e.g., a DLT_ of DLT_RAW), and those
should be handled as they have traditionally been.

Rename "gen_null()" to "gen_mpls_linktype()" to make it clearer what it
does (it checks the MPLS stack as well as the IP header).
This commit is contained in:
guy 2005-08-08 02:38:29 +00:00
parent 638626c0d8
commit c6b5551a8b
1 changed files with 89 additions and 66 deletions

155
gencode.c
View File

@ -21,7 +21,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.255 2005-07-31 19:01:14 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.256 2005-08-08 02:38:29 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -205,7 +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_null(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);
@ -700,6 +700,11 @@ static u_int off_mac;
*/
static u_int off_linktype;
/*
* TRUE if we're checking MPLS-encapsulated packets.
*/
static int is_mpls = 0;
/*
* TRUE if the link layer includes an ATM pseudo-header.
*/
@ -779,6 +784,14 @@ init_linktype(p)
off_proto = -1;
off_payload = -1;
/*
* Assume also that we're not checking MPLS-encapsulated packets.
*/
is_mpls = 0;
/*
* And assume we're not doing SS7.
*/
off_sio = -1;
off_opc = -1;
off_dpc = -1;
@ -1854,22 +1867,24 @@ gen_linktype(proto)
{
struct block *b0, *b1, *b2;
/* has the linktype been poisoned by MPLS expression ? */
if (off_linktype == (u_int)-1) {
switch(proto) {
/* FIXME add other L3 proto IDs */
case ETHERTYPE_IP:
case PPP_IP:
return gen_null(Q_IP);
/* FIXME add other L3 proto IDs */
case ETHERTYPE_IPV6:
case PPP_IPV6:
return gen_null(Q_IPV6);
default:
bpf_error("unsupported protocol over mpls");
/* NOTREACHED */
}
}
/* are we checking MPLS-encapsulated packets? */
if (is_mpls) {
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) {
@ -2469,7 +2484,7 @@ gen_hostop(addr, mask, dir, proto, src_off, dst_off)
default:
abort();
}
b0 = gen_linktype(proto);
b0 = gen_linktype(proto);
b1 = gen_mcmp(OR_NET, offset, BPF_W, (bpf_int32)addr, mask);
gen_and(b0, b1);
return b1;
@ -3055,34 +3070,36 @@ gen_dnhostop(addr, dir)
return b1;
}
/* generate a null link-layer encapsulation
*
* which is matching for 0x4 in the first byte of the IPv4 header
* matching for 0x6 in the first byte of the IPv6 header
*
* we need this for matching to an IP payload in MPLS packets
/*
* 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_null(proto)
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);
gen_and(b0, b1);
return b1;
case Q_IPV6:
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);
gen_and(b0, b1);
return b1;
default:
default:
abort();
}
}
@ -3100,11 +3117,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 (!is_mpls) {
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;
@ -3454,7 +3475,7 @@ gen_proto_abbrev(proto)
break;
case Q_IP:
b1 = gen_linktype(ETHERTYPE_IP);
b1 = gen_linktype(ETHERTYPE_IP);
break;
case Q_ARP:
@ -4447,7 +4468,7 @@ gen_proto(v, proto, dir)
* So we always check for ETHERTYPE_IP.
*/
b0 = gen_linktype(ETHERTYPE_IP);
b0 = gen_linktype(ETHERTYPE_IP);
#ifndef CHASE_CHAIN
b1 = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)v);
#else
@ -6230,7 +6251,11 @@ struct block *
gen_vlan(vlan_num)
int vlan_num;
{
struct block *b0,*b1;
struct block *b0, *b1;
/* can't check for VLAN-encapsulated packets inside MPLS */
if (is_mpls)
bpf_error("no VLAN match after MPLS");
/*
* Change the offsets to point to the type and data fields within
@ -6262,28 +6287,25 @@ 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 */
if (orig_linktype != (u_int)-1)
b0 = gen_cmp(OR_LINK, orig_linktype, BPF_H, (bpf_int32)ETHERTYPE_8021Q);
else
bpf_error("no VLAN match after MPLS");
b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)ETHERTYPE_8021Q);
/* If a specific VLAN is requested, check VLAN id */
if (vlan_num >= 0) {
@ -6314,34 +6336,35 @@ 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;
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 {
/* poison the linktype to make sure higher level
* code generators don't try to match against IP related protocols like
* Q_ARP, Q_RARP etc. */
off_linktype = -1;
/*
* 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.
*/
is_mpls = 1;
switch (linktype) {
case DLT_C_HDLC: /* fall through */
case DLT_EN10MB:
b0 = gen_cmp(OR_LINK, orig_linktype, BPF_H,
b0 = gen_cmp(OR_LINK, off_linktype, BPF_H,
(bpf_int32)ETHERTYPE_MPLS);
break;
case DLT_PPP:
b0 = gen_cmp(OR_LINK, orig_linktype, BPF_H,
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 */
/* 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",