Index: net/if.c =================================================================== RCS file: /cvs/src/sys/net/if.c,v retrieving revision 1.537 diff -u -p -r1.537 if.c --- net/if.c 10 Jan 2018 23:50:39 -0000 1.537 +++ net/if.c 12 Jan 2018 01:50:44 -0000 @@ -1005,11 +1005,6 @@ if_deactivate(struct ifnet *ifp) */ dohooks(ifp->if_detachhooks, HOOK_REMOVE | HOOK_FREE); -#if NCARP > 0 - /* Remove the interface from any carp group it is a part of. */ - if (ifp->if_type != IFT_CARP && !SRPL_EMPTY_LOCKED(&ifp->if_carp)) - carp_ifdetach(ifp); -#endif NET_UNLOCK(); } Index: netinet/ip_carp.c =================================================================== RCS file: /cvs/src/sys/netinet/ip_carp.c,v retrieving revision 1.325 diff -u -p -r1.325 ip_carp.c --- netinet/ip_carp.c 12 Jan 2018 00:36:13 -0000 1.325 +++ netinet/ip_carp.c 12 Jan 2018 01:50:44 -0000 @@ -133,6 +133,7 @@ struct carp_softc { #define sc_carpdev sc_ac.ac_if.if_carpdev void *ah_cookie; void *lh_cookie; + void *dh_cookie; struct ip_moptions sc_imo; #ifdef INET6 struct ip6_moptions sc_im6o; @@ -215,7 +216,7 @@ int carp_proto_input_if(struct ifnet *, int carp6_proto_input_if(struct ifnet *, struct mbuf **, int *, int); #endif void carpattach(int); -void carpdetach(struct carp_softc *); +void carpdetach(void *); int carp_prepare_ad(struct mbuf *, struct carp_vhost_entry *, struct carp_header *); void carp_send_ad_all(void); @@ -901,8 +902,9 @@ carp_del_all_timeouts(struct carp_softc } void -carpdetach(struct carp_softc *sc) +carpdetach(void *arg) { + struct carp_softc *sc = arg; struct ifnet *ifp0; struct srpl *cif; @@ -929,26 +931,13 @@ carpdetach(struct carp_softc *sc) /* Restore previous input handler. */ if_ih_remove(ifp0, carp_input, NULL); - if (sc->lh_cookie != NULL) - hook_disestablish(ifp0->if_linkstatehooks, sc->lh_cookie); - SRPL_REMOVE_LOCKED(&carp_sc_rc, cif, sc, carp_softc, sc_list); if (SRPL_EMPTY_LOCKED(cif)) ifpromisc(ifp0, 0); sc->sc_carpdev = NULL; -} - -/* Detach an interface from the carp. */ -void -carp_ifdetach(struct ifnet *ifp0) -{ - struct carp_softc *sc, *nextsc; - struct srpl *cif = &ifp0->if_carp; - KERNEL_ASSERT_LOCKED(); /* touching if_carp */ - - SRPL_FOREACH_SAFE_LOCKED(sc, cif, sc_list, nextsc) - carpdetach(sc); + hook_disestablish(ifp0->if_linkstatehooks, sc->lh_cookie); + hook_disestablish(ifp0->if_detachhooks, sc->dh_cookie); } void @@ -1697,13 +1686,27 @@ 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; + } + cif = &ifp0->if_carp; if (SRPL_EMPTY_LOCKED(cif)) { if ((error = ifpromisc(ifp0, 1))) - return (error); + goto rm_lh; - } else if (carp_check_dup_vhids(sc, cif, NULL)) - return (EINVAL); + } else if (carp_check_dup_vhids(sc, cif, NULL)) { + error = EINVAL; + goto rm_lh; + } /* detach from old interface */ if (sc->sc_carpdev != NULL) @@ -1744,15 +1747,19 @@ carp_set_ifp(struct carp_softc *sc, stru sc->sc_if.if_flags |= IFF_UP; carp_set_enaddr(sc); - sc->lh_cookie = hook_establish(ifp0->if_linkstatehooks, 1, - carp_carpdev_state, ifp0); - /* Change input handler of the physical interface. */ if_ih_insert(ifp0, carp_input, NULL); carp_carpdev_state(ifp0); return (0); + +rm_lh: + hook_disestablish(ifp0->if_linkstatehooks, sc->lh_cookie); +rm_dh: + hook_disestablish(ifp0->if_detachhooks, sc->dh_cookie); + + return (error); } void Index: netinet/ip_carp.h =================================================================== RCS file: /cvs/src/sys/netinet/ip_carp.h,v retrieving revision 1.45 diff -u -p -r1.45 ip_carp.h --- netinet/ip_carp.h 10 Jan 2018 23:50:39 -0000 1.45 +++ netinet/ip_carp.h 12 Jan 2018 01:50:44 -0000 @@ -193,7 +193,6 @@ carpstat_inc(enum carpstat_counters c) counters_inc(carpcounters, c); } -void carp_ifdetach (struct ifnet *); int carp_proto_input(struct mbuf **, int *, int, int); void carp_carpdev_state(void *); void carp_group_demote_adj(struct ifnet *, int, char *);