Date: Sat, 21 Oct 2000 16:04:53 +0400 (MSD) From: yar@comp.chem.msu.su To: FreeBSD-gnats-submit@freebsd.org Subject: kern/22179: VLAN driver fails to hanlde interface flags properly Message-ID: <200010211204.e9LC4rv00676@yar.chem.msu.su>
next in thread | raw e-mail | index | archive | help
>Number: 22179 >Category: kern >Synopsis: VLAN driver fails to hanlde interface flags properly >Confidential: no >Severity: non-critical >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Sat Oct 21 05:10:01 PDT 2000 >Closed-Date: >Last-Modified: >Originator: Yar Tikhiy >Release: FreeBSD 4.1-STABLE i386 >Organization: Moscow State University >Environment: The bugs show up in all branches. >Description: 1. Many network interface drivers' XX_start() routines don't check if an interface is up and running because they rely on upper layers doing that. The vlan_start() routine, which calls XX_start() routines of underlying "parent" drivers, fails to do that, causing system panic when a packet is being sent via a vlan interface while its parnet interface is down. 2. The VLAN driver copies flags from a parent interface to a vlan interface mindlessly. However, setting some flags implies certain additional actions. In particular, bringing an interface up involves setting up a link-layer route to it. The VLAN driver fails to do that because it just copies the bit. 3. The if_up() and if_down() routines must be called at splnet() or equivalent. They also shouldn't be called if an interface is already up or down, correspondingly, because they do no additional checks. The VLAN driver is not aware of the above. I'd also suggest adding a couple of words on the properties of if_up()/if_down() to the ifnet(9) man page. >How-To-Repeat: 1. Try to assign an IP address to a VLAN interface which parent is down and see the system panic due to sending a gratituous ARP through the parent. 2. Assign a parent and an IP address to a VLAN interface. Then remove the parent with "ifconfig vlanX -vlandev". Then add another (or the same) parent back. See that packets don't go out, because there is no proper link-layer route to the VLAN interface. >Fix: --- if_vlan.c.orig Sat Oct 21 14:13:01 2000 +++ if_vlan.c Sat Oct 21 15:53:10 2000 @@ -205,6 +205,17 @@ bpf_mtap(ifp, m); /* + * Do not run parent's if_start() if it's not up, + * or parent's driver will cause a system crash + */ + if ((p->if_flags & (IFF_UP | IFF_RUNNING)) != + (IFF_UP | IFF_RUNNING)) { + m_freem(m); + ifp->if_data.ifi_collisions++; + continue; + } + + /* * If the LINK0 flag is set, it means the underlying interface * can do VLAN tag insertion itself and doesn't require us to * create a special header for it. In this case, we just pass @@ -362,9 +373,10 @@ ifv->ifv_if.if_mtu = p->if_data.ifi_mtu - EVL_ENCAPLEN; /* - * Preserve the state of the LINK0 flag for ourselves. + * Copy only a selected subset of flags from the parent */ - ifv->ifv_if.if_flags = (p->if_flags & ~(IFF_LINK0)); + ifv->ifv_if.if_flags = (p->if_flags & + (IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX | IFF_POINTOPOINT)); /* * Set up our ``Ethernet address'' to reflect the underlying @@ -488,8 +500,12 @@ break; if (vlr.vlr_parent[0] == '\0') { vlan_unconfig(ifp); - if_down(ifp); - ifp->if_flags &= ~(IFF_UP|IFF_RUNNING); + if (ifp->if_flags & IFF_UP) { + int s = splimp(); + if_down(ifp); + splx(s); + } + ifp->if_flags &= ~IFF_RUNNING; break; } p = ifunit(vlr.vlr_parent); >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?200010211204.e9LC4rv00676>