Skip site navigation (1)Skip section navigation (2)
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>