}
#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
#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
#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) || \
#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
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);
/* 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