diff options
author | yar <yar@FreeBSD.org> | 2001-03-28 15:52:12 +0000 |
---|---|---|
committer | yar <yar@FreeBSD.org> | 2001-03-28 15:52:12 +0000 |
commit | 4d55d58720d6ddd6d85f7b32cb6ad850331dc6f2 (patch) | |
tree | e9cf30ea4c22a4f06893f8b186c22986425a30c3 /sys/net/if_vlan.c | |
parent | 18be3bb86d1dd6804a2d8e4d550b62060298291c (diff) | |
download | FreeBSD-src-4d55d58720d6ddd6d85f7b32cb6ad850331dc6f2.zip FreeBSD-src-4d55d58720d6ddd6d85f7b32cb6ad850331dc6f2.tar.gz |
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
Diffstat (limited to 'sys/net/if_vlan.c')
-rw-r--r-- | sys/net/if_vlan.c | 31 |
1 files changed, 25 insertions, 6 deletions
diff --git a/sys/net/if_vlan.c b/sys/net/if_vlan.c index 6ff8daf..639a59c 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); @@ -227,6 +229,17 @@ vlan_start(struct ifnet *ifp) 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 * create a special header for it. In this case, we just pass @@ -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); |