From f074e7d461c6e3fdf7124987027f28d88c3b8cec Mon Sep 17 00:00:00 2001 From: mpi Date: Fri, 10 Apr 2015 08:48:24 +0000 Subject: [PATCH] Run detach hook and similar before cleaning up any other resource when an interface is destroyed/removed. This way we can ensure pseudo-driver changes done after attaching an interface are undone before detaching it. Note: it is safe to call if_deactivate() multiple times as the interface should not have any attached pseudo-interface after the first call. ok deraadt@, dlg@ --- sys/net/if.c | 54 ++++++++++++++++++++++++++---------------- sys/net/if.h | 3 ++- sys/net/if_ethersubr.c | 5 +++- 3 files changed, 40 insertions(+), 22 deletions(-) diff --git a/sys/net/if.c b/sys/net/if.c index c697bfe18d6..a7c317cde30 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if.c,v 1.327 2015/04/07 10:46:20 mpi Exp $ */ +/* $OpenBSD: if.c,v 1.328 2015/04/10 08:48:24 mpi Exp $ */ /* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */ /* @@ -521,22 +521,12 @@ nettxintr(void) splx(s); } -/* - * Detach an interface from everything in the kernel. Also deallocate - * private resources. - */ void -if_detach(struct ifnet *ifp) +if_deactivate(struct ifnet *ifp) { - struct ifaddr *ifa; - struct ifg_list *ifg; - int s = splnet(); - struct domain *dp; + int s; - ifp->if_flags &= ~IFF_OACTIVE; - ifp->if_start = if_detached_start; - ifp->if_ioctl = if_detached_ioctl; - ifp->if_watchdog = NULL; + s = splnet(); /* * Call detach hooks from head to tail. To make sure detach @@ -545,12 +535,6 @@ if_detach(struct ifnet *ifp) */ dohooks(ifp->if_detachhooks, HOOK_REMOVE | HOOK_FREE); - /* Remove the watchdog timeout */ - timeout_del(ifp->if_slowtimo); - - /* Remove the link state task */ - task_del(systq, ifp->if_linkstatetask); - #if NBRIDGE > 0 /* Remove the interface from any bridge it is part of. */ if (ifp->if_bridgeport) @@ -563,6 +547,36 @@ if_detach(struct ifnet *ifp) carp_ifdetach(ifp); #endif + splx(s); +} + +/* + * Detach an interface from everything in the kernel. Also deallocate + * private resources. + */ +void +if_detach(struct ifnet *ifp) +{ + struct ifaddr *ifa; + struct ifg_list *ifg; + struct domain *dp; + int s; + + /* Undo pseudo-driver changes. */ + if_deactivate(ifp); + + s = splnet(); + ifp->if_flags &= ~IFF_OACTIVE; + ifp->if_start = if_detached_start; + ifp->if_ioctl = if_detached_ioctl; + ifp->if_watchdog = NULL; + + /* Remove the watchdog timeout */ + timeout_del(ifp->if_slowtimo); + + /* Remove the link state task */ + task_del(systq, ifp->if_linkstatetask); + #if NBPFILTER > 0 bpfdetach(ifp); #endif diff --git a/sys/net/if.h b/sys/net/if.h index 70e574b2089..20d69d6c4c8 100644 --- a/sys/net/if.h +++ b/sys/net/if.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if.h,v 1.161 2015/03/18 12:23:15 dlg Exp $ */ +/* $OpenBSD: if.h,v 1.162 2015/04/10 08:48:24 mpi Exp $ */ /* $NetBSD: if.h,v 1.23 1996/05/07 02:40:27 thorpej Exp $ */ /* @@ -446,6 +446,7 @@ void if_attach(struct ifnet *); void if_attachdomain(void); void if_attachtail(struct ifnet *); void if_attachhead(struct ifnet *); +void if_deactivate(struct ifnet *); void if_detach(struct ifnet *); void if_down(struct ifnet *); void if_downall(void); diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index 292b6871401..2bd2e75acae 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ethersubr.c,v 1.191 2015/04/07 10:46:20 mpi Exp $ */ +/* $OpenBSD: if_ethersubr.c,v 1.192 2015/04/10 08:48:24 mpi Exp $ */ /* $NetBSD: if_ethersubr.c,v 1.19 1996/05/07 02:40:30 thorpej Exp $ */ /* @@ -802,6 +802,9 @@ ether_ifdetach(struct ifnet *ifp) struct ifih *ether_ifih; struct ether_multi *enm; + /* Undo pseudo-driver changes. */ + if_deactivate(ifp); + ether_ifih = SLIST_FIRST(&ifp->if_inputs); SLIST_REMOVE_HEAD(&ifp->if_inputs, ifih_next); -- 2.20.1