diff options
author | fenner <fenner@FreeBSD.org> | 2001-07-24 17:14:37 +0000 |
---|---|---|
committer | fenner <fenner@FreeBSD.org> | 2001-07-24 17:14:37 +0000 |
commit | 11a219dc8bda8815bec6a56cbf917d0ee1dbede4 (patch) | |
tree | a0b9d03f06dfad3ef2b2a8995b24e35ae5f2cc7f /sys | |
parent | 20223509f96eb1028032f7f415179dc136a4ee30 (diff) | |
download | FreeBSD-src-11a219dc8bda8815bec6a56cbf917d0ee1dbede4.zip FreeBSD-src-11a219dc8bda8815bec6a56cbf917d0ee1dbede4.tar.gz |
Eliminate the panic, reported by Daniel Sobral, which occurs when
vlan_unconfig()-ing an interface on which multicast groups have been
joined. Instead, keep the list of groups around (and, in fact, allow
changing of the membership list) and re-join them when the vlan interface
is reassociated with a lower level interface.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/net/if_vlan.c | 53 |
1 files changed, 36 insertions, 17 deletions
diff --git a/sys/net/if_vlan.c b/sys/net/if_vlan.c index e57dfb9..40067dc 100644 --- a/sys/net/if_vlan.c +++ b/sys/net/if_vlan.c @@ -120,6 +120,13 @@ vlan_setmulti(struct ifnet *ifp) sc = ifp->if_softc; ifp_p = sc->ifv_p; + /* + * If we don't have a parent, just remember the membership for + * when we do. + */ + if (ifp_p == NULL) + return(0); + bzero((char *)&sdl, sizeof sdl); sdl.sdl_len = sizeof sdl; sdl.sdl_family = AF_LINK; @@ -410,6 +417,13 @@ vlan_config(struct ifvlan *ifv, struct ifnet *p) sdl1->sdl_alen = ETHER_ADDR_LEN; bcopy(LLADDR(sdl2), LLADDR(sdl1), ETHER_ADDR_LEN); bcopy(LLADDR(sdl2), ifv->ifv_ac.ac_enaddr, ETHER_ADDR_LEN); + + /* + * Configure multicast addresses that may already be + * joined on the vlan device. + */ + (void)vlan_setmulti(&ifv->ifv_if); + return 0; } @@ -426,25 +440,30 @@ vlan_unconfig(struct ifnet *ifp) ifv = ifp->if_softc; p = ifv->ifv_p; - /* - * Since the interface is being unconfigured, we need to - * empty the list of multicast groups that we may have joined - * while we were alive and remove them from the parent's list - * as well. - */ - while(SLIST_FIRST(&ifv->vlan_mc_listhead) != NULL) { - struct sockaddr_dl sdl; + if (p) { + struct sockaddr_dl sdl; - sdl.sdl_len = ETHER_ADDR_LEN; + /* + * Since the interface is being unconfigured, we need to + * empty the list of multicast groups that we may have joined + * while we were alive from the parent's list. + */ + bzero((char *)&sdl, sizeof sdl); + sdl.sdl_len = sizeof sdl; sdl.sdl_family = AF_LINK; - mc = SLIST_FIRST(&ifv->vlan_mc_listhead); - bcopy((char *)&mc->mc_addr, LLADDR(&sdl), ETHER_ADDR_LEN); - error = if_delmulti(p, (struct sockaddr *)&sdl); - error = if_delmulti(ifp, (struct sockaddr *)&sdl); - if (error) - return(error); - SLIST_REMOVE_HEAD(&ifv->vlan_mc_listhead, mc_entries); - free(mc, M_DEVBUF); + sdl.sdl_index = p->if_index; + sdl.sdl_type = IFT_ETHER; + sdl.sdl_alen = ETHER_ADDR_LEN; + + while(SLIST_FIRST(&ifv->vlan_mc_listhead) != NULL) { + mc = SLIST_FIRST(&ifv->vlan_mc_listhead); + bcopy((char *)&mc->mc_addr, LLADDR(&sdl), ETHER_ADDR_LEN); + error = if_delmulti(p, (struct sockaddr *)&sdl); + if (error) + return(error); + SLIST_REMOVE_HEAD(&ifv->vlan_mc_listhead, mc_entries); + free(mc, M_DEVBUF); + } } /* Disconnect from parent. */ |