NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: kern/52554: IPv6 connections not routing to default gateway



On 03/10/2017 09:05, Roy Marples wrote:
> I appear as if by magic wearing my wizards robe and pointy hat!
> 
> dhcpcd looks like it should be doing this correctly.
> https://roy.marples.name/git/dhcpcd.git/tree/src/ipv6nd.c#n506

OK, so it turned out there were quite a few issues with multiple routers
in dhcpcd-7 which I've fixed.
Here's a patch to fix them - it applies to dhcpcd-7.0.0-rc2, which is in
-current and pkgsrc-current.
It *might* apply to the version in NetBSD-8, but I'm not sure.

You could also take a copy of my git dhcpcd repo with these patches
already or download a tarball from my site and apply the attached patch:
git://roy.marples.name/dhcpcd.git
ftp://roy.marples.name/pub/dhcpcd/dhcpcd-7.0.0-rc2.tar.xz

Let me know how it works out for you!

Roy
diff --git a/src/ipv6nd.c b/src/ipv6nd.c
index 24b1cf55..4b2127ff 100644
--- a/src/ipv6nd.c
+++ b/src/ipv6nd.c
@@ -158,6 +158,10 @@ static void ipv6nd_handledata(void *);
 #define IPV6_RECVPKTINFO IPV6_PKTINFO
 #endif
 
+/* Handy defines */
+#define ipv6nd_free_ra(ra) ipv6nd_freedrop_ra((ra),  0)
+#define ipv6nd_drop_ra(ra) ipv6nd_freedrop_ra((ra),  1)
+
 void
 ipv6nd_printoptions(const struct dhcpcd_ctx *ctx,
     const struct dhcp_opt *opts, size_t opts_len)
@@ -448,14 +452,14 @@ ipv6nd_removefreedrop_ra(struct ra *rap, int remove_ra, int drop_ra)
 
 	eloop_timeout_delete(rap->iface->ctx->eloop, NULL, rap->iface);
 	eloop_timeout_delete(rap->iface->ctx->eloop, NULL, rap);
-	if (remove_ra && !drop_ra)
+	if (remove_ra)
 		TAILQ_REMOVE(rap->iface->ctx->ra_routers, rap, next);
 	ipv6_freedrop_addrs(&rap->addrs, drop_ra, NULL);
 	free(rap->data);
 	free(rap);
 }
 
-void
+static void
 ipv6nd_freedrop_ra(struct ra *rap, int drop)
 {
 
@@ -1396,27 +1400,20 @@ ipv6nd_expirera(void *arg)
 void
 ipv6nd_drop(struct interface *ifp)
 {
-	struct ra *rap;
+	struct ra *rap, *ran;
 	uint8_t expired = 0;
-	TAILQ_HEAD(rahead, ra) rtrs;
 
 	if (ifp->ctx->ra_routers == NULL)
 		return;
 
 	eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
-	TAILQ_INIT(&rtrs);
-	TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
+	TAILQ_FOREACH_SAFE(rap, ifp->ctx->ra_routers, next, ran) {
 		if (rap->iface == ifp) {
 			rap->expired = expired = 1;
-			TAILQ_REMOVE(ifp->ctx->ra_routers, rap, next);
-			TAILQ_INSERT_TAIL(&rtrs, rap, next);
+			ipv6nd_drop_ra(rap);
 		}
 	}
 	if (expired) {
-		while ((rap = TAILQ_FIRST(&rtrs))) {
-			TAILQ_REMOVE(&rtrs, rap, next);
-			ipv6nd_drop_ra(rap);
-		}
 		rt_build(ifp->ctx, AF_INET6);
 		if ((ifp->options->options & DHCPCD_NODROP) != DHCPCD_NODROP)
 			script_runreason(ifp, "ROUTERADVERT");
diff --git a/src/ipv6nd.h b/src/ipv6nd.h
index 6254760b..d49fd34c 100644
--- a/src/ipv6nd.h
+++ b/src/ipv6nd.h
@@ -93,9 +93,6 @@ const struct ipv6_addr *ipv6nd_iffindaddr(const struct interface *ifp,
     const struct in6_addr *addr, unsigned int flags);
 struct ipv6_addr *ipv6nd_findaddr(struct dhcpcd_ctx *,
     const struct in6_addr *, unsigned int);
-void ipv6nd_freedrop_ra(struct ra *, int);
-#define ipv6nd_free_ra(ra) ipv6nd_freedrop_ra((ra),  0)
-#define ipv6nd_drop_ra(ra) ipv6nd_freedrop_ra((ra),  1)
 ssize_t ipv6nd_free(struct interface *);
 void ipv6nd_expirera(void *arg);
 int ipv6nd_hasra(const struct interface *);
diff --git a/src/route.c b/src/route.c
index 08ac7c05..29ca47eb 100644
--- a/src/route.c
+++ b/src/route.c
@@ -418,7 +418,7 @@ rt_cmp(const struct rt *r1, const struct rt *r2)
 #ifdef HAVE_ROUTE_METRIC
 	    r1->rt_metric == r2->rt_metric &&
 #endif
-	    sa_cmp(&r1->rt_gateway, &r1->rt_gateway) == 0);
+	    sa_cmp(&r1->rt_gateway, &r2->rt_gateway) == 0);
 }
 
 static bool
@@ -464,9 +464,6 @@ rt_build(struct dhcpcd_ctx *ctx, int af)
 	struct rt_head routes, added;
 	struct rt *rt, *rtn;
 	unsigned long long o;
-#ifdef INET6
-	bool have_default = false;
-#endif
 
 	/* We need to have the interfaces in the correct order to ensure
 	 * our routes are managed correctly. */
@@ -500,17 +497,10 @@ rt_build(struct dhcpcd_ctx *ctx, int af)
 		if (rt_doroute(rt)) {
 			TAILQ_REMOVE(&routes, rt, rt_next);
 			TAILQ_INSERT_TAIL(&added, rt, rt_next);
-#ifdef INET6
-			if (sa_is_unspecified(&rt->rt_dest) &&
-			    sa_is_unspecified(&rt->rt_netmask))
-				have_default = true;
-#endif
 		}
 	}
 
-	/* Remove old routes we used to manage
-	 * If we own the default route, but not RA management itself
-	 * then we need to preserve the last best default route we had */
+	/* Remove old routes we used to manage. */
 	TAILQ_FOREACH_SAFE(rt, &ctx->routes, rt_next, rtn) {
 		if (rt->rt_dest.sa_family != af &&
 		    rt->rt_gateway.sa_family != af)
@@ -520,16 +510,6 @@ rt_build(struct dhcpcd_ctx *ctx, int af)
 			o = rt->rt_ifp->options ?
 			    rt->rt_ifp->options->options :
 			    ctx->options;
-#ifdef INET6
-			if (!have_default &&
-			    rt->rt_dest.sa_family == AF_INET6 &&
-			    sa_is_unspecified(&rt->rt_dest))
-				have_default = true;
-				/* no need to add it back to our routing table
-				 * as we delete an exiting route when we add
-				 * a new one */
-			else
-#endif
 			if ((o &
 				(DHCPCD_EXITING | DHCPCD_PERSISTENT)) !=
 				(DHCPCD_EXITING | DHCPCD_PERSISTENT))


Home | Main Index | Thread Index | Old Index