hook_establish can fail, but drivers are inconsistent about checking for
that. apparently there's also a requirement that detach hooks are
run in opposite order to the one they were established in, but that
is also applied inconsistently by drivers.

this replaces if_detachhooks with a task_list, and has users of it
allocate an set a struct task to put on it. this means the users of it
allocate the task up front as part of their per port or softc structure,
so adding the task to the if_detachhooks list cannot fail. to enforce
the required ordering, ive added wrappers around the list operations.

ive had this as a long standing itch to scratch, but i was forced into
action after looking at a report by markus@ about the order of these
hook establishment/disestablishments in carp. if you reparent a carp
interface, you've established detach hooks on multiple interfaces, but
if you need to roll back you can lose one of them. this reorders the ops
so you only add the detach hook after you've been put on the new
interface, and because adding the detach hook is reliable there's no
rollback or unwinding to implement.

i would love some testing. ive only kicked a few of the tyres on this
one.

ok?

if people are ok with this, i'll go through and do the same for the link
state and address change hooks.

Index: net/if.c
===================================================================
RCS file: /cvs/src/sys/net/if.c,v
retrieving revision 1.588
diff -u -p -r1.588 if.c
--- net/if.c    21 Aug 2019 15:32:18 -0000      1.588
+++ net/if.c    4 Nov 2019 22:51:52 -0000
@@ -632,9 +623,7 @@ if_attach_common(struct ifnet *ifp)
        ifp->if_linkstatehooks = malloc(sizeof(*ifp->if_linkstatehooks),
            M_TEMP, M_WAITOK);
        TAILQ_INIT(ifp->if_linkstatehooks);
-       ifp->if_detachhooks = malloc(sizeof(*ifp->if_detachhooks),
-           M_TEMP, M_WAITOK);
-       TAILQ_INIT(ifp->if_detachhooks);
+       TAILQ_INIT(&ifp->if_detachhooks);
 
        if (ifp->if_rtrequest == NULL)
                ifp->if_rtrequest = if_rtrequest_dummy;
@@ -1046,17 +1035,36 @@ if_netisr(void *unused)
 void
 if_deactivate(struct ifnet *ifp)
 {
-       NET_LOCK();
+       struct task *t, *nt;
+
        /*
         * Call detach hooks from head to tail.  To make sure detach
         * hooks are executed in the reverse order they were added, all
         * the hooks have to be added to the head!
         */
-       dohooks(ifp->if_detachhooks, HOOK_REMOVE | HOOK_FREE);
 
+       NET_LOCK();
+       TAILQ_FOREACH_SAFE(t, &ifp->if_detachhooks, t_entry, nt)
+               (*t->t_func)(t->t_arg);
+
+       KASSERT(TAILQ_EMPTY(&ifp->if_detachhooks));
        NET_UNLOCK();
 }
 
+void
+if_detachhook_add(struct ifnet *ifp, struct task *t)
+{
+       NET_ASSERT_LOCKED();
+       TAILQ_INSERT_HEAD(&ifp->if_detachhooks, t, t_entry);
+}
+
+void
+if_detachhook_del(struct ifnet *ifp, struct task *t)
+{
+       NET_ASSERT_LOCKED();
+       TAILQ_REMOVE(&ifp->if_detachhooks, t, t_entry);
+}
+
 /*
  * Detach an interface from everything in the kernel.  Also deallocate
  * private resources.
@@ -1132,7 +1140,6 @@ if_detach(struct ifnet *ifp)
 
        free(ifp->if_addrhooks, M_TEMP, sizeof(*ifp->if_addrhooks));
        free(ifp->if_linkstatehooks, M_TEMP, sizeof(*ifp->if_linkstatehooks));
-       free(ifp->if_detachhooks, M_TEMP, sizeof(*ifp->if_detachhooks));
 
        for (i = 0; (dp = domains[i]) != NULL; i++) {
                if (dp->dom_ifdetach && ifp->if_afdata[dp->dom_family])
Index: net/if_aggr.c
===================================================================
RCS file: /cvs/src/sys/net/if_aggr.c,v
retrieving revision 1.19
diff -u -p -r1.19 if_aggr.c
--- net/if_aggr.c       5 Aug 2019 10:42:51 -0000       1.19
+++ net/if_aggr.c       4 Nov 2019 22:51:52 -0000
@@ -336,7 +336,7 @@ struct aggr_port {
            struct rtentry *);
 
        void                    *p_lcookie;
-       void                    *p_dcookie;
+       struct task              p_dtask;
 
        struct aggr_softc       *p_aggr;
        TAILQ_ENTRY(aggr_port)   p_entry;
@@ -1138,8 +1138,9 @@ aggr_add_port(struct aggr_softc *sc, con
 
        p->p_lcookie = hook_establish(ifp0->if_linkstatehooks, 1,
            aggr_p_linkch, p);
-       p->p_dcookie = hook_establish(ifp0->if_detachhooks, 0,
-           aggr_p_detach, p);
+
+       task_set(&p->p_dtask, aggr_p_detach, p);
+       if_detachhook_add(ifp0, &p->p_dtask);
 
        task_set(&p->p_rxm_task, aggr_rx, p);
        mq_init(&p->p_rxm_mq, 3, IPL_NET);
@@ -1427,7 +1428,7 @@ aggr_p_dtor(struct aggr_softc *sc, struc
                    ifp->if_xname, op, ifp0->if_xname);
        }
 
-       hook_disestablish(ifp0->if_detachhooks, p->p_dcookie);
+       if_detachhook_del(ifp0, &p->p_dtask);
        hook_disestablish(ifp0->if_linkstatehooks, p->p_lcookie);
 
        if_put(ifp0);
Index: net/if_bpe.c
===================================================================
RCS file: /cvs/src/sys/net/if_bpe.c,v
retrieving revision 1.8
diff -u -p -r1.8 if_bpe.c
--- net/if_bpe.c        17 Jul 2019 16:46:17 -0000      1.8
+++ net/if_bpe.c        4 Nov 2019 22:51:52 -0000
@@ -103,7 +103,7 @@ struct bpe_softc {
        uint8_t                 sc_group[ETHER_ADDR_LEN];
 
        void *                  sc_lh_cookie;
-       void *                  sc_dh_cookie;
+       struct task             sc_dtask;
 
        struct bpe_map          sc_bridge_map;
        struct rwlock           sc_bridge_lock;
@@ -174,6 +174,8 @@ bpe_clone_create(struct if_clone *ifc, i
        sc->sc_txhprio = IF_HDRPRIO_PACKET;
        sc->sc_rxhprio = IF_HDRPRIO_OUTER;
 
+       task_set(&sc->sc_dtask, bpe_detach_hook, sc);
+
        rw_init(&sc->sc_bridge_lock, "bpebr");
        RBT_INIT(bpe_map, &sc->sc_bridge_map);
        sc->sc_bridge_num = 0;
@@ -636,8 +638,7 @@ bpe_up(struct bpe_softc *sc)
            bpe_link_hook, sc);
 
        /* Register callback if parent wants to unregister */
-       sc->sc_dh_cookie = hook_establish(ifp0->if_detachhooks, 0,
-           bpe_detach_hook, sc);
+       if_detachhook_add(ifp0, &sc->sc_dtask);
 
        /* we're running now */
        SET(ifp->if_flags, IFF_RUNNING);
@@ -674,7 +675,7 @@ bpe_down(struct bpe_softc *sc)
 
        ifp0 = if_get(sc->sc_key.k_if);
        if (ifp0 != NULL) {
-               hook_disestablish(ifp0->if_detachhooks, sc->sc_dh_cookie);
+               if_detachhook_del(ifp0, &sc->sc_dtask);
                hook_disestablish(ifp0->if_linkstatehooks, sc->sc_lh_cookie);
                bpe_multi(sc, ifp0, SIOCDELMULTI);
        }
Index: net/if_bridge.c
===================================================================
RCS file: /cvs/src/sys/net/if_bridge.c,v
retrieving revision 1.337
diff -u -p -r1.337 if_bridge.c
--- net/if_bridge.c     20 Jul 2019 23:01:51 -0000      1.337
+++ net/if_bridge.c     4 Nov 2019 22:51:52 -0000
@@ -325,8 +325,8 @@ bridge_ioctl(struct ifnet *ifp, u_long c
                SIMPLEQ_INIT(&bif->bif_brlin);
                SIMPLEQ_INIT(&bif->bif_brlout);
                ifs->if_bridgeidx = ifp->if_index;
-               bif->bif_dhcookie = hook_establish(ifs->if_detachhooks, 0,
-                   bridge_ifdetach, bif);
+               task_set(&bif->bif_dtask, bridge_ifdetach, bif);
+               if_detachhook_add(ifs, &bif->bif_dtask);
                if_ih_insert(bif->ifp, bridge_input, NULL);
                SMR_SLIST_INSERT_HEAD_LOCKED(&sc->sc_iflist, bif, bif_next);
                break;
@@ -385,8 +385,8 @@ bridge_ioctl(struct ifnet *ifp, u_long c
                bif->bif_flags = IFBIF_SPAN;
                SIMPLEQ_INIT(&bif->bif_brlin);
                SIMPLEQ_INIT(&bif->bif_brlout);
-               bif->bif_dhcookie = hook_establish(ifs->if_detachhooks, 0,
-                   bridge_spandetach, bif);
+               task_set(&bif->bif_dtask, bridge_spandetach, bif);
+               if_detachhook_add(ifs, &bif->bif_dtask);
                SMR_SLIST_INSERT_HEAD_LOCKED(&sc->sc_spanlist, bif, bif_next);
                break;
        case SIOCBRDGDELS:
@@ -547,7 +547,7 @@ bridge_ifremove(struct bridge_iflist *bi
        int error;
 
        SMR_SLIST_REMOVE_LOCKED(&sc->sc_iflist, bif, bridge_iflist, bif_next);
-       hook_disestablish(bif->ifp->if_detachhooks, bif->bif_dhcookie);
+       if_detachhook_del(bif->ifp, &bif->bif_dtask);
        if_ih_remove(bif->ifp, bridge_input, NULL);
 
        smr_barrier();
@@ -575,7 +575,7 @@ bridge_spanremove(struct bridge_iflist *
        struct bridge_softc *sc = bif->bridge_sc;
 
        SMR_SLIST_REMOVE_LOCKED(&sc->sc_spanlist, bif, bridge_iflist, bif_next);
-       hook_disestablish(bif->ifp->if_detachhooks, bif->bif_dhcookie);
+       if_detachhook_del(bif->ifp, &bif->bif_dtask);
 
        smr_barrier();
 
Index: net/if_bridge.h
===================================================================
RCS file: /cvs/src/sys/net/if_bridge.h,v
retrieving revision 1.65
diff -u -p -r1.65 if_bridge.h
--- net/if_bridge.h     12 May 2019 19:53:22 -0000      1.65
+++ net/if_bridge.h     4 Nov 2019 22:51:52 -0000
@@ -425,7 +425,7 @@ struct bridge_iflist {
        struct ifnet                    *ifp;           /* [I] net interface */
        u_int32_t                       bif_flags;      /* member flags */
        u_int32_t                       bif_protected;  /* protected domains */
-       void                            *bif_dhcookie;
+       struct task                     bif_dtask;
 };
 #define bif_state                      bif_stp->bp_state
 
Index: net/if_gre.c
===================================================================
RCS file: /cvs/src/sys/net/if_gre.c,v
retrieving revision 1.152
diff -u -p -r1.152 if_gre.c
--- net/if_gre.c        29 Jul 2019 16:28:25 -0000      1.152
+++ net/if_gre.c        4 Nov 2019 22:51:52 -0000
@@ -430,7 +407,7 @@ struct nvgre_softc {
 
        void                    *sc_inm;
        void                    *sc_lhcookie;
-       void                    *sc_dhcookie;
+       struct task              sc_dtask;
 
        struct rwlock            sc_ether_lock;
        struct nvgre_map         sc_ether_map;
@@ -792,6 +769,7 @@ nvgre_clone_create(struct if_clone *ifc,
 
        mq_init(&sc->sc_send_list, IFQ_MAXLEN * 2, IPL_SOFTNET);
        task_set(&sc->sc_send_task, nvgre_send, sc);
+       task_set(&sc->sc_dtask, nvgre_detach, sc);
 
        rw_init(&sc->sc_ether_lock, "nvgrelk");
        RBT_INIT(nvgre_map, &sc->sc_ether_map);
@@ -3663,12 +3630,7 @@ nvgre_up(struct nvgre_softc *sc)
                goto delmulti;
        }
 
-       sc->sc_dhcookie = hook_establish(ifp0->if_detachhooks, 0,
-           nvgre_detach, sc);
-       if (sc->sc_dhcookie == NULL) {
-               error = ENOMEM;
-               goto dislh;
-       }
+       if_detachhook_add(ifp0, &sc->sc_dtask);
 
        if_put(ifp0);
 
@@ -3679,8 +3641,6 @@ nvgre_up(struct nvgre_softc *sc)
 
        return (0);
 
-dislh:
-       hook_disestablish(ifp0->if_linkstatehooks, sc->sc_lhcookie);
 delmulti:
        switch (tunnel->t_af) {
        case AF_INET:
@@ -3726,7 +3686,7 @@ nvgre_down(struct nvgre_softc *sc)
 
        ifp0 = if_get(sc->sc_ifp0);
        if (ifp0 != NULL) {
-               hook_disestablish(ifp0->if_detachhooks, sc->sc_dhcookie);
+               if_detachhook_del(ifp0, &sc->sc_dtask);
                hook_disestablish(ifp0->if_linkstatehooks, sc->sc_lhcookie);
        }
        if_put(ifp0);
Index: net/if_pfsync.c
===================================================================
RCS file: /cvs/src/sys/net/if_pfsync.c,v
retrieving revision 1.264
diff -u -p -r1.264 if_pfsync.c
--- net/if_pfsync.c     10 Jun 2019 16:32:51 -0000      1.264
+++ net/if_pfsync.c     4 Nov 2019 22:51:52 -0000
@@ -236,7 +236,7 @@ struct pfsync_softc {
        TAILQ_HEAD(, tdb)        sc_tdb_q;
 
        void                    *sc_lhcookie;
-       void                    *sc_dhcookie;
+       struct task              sc_dtask;
 
        struct timeout           sc_tmo;
 };
@@ -321,6 +321,7 @@ pfsync_clone_create(struct if_clone *ifc
            NULL);
        TAILQ_INIT(&sc->sc_upd_req_list);
        TAILQ_INIT(&sc->sc_deferrals);
+       task_set(&sc->sc_dtask, pfsync_ifdetach, sc);
        sc->sc_deferred = 0;
 
        TAILQ_INIT(&sc->sc_tdb_q);
@@ -381,8 +382,7 @@ pfsync_clone_destroy(struct ifnet *ifp)
                hook_disestablish(
                    sc->sc_sync_if->if_linkstatehooks,
                    sc->sc_lhcookie);
-               hook_disestablish(sc->sc_sync_if->if_detachhooks,
-                   sc->sc_dhcookie);
+               if_detachhook_del(sc->sc_sync_if, &sc->sc_dtask);
        }
 
        /* XXXSMP breaks atomicity */
@@ -1350,9 +1350,8 @@ pfsyncioctl(struct ifnet *ifp, u_long cm
                                hook_disestablish(
                                    sc->sc_sync_if->if_linkstatehooks,
                                    sc->sc_lhcookie);
-                               hook_disestablish(
-                                   sc->sc_sync_if->if_detachhooks,
-                                   sc->sc_dhcookie);
+                               if_detachhook_del(sc->sc_sync_if,
+                                   &sc->sc_dtask);
                        }
                        sc->sc_sync_if = NULL;
                        if (imo->imo_num_memberships > 0) {
@@ -1376,9 +1375,7 @@ pfsyncioctl(struct ifnet *ifp, u_long cm
                        hook_disestablish(
                            sc->sc_sync_if->if_linkstatehooks,
                            sc->sc_lhcookie);
-                       hook_disestablish(
-                           sc->sc_sync_if->if_detachhooks,
-                           sc->sc_dhcookie);
+                       if_detachhook_del(sc->sc_sync_if, &sc->sc_dtask);
                }
                sc->sc_sync_if = sifp;
 
@@ -1424,8 +1421,7 @@ pfsyncioctl(struct ifnet *ifp, u_long cm
                sc->sc_lhcookie =
                    hook_establish(sc->sc_sync_if->if_linkstatehooks, 1,
                    pfsync_syncdev_state, sc);
-               sc->sc_dhcookie = hook_establish(sc->sc_sync_if->if_detachhooks,
-                   0, pfsync_ifdetach, sc);
+               if_detachhook_add(sc->sc_sync_if, &sc->sc_dtask);
 
                pfsync_request_full_update(sc);
 
Index: net/if_switch.c
===================================================================
RCS file: /cvs/src/sys/net/if_switch.c,v
retrieving revision 1.29
diff -u -p -r1.29 if_switch.c
--- net/if_switch.c     30 Sep 2019 01:53:05 -0000      1.29
+++ net/if_switch.c     4 Nov 2019 22:51:52 -0000
@@ -533,8 +533,8 @@ switch_port_add(struct switch_softc *sc,
        ifs->if_switchport = (caddr_t)swpo;
        if_ih_insert(ifs, switch_input, NULL);
        swpo->swpo_port_no = swofp_assign_portno(sc, ifs->if_index);
-       swpo->swpo_dhcookie = hook_establish(ifs->if_detachhooks, 0,
-           switch_port_detach, ifs);
+       task_set(&swpo->swpo_dtask, switch_port_detach, ifs);
+       if_detachhook_add(ifs, &swpo->swpo_dtask);
 
        nanouptime(&swpo->swpo_appended);
 
@@ -601,7 +601,7 @@ switch_port_detach(void *arg)
                switch_port_unset_local(sc, swpo);
 
        ifp->if_switchport = NULL;
-       hook_disestablish(ifp->if_detachhooks, swpo->swpo_dhcookie);
+       if_detachhook_del(ifp, &swpo->swpo_dtask);
        ifpromisc(ifp, 0);
        if_ih_remove(ifp, switch_input, NULL);
        TAILQ_REMOVE(&sc->sc_swpo_list, swpo, swpo_list_next);
Index: net/if_switch.h
===================================================================
RCS file: /cvs/src/sys/net/if_switch.h,v
retrieving revision 1.11
diff -u -p -r1.11 if_switch.h
--- net/if_switch.h     10 May 2019 15:13:38 -0000      1.11
+++ net/if_switch.h     4 Nov 2019 22:51:52 -0000
@@ -175,7 +175,7 @@ struct switch_port {
        struct switch_softc             *swpo_switch;
        uint32_t                         swpo_flags;
        uint32_t                         swpo_protected;
-       void                            *swpo_dhcookie;
+       struct task                      swpo_dtask;
        void                            (*swop_bk_start)(struct ifnet *);
 };
 
Index: net/if_tpmr.c
===================================================================
RCS file: /cvs/src/sys/net/if_tpmr.c,v
retrieving revision 1.4
diff -u -p -r1.4 if_tpmr.c
--- net/if_tpmr.c       12 Sep 2019 02:02:54 -0000      1.4
+++ net/if_tpmr.c       4 Nov 2019 22:51:52 -0000
@@ -87,7 +87,7 @@ struct tpmr_port {
            struct rtentry *);
 
        void                    *p_lcookie;
-       void                    *p_dcookie;
+       struct task              p_dtask;
 
        struct tpmr_softc       *p_tpmr;
        unsigned int             p_slot;
@@ -565,8 +565,8 @@ tpmr_add_port(struct tpmr_softc *sc, con
 
        p->p_lcookie = hook_establish(ifp0->if_linkstatehooks, 1,
            tpmr_p_linkch, p);
-       p->p_dcookie = hook_establish(ifp0->if_detachhooks, 0,
-           tpmr_p_detach, p);
+       task_set(&p->p_dtask, tpmr_p_detach, p);
+       if_detachhook_add(ifp0, &p->p_dtask);
 
        /* commit */
        DPRINTF(sc, "%s %s trunkport: creating port\n",
@@ -724,7 +724,7 @@ tpmr_p_dtor(struct tpmr_softc *sc, struc
                    ifp->if_xname, ifp0->if_xname);
        }
 
-       hook_disestablish(ifp0->if_detachhooks, p->p_dcookie);
+       if_detachhook_del(ifp0, &p->p_dtask);
        hook_disestablish(ifp0->if_linkstatehooks, p->p_lcookie);
 
        smr_barrier();
Index: net/if_trunk.c
===================================================================
RCS file: /cvs/src/sys/net/if_trunk.c,v
retrieving revision 1.141
diff -u -p -r1.141 if_trunk.c
--- net/if_trunk.c      5 Jul 2019 01:24:56 -0000       1.141
+++ net/if_trunk.c      4 Nov 2019 22:51:52 -0000
@@ -376,8 +376,8 @@ trunk_port_create(struct trunk_softc *tr
            trunk_port_state, tp);
 
        /* Register callback if parent wants to unregister */
-       tp->dh_cookie = hook_establish(ifp->if_detachhooks, 0,
-           trunk_port_ifdetach, tp);
+       task_set(&tp->tp_dtask, trunk_port_ifdetach, tp);
+       if_detachhook_add(ifp, &tp->tp_dtask);
 
        if (tr->tr_port_create != NULL)
                error = (*tr->tr_port_create)(tp);
@@ -437,7 +437,7 @@ trunk_port_destroy(struct trunk_port *tp
        ifp->if_output = tp->tp_output;
 
        hook_disestablish(ifp->if_linkstatehooks, tp->lh_cookie);
-       hook_disestablish(ifp->if_detachhooks, tp->dh_cookie);
+       if_detachhook_del(ifp, &tp->tp_dtask);
 
        /* Finally, remove the port from the trunk */
        SLIST_REMOVE(&tr->tr_ports, tp, trunk_port, tp_entries);
Index: net/if_trunk.h
===================================================================
RCS file: /cvs/src/sys/net/if_trunk.h,v
retrieving revision 1.27
diff -u -p -r1.27 if_trunk.h
--- net/if_trunk.h      29 Apr 2019 04:26:47 -0000      1.27
+++ net/if_trunk.h      4 Nov 2019 22:51:52 -0000
@@ -166,7 +166,7 @@ struct trunk_port {
        u_int32_t                       tp_prio;        /* port priority */
        u_int32_t                       tp_flags;       /* port flags */
        void                            *lh_cookie;     /* if state hook */
-       void                            *dh_cookie;     /* if detach hook */
+       struct task                     tp_dtask;       /* if detach hook */
 
        /* Redirected callbacks */
        int     (*tp_ioctl)(struct ifnet *, u_long, caddr_t);
Index: net/if_var.h
===================================================================
RCS file: /cvs/src/sys/net/if_var.h,v
retrieving revision 1.100
diff -u -p -r1.100 if_var.h
--- net/if_var.h        26 Jun 2019 09:36:06 -0000      1.100
+++ net/if_var.h        4 Nov 2019 22:51:52 -0000
@@ -126,7 +126,7 @@ struct ifnet {                              /* and the 
entries */
        TAILQ_HEAD(, ifg_list) if_groups; /* [N] list of groups per if */
        struct hook_desc_head *if_addrhooks; /* [I] address change callbacks */
        struct hook_desc_head *if_linkstatehooks; /* [I] link change callbacks*/
-       struct hook_desc_head *if_detachhooks; /* [I] detach callbacks */
+       struct task_list if_detachhooks; /* [I] detach callbacks */
                                /* [I] check or clean routes (+ or -)'d */
        void    (*if_rtrequest)(struct ifnet *, int, struct rtentry *);
        char    if_xname[IFNAMSIZ];     /* [I] external name (name + unit) */
@@ -373,6 +373,9 @@ void        if_ih_insert(struct ifnet *, int (*
            void *), void *);
 void   if_ih_remove(struct ifnet *, int (*)(struct ifnet *, struct mbuf *,
            void *), void *);
+
+void   if_detachhook_add(struct ifnet *, struct task *);
+void   if_detachhook_del(struct ifnet *, struct task *);
 
 void   if_rxr_livelocked(struct if_rxring *);
 void   if_rxr_init(struct if_rxring *, u_int, u_int);
Index: net/if_vlan.c
===================================================================
RCS file: /cvs/src/sys/net/if_vlan.c,v
retrieving revision 1.200
diff -u -p -r1.200 if_vlan.c
--- net/if_vlan.c       4 Nov 2019 04:17:31 -0000       1.200
+++ net/if_vlan.c       4 Nov 2019 22:51:52 -0000
@@ -98,7 +98,7 @@ struct vlan_softc {
        int                      sc_flags;
        struct refcnt            sc_refcnt;
        void                    *sc_lh_cookie;
-       void                    *sc_dh_cookie;
+       struct task              sc_dtask;
        struct ifih             *sc_ifih;
 };
 
@@ -192,6 +192,7 @@ vlan_clone_create(struct if_clone *ifc, 
        sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO);
        sc->sc_dead = 0;
        LIST_INIT(&sc->sc_mc_listhead);
+       task_set(&sc->sc_dtask, vlan_ifdetach, sc);
        ifp = &sc->sc_if;
        ifp->if_softc = sc;
        snprintf(ifp->if_xname, sizeof ifp->if_xname, "%s%d", ifc->ifc_name,
@@ -537,8 +538,7 @@ vlan_up(struct vlan_softc *sc)
            vlan_link_hook, sc);
 
        /* Register callback if parent wants to unregister */
-       sc->sc_dh_cookie = hook_establish(ifp0->if_detachhooks, 0,
-           vlan_ifdetach, sc);
+       if_detachhook_add(ifp0, &sc->sc_dtask);
 
        /* configure the parent to handle packets for this vlan */
        vlan_multi_apply(sc, ifp0, SIOCADDMULTI);
@@ -591,7 +591,7 @@ vlan_down(struct vlan_softc *sc)
                if (ISSET(sc->sc_flags, IFVF_PROMISC))
                        ifpromisc(ifp0, 0);
                vlan_multi_apply(sc, ifp0, SIOCDELMULTI);
-               hook_disestablish(ifp0->if_detachhooks, sc->sc_dh_cookie);
+               if_detachhook_del(ifp0, &sc->sc_dtask);
                hook_disestablish(ifp0->if_linkstatehooks, sc->sc_lh_cookie);
        }
        if_put(ifp0);
Index: net/if_vxlan.c
===================================================================
RCS file: /cvs/src/sys/net/if_vxlan.c,v
retrieving revision 1.73
diff -u -p -r1.73 if_vxlan.c
--- net/if_vxlan.c      10 Jun 2019 16:32:51 -0000      1.73
+++ net/if_vxlan.c      4 Nov 2019 22:51:52 -0000
@@ -64,7 +64,7 @@ struct vxlan_softc {
        struct ip_moptions       sc_imo;
        void                    *sc_ahcookie;
        void                    *sc_lhcookie;
-       void                    *sc_dhcookie;
+       struct task              sc_dtask;
 
        struct sockaddr_storage  sc_src;
        struct sockaddr_storage  sc_dst;
@@ -138,6 +138,7 @@ vxlan_clone_create(struct if_clone *ifc,
        sc->sc_vnetid = VXLAN_VNI_UNSET;
        sc->sc_txhprio = IFQ_TOS2PRIO(IPTOS_PREC_ROUTINE); /* 0 */
        sc->sc_df = htons(0);
+       task_set(&sc->sc_dtask, vxlan_if_change, sc);
        task_set(&sc->sc_sendtask, vxlan_send_dispatch, sc);
 
        ifp = &sc->sc_ac.ac_if;
@@ -223,11 +224,7 @@ vxlan_multicast_cleanup(struct ifnet *if
                            sc->sc_lhcookie);
                        sc->sc_lhcookie = NULL;
                }
-               if (sc->sc_dhcookie != NULL) {
-                       hook_disestablish(mifp->if_detachhooks,
-                           sc->sc_dhcookie);
-                       sc->sc_dhcookie = NULL;
-               }
+               if_detachhook_del(mifp, &sc->sc_dtask);
 
                if_put(mifp);
        }
@@ -297,12 +294,11 @@ vxlan_multicast_join(struct ifnet *ifp, 
         * Use interface hooks to track any changes on the interface
         * that is used to send out the tunnel traffic as multicast.
         */
+       if_detachhook_add(mifp, &sc->sc_dtask);
        if ((sc->sc_ahcookie = hook_establish(mifp->if_addrhooks,
            0, vxlan_addr_change, sc)) == NULL ||
            (sc->sc_lhcookie = hook_establish(mifp->if_linkstatehooks,
-           0, vxlan_link_change, sc)) == NULL ||
-           (sc->sc_dhcookie = hook_establish(mifp->if_detachhooks,
-           0, vxlan_if_change, sc)) == NULL)
+           0, vxlan_link_change, sc)) == NULL)
                panic("%s: cannot allocate interface hook",
                    mifp->if_xname);
 
Index: netinet/ip_carp.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_carp.c,v
retrieving revision 1.338
diff -u -p -r1.338 ip_carp.c
--- netinet/ip_carp.c   10 Jun 2019 16:32:51 -0000      1.338
+++ netinet/ip_carp.c   4 Nov 2019 22:51:52 -0000
@@ -133,7 +133,7 @@ struct carp_softc {
 #define        sc_carpdev      sc_ac.ac_if.if_carpdev
        void *ah_cookie;
        void *lh_cookie;
-       void *dh_cookie;
+       struct task sc_dtask;
        struct ip_moptions sc_imo;
 #ifdef INET6
        struct ip6_moptions sc_im6o;
@@ -808,6 +808,8 @@ carp_clone_create(struct if_clone *ifc, 
                return (ENOMEM);
        }
 
+       task_set(&sc->sc_dtask, carpdetach, sc);
+
        sc->sc_suppress = 0;
        sc->sc_advbase = CARP_DFLTINTV;
        sc->sc_naddrs = sc->sc_naddrs6 = 0;
@@ -955,7 +957,7 @@ carpdetach(void *arg)
        sc->sc_carpdev = NULL;
 
        hook_disestablish(ifp0->if_linkstatehooks, sc->lh_cookie);
-       hook_disestablish(ifp0->if_detachhooks, sc->dh_cookie);
+       if_detachhook_del(ifp0, &sc->sc_dtask);
 }
 
 void
@@ -1685,17 +1687,10 @@ carp_set_ifp(struct carp_softc *sc, stru
        if (ifp0->if_type != IFT_ETHER)
                return (EINVAL);
 
-       sc->dh_cookie = hook_establish(ifp0->if_detachhooks, 0,
-            carpdetach, sc);
-       if (sc->dh_cookie == NULL)
-               return (ENOMEM);
-
        sc->lh_cookie = hook_establish(ifp0->if_linkstatehooks, 1,
            carp_carpdev_state, ifp0);
-       if (sc->lh_cookie == NULL) {
-               error = ENOMEM;
-               goto rm_dh;
-       }
+       if (sc->lh_cookie == NULL)
+               return (ENOMEM);
 
        cif = &ifp0->if_carp;
        if (SRPL_EMPTY_LOCKED(cif)) {
@@ -1712,6 +1707,7 @@ carp_set_ifp(struct carp_softc *sc, stru
                carpdetach(sc);
 
        /* attach carp interface to physical interface */
+       if_detachhook_add(ifp0, &sc->sc_dtask);
        sc->sc_carpdev = ifp0;
        sc->sc_if.if_capabilities = ifp0->if_capabilities &
            IFCAP_CSUM_MASK;
@@ -1755,8 +1751,6 @@ carp_set_ifp(struct carp_softc *sc, stru
 
 rm_lh:
        hook_disestablish(ifp0->if_linkstatehooks, sc->lh_cookie);
-rm_dh:
-       hook_disestablish(ifp0->if_detachhooks, sc->dh_cookie);
 
        return (error);
 }

Reply via email to