diff --git a/sys/netgraph/ng_eiface.c b/sys/netgraph/ng_eiface.c --- a/sys/netgraph/ng_eiface.c +++ b/sys/netgraph/ng_eiface.c @@ -33,10 +33,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -77,6 +79,9 @@ { 0 } }; +static struct sx ng_eiface_lock; +SX_SYSINIT(ng_eiface_lock, &ng_eiface_lock, "ng_eiface_lock"); + /* Node private data */ struct ng_eiface_private { struct ifnet *ifp; /* per-interface network data */ @@ -133,7 +138,7 @@ static int ng_eiface_ioctl(struct ifnet *ifp, u_long command, caddr_t data) { - const priv_p priv = (priv_p)ifp->if_softc; + priv_p priv; struct ifreq *const ifr = (struct ifreq *)data; int error = 0; @@ -178,7 +183,11 @@ /* (Fake) media type manipulation */ case SIOCSIFMEDIA: case SIOCGIFMEDIA: - error = ifmedia_ioctl(ifp, ifr, &priv->media, command); + sx_slock(&ng_eiface_lock); + priv = (priv_p)ifp->if_softc; + if (priv != NULL) + error = ifmedia_ioctl(ifp, ifr, &priv->media, command); + sx_sunlock(&ng_eiface_lock); break; /* Stuff that's not supported */ @@ -612,17 +621,20 @@ struct ifnet *const ifp = priv->ifp; /* - * the ifnet may be in a different vnet than the netgraph node, + * the ifnet may be in a different vnet than the netgraph node, * hence we have to change the current vnet context here. */ + sx_xlock(&ng_eiface_lock); + ifp->if_softc = NULL; CURVNET_SET_QUIET(ifp->if_vnet); ether_ifdetach(ifp); - ifmedia_removeall(&priv->media); if_free(ifp); + ifmedia_removeall(&priv->media); CURVNET_RESTORE(); free_unr(V_ng_eiface_unit, priv->unit); free(priv, M_NETGRAPH); NG_NODE_SET_PRIVATE(node, NULL); + sx_xunlock(&ng_eiface_lock); NG_NODE_UNREF(node); return (0); }