From c1d1a885ae469dd98533b38da3c7753de1597d77 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Mon, 14 Oct 2024 10:48:23 +0100 Subject: [PATCH] IPv6: allow any global address for default route Regardless if we are a router or not. BSD IPv6 source address selection does really matter for this. This fixes FreeBSD systes where the forwarding sysctl is set by the routing script which starts late in the day where dhcpcd is already running and won't get the default route applied until another RA comes in which could be a while. --- src/if-bsd.c | 34 +--------------------------------- src/if-linux.c | 17 ----------------- src/if-sun.c | 7 ------- src/ipv6.c | 28 +++++++--------------------- src/privsep-root.c | 17 ----------------- src/privsep-root.h | 1 - 6 files changed, 8 insertions(+), 96 deletions(-) diff --git a/src/if-bsd.c b/src/if-bsd.c index 42d13505..7c3e5e10 100644 --- a/src/if-bsd.c +++ b/src/if-bsd.c @@ -1658,8 +1658,7 @@ if_machinearch(char *str, size_t len) } #ifdef INET6 -#if (defined(IPV6CTL_ACCEPT_RTADV) && !defined(ND6_IFF_ACCEPT_RTADV)) || \ - defined(IPV6CTL_FORWARDING) +#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 @@ -1731,37 +1730,6 @@ if_applyra(const struct ra *rap) #endif } -#ifndef IPV6CTL_FORWARDING -#define get_inet6_sysctlbyname(code) inet6_sysctlbyname(code, 0, 0) -#define set_inet6_sysctlbyname(code, val) inet6_sysctlbyname(code, val, 1) -static int -inet6_sysctlbyname(const char *name, int val, int action) -{ - size_t size; - - size = sizeof(val); - if (action) { - if (sysctlbyname(name, NULL, 0, &val, size) == -1) - return -1; - return 0; - } - if (sysctlbyname(name, &val, &size, NULL, 0) == -1) - return -1; - return val; -} -#endif - -int -ip6_forwarding(__unused const char *ifname) -{ - -#ifdef IPV6CTL_FORWARDING - return get_inet6_sysctl(IPV6CTL_FORWARDING); -#else - return get_inet6_sysctlbyname("net.inet6.ip6.forwarding"); -#endif -} - #ifdef SIOCIFAFATTACH static int if_af_attach(const struct interface *ifp, int af) diff --git a/src/if-linux.c b/src/if-linux.c index 3217161d..53fa48f5 100644 --- a/src/if-linux.c +++ b/src/if-linux.c @@ -2265,21 +2265,4 @@ if_applyra(const struct ra *rap) return error; } -int -ip6_forwarding(const char *ifname) -{ - char path[256], buf[64]; - int error, i; - - if (ifname == NULL) - ifname = "all"; - snprintf(path, sizeof(path), "%s/%s/forwarding", p_conf, ifname); - if (readfile(path, buf, sizeof(buf)) == -1) - return -1; - i = (int)strtoi(buf, NULL, 0, INT_MIN, INT_MAX, &error); - if (error != 0 && error != ENOTSUP) - return -1; - return i; -} - #endif /* INET6 */ diff --git a/src/if-sun.c b/src/if-sun.c index e22634d9..c1350cb6 100644 --- a/src/if-sun.c +++ b/src/if-sun.c @@ -1746,11 +1746,4 @@ if_setup_inet6(__unused const struct interface *ifp) { } - -int -ip6_forwarding(__unused const char *ifname) -{ - - return 1; -} #endif diff --git a/src/ipv6.c b/src/ipv6.c index 1b6c264c..46a1278e 100644 --- a/src/ipv6.c +++ b/src/ipv6.c @@ -1114,29 +1114,10 @@ ipv6_anyglobal(struct interface *sifp) { struct ipv6_addr *ia; struct interface *ifp; - bool forwarding; - - ia = ipv6_ifanyglobal(sifp); - if (ia != NULL) - return ia; - - /* BSD forwarding is either on or off. - * Linux forwarding is technically the same as it's - * configured by the "all" interface. - * Per interface only affects IsRouter of NA messages. */ -#ifdef PRIVSEP_SYSCTL - if (IN_PRIVSEP(sifp->ctx)) - forwarding = ps_root_ip6forwarding(sifp->ctx, NULL) > 0; - else -#endif - forwarding = ip6_forwarding(NULL) > 0; - - if (!forwarding) - return NULL; + /* IP6 source address selection does not care if we are a router + * or not, so just find a global address on any interface. */ TAILQ_FOREACH(ifp, sifp->ctx->ifaces, next) { - if (ifp == sifp) - continue; ia = ipv6_ifanyglobal(ifp); if (ia != NULL) return ia; @@ -2356,6 +2337,11 @@ inet6_raroutes(rb_tree_t *routes, struct dhcpcd_ctx *ctx) /* add default route */ if (rap->lifetime == 0) continue; + /* We only want to install a default route if we have + * an address that we can use other it. + * If we don't have any global addresses any request + * over the interface just times out. + * This avoids a badly setup IPv6 enabled router. */ if (ipv6_anyglobal(rap->iface) == NULL) continue; rt = inet6_makerouter(rap); diff --git a/src/privsep-root.c b/src/privsep-root.c index d33286ec..8a994b80 100644 --- a/src/privsep-root.c +++ b/src/privsep-root.c @@ -611,11 +611,6 @@ ps_root_recvmsgcb(void *arg, struct ps_msghdr *psm, struct msghdr *msg) free_rdata = true; break; #endif -#if defined(INET6) && defined(PRIVSEP_SYSCTL) - case PS_IP6FORWARDING: - err = ip6_forwarding(data); - break; -#endif #ifdef PLUGIN_DEV case PS_DEV_INITTED: err = dev_initialised(ctx, data); @@ -1173,18 +1168,6 @@ err: } #endif -#ifdef PRIVSEP_SYSCTL -ssize_t -ps_root_ip6forwarding(struct dhcpcd_ctx *ctx, const char *ifname) -{ - - if (ps_sendcmd(ctx, PS_ROOT_FD(ctx), PS_IP6FORWARDING, 0, - ifname, ifname != NULL ? strlen(ifname) + 1 : 0) == -1) - return -1; - return ps_root_readerror(ctx, NULL, 0); -} -#endif - #ifdef AUTH int ps_root_getauthrdm(struct dhcpcd_ctx *ctx, uint64_t *rdm) diff --git a/src/privsep-root.h b/src/privsep-root.h index 3bc5f224..aede188c 100644 --- a/src/privsep-root.h +++ b/src/privsep-root.h @@ -43,7 +43,6 @@ void ps_root_signalcb(int, void *); ssize_t ps_root_readerror(struct dhcpcd_ctx *, void *, size_t); ssize_t ps_root_mreaderror(struct dhcpcd_ctx *, void **, size_t *); ssize_t ps_root_ioctl(struct dhcpcd_ctx *, ioctl_request_t, void *, size_t); -ssize_t ps_root_ip6forwarding(struct dhcpcd_ctx *, const char *); ssize_t ps_root_unlink(struct dhcpcd_ctx *, const char *); ssize_t ps_root_filemtime(struct dhcpcd_ctx *, const char *, time_t *); ssize_t ps_root_readfile(struct dhcpcd_ctx *, const char *, void *, size_t); -- 2.47.3