diff --git a/sys/net/if.c b/sys/net/if.c index 003f3ea7e315..7029b9c85ed0 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -2095,6 +2095,14 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td) return (EINVAL); if (ifunit(new_name) != NULL) return (EEXIST); + + /* + * XXX: Locking. Nothing else seems to lock if_flags, + * and there are numerous other races with the + * ifunit() checks not being atomic with namespace + * changes (renames, vmoves, if_attach, etc). + */ + ifp->if_flags |= IFF_RENAMING; /* Announce the departure of the interface. */ rt_ifannouncemsg(ifp, IFAN_DEPARTURE); @@ -2129,6 +2137,8 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td) EVENTHANDLER_INVOKE(ifnet_arrival_event, ifp); /* Announce the return of the interface. */ rt_ifannouncemsg(ifp, IFAN_ARRIVAL); + + ifp->if_flags &= ~IFF_RENAMING; break; #ifdef VIMAGE diff --git a/sys/net/if.h b/sys/net/if.h index 857ab7fb460b..f94b54a1b622 100644 --- a/sys/net/if.h +++ b/sys/net/if.h @@ -150,6 +150,7 @@ struct if_data { #define IFF_MONITOR 0x40000 /* (n) user-requested monitor mode */ #define IFF_STATICARP 0x80000 /* (n) static ARP */ #define IFF_DYING 0x200000 /* (n) interface is winding down */ +#define IFF_RENAMING 0x400000 /* (n) interface is being renamed */ /* * Old names for driver flags so that user space tools can continue to use diff --git a/sys/net/if_vlan.c b/sys/net/if_vlan.c index bb9068284bf0..99f714eb69cc 100644 --- a/sys/net/if_vlan.c +++ b/sys/net/if_vlan.c @@ -466,7 +466,8 @@ vlan_setmulti(struct ifnet *ifp) * A handler for network interface departure events. * Track departure of trunks here so that we don't access invalid * pointers or whatever if a trunk is ripped from under us, e.g., - * by ejecting its hot-plug card. + * by ejecting its hot-plug card. However, if an ifnet is simply + * being renamed, then there's no need to tear down the state. */ static void vlan_ifdetach(void *arg __unused, struct ifnet *ifp) @@ -481,6 +482,10 @@ vlan_ifdetach(void *arg __unused, struct ifnet *ifp) if (ifp->if_vlantrunk == NULL) return; + /* If the ifnet is just being renamed, don't do anything. */ + if (ifp->if_flags & IFF_RENAMING) + return; + VLAN_LOCK(); /* * OK, it's a trunk. Loop over and detach all vlan's on it.