Date: Tue, 10 Oct 2000 11:24:18 +1100 (EST) From: peter.jeremy@alcatel.com.au To: FreeBSD-gnats-submit@FreeBSD.ORG, patches@tcpdump.org Subject: bin/21880: Improved VLAN support for libcap/tcpdump Message-ID: <00Oct10.112415est.115209@border.alcanet.com.au>
next in thread | raw e-mail | index | archive | help
>Number: 21880
>Category: bin
>Synopsis: Improved VLAN support for libcap/tcpdump
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: change-request
>Submitter-Id: current-users
>Arrival-Date: Mon Oct 09 17:30:00 PDT 2000
>Closed-Date:
>Last-Modified:
>Originator: Peter Jeremy
>Release: FreeBSD 5.0-CURRENT i386
>Organization:
Alcatel Australia Limited
>Environment:
FreeBSD 5-CURRENT, including tcpdump 3.5 and libpcap 0.5
>Description:
Whilst tcpdump will correctly decode IEEE 802.1Q VLAN packets,
it cannot filter them readily. The patch below adds a new
"vlan" keyword which alows filtering on specific VLAN numbers
as well as altering the Ethernet frame decoding offsets to
suit 802.1Q frames. It would be trivial to extend this to
other media types (eg FDDI), but I don't have access to test
them.
The patches also add a space following the vlan priority to
separate it from the source host name.
Note that (at least for FreeBSD), the tcpdump man page belongs
in section 8, not section 1. This requires a repo-copy, as
well as some trivial patches.
>How-To-Repeat:
Run tcpdump on a device carrying a VLAN trunk.
>Fix:
(Note that the CVS id's below reflect the FreeBSD repository, not the
tcpdump.org repository)
Index: print-ether.c
===================================================================
RCS file: /home/CVSROOT/./src/contrib/tcpdump/print-ether.c,v
retrieving revision 1.9
diff -u -r1.9 print-ether.c
--- print-ether.c 2000/01/30 01:00:52 1.9
+++ print-ether.c 2000/10/09 20:32:36
@@ -205,7 +205,7 @@
return (1);
case ETHERTYPE_8021Q:
- printf("802.1Q vlan#%d P%d%s",
+ printf("802.1Q vlan#%d P%d%s ",
ntohs(*(unsigned short*)p)&0xFFF,
ntohs(*(unsigned short*)p)>>13,
(ntohs(*(unsigned short*)p)&0x1000) ? " CFI" : "");
Index: tcpdump.1
===================================================================
RCS file: /home/CVSROOT/./src/contrib/tcpdump/tcpdump.1,v
retrieving revision 1.8
diff -u -r1.8 tcpdump.1
--- tcpdump.1 2000/01/30 01:00:55 1.8
+++ tcpdump.1 2000/10/10 00:03:56
@@ -555,6 +555,13 @@
.in -.5i
where \fIp\fR is one of the above protocols.
Note that \fItcpdump\fR does an incomplete job of parsing these protocols.
+.IP "\fBvlan \fI[vlan_id]\fR"
+True if the packet is an IEEE 802.1Q VLAN packet.
+If \fI[vlan_id]\fR is specified, only true is the packet has the specified
+\fIvlan_id\fR.
+Note that the first \fBvlan\fR keyword encountered in \fIexpression\fR
+changes the decoding offsets for the remainder of \fIexpression\fR
+on the assumption that the packet is a VLAN packet.
.IP "\fIexpr relop expr\fR"
True if the relation holds, where \fIrelop\fR is one of >, <, >=, <=, =, !=,
and \fIexpr\fR is an arithmetic expression composed of integer constants
Index: ethertype.h
===================================================================
RCS file: /home/CVSROOT/src/contrib/libpcap/ethertype.h,v
retrieving revision 1.1.1.2
diff -u -r1.1.1.2 ethertype.h
--- ethertype.h 2000/01/30 00:32:39 1.1.1.2
+++ ethertype.h 2000/10/09 23:20:45
@@ -74,6 +74,9 @@
#ifndef ETHERTYPE_IPV6
#define ETHERTYPE_IPV6 0x80f3
#endif
+#ifndef ETHERTYPE_8021Q
+#define ETHERTYPE_8021Q 0x8100
+#endif
#ifndef ETHERTYPE_LOOPBACK
#define ETHERTYPE_LOOPBACK 0x9000
#endif
Index: gencode.c
===================================================================
RCS file: /home/CVSROOT/src/contrib/libpcap/gencode.c,v
retrieving revision 1.8
diff -u -r1.8 gencode.c
--- gencode.c 2000/03/04 23:57:39 1.8
+++ gencode.c 2000/10/09 23:25:19
@@ -2872,3 +2872,50 @@
dir);
return (b0);
}
+
+/*
+ * support IEEE 802.1Q VLAN trunk over ethernet
+ */
+struct block *
+gen_vlan(vlan_num)
+ int vlan_num;
+{
+ static u_int orig_linktype = -1, orig_nl = -1;
+ struct block *b0;
+
+ /*
+ * Change the offsets to point to the type and data fields within
+ * the VLAN packet. This is somewhat of a kludge.
+ */
+ if (orig_nl == (u_int)-1) {
+ orig_linktype = off_linktype; /* save original values */
+ orig_nl = off_nl;
+
+ switch (linktype) {
+
+ case DLT_EN10MB:
+ off_linktype = 16;
+ off_nl = 18;
+ break;
+
+ default:
+ bpf_error("no VLAN support for data link type 0x%x",
+ linktype);
+ return;
+ }
+ }
+
+ /* check for VLAN */
+ b0 = gen_cmp(orig_linktype, BPF_H, (bpf_int32)ETHERTYPE_8021Q);
+
+ /* If a specific VLAN is requested, check VLAN id */
+ if (vlan_num >= 0) {
+ struct block *b1;
+
+ b1 = gen_cmp(orig_nl, BPF_H, (bpf_int32)vlan_num);
+ gen_and(b0, b1);
+ b0 = b1;
+ }
+
+ return (b0);
+}
Index: gencode.h
===================================================================
RCS file: /home/CVSROOT/src/contrib/libpcap/gencode.h,v
retrieving revision 1.3
diff -u -r1.3 gencode.h
--- gencode.h 2000/01/30 00:43:34 1.3
+++ gencode.h 2000/10/09 23:17:34
@@ -180,6 +180,8 @@
struct block *gen_multicast(int);
struct block *gen_inbound(int);
+struct block *gen_vlan(int);
+
void bpf_optimize(struct block **);
#if __STDC__
__dead void bpf_error(const char *, ...)
Index: grammar.y
===================================================================
RCS file: /home/CVSROOT/src/contrib/libpcap/grammar.y,v
retrieving revision 1.5
diff -u -r1.5 grammar.y
--- grammar.y 2000/01/30 00:43:34 1.5
+++ grammar.y 2000/10/09 23:30:19
@@ -115,6 +115,7 @@
%token LEN
%token ISO ESIS ISIS
%token IPV6 ICMPV6 AH ESP
+%token VLAN
%type <s> ID
%type <e> EID
@@ -161,14 +162,7 @@
| HID {
/* Decide how to parse HID based on proto */
$$.q = $<blk>0.q;
- switch ($$.q.proto) {
- case Q_DECNET:
- $$.b = gen_ncode($1, 0, $$.q);
- break;
- default:
- $$.b = gen_ncode($1, 0, $$.q);
- break;
- }
+ $$.b = gen_ncode($1, 0, $$.q);
}
| HID6 '/' NUM {
#ifdef INET6
@@ -273,6 +267,8 @@
| BYTE NUM byteop NUM { $$ = gen_byteop($3, $2, $4); }
| INBOUND { $$ = gen_inbound(0); }
| OUTBOUND { $$ = gen_inbound(1); }
+ | VLAN pnum { $$ = gen_vlan($2); }
+ | VLAN { $$ = gen_vlan(-1); }
;
relop: '>' { $$ = BPF_JGT; }
| GEQ { $$ = BPF_JGE; }
Index: scanner.l
===================================================================
RCS file: /home/CVSROOT/src/contrib/libpcap/scanner.l,v
retrieving revision 1.5
diff -u -r1.5 scanner.l
--- scanner.l 2000/01/30 00:43:35 1.5
+++ scanner.l 2000/10/09 21:57:49
@@ -232,6 +232,8 @@
inbound return INBOUND;
outbound return OUTBOUND;
+vlan return VLAN;
+
[ \n\t] ;
[+\-*/:\[\]!<>()&|=] return yytext[0];
">=" return GEQ;
>Release-Note:
>Audit-Trail:
>Unformatted:
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?00Oct10.112415est.115209>
