From owner-freebsd-net@FreeBSD.org Mon Dec  6 04:23:11 1999
Return-Path: <owner-freebsd-net@FreeBSD.org>
Received: from Thingol.KryptoKom.DE (Thingol.KryptoKom.DE [194.245.91.1])
	by hub.freebsd.org (Postfix) with ESMTP
	id A191C14FE9; Mon,  6 Dec 1999 04:23:00 -0800 (PST)
	(envelope-from owner-freebsd-net@FreeBSD.org)
Received: (from root@localhost)
	by Thingol.KryptoKom.DE (8.9.1/8.9.1) id NAA02726;
	Mon, 6 Dec 1999 13:21:05 +0100
Received: from cirdan.kryptokom.de by KryptoWall via smtpp (Version 1.2.0) id kwa02664; Mon Dec 06 13:20:45 1999
Received: (from root@localhost)
	by Cirdan.KryptoKom.DE (8.9.1/8.8.8) id MAA24012;
	Mon, 6 Dec 1999 12:35:19 GMT
Received: from Thingol.KryptoKom.DE (Thingol.KryptoKom.DE [192.168.6.1])
	by Cirdan.KryptoKom.DE (8.9.1/8.8.8) with ESMTP id HAA12336
	for <Thomas.Klein@KryptoKom.DE>; Mon, 6 Dec 1999 07:54:53 GMT
Received: (from root@localhost)
	by Thingol.KryptoKom.DE (8.9.1/8.9.1) id IAA24423
	for <Thomas.Klein@KryptoKom.DE>; Mon, 6 Dec 1999 08:40:18 +0100
Received: from baerenklau.de.freebsd.org by KryptoWall via smtpp (Version 1.2.0) id kwc24295; Mon Dec 06 08:39:57 1999
Received: from hub.freebsd.org (hub.FreeBSD.ORG [204.216.27.18])
	by baerenklau.de.freebsd.org (8.8.8/8.8.8) with ESMTP id BAA29699;
	Mon, 6 Dec 1999 01:47:03 +0100 (CET)
	(envelope-from owner-freebsd-net@FreeBSD.ORG)
Received: by hub.freebsd.org (Postfix, from userid 538)
	id 3B25D14D08; Sun,  5 Dec 1999 16:43:19 -0800 (PST)
Received: from localhost (localhost [127.0.0.1])
	by hub.freebsd.org (Postfix) with SMTP
	id EF34F1CD44E; Sun,  5 Dec 1999 16:43:18 -0800 (PST)
	(envelope-from owner-freebsd-net)
Received: by hub.freebsd.org (bulk_mailer v1.12); Sun, 5 Dec 1999 16:43:18 -0800
Received: from dustdevil.waterspout.com (dustdevil.waterspout.com [208.13.60.151])
	by hub.freebsd.org (Postfix) with ESMTP
	id 94C4A14DCF; Sun,  5 Dec 1999 16:43:11 -0800 (PST)
	(envelope-from csg@waterspout.com)
Received: by dustdevil.waterspout.com (Postfix, from userid 1000)
	id A36069E; Sun,  5 Dec 1999 19:45:39 -0500 (EST)
Message-Id: <19991206004539.A36069E@dustdevil.waterspout.com>
Date: Sun,  5 Dec 1999 19:45:39 -0500 (EST)
From: csg@waterspout.com
Sender: owner-freebsd-net@FreeBSD.org
Reply-To: csg@waterspout.com
To: FreeBSD-gnats-submit@FreeBSD.org
Cc: ajk@waterspout.com, freebsd-net@FreeBSD.org
Subject: Bug in Hardware VLAN Tag Support
X-Send-Pr-Version: 3.2

>Number:         15303
>Category:       kern
>Synopsis:       Bug in Hardware VLAN Tag Support
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Dec  6 06:10:01 PST 1999
>Closed-Date:    Tue Dec 7 06:57:31 PST 1999
>Last-Modified:  Tue Dec  7 07:03:47 PST 1999
>Originator:     C. Stephen Gunn
>Release:        FreeBSD 3.3-STABLE i386
>Organization:
Waterspout Communications, Inc.
>Environment:

FreeBSD 4.0-CURRENT.  This doesn't apply to FreeBSD 3-STABLE (yet)
since VLAN's are completely broken in stable with the ti0 device.

>Description:

sys/net/if_vlan.c contains support for ethernet hardware that
support tagged VLANs in hardware.  Currently (AFAIK) only the "ti"
driver written by Bill Paul has support for these features.

Apparently, when the ethernet driver detects a tagged frame from the
hardware, it passes the frame, along with the tag to vlan_input_tag()
instead of the normal vlan_input() call from inside ether_input().

The problem arrises in an attempt to log errors on the parent device.
vlan_input_tag() walks the list of vlan devices, looking for a matching
and tries to log the error on the parent device if appropriately.

Unfortunatly, the current code incorrectly assumes that all vlans
are configured, and/or associated with a parent device.  If you 
receive a frame for a VLAN that's not in the list, you walk off
the end of the list.  Boom.

>How-To-Repeat:

1. Setup a host with multiple VLAN's on an 802.1Q trunk to the machine,
   with a ti0 ethernet interface.

2. Configure some but not all of the vlan interfaces:

   # ifconfig <parent-device> up
   # ifconfig vlan0 vlandev <parent-device> vlan <tag-number 1>
   # ifconfig vlan1 vlandev <parent-device> vlan <tag-number 2>
 
3. Wait for traffic on an as-of-yet unconfigured vlan number.

4. Watch your machine crashdump..

>Fix:

This patch modifies vlan_input_tag to return -1 in the event of an
error so the parent device can maintain its counters for us.

- BEGIN PATCH -----------------------------------------------------------------

Index: pci/if_ti.c
===================================================================
RCS file: /usr/local/share/cvs/FreeBSD/src/sys/pci/if_ti.c,v
retrieving revision 1.24
diff -u -r1.24 if_ti.c
--- if_ti.c     1999/09/23 03:32:54     1.24
+++ if_ti.c     1999/12/05 22:28:44
@@ -1887,7 +1887,8 @@
                 * to vlan_input() instead of ether_input().
                 */
                if (have_tag) {
-                       vlan_input_tag(eh, m, vlan_tag);
+                       if (vlan_input_tag(eh, m, vlan_tag) < 0)
+                               ifp->if_data.ifi_noproto++;
                        have_tag = vlan_tag = 0;
                        continue;
                }
Index: if_vlan.c
===================================================================
RCS file: /usr/local/share/cvs/FreeBSD/src/sys/net/if_vlan.c,v
retrieving revision 1.10
diff -u -r1.10 if_vlan.c
--- if_vlan.c   1999/09/25 12:05:57     1.10
+++ if_vlan.c   1999/12/06 00:17:05
@@ -272,7 +272,7 @@
        return;
 }

-void
+int
 vlan_input_tag(struct ether_header *eh, struct mbuf *m, u_int16_t t)
 {
        int i;
@@ -284,10 +284,9 @@
                        break;
        }

-       if (i >= NVLAN || (ifv->ifv_if.if_flags & IFF_UP) == 0) {
-               m_freem(m);
-               ifv->ifv_p->if_data.ifi_noproto++;
-               return;
+       if (i >= NVLAN) {
+               m_free(m);
+               return -1;      /* So the parent can take note */
        }

        /*
@@ -312,7 +311,7 @@
        }
        ifv->ifv_if.if_ipackets++;
        ether_input(&ifv->ifv_if, eh, m);
-       return;
+       return 0;
 }

 int
Index: if_vlan_var.h
===================================================================
RCS file: /usr/local/share/cvs/FreeBSD/src/sys/net/if_vlan_var.h,v
retrieving revision 1.3
diff -u -r1.3 if_vlan_var.h
--- if_vlan_var.h       1999/08/28 00:48:24     1.3
+++ if_vlan_var.h       1999/12/05 22:19:22
@@ -85,7 +85,7 @@
 /* shared with if_ethersubr.c: */
 extern u_int vlan_proto;
 extern int vlan_input(struct ether_header *eh, struct mbuf *m);
-extern void vlan_input_tag(struct ether_header *eh,
+extern int vlan_input_tag(struct ether_header *eh,
                        struct mbuf *m, u_int16_t t);
 #endif

- END PATCH -------------------------------------------------------------------


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-net" in the body of the message


>Release-Note:
>Audit-Trail:

From: csg@waterspout.com (C. Stephen Gunn)
To: freebsd-gnats-submit@freebsd.org, csg@waterspout.com
Cc: wollman@freebsd.org
Subject: Re: kern/15303: Bug in Hardware VLAN Tag Support
Date: Mon,  6 Dec 1999 13:31:24 -0500 (EST)

 Oops.  Looks like my laptop crash ended up sending two copies
 of this PR.  Please ignore this duplicate report.
 
  - Steve
 
 
State-Changed-From-To: open->closed 
State-Changed-By: sheldonh 
State-Changed-When: Tue Dec 7 06:57:31 PST 1999 
State-Changed-Why:  
Duplicate of PR 15291. 
>Unformatted:
