From 34b14cedc67fc7ee84d9bf17b260e90722217bf3 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Thu, 5 Sep 2019 10:03:13 +0100 Subject: [PATCH] inet6: Fix default route not being installed We need to check for global addresses on any forwarding interface, not just the interface we received the RA on. Otherwise this breaks routers who get a default route only from the RA and IPv6 addresses only by prefix delegation to other interfaces. --- src/ipv6.c | 39 +++++++++++++++++++++------------------ src/ipv6.h | 2 +- src/ipv6nd.c | 2 +- 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/src/ipv6.c b/src/ipv6.c index ca54dab9..99f6a8a4 100644 --- a/src/ipv6.c +++ b/src/ipv6.c @@ -1065,28 +1065,31 @@ ipv6_getstate(struct interface *ifp) } struct ipv6_addr * -ipv6_ifanyglobal(struct interface *ifp) +ipv6_anyglobal(struct interface *sifp) { + struct interface *ifp; struct ipv6_state *state; struct ipv6_addr *ia; - if (ifp->carrier == LINK_DOWN) - return NULL; - - state = IPV6_STATE(ifp); - if (state == NULL) - return NULL; + TAILQ_FOREACH(ifp, sifp->ctx->ifaces, next) { + if (ifp != sifp && ip6_forwarding(ifp->name) != 1) + continue; - TAILQ_FOREACH(ia, &state->addrs, next) { - if (IN6_IS_ADDR_LINKLOCAL(&ia->addr)) + state = IPV6_STATE(ifp); + if (state == NULL) continue; - /* Let's be optimistic. - * Any decent OS won't forward or accept traffic - * from/to tentative or detached addresses. */ - if (!(ia->addr_flags & IN6_IFF_DUPLICATED)) - break; + + TAILQ_FOREACH(ia, &state->addrs, next) { + if (IN6_IS_ADDR_LINKLOCAL(&ia->addr)) + continue; + /* Let's be optimistic. + * Any decent OS won't forward or accept traffic + * from/to tentative or detached addresses. */ + if (!(ia->addr_flags & IN6_IFF_DUPLICATED)) + return ia; + } } - return ia; + return NULL; } void @@ -1133,7 +1136,7 @@ ipv6_handleifa(struct dhcpcd_ctx *ctx, return; if ((state = ipv6_getstate(ifp)) == NULL) return; - anyglobal = ipv6_ifanyglobal(ifp) != NULL; + anyglobal = ipv6_anyglobal(ifp) != NULL; TAILQ_FOREACH(ia, &state->addrs, next) { if (IN6_ARE_ADDR_EQUAL(&ia->addr, addr)) @@ -1252,7 +1255,7 @@ out: * call rt_build to add/remove the default route. */ if (ifp->active && ifp->options->options & DHCPCD_IPV6 && !(ctx->options & DHCPCD_RTBUILD) && - (ipv6_ifanyglobal(ifp) != NULL) != anyglobal) + (ipv6_anyglobal(ifp) != NULL) != anyglobal) rt_build(ctx, AF_INET6); } @@ -2335,7 +2338,7 @@ inet6_raroutes(rb_tree_t *routes, struct dhcpcd_ctx *ctx) } if (rap->lifetime == 0) continue; - if (ipv6_ifanyglobal(rap->iface) == NULL) + if (ipv6_anyglobal(rap->iface) == NULL) continue; rt = inet6_makerouter(rap); if (rt == NULL) diff --git a/src/ipv6.h b/src/ipv6.h index 7dbf4fe6..547957eb 100644 --- a/src/ipv6.h +++ b/src/ipv6.h @@ -273,7 +273,7 @@ int ipv6_handleifa_addrs(int, struct ipv6_addrhead *, const struct ipv6_addr *, struct ipv6_addr *ipv6_iffindaddr(struct interface *, const struct in6_addr *, int); int ipv6_hasaddr(const struct interface *); -struct ipv6_addr *ipv6_ifanyglobal(struct interface *); +struct ipv6_addr *ipv6_anyglobal(struct interface *); int ipv6_findaddrmatch(const struct ipv6_addr *, const struct in6_addr *, unsigned int); struct ipv6_addr *ipv6_findaddr(struct dhcpcd_ctx *, diff --git a/src/ipv6nd.c b/src/ipv6nd.c index affc9117..929b071d 100644 --- a/src/ipv6nd.c +++ b/src/ipv6nd.c @@ -1290,7 +1290,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx, } } - if (new_data && !has_address && rap->lifetime && !ipv6_ifanyglobal(ifp)) + if (new_data && !has_address && rap->lifetime && !ipv6_anyglobal(ifp)) logwarnx("%s: no global addresses for default route", ifp->name); -- 2.47.2