summaryrefslogtreecommitdiffstats
path: root/sys/net/if_vlan.c
diff options
context:
space:
mode:
authoryar <yar@FreeBSD.org>2001-03-28 15:52:12 +0000
committeryar <yar@FreeBSD.org>2001-03-28 15:52:12 +0000
commit4d55d58720d6ddd6d85f7b32cb6ad850331dc6f2 (patch)
treee9cf30ea4c22a4f06893f8b186c22986425a30c3 /sys/net/if_vlan.c
parent18be3bb86d1dd6804a2d8e4d550b62060298291c (diff)
downloadFreeBSD-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.c31
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);
OpenPOWER on IntegriCloud