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

Reply via email to