Mercurial > hg > dhcpcd
changeset 4218:f618f850efdc draft
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.
| author | Roy Marples <roy@marples.name> |
|---|---|
| date | Fri, 02 Feb 2018 11:24:58 +0000 |
| parents | 1ab032609a30 |
| children | 9ea5c495aebb |
| files | src/dhcpcd.c src/dhcpcd.conf.5.in src/if-bsd.c src/if-linux.c src/if.h |
| diffstat | 5 files changed, 112 insertions(+), 157 deletions(-) [+] |
line wrap: on
line diff
--- a/src/dhcpcd.c Mon Jan 29 10:53:05 2018 +0000 +++ b/src/dhcpcd.c Fri Feb 02 11:24:58 2018 +0000 @@ -437,19 +437,15 @@ 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
--- a/src/dhcpcd.conf.5.in Mon Jan 29 10:53:05 2018 +0000 +++ b/src/dhcpcd.conf.5.in Fri Feb 02 11:24:58 2018 +0000 @@ -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 @@ .%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.
--- a/src/if-bsd.c Mon Jan 29 10:53:05 2018 +0000 +++ b/src/if-bsd.c Fri Feb 02 11:24:58 2018 +0000 @@ -1248,7 +1248,7 @@ } #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 @@ #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 @@ #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 @@ #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; - } -#endif - -#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; - } -#ifdef ND6_IFF_OVERRIDE_RTADV - if (!(ctx->options & DHCPCD_TEST) && - flags & ND6_IFF_OVERRIDE_RTADV) - flags &= ~ND6_IFF_OVERRIDE_RTADV; -#endif + /* NUD is kind of essential. */ + flags |= ND6_IFF_PERFORMNUD; #endif #ifdef ND6_IFF_IFDISABLED - flags &= ~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 (ifp->options->options & DHCPCD_IPV6RS) + flags &= ~ND6_IFF_ACCEPT_RTADV; +#ifdef ND6_IFF_OVERRIDE_RTADV + if (ifp->options->options & DHCPCD_IPV6RS) + flags |= ND6_IFF_OVERRIDE_RTADV; +#endif #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; +#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); + + 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"); } -#else - return flags & ND6_IFF_ACCEPT_RTADV ? 1 : 0; + } #endif -#else - return ctx->ra_global; -#endif - } -#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; - } - ra = 0; -#else - ra = 0; - if (!(ctx->options & DHCPCD_TEST)) { +#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 *)&ifname) == -1) + logwarn("SIOCSPFXFLUSH_IN6"); + } #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) - logwarn("SIOCSRTRFLUSH_IN6"); - if (ioctl(s, SIOCSPFXFLUSH_IN6, (void *)&dummy) == -1) - logwarn("SIOCSPFXFLUSH_IN6"); -#endif - } - - ctx->ra_global = ra; - return ra; } #endif
--- a/src/if-linux.c Mon Jan 29 10:53:05 2018 +0000 +++ b/src/if-linux.c Fri Feb 02 11:24:58 2018 +0000 @@ -1680,33 +1680,33 @@ 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 @@ /* 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
--- a/src/if.h Mon Jan 29 10:53:05 2018 +0000 +++ b/src/if.h Fri Feb 02 11:24:58 2018 +0000 @@ -187,7 +187,7 @@ #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);
