From: Roy Marples Date: Fri, 2 Feb 2018 11:24:58 +0000 (+0000) Subject: inet6: simplify setup of kernel X-Git-Tag: v7.0.2~25 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fabcbe2ee6884b9cd235780c2a22b22d691bf7ac;p=thirdparty%2Fdhcpcd.git inet6: simplify setup of kernel Rename if_checkipv6 to if_setup_inet6 so it's more descriptive. simpify code as we don't really care about the result. Restore the prior behavior of not disabling kernel RA handling if dhcpcd is not doing it. --- diff --git a/src/dhcpcd.c b/src/dhcpcd.c index 7f3ef86b..d025ccdf 100644 --- a/src/dhcpcd.c +++ b/src/dhcpcd.c @@ -437,19 +437,15 @@ configure_interface1(struct interface *ifp) ifo->options &= ~(DHCPCD_IPV6RS | DHCPCD_DHCP6 | DHCPCD_WAITIP6); - /* We want to disable kernel interface RA as early as possible. */ + /* We want to setup INET6 on the interface as soon as possible. */ if (ifp->active == IF_ACTIVE_USER && - !(ifp->ctx->options & DHCPCD_DUMPLEASE)) + ifo->options & DHCPCD_IPV6 && + !(ifp->ctx->options & (DHCPCD_DUMPLEASE | DHCPCD_TEST))) { - int ra_global, ra_iface; - /* If not doing any DHCP, disable the RDNSS requirement. */ if (!(ifo->options & (DHCPCD_DHCP | DHCPCD_DHCP6))) ifo->options &= ~DHCPCD_IPV6RA_REQRDNSS; - ra_global = if_checkipv6(ifp->ctx, NULL); - ra_iface = if_checkipv6(ifp->ctx, ifp); - if (ra_global == -1 || ra_iface == -1) - ifo->options &= ~DHCPCD_IPV6RS; + if_setup_inet6(ifp); } #endif diff --git a/src/dhcpcd.conf.5.in b/src/dhcpcd.conf.5.in index 1afa4e80..f1a8a8d7 100644 --- a/src/dhcpcd.conf.5.in +++ b/src/dhcpcd.conf.5.in @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd January 8, 2018 +.Dd February 2, 2018 .Dt DHCPCD.CONF 5 .Os .Sh NAME @@ -480,9 +480,9 @@ See .%T "RFC 3927" .Re .It Ic noipv6 -Don't attempt to configure an IPv6 address. +Don't solicit or accept IPv6 Router Advertisements and DHCPv6. .It Ic noipv6rs -Disable solicitation and receipt of IPv6 Router Advertisements. +Don't solicit or accept IPv6 Router Advertisements. .It Ic nolink Don't receive link messages about carrier status. You should only set this for buggy interface drivers. diff --git a/src/if-bsd.c b/src/if-bsd.c index 6ec9e12b..26d75df9 100644 --- a/src/if-bsd.c +++ b/src/if-bsd.c @@ -1248,7 +1248,7 @@ if_machinearch(char *str, size_t len) } #ifdef INET6 -#ifdef IPV6CTL_ACCEPT_RTADV +#if defined(IPV6CTL_ACCEPT_RTADV) && !defined(ND6_IFF_ACCEPT_RTADV) #define get_inet6_sysctl(code) inet6_sysctl(code, 0, 0) #define set_inet6_sysctl(code, val) inet6_sysctl(code, val, 1) static int @@ -1273,6 +1273,7 @@ inet6_sysctl(int code, int val, int action) #ifdef IPV6_MANAGETEMPADDR #ifndef IPV6CTL_TEMPVLTIME + #define get_inet6_sysctlbyname(code) inet6_sysctlbyname(code, 0, 0) #define set_inet6_sysctlbyname(code, val) inet6_sysctlbyname(code, val, 1) static int @@ -1358,21 +1359,24 @@ set_ifxflags(int s, const struct interface *ifp) #ifdef IFXF_NOINET6 flags &= ~IFXF_NOINET6; #endif - if (!(ifp->ctx->options & DHCPCD_TEST)) + /* + * If dhcpcd is doing RS, disable RA support + * in the kernel. Otherwise, leave it alone. + * Logically it should be disabled regardless as dhcpcd can + * do it better and the user saying no RS means no RS even the kernel, + * but some crazy people want the kernel to do it still. + */ + if (ifp->options->options & DHCPCD_IPV6RS) flags &= ~IFXF_AUTOCONF6; if (ifr.ifr_flags == flags) return 0; - if (ifp->ctx->options & DHCPCD_TEST) { - errno = EPERM; - return -1; - } ifr.ifr_flags = flags; return ioctl(s, SIOCSIFXFLAGS, (void *)&ifr); } #endif /* OpenBSD removed ND6 flags entirely, so we need to check for their - * existnance. */ + * existance. */ #if defined(ND6_IFF_AUTO_LINKLOCAL) || \ defined(ND6_IFF_PERFORMNUD) || \ defined(ND6_IFF_ACCEPT_RTADV) || \ @@ -1381,147 +1385,108 @@ set_ifxflags(int s, const struct interface *ifp) #define ND6_NDI_FLAGS #endif -int -if_checkipv6(struct dhcpcd_ctx *ctx, const struct interface *ifp) +void +if_setup_inet6(const struct interface *ifp) { struct priv *priv; - int s, ra; + int s; +#ifdef ND6_NDI_FLAGS + struct in6_ndireq nd; + int flags; +#endif - priv = (struct priv *)ctx->priv; + priv = (struct priv *)ifp->ctx->priv; s = priv->pf_inet6_fd; - if (ifp) { #ifdef ND6_NDI_FLAGS - struct in6_ndireq nd; - int flags; - - memset(&nd, 0, sizeof(nd)); - strlcpy(nd.ifname, ifp->name, sizeof(nd.ifname)); - if (ioctl(s, SIOCGIFINFO_IN6, &nd) == -1) - return -1; - flags = (int)nd.ndi.flags; + memset(&nd, 0, sizeof(nd)); + strlcpy(nd.ifname, ifp->name, sizeof(nd.ifname)); + if (ioctl(s, SIOCGIFINFO_IN6, &nd) == -1) + logerr("%s: SIOCGIFINFO_FLAGS", ifp->name); + flags = (int)nd.ndi.flags; #endif #ifdef ND6_IFF_AUTO_LINKLOCAL - if (!(ctx->options & DHCPCD_TEST) && - flags & ND6_IFF_AUTO_LINKLOCAL) - { - logdebugx("%s: disabling Kernel IPv6 auto " - "link-local support", - ifp->name); - flags &= ~ND6_IFF_AUTO_LINKLOCAL; - } + /* Unlike the kernel, + * dhcpcd make make a stable private address. */ + flags &= ~ND6_IFF_AUTO_LINKLOCAL; #endif #ifdef ND6_IFF_PERFORMNUD - if ((flags & ND6_IFF_PERFORMNUD) == 0) { - /* NUD is kind of essential. */ - flags |= ND6_IFF_PERFORMNUD; - } + /* NUD is kind of essential. */ + flags |= ND6_IFF_PERFORMNUD; #endif +#ifdef ND6_IFF_IFDISABLED + /* Ensure the interface is not disabled. */ + flags &= ~ND6_IFF_IFDISABLED; +#endif + + /* + * If dhcpcd is doing RS, disable RA support + * in the kernel. Otherwise, leave it alone. + * Logically it should be disabled regardless as dhcpcd can + * do it better and the user saying no RS means no RS even the kernel, + * but some crazy people want the kernel to do it still. + */ #ifdef ND6_IFF_ACCEPT_RTADV - if (!(ctx->options & DHCPCD_TEST) && - flags & ND6_IFF_ACCEPT_RTADV) - { - logdebugx("%s: disabling Kernel IPv6 RA support", - ifp->name); - flags &= ~ND6_IFF_ACCEPT_RTADV; - } + if (ifp->options->options & DHCPCD_IPV6RS) + flags &= ~ND6_IFF_ACCEPT_RTADV; #ifdef ND6_IFF_OVERRIDE_RTADV - if (!(ctx->options & DHCPCD_TEST) && - flags & ND6_IFF_OVERRIDE_RTADV) - flags &= ~ND6_IFF_OVERRIDE_RTADV; + if (ifp->options->options & DHCPCD_IPV6RS) + flags |= ND6_IFF_OVERRIDE_RTADV; #endif #endif -#ifdef ND6_IFF_IFDISABLED - flags &= ~ND6_IFF_IFDISABLED; -#endif - #ifdef ND6_NDI_FLAGS - if (nd.ndi.flags != (uint32_t)flags) { - if (ctx->options & DHCPCD_TEST) { - logwarnx("%s: interface not IPv6 enabled", - ifp->name); - return -1; - } - nd.ndi.flags = (uint32_t)flags; - if (ioctl(s, SIOCSIFINFO_FLAGS, &nd) == -1) { - logerr("%s: SIOCSIFINFO_FLAGS", ifp->name); - return -1; - } - } + if (nd.ndi.flags != (uint32_t)flags) { + nd.ndi.flags = (uint32_t)flags; + if (ioctl(s, SIOCSIFINFO_FLAGS, &nd) == -1) + logerr("%s: SIOCSIFINFO_FLAGS", ifp->name); + } #endif - /* Enabling IPv6 by whatever means must be the - * last action undertaken to ensure kernel RS and - * LLADDR auto configuration are disabled where applicable. */ + /* Enabling IPv6 by whatever means must be the + * last action undertaken to ensure kernel RS and + * LLADDR auto configuration are disabled where applicable. */ #ifdef SIOCIFAFATTACH - if (af_attach(s, ifp, AF_INET6) == -1) { - logerr("%s: af_attach", ifp->name); - return -1; - } + if (af_attach(s, ifp, AF_INET6) == -1) + logerr("%s: af_attach", ifp->name); #endif #ifdef SIOCGIFXFLAGS - if (set_ifxflags(s, ifp) == -1) { - logerr("%s: set_ifxflags", ifp->name); - return -1; - } + if (set_ifxflags(s, ifp) == -1) + logerr("%s: set_ifxflags", ifp->name); #endif -#ifdef ND6_IFF_ACCEPT_RTADV -#ifdef ND6_IFF_OVERRIDE_RTADV - switch (flags & (ND6_IFF_ACCEPT_RTADV|ND6_IFF_OVERRIDE_RTADV)) { - case (ND6_IFF_ACCEPT_RTADV|ND6_IFF_OVERRIDE_RTADV): - return 1; - case ND6_IFF_ACCEPT_RTADV: - return ctx->ra_global; - default: - return 0; - } -#else - return flags & ND6_IFF_ACCEPT_RTADV ? 1 : 0; -#endif -#else - return ctx->ra_global; -#endif - } +#if defined(IPV6CTL_ACCEPT_RTADV) && !defined(ND6_IFF_ACCEPT_RTADV) + /* If we cannot control ra per interface, disable it globally. */ + if (ifp->options->options & DHCPCD_IPV6RS) { + int ra = get_inet6_sysctl(IPV6CTL_ACCEPT_RTADV); -#ifdef IPV6CTL_ACCEPT_RTADV - ra = get_inet6_sysctl(IPV6CTL_ACCEPT_RTADV); - if (ra == -1) - if (errno == ENOENT) - ra = 0; - else - logerr("IPV6CTL_ACCEPT_RTADV"); - else if (ra != 0 && !(ctx->options & DHCPCD_TEST)) { - logdebugx("disabling Kernel IPv6 RA support"); - if (set_inet6_sysctl(IPV6CTL_ACCEPT_RTADV, 0) == -1) { - logerr("IPV6CTL_ACCEPT_RTADV"); - return ra; + if (ra == -1) { + if (errno != ENOENT) + logerr("IPV6CTL_ACCEPT_RTADV"); + else if (ra != 0) + if (set_inet6_sysctl(IPV6CTL_ACCEPT_RTADV, 0) == -1) + logerr("IPV6CTL_ACCEPT_RTADV"); } - ra = 0; -#else - ra = 0; - if (!(ctx->options & DHCPCD_TEST)) { + } #endif -#if defined(IPV6CTL_ACCEPT_RTADV) || defined(ND6_IFF_ACCEPT_RTADV) - /* Flush the kernel knowledge of advertised routers - * and prefixes so the kernel does not expire prefixes - * and default routes we are trying to own. */ - char dummy[IFNAMSIZ + 8]; - strlcpy(dummy, "lo0", sizeof(dummy)); - if (ioctl(s, SIOCSRTRFLUSH_IN6, (void *)&dummy) == -1) +#if defined(IPV6CTL_ACCEPT_RTADV) || defined(ND6_IFF_ACCEPT_RTADV) + /* Flush the kernel knowledge of advertised routers + * and prefixes so the kernel does not expire prefixes + * and default routes we are trying to own. */ + if (ifp->options->options & DHCPCD_IPV6RS) { + char ifname[IFNAMSIZ + 8]; + + strlcpy(ifname, ifp->name, sizeof(ifname)); + if (ioctl(s, SIOCSRTRFLUSH_IN6, (void *)&ifname) == -1) logwarn("SIOCSRTRFLUSH_IN6"); - if (ioctl(s, SIOCSPFXFLUSH_IN6, (void *)&dummy) == -1) + if (ioctl(s, SIOCSPFXFLUSH_IN6, (void *)&ifname) == -1) logwarn("SIOCSPFXFLUSH_IN6"); -#endif } - - ctx->ra_global = ra; - return ra; +#endif } #endif diff --git a/src/if-linux.c b/src/if-linux.c index b934834a..e802366a 100644 --- a/src/if-linux.c +++ b/src/if-linux.c @@ -1680,33 +1680,33 @@ if_disable_autolinklocal(struct dhcpcd_ctx *ctx, unsigned int ifindex) static const char *prefix = "/proc/sys/net/ipv6/conf"; -int -if_checkipv6(struct dhcpcd_ctx *ctx, const struct interface *ifp) +void +if_setup_inet6(const struct interface *ifp) { const char *ifname; int ra; char path[256]; - if (ifp == NULL) - ifname = "all"; - else if (!(ctx->options & DHCPCD_TEST)) { - if (if_disable_autolinklocal(ctx, ifp->index) == -1) - logdebug("%s: if_disable_autolinklocal", - ifp->name); - } - if (ifp) - ifname = ifp->name; + /* Unlike the kernel, + * dhcpcd make make a stable private address. */ + if (if_disable_autolinklocal(ifp->ctx, ifp->index) == -1) + logdebug("%s: if_disable_autolinklocal", ifp->name); + + /* + * If dhcpcd is doing RS, disable RA support + * in the kernel. Otherwise, leave it alone. + * Logically it should be disabled regardless as dhcpcd can + * do it better and the user saying no RS means no RS even the kernel, + * but some crazy people want the kernel to do it still. + */ + if (!(ifp->options->options & DHCPCD_IPV6RS)) + return; snprintf(path, sizeof(path), "%s/%s/autoconf", prefix, ifname); ra = check_proc_int(path); - if (ra != 1) { - if (ctx->options & DHCPCD_TEST) - logwarnx("%s: IPv6 kernel autoconf disabled", ifname); - } else if (ra != -1 && !(ctx->options & DHCPCD_TEST)) { - if (write_path(path, "0") == -1) { + if (ra != 1 && ra != -1) { + if (write_path(path, "0") == -1) logerr("%s: %s", __func__, path); - return -1; - } } snprintf(path, sizeof(path), "%s/%s/accept_ra", prefix, ifname); @@ -1717,16 +1717,10 @@ if_checkipv6(struct dhcpcd_ctx *ctx, const struct interface *ifp) /* The sysctl probably doesn't exist, but this isn't an * error as such so just log it and continue */ logfunc("%s", path); - } else if (ra != 0 && !(ctx->options & DHCPCD_TEST)) { - logdebugx("%s: disabling kernel IPv6 RA support", ifname); - if (write_path(path, "0") == -1) { + } else if (ra != 0) { + if (write_path(path, "0") == -1) logerr("%s: %s", __func__, path); - return ra; - } - return 0; } - - return ra; } #ifdef IPV6_MANAGETEMPADDR diff --git a/src/if.h b/src/if.h index a1945fe6..602f8e83 100644 --- a/src/if.h +++ b/src/if.h @@ -187,7 +187,7 @@ int if_addrflags(const struct interface *, const struct in_addr *, #endif #ifdef INET6 -int if_checkipv6(struct dhcpcd_ctx *ctx, const struct interface *); +void if_setup_inet6(const struct interface *); #ifdef IPV6_MANAGETEMPADDR int ip6_use_tempaddr(const char *ifname); int ip6_temp_preferred_lifetime(const char *ifname);