Run detach hook and similar before cleaning up any other resource when
authormpi <mpi@openbsd.org>
Fri, 10 Apr 2015 08:48:24 +0000 (08:48 +0000)
committermpi <mpi@openbsd.org>
Fri, 10 Apr 2015 08:48:24 +0000 (08:48 +0000)
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
sys/net/if.h
sys/net/if_ethersubr.c

index c697bfe..a7c317c 100644 (file)
@@ -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
index 70e574b..20d69d6 100644 (file)
@@ -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);
index 292b687..2bd2e75 100644 (file)
@@ -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);