summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2015-04-10 08:48:25 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2015-04-10 08:48:25 +0000
commitd818ce59022ffdd6e1b97368c02dcecf507298ac (patch)
tree3571dc9583f9eccd6c4bf911101e32128e9c828d
parentd0b64d19dc2696dc109bc6a62dc77d7498945874 (diff)
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@
-rw-r--r--sys/net/if.c54
-rw-r--r--sys/net/if.h3
-rw-r--r--sys/net/if_ethersubr.c5
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);