From c697ed218af7d4237b6f734208eda8367b04323c Mon Sep 17 00:00:00 2001 From: thompsa Date: Thu, 13 Oct 2005 23:05:55 +0000 Subject: From 101 ways to panic your kernel. Use bridge_ifdetach() to notify the bridge that a member has been detached. The bridge can then remove it from its interface list and not try to send out via a dead pointer. --- sys/net/if_bridge.c | 6 +++++- sys/net/if_ethersubr.c | 8 ++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index 85afcfd..81925d4 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -177,6 +177,7 @@ extern struct mbuf *(*bridge_input_p)(struct ifnet *, struct mbuf *); extern int (*bridge_output_p)(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); extern void (*bridge_dn_p)(struct mbuf *, struct ifnet *); +extern void (*bridge_detach_p)(struct ifnet *); int bridge_rtable_prune_period = BRIDGE_RTABLE_PRUNE_PERIOD; @@ -355,6 +356,7 @@ bridge_modevent(module_t mod, int type, void *data) bridge_input_p = bridge_input; bridge_output_p = bridge_output; bridge_dn_p = bridge_dummynet; + bridge_detach_p = bridge_ifdetach; bstp_linkstate_p = bstp_linkstate; break; case MOD_UNLOAD: @@ -366,6 +368,7 @@ bridge_modevent(module_t mod, int type, void *data) bridge_input_p = NULL; bridge_output_p = NULL; bridge_dn_p = NULL; + bridge_detach_p = NULL; bstp_linkstate_p = NULL; mtx_destroy(&bridge_list_mtx); break; @@ -1204,12 +1207,13 @@ bridge_ifdetach(struct ifnet *ifp) struct bridge_softc *sc = ifp->if_bridge; struct ifbreq breq; - BRIDGE_LOCK_ASSERT(sc); + BRIDGE_LOCK(sc); memset(&breq, 0, sizeof(breq)); snprintf(breq.ifbr_ifsname, sizeof(breq.ifbr_ifsname), ifp->if_xname); (void) bridge_ioctl_del(sc, &breq); + BRIDGE_UNLOCK(sc); } /* diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index 578ea99..8bce103 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -110,6 +110,7 @@ struct mbuf *(*bridge_input_p)(struct ifnet *, struct mbuf *); int (*bridge_output_p)(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); void (*bridge_dn_p)(struct mbuf *, struct ifnet *); +void (*bridge_detach_p)(struct ifnet *ifp); static const u_char etherbroadcastaddr[ETHER_ADDR_LEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; @@ -909,6 +910,13 @@ ether_ifdetach(struct ifnet *ifp) ("ng_ether_detach_p is NULL")); (*ng_ether_detach_p)(ifp); } + + if (ifp->if_bridge) { + KASSERT(bridge_detach_p != NULL, + ("bridge_detach_p is NULL")); + (*bridge_detach_p)(ifp); + } + bpfdetach(ifp); if_detach(ifp); } -- cgit v1.1