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>