summaryrefslogtreecommitdiffstats
path: root/sys/net
diff options
context:
space:
mode:
authorthompsa <thompsa@FreeBSD.org>2005-10-23 22:30:07 +0000
committerthompsa <thompsa@FreeBSD.org>2005-10-23 22:30:07 +0000
commit6ca525e44337b09e5a4333a2467ad0810a8d2b56 (patch)
tree94480badb4688ba827235eb3c656756f4e4fee8a /sys/net
parentc22f36215286eaca7767c1116a2fe2d8616b8c9c (diff)
downloadFreeBSD-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')
-rw-r--r--sys/net/if_bridge.c45
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);
}
OpenPOWER on IntegriCloud