diff options
author | thompsa <thompsa@FreeBSD.org> | 2005-10-23 22:30:07 +0000 |
---|---|---|
committer | thompsa <thompsa@FreeBSD.org> | 2005-10-23 22:30:07 +0000 |
commit | 6ca525e44337b09e5a4333a2467ad0810a8d2b56 (patch) | |
tree | 94480badb4688ba827235eb3c656756f4e4fee8a /sys/net/if_bridge.c | |
parent | c22f36215286eaca7767c1116a2fe2d8616b8c9c (diff) | |
download | FreeBSD-src-6ca525e44337b09e5a4333a2467ad0810a8d2b56.zip FreeBSD-src-6ca525e44337b09e5a4333a2467ad0810a8d2b56.tar.gz |
If we have been called from ether_ifdetach() then do not try and clear the
promisc flag from the member interface, this is a no-op anyway since the
interface is disappearing. The driver may have already released
its resources such as miibus and this is likely to panic the kernel.
Submitted and tested by: Wojciech A. Koszek
MFC after: 2 weeks
Diffstat (limited to 'sys/net/if_bridge.c')
-rw-r--r-- | sys/net/if_bridge.c | 45 |
1 files changed, 25 insertions, 20 deletions
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index 63484e8..0b2bd752 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -219,7 +219,7 @@ static struct bridge_iflist *bridge_lookup_member(struct bridge_softc *, static struct bridge_iflist *bridge_lookup_member_if(struct bridge_softc *, struct ifnet *ifp); static void bridge_delete_member(struct bridge_softc *, - struct bridge_iflist *); + struct bridge_iflist *, int); static int bridge_ioctl_add(struct bridge_softc *, void *); static int bridge_ioctl_del(struct bridge_softc *, void *); @@ -506,7 +506,7 @@ bridge_clone_destroy(struct ifnet *ifp) ifp->if_flags &= ~IFF_UP; while ((bif = LIST_FIRST(&sc->sc_iflist)) != NULL) - bridge_delete_member(sc, bif); + bridge_delete_member(sc, bif, 0); BRIDGE_UNLOCK(sc); @@ -690,26 +690,29 @@ bridge_lookup_member_if(struct bridge_softc *sc, struct ifnet *member_ifp) * Delete the specified member interface. */ static void -bridge_delete_member(struct bridge_softc *sc, struct bridge_iflist *bif) +bridge_delete_member(struct bridge_softc *sc, struct bridge_iflist *bif, + int gone) { struct ifnet *ifs = bif->bif_ifp; BRIDGE_LOCK_ASSERT(sc); - switch (ifs->if_type) { - case IFT_ETHER: - case IFT_L2VLAN: - /* - * Take the interface out of promiscuous mode. - */ - (void) ifpromisc(ifs, 0); - break; - - default: + if (!gone) { + switch (ifs->if_type) { + case IFT_ETHER: + case IFT_L2VLAN: + /* + * Take the interface out of promiscuous mode. + */ + (void) ifpromisc(ifs, 0); + break; + + default: #ifdef DIAGNOSTIC - panic("bridge_delete_member: impossible"); + panic("bridge_delete_member: impossible"); #endif - break; + break; + } } ifs->if_bridge = NULL; @@ -811,7 +814,7 @@ bridge_ioctl_del(struct bridge_softc *sc, void *arg) if (bif == NULL) return (ENOENT); - bridge_delete_member(sc, bif); + bridge_delete_member(sc, bif, 0); return (0); } @@ -1207,14 +1210,16 @@ static void bridge_ifdetach(struct ifnet *ifp) { struct bridge_softc *sc = ifp->if_bridge; - struct ifbreq breq; + struct bridge_iflist *bif; BRIDGE_LOCK(sc); - memset(&breq, 0, sizeof(breq)); - snprintf(breq.ifbr_ifsname, sizeof(breq.ifbr_ifsname), ifp->if_xname); + bif = bridge_lookup_member_if(sc, ifp); + if (bif == NULL) + return; + + bridge_delete_member(sc, bif, 1); - (void) bridge_ioctl_del(sc, &breq); BRIDGE_UNLOCK(sc); } |