Hello, i wish to share (hoping it might be found of interest) a patch i've written for personal use; it merges fine against the daily tarball of 09-06-2005 (yesterday). It aims to enhance the actual support for MPLS label hierarchies in a BPF filter.
Actually it's not possible, for example, to match a label ignoring the content of the upper ones. The patch allows to write an expression like 'mpls 1:100000 and mpls 3:1024' which checks whether the 2nd label has value 100000 and the 4th has value 1024 (the top label is meant to be 0). Though, i'm conscious of the following facts: a) the patch breaks the actual filter syntax (not specifying the position of the label in the stack is legal but matches everytime against the top label); b) it breaks the strict bottom-up approach because it allows to jump behind but still inside the MPLS stack (ie, 'mpls 3:1024 and mpls 1:100000' is legal); c) it does not address the issue of supporting upper layers in presence of MPLS in a BPF filter. Cheers, Paolo
diff -ur libpcap-2005.06.09/gencode.c libpcap-2005.06.09-paolo/gencode.c --- libpcap-2005.06.09/gencode.c 2005-06-06 16:10:58.000000000 +0200 +++ libpcap-2005.06.09-paolo/gencode.c 2005-06-10 11:29:26.000000000 +0200 @@ -6221,10 +6221,15 @@ * support for MPLS */ struct block * -gen_mpls(label_num) +gen_mpls(stack_pos, label_num) + int stack_pos; int label_num; { struct block *b0; + int nl; + + if (orig_nl == -1) orig_nl = off_nl; + nl = orig_nl+(stack_pos*4)+4; /* * Change the offsets to point to the type and data fields within @@ -6235,25 +6240,23 @@ * * 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; + off_nl_nosnap = nl; + off_nl = nl; - 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: - off_nl_nosnap += 4; - off_nl += 4; + off_nl_nosnap = nl; + off_nl = nl; - b0 = gen_cmp(OR_LINK, orig_linktype, BPF_H, + b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)PPP_MPLS_UCAST); break; @@ -6274,7 +6277,7 @@ 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, + b1 = gen_mcmp(OR_LINK, orig_nl+(stack_pos*4), BPF_W, (bpf_int32)label_num, 0xfffff000); /* only compare the first 20 bits */ gen_and(b0, b1); b0 = b1; diff -ur libpcap-2005.06.09/gencode.h libpcap-2005.06.09-paolo/gencode.h --- libpcap-2005.06.09/gencode.h 2005-05-02 23:13:08.000000000 +0200 +++ libpcap-2005.06.09-paolo/gencode.h 2005-06-10 11:15:29.000000000 +0200 @@ -280,7 +280,7 @@ struct block *gen_inbound(int); struct block *gen_vlan(int); -struct block *gen_mpls(int); +struct block *gen_mpls(int, int); struct block *gen_atmfield_code(int atmfield, bpf_int32 jvalue, bpf_u_int32 jtype, int reverse); struct block *gen_atmtype_abbrev(int type); diff -ur libpcap-2005.06.09/grammar.y libpcap-2005.06.09-paolo/grammar.y --- libpcap-2005.06.09/grammar.y 2005-05-02 23:13:09.000000000 +0200 +++ libpcap-2005.06.09-paolo/grammar.y 2005-06-10 11:15:29.000000000 +0200 @@ -325,8 +325,9 @@ | OUTBOUND { $$ = gen_inbound(1); } | VLAN pnum { $$ = gen_vlan($2); } | VLAN { $$ = gen_vlan(-1); } - | MPLS pnum { $$ = gen_mpls($2); } - | MPLS { $$ = gen_mpls(-1); } + | MPLS pnum { $$ = gen_mpls(0, $2); } + | MPLS pnum ':' pnum { $$ = gen_mpls($2, $4); } + | MPLS { $$ = gen_mpls(-1, -1); } | pfvar { $$ = $1; } ;
- This is the tcpdump-workers list. Visit https://lists.sandelman.ca/ to unsubscribe.