From owner-svn-src-all@FreeBSD.ORG Sat Sep 11 22:02:36 2010 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 738331065670; Sat, 11 Sep 2010 22:02:36 +0000 (UTC) (envelope-from will@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 605E18FC08; Sat, 11 Sep 2010 22:02:36 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o8BM2aOE046743; Sat, 11 Sep 2010 22:02:36 GMT (envelope-from will@svn.freebsd.org) Received: (from will@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o8BM2aJL046730; Sat, 11 Sep 2010 22:02:36 GMT (envelope-from will@svn.freebsd.org) Message-Id: <201009112202.o8BM2aJL046730@svn.freebsd.org> From: Will Andrews Date: Sat, 11 Sep 2010 22:02:36 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r212482 - in stable/8/sys: modules modules/if_carp net netinet netinet6 X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 11 Sep 2010 22:02:36 -0000 Author: will Date: Sat Sep 11 22:02:36 2010 New Revision: 212482 URL: http://svn.freebsd.org/changeset/base/212482 Log: MFC r211157, r211193, r212265, r212266: make it possible to load carp(4) as a kld using function pointer hooks and {pf_,ip,ip6}proto_{un,}register(). Reviewed by: bz Approved by: ken (mentor) Added: stable/8/sys/modules/if_carp/ - copied from r211157, head/sys/modules/if_carp/ Modified: stable/8/sys/modules/Makefile stable/8/sys/net/if.c stable/8/sys/net/if_bridge.c stable/8/sys/net/if_ethersubr.c stable/8/sys/netinet/if_ether.c stable/8/sys/netinet/in.c stable/8/sys/netinet/in_proto.c stable/8/sys/netinet/ip_carp.c stable/8/sys/netinet/ip_carp.h stable/8/sys/netinet/ip_input.c stable/8/sys/netinet6/in6_proto.c stable/8/sys/netinet6/nd6_nbr.c Directory Properties: stable/8/sys/ (props changed) stable/8/sys/amd64/include/xen/ (props changed) stable/8/sys/cddl/contrib/opensolaris/ (props changed) stable/8/sys/contrib/dev/acpica/ (props changed) stable/8/sys/contrib/pf/ (props changed) stable/8/sys/dev/xen/xenpci/ (props changed) Modified: stable/8/sys/modules/Makefile ============================================================================== --- stable/8/sys/modules/Makefile Sat Sep 11 21:52:40 2010 (r212481) +++ stable/8/sys/modules/Makefile Sat Sep 11 22:02:36 2010 (r212482) @@ -111,6 +111,7 @@ SUBDIR= ${_3dfx} \ ${_ida} \ ${_ie} \ if_bridge \ + if_carp \ if_disc \ if_edsc \ if_ef \ Modified: stable/8/sys/net/if.c ============================================================================== --- stable/8/sys/net/if.c Sat Sep 11 21:52:40 2010 (r212481) +++ stable/8/sys/net/if.c Sat Sep 11 22:02:36 2010 (r212482) @@ -33,7 +33,6 @@ #include "opt_compat.h" #include "opt_inet6.h" #include "opt_inet.h" -#include "opt_carp.h" #include "opt_ddb.h" #include @@ -81,6 +80,7 @@ /*XXX*/ #include #include +#include #ifdef INET6 #include #include @@ -89,11 +89,6 @@ #ifdef INET #include #endif -#if defined(INET) || defined(INET6) -#ifdef DEV_CARP -#include -#endif -#endif #include @@ -128,6 +123,22 @@ SX_SYSINIT(ifdescr_sx, &ifdescr_sx, "ifn void (*bstp_linkstate_p)(struct ifnet *ifp, int state); void (*ng_ether_link_state_p)(struct ifnet *ifp, int state); void (*lagg_linkstate_p)(struct ifnet *ifp, int state); +/* These are external hooks for CARP. */ +void (*carp_linkstate_p)(struct ifnet *ifp); +#if defined(INET) || defined(INET6) +struct ifnet *(*carp_forus_p)(struct ifnet *ifp, u_char *dhost); +int (*carp_output_p)(struct ifnet *ifp, struct mbuf *m, + struct sockaddr *sa, struct rtentry *rt); +#endif +#ifdef INET +int (*carp_iamatch_p)(struct ifnet *, struct in_ifaddr *, struct in_addr *, + u_int8_t **); +#endif +#ifdef INET6 +struct ifaddr *(*carp_iamatch6_p)(struct ifnet *ifp, struct in6_addr *taddr6); +caddr_t (*carp_macmatch6_p)(struct ifnet *ifp, struct mbuf *m, + const struct in6_addr *taddr); +#endif struct mbuf *(*tbr_dequeue_ptr)(struct ifaltq *, int) = NULL; @@ -1851,12 +1862,8 @@ if_unroute(struct ifnet *ifp, int flag, pfctlinput(PRC_IFDOWN, ifa->ifa_addr); ifp->if_qflush(ifp); -#if defined(INET) || defined(INET6) -#ifdef DEV_CARP if (ifp->if_carp) - carp_carpdev_state(ifp->if_carp); -#endif -#endif + (*carp_linkstate_p)(ifp); rt_ifmsg(ifp); } @@ -1877,12 +1884,8 @@ if_route(struct ifnet *ifp, int flag, in TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) if (fam == PF_UNSPEC || (fam == ifa->ifa_addr->sa_family)) pfctlinput(PRC_IFUP, ifa->ifa_addr); -#if defined(INET) || defined(INET6) -#ifdef DEV_CARP if (ifp->if_carp) - carp_carpdev_state(ifp->if_carp); -#endif -#endif + (*carp_linkstate_p)(ifp); rt_ifmsg(ifp); #ifdef INET6 in6_if_up(ifp); @@ -1925,12 +1928,8 @@ do_link_state_change(void *arg, int pend if ((ifp->if_type == IFT_ETHER || ifp->if_type == IFT_L2VLAN) && IFP2AC(ifp)->ac_netgraph != NULL) (*ng_ether_link_state_p)(ifp, link_state); -#if defined(INET) || defined(INET6) -#ifdef DEV_CARP if (ifp->if_carp) - carp_carpdev_state(ifp->if_carp); -#endif -#endif + (*carp_linkstate_p)(ifp); if (ifp->if_bridge) { KASSERT(bstp_linkstate_p != NULL,("if_bridge bstp not loaded!")); (*bstp_linkstate_p)(ifp, link_state); Modified: stable/8/sys/net/if_bridge.c ============================================================================== --- stable/8/sys/net/if_bridge.c Sat Sep 11 21:52:40 2010 (r212481) +++ stable/8/sys/net/if_bridge.c Sat Sep 11 22:02:36 2010 (r212482) @@ -79,7 +79,6 @@ __FBSDID("$FreeBSD$"); #include "opt_inet.h" #include "opt_inet6.h" -#include "opt_carp.h" #include #include @@ -121,10 +120,8 @@ __FBSDID("$FreeBSD$"); #include #endif #if defined(INET) || defined(INET6) -#ifdef DEV_CARP #include #endif -#endif #include #include /* for struct arpcom */ #include @@ -2252,13 +2249,13 @@ bridge_input(struct ifnet *ifp, struct m return (m); } -#if (defined(INET) || defined(INET6)) && defined(DEV_CARP) +#if (defined(INET) || defined(INET6)) # define OR_CARP_CHECK_WE_ARE_DST(iface) \ || ((iface)->if_carp \ - && carp_forus((iface)->if_carp, eh->ether_dhost)) + && (*carp_forus_p)((iface), eh->ether_dhost)) # define OR_CARP_CHECK_WE_ARE_SRC(iface) \ || ((iface)->if_carp \ - && carp_forus((iface)->if_carp, eh->ether_shost)) + && (*carp_forus_p)((iface), eh->ether_shost)) #else # define OR_CARP_CHECK_WE_ARE_DST(iface) # define OR_CARP_CHECK_WE_ARE_SRC(iface) Modified: stable/8/sys/net/if_ethersubr.c ============================================================================== --- stable/8/sys/net/if_ethersubr.c Sat Sep 11 21:52:40 2010 (r212481) +++ stable/8/sys/net/if_ethersubr.c Sat Sep 11 22:02:36 2010 (r212482) @@ -35,7 +35,6 @@ #include "opt_inet6.h" #include "opt_ipx.h" #include "opt_netgraph.h" -#include "opt_carp.h" #include "opt_mbuf_profiling.h" #include @@ -70,6 +69,7 @@ #include #include #include +#include #include #include #include @@ -78,12 +78,6 @@ #include #endif -#if defined(INET) || defined(INET6) -#ifdef DEV_CARP -#include -#endif -#endif - #ifdef IPX #include #include @@ -402,12 +396,10 @@ ether_output(struct ifnet *ifp, struct m } #if defined(INET) || defined(INET6) -#ifdef DEV_CARP if (ifp->if_carp && - (error = carp_output(ifp, m, dst, NULL))) + (error = (*carp_output_p)(ifp, m, dst, NULL))) goto bad; #endif -#endif /* Handle ng_ether(4) processing, if any */ if (IFP2AC(ifp)->ac_netgraph != NULL) { @@ -727,7 +719,6 @@ ether_input(struct ifnet *ifp, struct mb } #if defined(INET) || defined(INET6) -#ifdef DEV_CARP /* * Clear M_PROMISC on frame so that carp(4) will see it when the * mbuf flows up to Layer 3. @@ -738,11 +729,10 @@ ether_input(struct ifnet *ifp, struct mb * TODO: Maintain a hash table of ethernet addresses other than * ether_dhost which may be active on this ifp. */ - if (ifp->if_carp && carp_forus(ifp->if_carp, eh->ether_dhost)) { + if (ifp->if_carp && (*carp_forus_p)(ifp, eh->ether_dhost)) { m->m_flags &= ~M_PROMISC; } else #endif -#endif { /* * If the frame received was not for our MAC address, set the Modified: stable/8/sys/netinet/if_ether.c ============================================================================== --- stable/8/sys/netinet/if_ether.c Sat Sep 11 21:52:40 2010 (r212481) +++ stable/8/sys/netinet/if_ether.c Sat Sep 11 22:02:36 2010 (r212482) @@ -39,7 +39,6 @@ __FBSDID("$FreeBSD$"); #include "opt_inet.h" -#include "opt_carp.h" #include #include @@ -65,14 +64,13 @@ __FBSDID("$FreeBSD$"); #include #include #include +#if defined(INET) || defined(INET6) +#include +#endif #include #include -#ifdef DEV_CARP -#include -#endif - #include #define SIN(s) ((struct sockaddr_in *)s) @@ -494,9 +492,7 @@ in_arpinput(struct mbuf *m) int op, flags; int req_len; int bridged = 0, is_bridge = 0; -#ifdef DEV_CARP int carp_match = 0; -#endif struct sockaddr_in sin; sin.sin_len = sizeof(struct sockaddr_in); sin.sin_family = AF_INET; @@ -539,16 +535,14 @@ in_arpinput(struct mbuf *m) IN_IFADDR_RUNLOCK(); goto match; } -#ifdef DEV_CARP if (ifp->if_carp != NULL && - carp_iamatch(ifp->if_carp, ia, &isaddr, &enaddr) && + (*carp_iamatch_p)(ifp, ia, &isaddr, &enaddr) && itaddr.s_addr == ia->ia_addr.sin_addr.s_addr) { carp_match = 1; ifa_ref(&ia->ia_ifa); IN_IFADDR_RUNLOCK(); goto match; } -#endif } LIST_FOREACH(ia, INADDR_HASH(isaddr.s_addr), ia_hash) if (((bridged && ia->ia_ifp->if_bridge != NULL) || @@ -648,11 +642,7 @@ match: IF_AFDATA_UNLOCK(ifp); if (la != NULL) { /* the following is not an error when doing bridging */ - if (!bridged && la->lle_tbl->llt_ifp != ifp -#ifdef DEV_CARP - && (ifp->if_type != IFT_CARP || !carp_match) -#endif - ) { + if (!bridged && la->lle_tbl->llt_ifp != ifp && !carp_match) { if (log_arp_wrong_iface) log(LOG_ERR, "arp: %s is on %s " "but got reply from %*D on %s\n", Modified: stable/8/sys/netinet/in.c ============================================================================== --- stable/8/sys/netinet/in.c Sat Sep 11 21:52:40 2010 (r212481) +++ stable/8/sys/netinet/in.c Sat Sep 11 22:02:36 2010 (r212482) @@ -33,7 +33,6 @@ #include __FBSDID("$FreeBSD$"); -#include "opt_carp.h" #include "opt_mpath.h" #include @@ -891,13 +890,11 @@ in_ifinit(struct ifnet *ifp, struct in_i ia->ia_net = i & ia->ia_netmask; ia->ia_subnet = i & ia->ia_subnetmask; in_socktrim(&ia->ia_sockmask); -#ifdef DEV_CARP /* * XXX: carp(4) does not have interface route */ if (ifp->if_type == IFT_CARP) return (0); -#endif /* * Add route for the network. */ @@ -1153,12 +1150,12 @@ in_scrubprefix(struct in_ifaddr *target) * the route itself to it. Make sure that routing daemons * get a heads-up. * - * XXX: a special case for carp(4) interface + * XXX: a special case for carp(4) interface - this should + * be more generally specified as an interface that + * doesn't support such action. */ if ((ia->ia_flags & IFA_ROUTE) == 0 -#ifdef DEV_CARP && (ia->ia_ifp->if_type != IFT_CARP) -#endif ) { IN_IFADDR_RUNLOCK(); rtinit(&(target->ia_ifa), (int)RTM_DELETE, Modified: stable/8/sys/netinet/in_proto.c ============================================================================== --- stable/8/sys/netinet/in_proto.c Sat Sep 11 21:52:40 2010 (r212481) +++ stable/8/sys/netinet/in_proto.c Sat Sep 11 22:02:36 2010 (r212482) @@ -37,7 +37,6 @@ __FBSDID("$FreeBSD$"); #include "opt_ipsec.h" #include "opt_inet6.h" #include "opt_pf.h" -#include "opt_carp.h" #include "opt_sctp.h" #include "opt_mpath.h" @@ -94,10 +93,6 @@ static struct pr_usrreqs nousrreqs; #include #endif -#ifdef DEV_CARP -#include -#endif - extern struct domain inetdomain; /* Spacer for loadable protocols. */ @@ -330,18 +325,6 @@ struct protosw inetsw[] = { .pr_usrreqs = &rip_usrreqs }, #endif /* DEV_PFSYNC */ -#ifdef DEV_CARP -{ - .pr_type = SOCK_RAW, - .pr_domain = &inetdomain, - .pr_protocol = IPPROTO_CARP, - .pr_flags = PR_ATOMIC|PR_ADDR, - .pr_input = carp_input, - .pr_output = (pr_output_t*)rip_output, - .pr_ctloutput = rip_ctloutput, - .pr_usrreqs = &rip_usrreqs -}, -#endif /* DEV_CARP */ /* Spacer n-times for loadable protocols. */ IPPROTOSPACER, IPPROTOSPACER, @@ -413,6 +396,3 @@ SYSCTL_NODE(_net_inet, IPPROTO_RAW, raw, #ifdef DEV_PFSYNC SYSCTL_NODE(_net_inet, IPPROTO_PFSYNC, pfsync, CTLFLAG_RW, 0, "PFSYNC"); #endif -#ifdef DEV_CARP -SYSCTL_NODE(_net_inet, IPPROTO_CARP, carp, CTLFLAG_RW, 0, "CARP"); -#endif Modified: stable/8/sys/netinet/ip_carp.c ============================================================================== --- stable/8/sys/netinet/ip_carp.c Sat Sep 11 21:52:40 2010 (r212481) +++ stable/8/sys/netinet/ip_carp.c Sat Sep 11 22:02:36 2010 (r212482) @@ -27,7 +27,6 @@ #include __FBSDID("$FreeBSD$"); -#include "opt_carp.h" #include "opt_bpf.h" #include "opt_inet.h" #include "opt_inet6.h" @@ -44,6 +43,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -79,6 +79,7 @@ __FBSDID("$FreeBSD$"); #ifdef INET6 #include #include +#include #include #include #include @@ -136,6 +137,7 @@ struct carp_softc { int carp_suppress_preempt = 0; int carp_opts[CARPCTL_MAXID] = { 0, 1, 0, 1, 0, 0 }; /* XXX for now */ +SYSCTL_NODE(_net_inet, IPPROTO_CARP, carp, CTLFLAG_RW, 0, "CARP"); SYSCTL_INT(_net_inet_carp, CARPCTL_ALLOW, allow, CTLFLAG_RW, &carp_opts[CARPCTL_ALLOW], 0, "Accept incoming CARP packets"); SYSCTL_INT(_net_inet_carp, CARPCTL_PREEMPT, preempt, CTLFLAG_RW, @@ -160,6 +162,10 @@ struct carp_if { struct mtx vhif_mtx; }; +#define CARP_INET 0 +#define CARP_INET6 1 +static int proto_reg[] = {-1, -1}; + /* Get carp_if from softc. Valid after carp_set_addr{,6}. */ #define SC2CIF(sc) ((struct carp_if *)(sc)->sc_carpdev->if_carp) @@ -1146,14 +1152,15 @@ carp_addrcount(struct carp_if *cif, stru } int -carp_iamatch(void *v, struct in_ifaddr *ia, +carp_iamatch(struct ifnet *ifp, struct in_ifaddr *ia, struct in_addr *isaddr, u_int8_t **enaddr) { - struct carp_if *cif = v; + struct carp_if *cif; struct carp_softc *vh; int index, count = 0; struct ifaddr *ifa; + cif = ifp->if_carp; CARP_LOCK(cif); if (carp_opts[CARPCTL_ARPBALANCE]) { @@ -1222,12 +1229,13 @@ carp_iamatch(void *v, struct in_ifaddr * #ifdef INET6 struct ifaddr * -carp_iamatch6(void *v, struct in6_addr *taddr) +carp_iamatch6(struct ifnet *ifp, struct in6_addr *taddr) { - struct carp_if *cif = v; + struct carp_if *cif; struct carp_softc *vh; struct ifaddr *ifa; + cif = ifp->if_carp; CARP_LOCK(cif); TAILQ_FOREACH(vh, &cif->vhif_vrs, sc_list) { IF_ADDR_LOCK(SC2IFP(vh)); @@ -1250,14 +1258,15 @@ carp_iamatch6(void *v, struct in6_addr * return (NULL); } -void * -carp_macmatch6(void *v, struct mbuf *m, const struct in6_addr *taddr) +caddr_t +carp_macmatch6(struct ifnet *ifp, struct mbuf *m, const struct in6_addr *taddr) { struct m_tag *mtag; - struct carp_if *cif = v; + struct carp_if *cif; struct carp_softc *sc; struct ifaddr *ifa; + cif = ifp->if_carp; CARP_LOCK(cif); TAILQ_FOREACH(sc, &cif->vhif_vrs, sc_list) { IF_ADDR_LOCK(SC2IFP(sc)); @@ -1293,15 +1302,16 @@ carp_macmatch6(void *v, struct mbuf *m, #endif struct ifnet * -carp_forus(void *v, void *dhost) +carp_forus(struct ifnet *ifp, u_char *dhost) { - struct carp_if *cif = v; + struct carp_if *cif; struct carp_softc *vh; u_int8_t *ena = dhost; if (ena[0] || ena[1] || ena[2] != 0x5e || ena[3] || ena[4] != 1) return (NULL); + cif = ifp->if_carp; CARP_LOCK(cif); TAILQ_FOREACH(vh, &cif->vhif_vrs, sc_list) if ((SC2IFP(vh)->if_flags & IFF_UP) && @@ -2209,10 +2219,11 @@ carp_set_state(struct carp_softc *sc, in } void -carp_carpdev_state(void *v) +carp_carpdev_state(struct ifnet *ifp) { - struct carp_if *cif = v; + struct carp_if *cif; + cif = ifp->if_carp; CARP_LOCK(cif); carp_carpdev_state_locked(cif); CARP_UNLOCK(cif); @@ -2263,24 +2274,136 @@ carp_sc_state_locked(struct carp_softc * return; } +#ifdef INET +extern struct domain inetdomain; +static struct protosw in_carp_protosw = { + .pr_type = SOCK_RAW, + .pr_domain = &inetdomain, + .pr_protocol = IPPROTO_CARP, + .pr_flags = PR_ATOMIC|PR_ADDR, + .pr_input = carp_input, + .pr_output = (pr_output_t *)rip_output, + .pr_ctloutput = rip_ctloutput, + .pr_usrreqs = &rip_usrreqs +}; +#endif + +#ifdef INET6 +extern struct domain inet6domain; +static struct ip6protosw in6_carp_protosw = { + .pr_type = SOCK_RAW, + .pr_domain = &inet6domain, + .pr_protocol = IPPROTO_CARP, + .pr_flags = PR_ATOMIC|PR_ADDR, + .pr_input = carp6_input, + .pr_output = rip6_output, + .pr_ctloutput = rip6_ctloutput, + .pr_usrreqs = &rip6_usrreqs +}; +#endif + +static void +carp_mod_cleanup(void) +{ + + if (if_detach_event_tag == NULL) + return; + EVENTHANDLER_DEREGISTER(ifnet_departure_event, if_detach_event_tag); + if_clone_detach(&carp_cloner); +#ifdef INET + if (proto_reg[CARP_INET] == 0) { + (void)ipproto_unregister(IPPROTO_CARP); + pf_proto_unregister(PF_INET, IPPROTO_CARP, SOCK_RAW); + proto_reg[CARP_INET] = -1; + } + carp_iamatch_p = NULL; +#endif +#ifdef INET6 + if (proto_reg[CARP_INET6] == 0) { + (void)ip6proto_unregister(IPPROTO_CARP); + pf_proto_unregister(PF_INET6, IPPROTO_CARP, SOCK_RAW); + proto_reg[CARP_INET6] = -1; + } + carp_iamatch6_p = NULL; + carp_macmatch6_p = NULL; +#endif + carp_linkstate_p = NULL; + carp_forus_p = NULL; + carp_output_p = NULL; + mtx_destroy(&carp_mtx); +} + +static int +carp_mod_load(void) +{ + int err; + + if_detach_event_tag = EVENTHANDLER_REGISTER(ifnet_departure_event, + carp_ifdetach, NULL, EVENTHANDLER_PRI_ANY); + if (if_detach_event_tag == NULL) + return (ENOMEM); + mtx_init(&carp_mtx, "carp_mtx", NULL, MTX_DEF); + LIST_INIT(&carpif_list); + if_clone_attach(&carp_cloner); + carp_linkstate_p = carp_carpdev_state; + carp_forus_p = carp_forus; + carp_output_p = carp_output; +#ifdef INET6 + carp_iamatch6_p = carp_iamatch6; + carp_macmatch6_p = carp_macmatch6; + proto_reg[CARP_INET6] = pf_proto_register(PF_INET6, + (struct protosw *)&in6_carp_protosw); + if (proto_reg[CARP_INET6] != 0) { + printf("carp: error %d attaching to PF_INET6\n", + proto_reg[CARP_INET6]); + carp_mod_cleanup(); + return (EINVAL); + } + err = ip6proto_register(IPPROTO_CARP); + if (err) { + printf("carp: error %d registering with INET6\n", err); + carp_mod_cleanup(); + return (EINVAL); + } +#endif +#ifdef INET + carp_iamatch_p = carp_iamatch; + proto_reg[CARP_INET] = pf_proto_register(PF_INET, &in_carp_protosw); + if (proto_reg[CARP_INET] != 0) { + printf("carp: error %d attaching to PF_INET\n", + proto_reg[CARP_INET]); + carp_mod_cleanup(); + return (EINVAL); + } + err = ipproto_register(IPPROTO_CARP); + if (err) { + printf("carp: error %d registering with INET\n", err); + carp_mod_cleanup(); + return (EINVAL); + } +#endif + return 0; +} + static int carp_modevent(module_t mod, int type, void *data) { switch (type) { case MOD_LOAD: - if_detach_event_tag = EVENTHANDLER_REGISTER(ifnet_departure_event, - carp_ifdetach, NULL, EVENTHANDLER_PRI_ANY); - if (if_detach_event_tag == NULL) - return (ENOMEM); - mtx_init(&carp_mtx, "carp_mtx", NULL, MTX_DEF); - LIST_INIT(&carpif_list); - if_clone_attach(&carp_cloner); - break; - + return carp_mod_load(); + /* NOTREACHED */ case MOD_UNLOAD: - EVENTHANDLER_DEREGISTER(ifnet_departure_event, if_detach_event_tag); - if_clone_detach(&carp_cloner); - mtx_destroy(&carp_mtx); + /* + * XXX: For now, disallow module unloading by default due to + * a race condition where a thread may dereference one of the + * function pointer hooks after the module has been + * unloaded, during processing of a packet, causing a panic. + */ +#ifdef CARPMOD_CAN_UNLOAD + carp_mod_cleanup(); +#else + return (EBUSY); +#endif break; default: @@ -2296,4 +2419,4 @@ static moduledata_t carp_mod = { 0 }; -DECLARE_MODULE(carp, carp_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); +DECLARE_MODULE(carp, carp_mod, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY); Modified: stable/8/sys/netinet/ip_carp.h ============================================================================== --- stable/8/sys/netinet/ip_carp.h Sat Sep 11 21:52:40 2010 (r212481) +++ stable/8/sys/netinet/ip_carp.h Sat Sep 11 22:02:36 2010 (r212482) @@ -157,15 +157,35 @@ struct carpreq { } #ifdef _KERNEL -void carp_carpdev_state(void *); +void carp_carpdev_state(struct ifnet *); void carp_input (struct mbuf *, int); int carp6_input (struct mbuf **, int *, int); int carp_output (struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); -int carp_iamatch (void *, struct in_ifaddr *, struct in_addr *, +int carp_iamatch (struct ifnet *, struct in_ifaddr *, struct in_addr *, u_int8_t **); -struct ifaddr *carp_iamatch6(void *, struct in6_addr *); -void *carp_macmatch6(void *, struct mbuf *, const struct in6_addr *); -struct ifnet *carp_forus (void *, void *); +struct ifaddr *carp_iamatch6(struct ifnet *, struct in6_addr *); +caddr_t carp_macmatch6(struct ifnet *, struct mbuf *, const struct in6_addr *); +struct ifnet *carp_forus (struct ifnet *, u_char *); + +/* These are external networking stack hooks for CARP */ +/* net/if.c */ +extern void (*carp_linkstate_p)(struct ifnet *); +/* net/if_bridge.c net/if_ethersubr.c */ +extern struct ifnet *(*carp_forus_p)(struct ifnet *, u_char *); +/* net/if_ethersubr.c */ +extern int (*carp_output_p)(struct ifnet *, struct mbuf *, + struct sockaddr *, struct rtentry *); +#ifdef INET +/* netinet/if_ether.c */ +extern int (*carp_iamatch_p)(struct ifnet *, struct in_ifaddr *, + struct in_addr *, u_int8_t **); +#endif +#ifdef INET6 +/* netinet6/nd6_nbr.c */ +extern struct ifaddr *(*carp_iamatch6_p)(struct ifnet *, struct in6_addr *); +extern caddr_t (*carp_macmatch6_p)(struct ifnet *, struct mbuf *, + const struct in6_addr *); +#endif #endif #endif /* _IP_CARP_H */ Modified: stable/8/sys/netinet/ip_input.c ============================================================================== --- stable/8/sys/netinet/ip_input.c Sat Sep 11 21:52:40 2010 (r212481) +++ stable/8/sys/netinet/ip_input.c Sat Sep 11 22:02:36 2010 (r212482) @@ -37,7 +37,6 @@ __FBSDID("$FreeBSD$"); #include "opt_ipstealth.h" #include "opt_ipsec.h" #include "opt_route.h" -#include "opt_carp.h" #include #include @@ -74,9 +73,7 @@ __FBSDID("$FreeBSD$"); #include #include #include -#ifdef DEV_CARP #include -#endif #ifdef IPSEC #include #endif /* IPSEC */ @@ -606,10 +603,7 @@ passin: */ checkif = V_ip_checkinterface && (V_ipforwarding == 0) && ifp != NULL && ((ifp->if_flags & IFF_LOOPBACK) == 0) && -#ifdef DEV_CARP - !ifp->if_carp && -#endif - (dchg == 0); + ifp->if_carp == NULL && (dchg == 0); /* * Check for exact addresses in the hash bucket. Modified: stable/8/sys/netinet6/in6_proto.c ============================================================================== --- stable/8/sys/netinet6/in6_proto.c Sat Sep 11 21:52:40 2010 (r212481) +++ stable/8/sys/netinet6/in6_proto.c Sat Sep 11 22:02:36 2010 (r212482) @@ -67,7 +67,6 @@ __FBSDID("$FreeBSD$"); #include "opt_inet6.h" #include "opt_ipsec.h" #include "opt_ipstealth.h" -#include "opt_carp.h" #include "opt_sctp.h" #include "opt_mpath.h" @@ -111,10 +110,6 @@ __FBSDID("$FreeBSD$"); #include #include -#ifdef DEV_CARP -#include -#endif - #ifdef SCTP #include #include @@ -331,18 +326,6 @@ struct ip6protosw inet6sw[] = { .pr_ctloutput = rip6_ctloutput, .pr_usrreqs = &rip6_usrreqs }, -#ifdef DEV_CARP -{ - .pr_type = SOCK_RAW, - .pr_domain = &inet6domain, - .pr_protocol = IPPROTO_CARP, - .pr_flags = PR_ATOMIC|PR_ADDR, - .pr_input = carp6_input, - .pr_output = rip6_output, - .pr_ctloutput = rip6_ctloutput, - .pr_usrreqs = &rip6_usrreqs -}, -#endif /* DEV_CARP */ /* Spacer n-times for loadable protocols. */ IP6PROTOSPACER, IP6PROTOSPACER, Modified: stable/8/sys/netinet6/nd6_nbr.c ============================================================================== --- stable/8/sys/netinet6/nd6_nbr.c Sat Sep 11 21:52:40 2010 (r212481) +++ stable/8/sys/netinet6/nd6_nbr.c Sat Sep 11 22:02:36 2010 (r212482) @@ -35,7 +35,6 @@ __FBSDID("$FreeBSD$"); #include "opt_inet.h" #include "opt_inet6.h" #include "opt_ipsec.h" -#include "opt_carp.h" #include "opt_mpath.h" #include @@ -73,10 +72,7 @@ __FBSDID("$FreeBSD$"); #include #include #include - -#ifdef DEV_CARP #include -#endif #define SDL(s) ((struct sockaddr_dl *)s) @@ -222,14 +218,10 @@ nd6_ns_input(struct mbuf *m, int off, in * (3) "tentative" address on which DAD is being performed. */ /* (1) and (3) check. */ -#ifdef DEV_CARP if (ifp->if_carp) - ifa = carp_iamatch6(ifp->if_carp, &taddr6); + ifa = (*carp_iamatch6_p)(ifp, &taddr6); if (ifa == NULL) ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6); -#else - ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6); -#endif /* (2) check. */ if (ifa == NULL) { @@ -1029,14 +1021,10 @@ nd6_na_output(struct ifnet *ifp, const s * my address) use lladdr configured for the interface. */ if (sdl0 == NULL) { -#ifdef DEV_CARP if (ifp->if_carp) - mac = carp_macmatch6(ifp->if_carp, m, taddr6); + mac = (*carp_macmatch6_p)(ifp, m, taddr6); if (mac == NULL) mac = nd6_ifptomac(ifp); -#else - mac = nd6_ifptomac(ifp); -#endif } else if (sdl0->sa_family == AF_LINK) { struct sockaddr_dl *sdl; sdl = (struct sockaddr_dl *)sdl0;