]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
inet6: simplify setup of kernel
authorRoy Marples <roy@marples.name>
Fri, 2 Feb 2018 11:24:58 +0000 (11:24 +0000)
committerRoy Marples <roy@marples.name>
Fri, 2 Feb 2018 11:24:58 +0000 (11:24 +0000)
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.

src/dhcpcd.c
src/dhcpcd.conf.5.in
src/if-bsd.c
src/if-linux.c
src/if.h

index 7f3ef86b145816789ae248dda406f2ac28dda952..d025ccdf43d737a3181bcdc992d888249d503a9e 100644 (file)
@@ -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
 
index 1afa4e802851f1ce5f0990000f2a730abf3f987a..f1a8a8d7d6670e95d6344dd0f3a07e2ee5bd46ee 100644 (file)
@@ -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.
index 6ec9e12ba8c820dec306b1c65b81b994bad5aaa5..26d75df9a8b7e6d22a21b8e02c1c951aed408fa4 100644 (file)
@@ -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
index b934834a9bee3268292f0fa12e023ed2ec660e55..e802366afb794f68319edea0a36d9a727e7a0df1 100644 (file)
@@ -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
index a1945fe6d10eeddae0f9c0ff132d6768af72b95e..602f8e8352aea74e768cea878742b06446782b36 100644 (file)
--- 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);