From owner-hackers+M63286=david=gwynne.id.au@openbsd.org Mon Jan 19 21:51:10 2015 Delivered-To: david@gwynne.id.au Received: by 10.216.49.9 with SMTP id w9csp181278web; Mon, 19 Jan 2015 03:51:11 -0800 (PST) X-Received: by 10.52.85.132 with SMTP id h4mr11993068vdz.40.1421668270586; Mon, 19 Jan 2015 03:51:10 -0800 (PST) Return-Path: Received: from shear.ucar.edu (lists.openbsd.org. [192.43.244.163]) by mx.google.com with ESMTPS id cy4si2048877vdd.103.2015.01.19.03.51.09 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 19 Jan 2015 03:51:10 -0800 (PST) Received-SPF: pass (google.com: manual fallback record for domain of owner-hackers+M63286=david=gwynne.id.au@openbsd.org designates 192.43.244.163 as permitted sender) client-ip=192.43.244.163; Authentication-Results: mx.google.com; spf=pass (google.com: manual fallback record for domain of owner-hackers+M63286=david=gwynne.id.au@openbsd.org designates 192.43.244.163 as permitted sender) smtp.mail=owner-hackers+M63286=david=gwynne.id.au@openbsd.org Received: from openbsd.org (localhost [127.0.0.1]) by shear.ucar.edu (8.14.8/8.14.5) with ESMTP id t0JC4ofm032509 for ; Mon, 19 Jan 2015 05:04:50 -0700 (MST) Received: from relay4-d.mail.gandi.net (relay4-d.mail.gandi.net [217.70.183.196]) by shear.ucar.edu (8.14.8/8.14.8) with ESMTP id t0JC4klI009995 (version=TLSv1/SSLv3 cipher=DHE-DSS-AES256-SHA bits=256 verify=NO) for ; Mon, 19 Jan 2015 05:04:47 -0700 (MST) Received: from mfilter19-d.gandi.net (mfilter19-d.gandi.net [217.70.178.147]) by relay4-d.mail.gandi.net (Postfix) with ESMTP id 7FCCD1720BF for ; Mon, 19 Jan 2015 12:50:59 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at mfilter19-d.gandi.net Received: from relay4-d.mail.gandi.net ([217.70.183.196]) by mfilter19-d.gandi.net (mfilter19-d.gandi.net [10.0.15.180]) (amavisd-new, port 10024) with ESMTP id N89h9Sw0E6Eo for ; Mon, 19 Jan 2015 12:50:57 +0100 (CET) X-Originating-IP: 77.11.39.132 Received: from noz.nolizard.org (koln-4d0b2784.pool.mediaways.net [77.11.39.132]) (Authenticated sender: mpieuchot@nolizard.org) by relay4-d.mail.gandi.net (Postfix) with ESMTPSA id A21C517209D for ; Mon, 19 Jan 2015 12:50:57 +0100 (CET) Received: from localhost (noz.nolizard.org [local]); by noz.nolizard.org (OpenSMTPD) with ESMTPA id 8bd4c65b; for ; Mon, 19 Jan 2015 12:50:56 +0100 (CET) Date: Mon, 19 Jan 2015 12:50:56 +0100 From: Martin Pieuchot To: hackers@openbsd.org Subject: carp(4) now requires a "carpdev" argument Message-ID: <20150119115056.GA32440@noz.nolizard.org> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline User-Agent: Mutt/1.5.23 (2014-03-12) List-Help: List-ID: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: X-Loop: hackers@openbsd.org Precedence: list Sender: owner-hackers@openbsd.org Status: RO Content-Length: 5859 Lines: 209 Apart from being inconsistent with other pseudo-device (trunk, vlan...) this "feature" to automagically find a corresponding parent interface when no "carpdev" argument is specified indirectly create various problems. These problems are all created by layers of layers of hacks added by generations of developers to deal with link-layer address setup, multicast groups setup and of course IPv6 link-local address setup. But the root of all these problems is: how to find the link-layer address of the parent interface. So let's try to keep carp(4) more deterministic by *always* requiring a "carpdev" argument. It doesn't matter if the carpdev (parent) interface has an IP or not. This diff is deliberately small as a first step. I appreciate testing and oks, it's running so far here on one IPv4 pair and one IPv4+IPv6 pair. Comments? Index: sys/netinet/ip_carp.c =================================================================== RCS file: /home/ncvs/src/sys/netinet/ip_carp.c,v retrieving revision 1.244 diff -u -p -r1.244 ip_carp.c --- sys/netinet/ip_carp.c 8 Jan 2015 10:55:45 -0000 1.244 +++ sys/netinet/ip_carp.c 19 Jan 2015 11:27:57 -0000 @@ -1849,59 +1849,20 @@ carp_addr_updated(void *v) int carp_set_addr(struct carp_softc *sc, struct sockaddr_in *sin) { - struct ifnet *ifp = NULL; struct in_addr *in = &sin->sin_addr; - struct ifaddr *ifa; - struct in_ifaddr *ia; - int error = 0; + int error; + + KASSERT(sc->sc_carpdev != NULL); /* XXX is this necessary? */ if (in->s_addr == INADDR_ANY) { - if (!(sc->sc_if.if_flags & IFF_UP)) - carp_set_state_all(sc, INIT); - if (sc->sc_naddrs) - sc->sc_if.if_flags |= IFF_UP; carp_setrun_all(sc, 0); return (0); } - /* we have to do this by hand to ensure we don't match on ourselves */ - TAILQ_FOREACH(ifp, &ifnet, if_list) { - /* and, yeah, we need a multicast-capable iface too */ - if ((ifp->if_type == IFT_CARP) || - (ifp->if_flags & IFF_MULTICAST) == 0 || - (ifp->if_rdomain != sc->sc_if.if_rdomain)) - continue; - - TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { - if (ifa->ifa_addr->sa_family != AF_INET) - continue; - - ia = ifatoia(ifa); - if ((in->s_addr & ia->ia_netmask) == ia->ia_net) - goto found; - } - } - -found: - if (ifp == NULL) - ifp = sc->sc_carpdev; - - if (sc->sc_carpdev != NULL && ifp != sc->sc_carpdev) - return (EADDRNOTAVAIL); - - if ((error = carp_set_ifp(sc, ifp))) - return (error); - - if (sc->sc_carpdev == NULL) - return (EADDRNOTAVAIL); - if (sc->sc_naddrs == 0 && (error = carp_join_multicast(sc)) != 0) return (error); - if (sc->sc_carpdev != NULL) - sc->sc_if.if_flags |= IFF_UP; - carp_set_state_all(sc, INIT); return (0); @@ -1934,65 +1895,18 @@ carp_join_multicast(struct carp_softc *s int carp_set_addr6(struct carp_softc *sc, struct sockaddr_in6 *sin6) { - struct ifnet *ifp = sc->sc_carpdev; - struct ifaddr *ifa; - struct in6_ifaddr *ia6; - int i, error = 0; + int error; + + KASSERT(sc->sc_carpdev != NULL); if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { - if (!(sc->sc_if.if_flags & IFF_UP)) - carp_set_state_all(sc, INIT); - if (sc->sc_naddrs6) - sc->sc_if.if_flags |= IFF_UP; carp_setrun_all(sc, 0); return (0); } - /* we have to do this by hand to ensure we don't match on ourselves */ - TAILQ_FOREACH(ifp, &ifnet, if_list) { - /* and, yeah, we need a multicast-capable iface too */ - if ((ifp->if_type == IFT_CARP) || - (ifp->if_flags & IFF_MULTICAST) == 0 || - (ifp->if_rdomain != sc->sc_if.if_rdomain)) - continue; - - TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { - if (ifa->ifa_addr->sa_family != AF_INET6) - continue; - - ia6 = ifatoia6(ifa); - for (i = 0; i < 4; i++) { - if ((sin6->sin6_addr.s6_addr32[i] & - ia6->ia_prefixmask.sin6_addr.s6_addr32[i]) != - (ia6->ia_addr.sin6_addr.s6_addr32[i] & - ia6->ia_prefixmask.sin6_addr.s6_addr32[i])) - break; - } - - if (i == 4) - goto found; - } - } - -found: - if (ifp == NULL) - ifp = sc->sc_carpdev; - - if (sc->sc_carpdev != NULL && ifp != sc->sc_carpdev) - return (EADDRNOTAVAIL); - - if ((error = carp_set_ifp(sc, ifp))) - return (error); - - if (sc->sc_carpdev == NULL) - return (EADDRNOTAVAIL); - if (sc->sc_naddrs6 == 0 && (error = carp_join_multicast6(sc)) != 0) return (error); - if (sc->sc_carpdev != NULL) - sc->sc_if.if_flags |= IFF_UP; - carp_set_state_all(sc, INIT); return (0); @@ -2055,20 +1969,17 @@ carp_ioctl(struct ifnet *ifp, u_long cmd struct ifaddr *ifa = (struct ifaddr *)addr; struct ifreq *ifr = (struct ifreq *)addr; struct ifnet *cdev = NULL; - int s, i, error = 0; + int i, error = 0; switch (cmd) { case SIOCSIFADDR: - s = splnet(); + if (sc->sc_carpdev == NULL) + return (EINVAL); + switch (ifa->ifa_addr->sa_family) { case AF_INET: sc->sc_if.if_flags |= IFF_UP; - /* - * emulate arp_ifinit() without doing a gratuitous arp - * request so that the routes are setup correctly. - */ ifa->ifa_rtrequest = arp_rtrequest; - error = carp_set_addr(sc, satosin(ifa->ifa_addr)); break; #ifdef INET6 @@ -2082,7 +1993,6 @@ carp_ioctl(struct ifnet *ifp, u_long cmd break; } break; - splx(s); case SIOCSIFFLAGS: vhe = LIST_FIRST(&sc->carp_vhosts); Index: share/man/man4/carp.4 =================================================================== RCS file: /home/ncvs/src/share/man/man4/carp.4,v retrieving revision 1.34 diff -u -p -r1.34 carp.4 --- share/man/man4/carp.4 12 Mar 2010 13:36:16 -0000 1.34 +++ share/man/man4/carp.4 19 Jan 2015 11:27:57 -0000 @@ -71,8 +71,6 @@ Finally is used to specify which interface the .Nm device attaches to. -If unspecified, the kernel attempts to set it by looking for -another interface with the same subnet. These configurations can be done using .Xr ifconfig 8 , or through the