(long line in the previous diff) 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 11 Nov 2018 12:53:20 -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 @@ -973,9 +976,11 @@ gen_hostop(addr, mask, dir, proto, src_o bpf_error("direction not supported on linktype 0x%x", linktype); } - b0 = gen_linktype(proto); b1 = gen_mcmp_nl(offset, BPF_W, (bpf_int32)addr, mask); - gen_and(b0, b1); + if (mpls_stack == 0) { + b0 = gen_linktype(proto); + gen_and(b0, b1); + } return b1; } @@ -1213,10 +1218,12 @@ gen_host(addr, mask, proto, dir) case Q_DEFAULT: b0 = gen_host(addr, mask, Q_IP, dir); - b1 = gen_host(addr, mask, Q_ARP, dir); - gen_or(b0, b1); - b0 = gen_host(addr, mask, Q_RARP, dir); - gen_or(b1, b0); + if (mpls_stack == 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; case Q_IP: @@ -3348,6 +3355,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 11 Nov 2018 12:53:20 -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 11 Nov 2018 12:53:20 -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 11 Nov 2018 12:53:20 -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 +.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 11 Nov 2018 12:53:20 -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;