On Sat, Dec 08, 2018 at 10:48:37AM +0100, Denis Fondras wrote:
> Add basic MPLS support in libpcap.
>
> Index: gencode.c
> ===================================================================
> RCS file: /cvs/src/lib/libpcap/gencode.c,v
> retrieving revision 1.51
> diff -u -p -r1.51 gencode.c
> --- gencode.c 10 Nov 2018 10:17:37 -0000 1.51
> +++ gencode.c 14 Nov 2018 12:50:46 -0000
> @@ -37,6 +37,8 @@ struct rtentry;
> #include <net/if_pflog.h>
> #include <net/pfvar.h>
>
> +#include <netmpls/mpls.h>
> +
> #include <net80211/ieee80211.h>
> #include <net80211/ieee80211_radiotap.h>
>
> @@ -69,6 +71,7 @@ static pcap_t *bpf_pcap;
>
> /* Hack for updating VLAN offsets. */
> static u_int orig_linktype = -1, orig_nl = -1, orig_nl_nosnap = -1;
> +static u_int mpls_stack = 0;
>
> /* XXX */
> #ifdef PCAP_FDDIPAD
> @@ -837,11 +840,11 @@ gen_linktype(proto)
> struct block *b0, *b1;
>
> /* If we're not using encapsulation and checking for IP, we're done */
> - if (off_linktype == -1 && proto == ETHERTYPE_IP)
> + if ((off_linktype == -1 || mpls_stack > 0) && proto == ETHERTYPE_IP)
> return gen_true();
> #ifdef INET6
> /* this isn't the right thing to do, but sometimes necessary */
> - if (off_linktype == -1 && proto == ETHERTYPE_IPV6)
> + if ((off_linktype == -1 || mpls_stack > 0) && proto == ETHERTYPE_IPV6)
> return gen_true();
> #endif
>
> @@ -3348,6 +3351,34 @@ gen_acode(eaddr, q)
> }
> bpf_error("ARCnet address used in non-arc expression");
> /* NOTREACHED */
> +}
> +
> +struct block *
> +gen_mpls(label)
> + int label;
> +{
> + struct block *b0;
> +
> + if (label > MPLS_LABEL_MAX)
> + bpf_error("invalid MPLS label : %d", label);
> +
> + if (mpls_stack > 0) /* Bottom-Of-Label-Stack bit ? */
> + b0 = gen_mcmp(off_nl-2, BPF_B, (bpf_int32)0, 0x1);
> + else
> + b0 = gen_linktype(ETHERTYPE_MPLS);
> +
> + if (label >= 0) {
> + struct block *b1;
> +
> + b1 = gen_mcmp(off_nl, BPF_W, (bpf_int32)(label << 12),
> + MPLS_LABEL_MASK);
> + gen_and(b0, b1);
> + b0 = b1;
> + }
> + off_nl += 4;
> + off_linktype += 4;
> + mpls_stack++;
> + return (b0);
> }
>
> /*
> Index: gencode.h
> ===================================================================
> RCS file: /cvs/src/lib/libpcap/gencode.h,v
> retrieving revision 1.18
> diff -u -p -r1.18 gencode.h
> --- gencode.h 3 Jun 2018 10:29:28 -0000 1.18
> +++ gencode.h 14 Nov 2018 12:50:46 -0000
> @@ -179,6 +179,7 @@ struct block *gen_multicast(int);
> struct block *gen_inbound(int);
>
> struct block *gen_vlan(int);
> +struct block *gen_mpls(int);
>
> struct block *gen_pf_ifname(char *);
> struct block *gen_pf_rnr(int);
> Index: grammar.y
> ===================================================================
> RCS file: /cvs/src/lib/libpcap/grammar.y,v
> retrieving revision 1.19
> diff -u -p -r1.19 grammar.y
> --- grammar.y 27 Oct 2009 23:59:30 -0000 1.19
> +++ grammar.y 14 Nov 2018 12:50:46 -0000
> @@ -115,7 +115,7 @@ pcap_parse()
> %token LSH RSH
> %token LEN
> %token IPV6 ICMPV6 AH ESP
> -%token VLAN
> +%token VLAN MPLS
>
> %type <s> ID
> %type <e> EID
> @@ -279,6 +279,8 @@ other: pqual TK_BROADCAST { $$ = gen_b
> | OUTBOUND { $$ = gen_inbound(1); }
> | VLAN pnum { $$ = gen_vlan($2); }
> | VLAN { $$ = gen_vlan(-1); }
> + | MPLS pnum { $$ = gen_mpls($2); }
> + | MPLS { $$ = gen_mpls(-1); }
> | pfvar { $$ = $1; }
> | pqual p80211 { $$ = $2; }
> ;
> Index: pcap-filter.3
> ===================================================================
> RCS file: /cvs/src/lib/libpcap/pcap-filter.3,v
> retrieving revision 1.2
> diff -u -p -r1.2 pcap-filter.3
> --- pcap-filter.3 19 Feb 2014 04:51:32 -0000 1.2
> +++ pcap-filter.3 14 Nov 2018 12:50:46 -0000
> @@ -522,6 +522,31 @@ filters on VLAN 200 encapsulated within
> .in -.5i
> filters IPv4 protocols encapsulated in VLAN 300 encapsulated within any
> higher order VLAN.
> +.IP "\fBmpls \fI[label]\fR"
> +True if the packet is an MPLS (Multi-Protocol Label Switching) packet.
> +If \fIlabel\fR is specified, only true if the packet has the specified
> +\fIlabel\fR.
> +Note that the first \fBmpls\fR keyword encountered in \fIexpression\fR
> +changes the decoding offsets for the remainder of \fIexpression\fR on
> +the assumption that the packet is an MPLS packet. The \fBmpls
> +\fI[label]\fR expression may be used more than once, to filter on MPLS
> +labels stack. Each use of that expression increments the filter offsets
> +by 4.
> +.IP
> +For example:
> +.in +.5i
> +.nf
> +\fBmpls 42 && mpls 12\fR
> +.fi
> +.in -.5i
> +filters on MPLS label 42 on top of MPLS label 12, and
I find this a bit unclear. On top is not very clear to me.
Is it [ 42, 12 ] or [ 12, 42 ]?
How about:
filters on MPLS label 42 first and requires the next label to be 12
> +.in +.5i
> +.nf
> +\fBmpls 42 && mpls 12 && net 192.0.2.0/24\fR
> +.fi
> +.in -.5i
> +filters network 192.0.2.0/24 transported inside packet with label 42 on
> +top of label 12.
> .IP "\fBtcp\fR, \fBudp\fR, \fBicmp\fR"
> Abbreviations for:
> .in +.5i
> Index: scanner.l
> ===================================================================
> RCS file: /cvs/src/lib/libpcap/scanner.l,v
> retrieving revision 1.25
> diff -u -p -r1.25 scanner.l
> --- scanner.l 3 Jun 2018 10:29:28 -0000 1.25
> +++ scanner.l 14 Nov 2018 12:50:46 -0000
> @@ -224,6 +224,7 @@ inbound return INBOUND;
> outbound return OUTBOUND;
>
> vlan return VLAN;
> +mpls return MPLS;
>
> on|ifname return PF_IFNAME;
> rset|ruleset return PF_RSET;
>
Apart from that I think this is OK.
--
:wq Claudio