(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;

Reply via email to