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:34:44 -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:
@@ -3350,6 +3357,33 @@ gen_acode(eaddr, q)
/* 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);
+}
+
/*
* support IEEE 802.1Q VLAN trunk over ethernet
*/
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:34:44 -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:34:44 -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:34:44 -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:34:44 -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;