From nobody Thu Mar 12 16:37:36 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4fWtZY2qZPz6Vc2V for ; Thu, 12 Mar 2026 16:37:41 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R12" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4fWtZY2S8xz3DWp for ; Thu, 12 Mar 2026 16:37:41 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1773333461; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=bB5D2LwHyzRruaZmY+VaO/FXlVch2GdgL7zFq0UQ6pg=; b=Yr6cx0kh9FzBBMYlWH6kXbyy/rVoq+TKRrJ0ROkR088hqEnNGRAmdBo+g6qxp1B1aU5xzY /8W+gqFUILF/kv47/E11S/Vum1L8Y4VCwXv/8ZH/NIsKccgJZxuFPaX3SXGL+B1NJzo6qq nP+1Nq26BUARChD/ycdlgjfKTkOkwIZpUHhRib0D9ukyh0VhDsrKYYlp0wIMTVZVtzjv44 ZNP5QneppckKxMTGGWlARsVYjjdcVyZKWdAdL1V4K3KUz0UcMUZZ9lh84X5jGgEzZkond6 IChDzAlEU9zIo/aHytDpAz32CqFlmtz0UGgaCPgh+Fl8HDzNmt3h6uMJfPyuvw== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1773333461; a=rsa-sha256; cv=none; b=G99IEZTguVzr/Un8UXaQgvdp8f51fxFAN1jRqmOx4cvknz12F5uk4385huCzlrr1YIMHOJ Ir7J/8CXhU8pPCiIQdi7EaCBglR2+cMMCJeVIInnkev+rvvqDRKd13gihZXvezPMKb94r3 TVO6Fxuz8QAQTQrDaCXnGdaTcvXoTgFzYfUauH7WTBUOYrTRjlHaOocdq1QJbZgTOxVS/k nM+f4c8Icio1CxW26VZtjFUwfvPOXFskgVAcjrdfD7IeVPnV5wRWyqioOEjMyT0GG7EN0O nAuIFGNrH5G2M7LT4E2aFdApTpisDpdReXnsuVIYLLnXTJfjZXJcyC/rrP4vXA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1773333461; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=bB5D2LwHyzRruaZmY+VaO/FXlVch2GdgL7zFq0UQ6pg=; b=H9jQLNrQmqV2kWfuWb/xFhOxmgz/aIr60+Drrakri+YzfvLsgn7Dx9IEYPlm8dD0/fKTAR OEHyeZbNLY2v4PyzWmIu58glFaZOmFQX4V7p61WZ4KT/2FB0DOAIJedRr98i5lGCDgL6JM vSlxGkNnhouGBpDqTMmtg7hDLREtWkzILCSGJ/GN3Mpya7twdwiARTrGg1ag1gfn/cnHeB 9TZ+vpww0s1p0le58KjPVA6b149GUsw10WcK85PxWuosITxKozxb8AqW23E/J/f5TTnIyY Qv1pMF185A2xaa2oY6qnngToiUIJodD2Ax88HVzMPhuLgX2AO9ZeBm1nvoZT/Q== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4fWtZY21fXztHH for ; Thu, 12 Mar 2026 16:37:41 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 43f2d by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Thu, 12 Mar 2026 16:37:36 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Gleb Smirnoff Subject: git: 72472e52e310 - main - carp: retire ioctl(2) API List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: glebius X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 72472e52e310ec348949a3a67d3fa17e33fb8e50 Auto-Submitted: auto-generated Date: Thu, 12 Mar 2026 16:37:36 +0000 Message-Id: <69b2ebd0.43f2d.56e7eb20@gitrepo.freebsd.org> The branch main has been updated by glebius: URL: https://cgit.FreeBSD.org/src/commit/?id=72472e52e310ec348949a3a67d3fa17e33fb8e50 commit 72472e52e310ec348949a3a67d3fa17e33fb8e50 Author: Gleb Smirnoff AuthorDate: 2026-03-12 16:30:46 +0000 Commit: Gleb Smirnoff CommitDate: 2026-03-12 16:37:26 +0000 carp: retire ioctl(2) API All supported stable branches use netlink(4) API to configure carp(4). The deleted code also has kernel stack leak vulnerability, that requires extra effort to fix. Reviewed by: pouria, kp Differential Revision: https://reviews.freebsd.org/D55804 --- sbin/ifconfig/carp.c | 9 +- share/man/man4/carp.4 | 12 +- sys/net/if.c | 10 -- sys/netinet/ip_carp.c | 437 ++++++++++++++------------------------------------ sys/netinet/ip_carp.h | 15 -- sys/sys/param.h | 2 +- 6 files changed, 133 insertions(+), 352 deletions(-) diff --git a/sbin/ifconfig/carp.c b/sbin/ifconfig/carp.c index 7c7398f92d48..f9737a9cb97c 100644 --- a/sbin/ifconfig/carp.c +++ b/sbin/ifconfig/carp.c @@ -156,8 +156,13 @@ setcarp_callback(if_ctx *ctx, void *arg __unused) if (carpr_vrrp_adv_inter != 0) carpr.carpr_vrrp_adv_inter = carpr_vrrp_adv_inter; - if (ifconfig_carp_set_info(lifh, ctx->ifname, &carpr)) - err(1, "SIOCSVH"); + if (ifconfig_carp_set_info(lifh, ctx->ifname, &carpr)) { + if (ifconfig_err_errtype(lifh) == OTHER) + err(1, "%s: %s", __func__, + strerror(ifconfig_err_errno(lifh))); + else + err(1, "%s: %d", __func__, ifconfig_err_errtype(lifh)); + } } static void diff --git a/share/man/man4/carp.4 b/share/man/man4/carp.4 index c972e0288791..4b0ece3b551f 100644 --- a/share/man/man4/carp.4 +++ b/share/man/man4/carp.4 @@ -24,7 +24,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd April 12, 2024 +.Dd March 11, 2026 .Dt CARP 4 .Os .Sh NAME @@ -71,10 +71,7 @@ and .Cm advskew are put inside CARP advertisements. These values can be configured using -.Xr ifconfig 8 , -or through the -.Dv SIOCSVH -.Xr ioctl 2 . +.Xr ifconfig 8 . .Pp CARP defaults to using multicast messages, but can be configured to unicast announcements to peers using the @@ -88,10 +85,7 @@ and Note that TTL verification is disabled if the peer address is not a multicast address. These values can be configured using -.Xr ifconfig 8 , -or through the -.Dv SIOCSPEER -.Xr ioctl 2 . +.Xr ifconfig 8 . .Pp .Xr carp 4 can be configured to use either the non-standard CARP protocol, or VRRPv3 (RFC 5798). diff --git a/sys/net/if.c b/sys/net/if.c index 5c4b1e17f77d..96da4da8c6c1 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -248,7 +248,6 @@ int (*carp_master_p)(struct ifaddr *); int (*carp_forus_p)(struct ifnet *ifp, u_char *dhost); int (*carp_output_p)(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *sa); -int (*carp_ioctl_p)(struct ifreq *, u_long, struct thread *); int (*carp_attach_p)(struct ifaddr *, int); void (*carp_detach_p)(struct ifaddr *, bool); #endif @@ -2923,15 +2922,6 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct thread *td) error = if_getgroupmembers(req); goto out_noref; } -#if defined(INET) || defined(INET6) - case SIOCSVH: - case SIOCGVH: - if (carp_ioctl_p == NULL) - error = EPROTONOSUPPORT; - else - error = (*carp_ioctl_p)(ifr, cmd, td); - goto out_noref; -#endif } ifp = ifunit_ref(ifr->ifr_name); diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c index 3fedbda6b57f..32823c6c4a87 100644 --- a/sys/netinet/ip_carp.c +++ b/sys/netinet/ip_carp.c @@ -160,23 +160,6 @@ struct carp_if { #define CIF_PROMISC 0x00000001 }; -/* Kernel equivalent of struct carpreq, but with more fields for new features. - * */ -struct carpkreq { - int carpr_count; - int carpr_vhid; - int carpr_state; - int carpr_advskew; - int carpr_advbase; - unsigned char carpr_key[CARP_KEY_LEN]; - /* Everything above this is identical to carpreq */ - struct in_addr carpr_addr; - struct in6_addr carpr_addr6; - carp_version_t carpr_version; - uint8_t carpr_vrrp_priority; - uint16_t carpr_vrrp_adv_inter; -}; - /* * Brief design of carp(4). * @@ -2256,216 +2239,6 @@ carp_free_if(struct carp_if *cif) free(cif, M_CARP); } -static bool -carp_carprcp(void *arg, struct carp_softc *sc, int priv) -{ - struct carpreq *carpr = arg; - - CARP_LOCK(sc); - carpr->carpr_state = sc->sc_state; - carpr->carpr_vhid = sc->sc_vhid; - switch (sc->sc_version) { - case CARP_VERSION_CARP: - carpr->carpr_advbase = sc->sc_advbase; - carpr->carpr_advskew = sc->sc_advskew; - if (priv) - bcopy(sc->sc_key, carpr->carpr_key, - sizeof(carpr->carpr_key)); - else - bzero(carpr->carpr_key, sizeof(carpr->carpr_key)); - break; - case CARP_VERSION_VRRPv3: - break; - } - CARP_UNLOCK(sc); - - return (true); -} - -static int -carp_ioctl_set(if_t ifp, struct carpkreq *carpr) -{ - struct epoch_tracker et; - struct carp_softc *sc = NULL; - int error = 0; - - if (carpr->carpr_vhid <= 0 || carpr->carpr_vhid > CARP_MAXVHID) - return (EINVAL); - - switch (carpr->carpr_version) { - case CARP_VERSION_CARP: - if (carpr->carpr_advbase != 0 && (carpr->carpr_advbase > 255 || - carpr->carpr_advbase < CARP_DFLTINTV)) - return (EINVAL); - if (carpr->carpr_advskew < 0 || carpr->carpr_advskew >= 255) - return (EINVAL); - break; - case CARP_VERSION_VRRPv3: - /* XXXGL: shouldn't we check anything? */ - break; - default: - return (EINVAL); - } - - if (ifp->if_carp) { - IFNET_FOREACH_CARP(ifp, sc) - if (sc->sc_vhid == carpr->carpr_vhid) - break; - } - - if (sc == NULL) - sc = carp_alloc(ifp, carpr->carpr_version, carpr->carpr_vhid); - else if (sc->sc_version != carpr->carpr_version) - return (EINVAL); - - CARP_LOCK(sc); - switch (sc->sc_version) { - case CARP_VERSION_CARP: - if (carpr->carpr_advbase != 0) - sc->sc_advbase = carpr->carpr_advbase; - sc->sc_advskew = carpr->carpr_advskew; - if (carpr->carpr_addr.s_addr != INADDR_ANY) - sc->sc_carpaddr = carpr->carpr_addr; - if (!IN6_IS_ADDR_UNSPECIFIED(&carpr->carpr_addr6)) { - memcpy(&sc->sc_carpaddr6, &carpr->carpr_addr6, - sizeof(sc->sc_carpaddr6)); - } - if (carpr->carpr_key[0] != '\0') { - bcopy(carpr->carpr_key, sc->sc_key, sizeof(sc->sc_key)); - carp_hmac_prepare(sc); - } - break; - case CARP_VERSION_VRRPv3: - if (carpr->carpr_vrrp_priority != 0) - sc->sc_vrrp_prio = carpr->carpr_vrrp_priority; - if (carpr->carpr_vrrp_adv_inter) - sc->sc_vrrp_adv_inter = carpr->carpr_vrrp_adv_inter; - break; - } - - if (sc->sc_state != INIT && - carpr->carpr_state != sc->sc_state) { - switch (carpr->carpr_state) { - case BACKUP: - callout_stop(&sc->sc_ad_tmo); - carp_set_state(sc, BACKUP, - "user requested via ifconfig"); - carp_setrun(sc, 0); - carp_delroute(sc); - break; - case MASTER: - NET_EPOCH_ENTER(et); - carp_master_down_locked(sc, - "user requested via ifconfig"); - NET_EPOCH_EXIT(et); - break; - default: - break; - } - } - CARP_UNLOCK(sc); - - return (error); -} - -static int -carp_ioctl_get(if_t ifp, struct ucred *cred, struct carpreq *carpr, - bool (*outfn)(void *, struct carp_softc *, int), void *arg) -{ - int priveleged; - struct carp_softc *sc; - - if (carpr->carpr_vhid < 0 || carpr->carpr_vhid > CARP_MAXVHID) - return (EINVAL); - if (carpr->carpr_count < 1) - return (EMSGSIZE); - if (ifp->if_carp == NULL) - return (ENOENT); - - priveleged = (priv_check_cred(cred, PRIV_NETINET_CARP) == 0); - if (carpr->carpr_vhid != 0) { - IFNET_FOREACH_CARP(ifp, sc) - if (sc->sc_vhid == carpr->carpr_vhid) - break; - if (sc == NULL) - return (ENOENT); - - if (! outfn(arg, sc, priveleged)) - return (ENOMEM); - carpr->carpr_count = 1; - } else { - int count; - - count = 0; - IFNET_FOREACH_CARP(ifp, sc) - count++; - - if (count > carpr->carpr_count) - return (EMSGSIZE); - - IFNET_FOREACH_CARP(ifp, sc) { - if (! outfn(arg, sc, priveleged)) - return (ENOMEM); - carpr->carpr_count = count; - } - } - - return (0); -} - -int -carp_ioctl(struct ifreq *ifr, u_long cmd, struct thread *td) -{ - struct carpreq carpr; - struct carpkreq carprk = { - .carpr_version = CARP_VERSION_CARP, - }; - struct ifnet *ifp; - int error = 0; - - if ((error = copyin(ifr_data_get_ptr(ifr), &carpr, sizeof carpr))) - return (error); - - ifp = ifunit_ref(ifr->ifr_name); - if ((error = carp_is_supported_if(ifp)) != 0) - goto out; - - if ((ifp->if_flags & IFF_MULTICAST) == 0) { - error = EADDRNOTAVAIL; - goto out; - } - - sx_xlock(&carp_sx); - switch (cmd) { - case SIOCSVH: - if ((error = priv_check(td, PRIV_NETINET_CARP))) - break; - - memcpy(&carprk, &carpr, sizeof(carpr)); - error = carp_ioctl_set(ifp, &carprk); - break; - - case SIOCGVH: - error = carp_ioctl_get(ifp, td->td_ucred, &carpr, - carp_carprcp, &carpr); - if (error == 0) { - error = copyout(&carpr, - (char *)ifr_data_get_ptr(ifr), - carpr.carpr_count * sizeof(carpr)); - } - break; - default: - error = EINVAL; - } - sx_xunlock(&carp_sx); - -out: - if (ifp != NULL) - if_rele(ifp); - - return (error); -} - static int carp_get_vhid(struct ifaddr *ifa) { @@ -2757,67 +2530,6 @@ nlattr_get_carp_key(struct nlattr *nla, struct nl_pstate *npt, const void *arg, return (0); } -struct carp_nl_send_args { - struct nlmsghdr *hdr; - struct nl_pstate *npt; -}; - -static bool -carp_nl_send(void *arg, struct carp_softc *sc, int priv) -{ - struct carp_nl_send_args *nlsa = arg; - struct nlmsghdr *hdr = nlsa->hdr; - struct nl_pstate *npt = nlsa->npt; - struct nl_writer *nw = npt->nw; - struct genlmsghdr *ghdr_new; - - if (!nlmsg_reply(nw, hdr, sizeof(struct genlmsghdr))) { - nlmsg_abort(nw); - return (false); - } - - ghdr_new = nlmsg_reserve_object(nw, struct genlmsghdr); - if (ghdr_new == NULL) { - nlmsg_abort(nw); - return (false); - } - - ghdr_new->cmd = CARP_NL_CMD_GET; - ghdr_new->version = 0; - ghdr_new->reserved = 0; - - CARP_LOCK(sc); - - nlattr_add_u32(nw, CARP_NL_VHID, sc->sc_vhid); - nlattr_add_u32(nw, CARP_NL_STATE, sc->sc_state); - nlattr_add_u8(nw, CARP_NL_VERSION, sc->sc_version); - switch (sc->sc_version) { - case CARP_VERSION_CARP: - nlattr_add_s32(nw, CARP_NL_ADVBASE, sc->sc_advbase); - nlattr_add_s32(nw, CARP_NL_ADVSKEW, sc->sc_advskew); - nlattr_add_in_addr(nw, CARP_NL_ADDR, &sc->sc_carpaddr); - nlattr_add_in6_addr(nw, CARP_NL_ADDR6, &sc->sc_carpaddr6); - if (priv) - nlattr_add(nw, CARP_NL_KEY, sizeof(sc->sc_key), - sc->sc_key); - break; - case CARP_VERSION_VRRPv3: - nlattr_add_u8(nw, CARP_NL_VRRP_PRIORITY, sc->sc_vrrp_prio); - nlattr_add_u16(nw, CARP_NL_VRRP_ADV_INTER, - sc->sc_vrrp_adv_inter); - break; - } - - CARP_UNLOCK(sc); - - if (! nlmsg_end(nw)) { - nlmsg_abort(nw); - return (false); - } - - return (true); -} - struct nl_carp_parsed { unsigned int ifindex; char *ifname; @@ -2856,16 +2568,20 @@ static int carp_nl_get(struct nlmsghdr *hdr, struct nl_pstate *npt) { struct nl_carp_parsed attrs = { }; - struct carp_nl_send_args args; - struct carpreq carpr = { }; struct epoch_tracker et; + struct nl_writer *nw = npt->nw; + struct carp_softc *sc; if_t ifp = NULL; int error; + bool privileged; error = nl_parse_nlmsg(hdr, &carp_parser, npt, &attrs); if (error != 0) return (error); + if (attrs.vhid < 0 || attrs.vhid > CARP_MAXVHID) + return (EINVAL); + NET_EPOCH_ENTER(et); if (attrs.ifname != NULL) ifp = ifunit_ref(attrs.ifname); @@ -2876,19 +2592,72 @@ carp_nl_get(struct nlmsghdr *hdr, struct nl_pstate *npt) if ((error = carp_is_supported_if(ifp)) != 0) goto out; - hdr->nlmsg_flags |= NLM_F_MULTI; - args.hdr = hdr; - args.npt = npt; + if (ifp->if_carp == NULL) { + error = ENOENT; + goto out; + } - carpr.carpr_vhid = attrs.vhid; - carpr.carpr_count = CARP_MAXVHID; + hdr->nlmsg_flags |= NLM_F_MULTI; + privileged = (priv_check_cred(nlp_get_cred(npt->nlp), + PRIV_NETINET_CARP) == 0); sx_xlock(&carp_sx); - error = carp_ioctl_get(ifp, nlp_get_cred(npt->nlp), &carpr, - carp_nl_send, &args); + IFNET_FOREACH_CARP(ifp, sc) { + struct genlmsghdr *ghdr_new; + + if (attrs.vhid != 0 && attrs.vhid != sc->sc_vhid) + continue; + + if (!nlmsg_reply(nw, hdr, sizeof(struct genlmsghdr))) { + nlmsg_abort(nw); + error = ENOMEM; + break; + } + + ghdr_new = nlmsg_reserve_object(nw, struct genlmsghdr); + if (ghdr_new == NULL) { + nlmsg_abort(nw); + error = ENOMEM; + break; + } + + ghdr_new->cmd = CARP_NL_CMD_GET; + ghdr_new->version = 0; + ghdr_new->reserved = 0; + + CARP_LOCK(sc); + nlattr_add_u32(nw, CARP_NL_VHID, sc->sc_vhid); + nlattr_add_u32(nw, CARP_NL_STATE, sc->sc_state); + nlattr_add_u8(nw, CARP_NL_VERSION, sc->sc_version); + switch (sc->sc_version) { + case CARP_VERSION_CARP: + nlattr_add_s32(nw, CARP_NL_ADVBASE, sc->sc_advbase); + nlattr_add_s32(nw, CARP_NL_ADVSKEW, sc->sc_advskew); + nlattr_add_in_addr(nw, CARP_NL_ADDR, &sc->sc_carpaddr); + nlattr_add_in6_addr(nw, CARP_NL_ADDR6, + &sc->sc_carpaddr6); + if (privileged) + nlattr_add(nw, CARP_NL_KEY, sizeof(sc->sc_key), + sc->sc_key); + break; + case CARP_VERSION_VRRPv3: + nlattr_add_u8(nw, CARP_NL_VRRP_PRIORITY, + sc->sc_vrrp_prio); + nlattr_add_u16(nw, CARP_NL_VRRP_ADV_INTER, + sc->sc_vrrp_adv_inter); + break; + } + CARP_UNLOCK(sc); + + if (! nlmsg_end(nw)) { + nlmsg_abort(nw); + error = ENOMEM; + break; + } + } sx_xunlock(&carp_sx); - if (! nlmsg_end_dump(npt->nw, error, hdr)) + if (! nlmsg_end_dump(nw, error, hdr)) error = ENOMEM; out: @@ -2902,8 +2671,8 @@ static int carp_nl_set(struct nlmsghdr *hdr, struct nl_pstate *npt) { struct nl_carp_parsed attrs = { }; - struct carpkreq carpr; struct epoch_tracker et; + struct carp_softc *sc; if_t ifp = NULL; int error; @@ -2949,26 +2718,66 @@ carp_nl_set(struct nlmsghdr *hdr, struct nl_pstate *npt) goto out; } - carpr.carpr_count = 1; - carpr.carpr_vhid = attrs.vhid; - carpr.carpr_state = attrs.state; - carpr.carpr_version = attrs.version; - switch (attrs.version) { + sx_xlock(&carp_sx); + if (ifp->if_carp) { + IFNET_FOREACH_CARP(ifp, sc) + if (sc->sc_vhid == attrs.vhid) + break; + } else + sc = NULL; + if (sc == NULL) + sc = carp_alloc(ifp, attrs.version, attrs.vhid); + else if (sc->sc_version != attrs.version) { + sx_xunlock(&carp_sx); + error = EINVAL; + goto out; + } + + CARP_LOCK(sc); + switch (sc->sc_version) { case CARP_VERSION_CARP: - carpr.carpr_advbase = attrs.advbase; - carpr.carpr_advskew = attrs.advskew; - carpr.carpr_addr = attrs.addr; - carpr.carpr_addr6 = attrs.addr6; - memcpy(&carpr.carpr_key, &attrs.key, sizeof(attrs.key)); + if (attrs.advbase != 0) + sc->sc_advbase = attrs.advbase; + sc->sc_advskew = attrs.advskew; + if (attrs.addr.s_addr != INADDR_ANY) + sc->sc_carpaddr = attrs.addr; + if (!IN6_IS_ADDR_UNSPECIFIED(&attrs.addr6)) { + memcpy(&sc->sc_carpaddr6, &attrs.addr6, + sizeof(sc->sc_carpaddr6)); + } + if (attrs.key[0] != '\0') { + bcopy(attrs.key, sc->sc_key, sizeof(sc->sc_key)); + carp_hmac_prepare(sc); + } break; case CARP_VERSION_VRRPv3: - carpr.carpr_vrrp_priority = attrs.vrrp_prio; - carpr.carpr_vrrp_adv_inter = attrs.vrrp_adv_inter; + if (attrs.vrrp_prio != 0) + sc->sc_vrrp_prio = attrs.vrrp_prio; + if (attrs.vrrp_adv_inter) + sc->sc_vrrp_adv_inter = attrs.vrrp_adv_inter; break; } - sx_xlock(&carp_sx); - error = carp_ioctl_set(ifp, &carpr); + if (sc->sc_state != INIT && sc->sc_state != attrs.state) { + switch (attrs.state) { + case BACKUP: + callout_stop(&sc->sc_ad_tmo); + carp_set_state(sc, BACKUP, + "user requested via ifconfig"); + carp_setrun(sc, 0); + carp_delroute(sc); + break; + case MASTER: + NET_EPOCH_ENTER(et); + carp_master_down_locked(sc, + "user requested via ifconfig"); + NET_EPOCH_EXIT(et); + break; + default: + break; + } + } + CARP_UNLOCK(sc); sx_xunlock(&carp_sx); out: @@ -3035,7 +2844,6 @@ carp_mod_cleanup(void) carp_iamatch6_p = NULL; carp_macmatch6_p = NULL; #endif - carp_ioctl_p = NULL; carp_attach_p = NULL; carp_detach_p = NULL; carp_get_vhid_p = NULL; @@ -3070,7 +2878,6 @@ carp_mod_load(void) carp_forus_p = carp_forus; carp_output_p = carp_output; carp_linkstate_p = carp_linkstate; - carp_ioctl_p = carp_ioctl; carp_attach_p = carp_attach; carp_detach_p = carp_detach; carp_demote_adj_p = carp_demote_adj; diff --git a/sys/netinet/ip_carp.h b/sys/netinet/ip_carp.h index dc3d9a68b43b..8d82286feb7d 100644 --- a/sys/netinet/ip_carp.h +++ b/sys/netinet/ip_carp.h @@ -160,23 +160,10 @@ struct carpstats { uint64_t carps_preempt; /* if enabled, preemptions */ }; -/* - * Configuration structure for SIOCSVH SIOCGVH - */ -struct carpreq { - int carpr_count; - int carpr_vhid; #define CARP_MAXVHID 255 - int carpr_state; #define CARP_STATES "INIT", "BACKUP", "MASTER" #define CARP_MAXSTATE 2 - int carpr_advskew; #define CARP_MAXSKEW 240 - int carpr_advbase; - unsigned char carpr_key[CARP_KEY_LEN]; -}; -#define SIOCSVH _IOWR('i', 245, struct ifreq) -#define SIOCGVH _IOWR('i', 246, struct ifreq) typedef enum carp_version { CARP_VERSION_CARP = 2, @@ -184,7 +171,6 @@ typedef enum carp_version { } carp_version_t; #ifdef _KERNEL -int carp_ioctl(struct ifreq *, u_long, struct thread *); int carp_attach(struct ifaddr *, int); void carp_detach(struct ifaddr *, bool); void carp_carpdev_state(struct ifnet *); @@ -198,7 +184,6 @@ int carp_forus(struct ifnet *, u_char *); /* These are external networking stack hooks for CARP */ /* net/if.c */ -extern int (*carp_ioctl_p)(struct ifreq *, u_long, struct thread *); extern int (*carp_attach_p)(struct ifaddr *, int); extern void (*carp_detach_p)(struct ifaddr *, bool); extern void (*carp_linkstate_p)(struct ifnet *); diff --git a/sys/sys/param.h b/sys/sys/param.h index 99c1af5e55bf..7547409a16c7 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -74,7 +74,7 @@ * cannot include sys/param.h and should only be updated here. */ #undef __FreeBSD_version -#define __FreeBSD_version 1600012 +#define __FreeBSD_version 1600013 /* * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,