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