From 249932144b7cfcd53cd6bd06e8d05aac5129c890 Mon Sep 17 00:00:00 2001 From: Yaroslav Tykhiy Date: Wed, 28 Mar 2001 15:52:12 +0000 Subject: [PATCH] Fix a number of minor bugs in the VLAN code: * Initialize the "struct sockaddr_dl sdl" correctly in vlan_setmulti(). PR: kern/22181 * The driver used to call malloc(..., M_NOWAIT), but to not check the return value. Change malloc(..., M_NOWAIT) to malloc(..., M_WAITOK) because the corresponding part of code is called from the upper half of the kernel only. PR: kern/22181 * Make sure a parent interface is up and running before invoking its if_start() routine in order to avoid system panic. PR: kern/22179 kern/24741 i386/25478 * Do not copy all the flags from a parent mindlessly. PR: kern/22179 * Do not call if_down() on a parent interface if it's already down. Call if_down() at splimp because if_down() needs that. PR: kern/22179 Reviewed by: wollman --- sys/net/if_vlan.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/sys/net/if_vlan.c b/sys/net/if_vlan.c index 6ff8daf36a1..639a59ca76a 100644 --- a/sys/net/if_vlan.c +++ b/sys/net/if_vlan.c @@ -120,8 +120,10 @@ vlan_setmulti(struct ifnet *ifp) sc = ifp->if_softc; ifp_p = sc->ifv_p; - sdl.sdl_len = ETHER_ADDR_LEN; + bzero((char *)&sdl, sizeof sdl); + sdl.sdl_len = sizeof sdl; sdl.sdl_family = AF_LINK; + sdl.sdl_alen = ETHER_ADDR_LEN; /* First, remove any existing filter entries. */ while(SLIST_FIRST(&sc->vlan_mc_listhead) != NULL) { @@ -138,7 +140,7 @@ vlan_setmulti(struct ifnet *ifp) TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; - mc = malloc(sizeof(struct vlan_mc_entry), M_DEVBUF, M_NOWAIT); + mc = malloc(sizeof(struct vlan_mc_entry), M_DEVBUF, M_WAITOK); bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr), (char *)&mc->mc_addr, ETHER_ADDR_LEN); SLIST_INSERT_HEAD(&sc->vlan_mc_listhead, mc, mc_entries); @@ -226,6 +228,17 @@ vlan_start(struct ifnet *ifp) if (ifp->if_bpf) bpf_mtap(ifp, m); + /* + * Do not run parent's if_start() if the parent is 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 @@ -376,9 +389,11 @@ vlan_config(struct ifvlan *ifv, struct ifnet *p) 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. + * Other flags are none of our business. */ - 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 @@ -502,8 +517,12 @@ vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 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);