Skip to content

Commit b4a1cf4

Browse files
author
Stefan Baranoff
committed
Add support for filtering VNTag frames
Add a "vntag" keyword similar to the existing "vlan" and "mpls" keywords to filter on VNTag frames. VNTag was proposed as 802.1Qbh but has been replaced in the standards by 802.1Qbr although some vendors are still using VNTag. Skips the 6 bytes of the VNTag header similar to the 4 byte skip of VLAN. They both inject themselves between Ethernet dest addr and EtherType.
1 parent 732df31 commit b4a1cf4

File tree

9 files changed

+151
-3
lines changed

9 files changed

+151
-3
lines changed

CHANGES

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ DayOfTheWeek, Month DD, YYYY / The Tcpdump Group
5050
Deprecate bpf_filter().
5151
Require a live capture for all Linux BPF extensions.
5252
Have "outbound" mean Tx only for DLT_SLIP.
53+
Add support for filtering VNTag frames (pull request #1480)
5354
rpcap:
5455
Support user names and passwords in rpcap:// and rpcaps:// URLs.
5556
Add a -t flag to rpcapd to specify the data channel port; from

ethertype.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,9 @@
115115
#ifndef ETHERTYPE_8021AD
116116
#define ETHERTYPE_8021AD 0x88a8
117117
#endif
118+
#ifndef ETHERTYPE_VNTAG
119+
#define ETHERTYPE_VNTAG 0x8926
120+
#endif
118121
#ifndef ETHERTYPE_LOOPBACK
119122
#define ETHERTYPE_LOOPBACK 0x9000
120123
#endif

gencode.c

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10715,3 +10715,76 @@ gen_atmmulti_abbrev(compiler_state_t *cstate, int type)
1071510715
}
1071610716
return b1;
1071710717
}
10718+
10719+
/*
10720+
* support VNTag (proposed as IEEE 802.1Qbh but never accepted) over Ethernet
10721+
* VNTag headers look like this on their own:
10722+
* 0 1 2 3 4 5
10723+
* 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
10724+
* | | | | | | |
10725+
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
10726+
* | EtherType |D|P| vif_list_id/dvif_id |L|R|ver| svif_id |
10727+
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
10728+
*
10729+
* In context that looks like this:
10730+
* 0 1 2 3 4 5
10731+
* 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
10732+
* | | | | | | |
10733+
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
10734+
* | Destination Address |
10735+
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
10736+
* | Source Address |
10737+
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
10738+
* | VNTag |
10739+
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
10740+
* | EtherType | Payload... |
10741+
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
10742+
*/
10743+
struct block *
10744+
gen_vntag(compiler_state_t *cstate)
10745+
{
10746+
struct block *b0;
10747+
10748+
/*
10749+
* Catch errors reported by us and routines below us, and return NULL
10750+
* on an error.
10751+
*/
10752+
if (setjmp(cstate->top_ctx))
10753+
return (NULL);
10754+
10755+
/*
10756+
* Check for a VNTag packet, and then change the offsets to point
10757+
* to the type and data fields within the VLAN after the VNTag packet.
10758+
* VNTag always requires VLAN afterwards, and that likely won't be
10759+
* offloaded so handle it just like inline VLAN. Apply the same rules
10760+
* and restrictions as VLAN, too.
10761+
*/
10762+
if (cstate->label_stack_depth > 0)
10763+
bpf_error(cstate, "no VNTag match after MPLS");
10764+
10765+
/* Assume any of the EtherTypes that can have VLAN can also have
10766+
* VNTag as well. With VNTag not being accepted as 802.1Qbh but
10767+
* being replaced in the standads by 802.1Qbr there's not much to go on
10768+
* other than a few vendor proprietary implementations.
10769+
*/
10770+
switch (cstate->linktype) {
10771+
case DLT_EN10MB:
10772+
case DLT_NETANALYZER:
10773+
case DLT_NETANALYZER_TRANSPARENT:
10774+
case DLT_IEEE802_11:
10775+
case DLT_PRISM_HEADER:
10776+
case DLT_IEEE802_11_RADIO_AVS:
10777+
case DLT_IEEE802_11_RADIO:
10778+
/* Make sure we have a VNTag frame, then jump over it. */
10779+
b0 = gen_linktype(cstate, ETHERTYPE_VNTAG);
10780+
cstate->off_linkpl.constant_part += 6;
10781+
cstate->off_linktype.constant_part += 6;
10782+
break;
10783+
default:
10784+
bpf_error(cstate, "no VNTag support for %s",
10785+
pcap_datalink_val_to_description_or_dlt(cstate->linktype));
10786+
/*NOTREACHED*/
10787+
}
10788+
10789+
return (b0);
10790+
}

gencode.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,7 @@ struct block *gen_llc_u_subtype(compiler_state_t *, bpf_u_int32);
352352

353353
struct block *gen_vlan(compiler_state_t *, bpf_u_int32, int);
354354
struct block *gen_mpls(compiler_state_t *, bpf_u_int32, int);
355+
struct block *gen_vntag(compiler_state_t *);
355356

356357
struct block *gen_pppoed(compiler_state_t *);
357358
struct block *gen_pppoes(compiler_state_t *, bpf_u_int32, int);

grammar.y.in

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,7 @@ DIAG_OFF_BISON_BYACC
389389
%token LSH RSH
390390
%token LEN
391391
%token IPV6 ICMPV6 AH ESP
392-
%token VLAN MPLS
392+
%token VLAN MPLS VNTAG
393393
%token PPPOED PPPOES GENEVE VXLAN
394394
%token ISO ESIS CLNP ISIS L1 L2 IIH LSP SNP CSNP PSNP
395395
%token STP
@@ -682,6 +682,7 @@ other: pqual TK_BROADCAST { CHECK_PTR_VAL(($$ = gen_broadcast(cstate, $1))); }
682682
| VLAN { CHECK_PTR_VAL(($$ = gen_vlan(cstate, 0, 0))); }
683683
| MPLS pnum { CHECK_PTR_VAL(($$ = gen_mpls(cstate, $2, 1))); }
684684
| MPLS { CHECK_PTR_VAL(($$ = gen_mpls(cstate, 0, 0))); }
685+
| VNTAG { CHECK_PTR_VAL(($$ = gen_vntag(cstate))); }
685686
| PPPOED { CHECK_PTR_VAL(($$ = gen_pppoed(cstate))); }
686687
| PPPOES pnum { CHECK_PTR_VAL(($$ = gen_pppoes(cstate, $2, 1))); }
687688
| PPPOES { CHECK_PTR_VAL(($$ = gen_pppoes(cstate, 0, 0))); }

pcap-filter.manmisc.in

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,6 +1012,24 @@ filters packets with an outer label of 100000 and an inner label of
10121012
.in -.5i
10131013
filters packets to or from 192.9.200.1 with an inner label of 1024 and
10141014
any outer label.
1015+
.IP "\fBvntag\fR"
1016+
True if the packet is a VNTag packet (identified by EtherType 0x8926).
1017+
Each use of that keyword increments the filter link header and payload offsets by 6.
1018+
.IP
1019+
For example:
1020+
.in +.5i
1021+
.nf
1022+
\fBvntag\fR
1023+
.fi
1024+
.in -.5i
1025+
filters on VNTag as the next EtherType and skips the VNTag header
1026+
.in +.5i
1027+
.nf
1028+
\fBvntag\fR and \fBvlan\fR and \fBip src host\fR 192.0.2.0
1029+
.fi
1030+
.in -.5i
1031+
filters on VNTag followed by any VLAN followed by an IPv4 packet from 192.0.2.0
1032+
skipping over the VNTag header, then VLAN header, to allow finding the IPv4
10151033
.IP \fBpppoed\fP
10161034
True if the packet is a PPP-over-Ethernet Discovery packet (Ethernet
10171035
type 0x8863).
@@ -1626,8 +1644,10 @@ The
16261644
keyword became available in libpcap 1.10.0.
16271645
.PP
16281646
The
1629-
.B vxlan
1630-
keyword became available in libpcap 1.11.0.
1647+
.BR vxlan
1648+
and
1649+
.B vntag
1650+
keywords became available in libpcap 1.11.0.
16311651
.SH SEE ALSO
16321652
.BR pcap (3PCAP)
16331653
.SH BUGS

scanner.l

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,7 @@ pppoed return PPPOED;
339339
pppoes return PPPOES;
340340
geneve return GENEVE;
341341
vxlan return VXLAN;
342+
vntag return VNTAG;
342343

343344
lane return LANE;
344345
llc return LLC;

testprogs/TESTrun

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9657,6 +9657,34 @@ my %accept_blocks = (
96579657
(020) ret #0
96589658
',
96599659
}, # dst_portrange_degenerate
9660+
vntag_eth => {
9661+
DLT => 'EN10MB',
9662+
aliases => ['vntag'],
9663+
opt => '
9664+
(000) ldh [12]
9665+
(001) jeq #0x8926 jt 2 jf 3
9666+
(002) ret #262144
9667+
(003) ret #0
9668+
',
9669+
}, # vntag_eth
9670+
vntag_eth_vlan_vntag_vlan => {
9671+
DLT => 'EN10MB',
9672+
aliases => ['vlan and vntag and vlan'],
9673+
opt => '
9674+
(000) ldh [12]
9675+
(001) jeq #0x8100 jt 4 jf 2
9676+
(002) jeq #0x88a8 jt 4 jf 3
9677+
(003) jeq #0x9100 jt 4 jf 11
9678+
(004) ldh [16]
9679+
(005) jeq #0x8926 jt 6 jf 11
9680+
(006) ldh [22]
9681+
(007) jeq #0x8100 jt 10 jf 8
9682+
(008) jeq #0x88a8 jt 10 jf 9
9683+
(009) jeq #0x9100 jt 10 jf 11
9684+
(010) ret #262144
9685+
(011) ret #0
9686+
',
9687+
}, # vntag_eth
96609688
);
96619689

96629690
# In apply_blocks the top-level keys are test block names. Each test block
@@ -10067,6 +10095,21 @@ my %apply_blocks = (
1006710095
expr => 'outbound',
1006810096
results => [46],
1006910097
},
10098+
vntag => {
10099+
savefile => 'vntag-novntag-mixed.pcap',
10100+
expr => 'vntag',
10101+
results => [262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
10102+
},
10103+
vntag_vlan_ip => {
10104+
savefile => 'vntag-novntag-mixed.pcap',
10105+
expr => 'vntag and vlan 100 and ip',
10106+
results => [262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
10107+
},
10108+
vntag_vlan_dest_ip => {
10109+
savefile => 'vntag-novntag-mixed.pcap',
10110+
expr => 'vntag and vlan 100 and ip dst 192.168.20.102',
10111+
results => [0, 262144, 0, 0, 262144, 262144, 0, 0, 262144, 262144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
10112+
},
1007010113
);
1007110114

1007210115
# * DLT, expr, netmask and skip: same as in accept_blocks above
@@ -10658,6 +10701,11 @@ my %reject_tests = (
1065810701
expr => "ip6 gateway eth-ipv4-ipv6.host123.libpcap.test",
1065910702
errstr => 'illegal modifier of \'gateway\'',
1066010703
},
10704+
vntag_not_supported => {
10705+
DLT => 'RAW',
10706+
expr => 'vntag',
10707+
errstr => 'no VNTag support',
10708+
},
1066110709
);
1066210710

1066310711
sub accept_test_label {

tests/filter/vntag-novntag-mixed.pcap

3.23 KB
Binary file not shown.

0 commit comments

Comments
 (0)