changeset 4645:7d0f6ee7b39e draft

BSD: Fix router reachability tests dhcpcd likes to indicate an on-link route as a NULL gateway. However, we were testing this for an AF_LINK address to ensure reachability. As such, it was possible to log a false positive. Instead, record the existance of a valid AF_LINK address via RTDF_GATELINK. While here, ensure that we only treat RTM_DELETE as unreachable and only other messages with RTDF_GATELINK as reachable, ignoring other states so that a new incomplete address won't make us unreachable if we're just discovering it.
author Roy Marples <roy@marples.name>
date Fri, 23 Aug 2019 18:01:24 +0100
parents 292402db994b
children c83adc0e8b5f
files src/if-bsd.c src/route.h
diffstat 2 files changed, 16 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/src/if-bsd.c	Wed Aug 21 17:16:25 2019 +0100
+++ b/src/if-bsd.c	Fri Aug 23 18:01:24 2019 +0100
@@ -674,9 +674,15 @@
 		if (rt->rt_netmask.sa_family == 255) /* Why? */
 			rt->rt_netmask.sa_family = rt->rt_dest.sa_family;
 	}
-	/* dhcpcd likes an unspecified gateway to indicate via the link. */
-	if (rt->rt_flags & RTF_GATEWAY &&
-	    rti_info[RTAX_GATEWAY]->sa_family != AF_LINK)
+	/* dhcpcd likes an unspecified gateway to indicate via the link.
+	 * However we need to know if gateway was a link with an address. */
+	if (rti_info[RTAX_GATEWAY]->sa_family == AF_LINK) {
+		const struct sockaddr_dl *sdl;
+
+		sdl = (const struct sockaddr_dl*)rti_info[RTAX_GATEWAY];
+		if (sdl->sdl_alen != 0)
+			rt->rt_dflags |= RTDF_GATELINK;
+	} else if (rtm->rtm_flags & RTF_GATEWAY)
 		if_copysa(&rt->rt_gateway, rti_info[RTAX_GATEWAY]);
 	if (rtm->rtm_addrs & RTA_IFA)
 		if_copysa(&rt->rt_ifa, rti_info[RTAX_IFA]);
@@ -1077,20 +1083,13 @@
 	 * BSD announces host routes.
 	 * As such, we should be notified of reachability by its
 	 * existance with a hardware address.
+	 * Ensure we don't call this for an incomplete state.
 	 */
-	if (rt.rt_dest.sa_family == AF_INET6 && rt.rt_flags & RTF_HOST) {
-		struct sockaddr_in6 dest;
-		struct sockaddr_dl sdl;
-
-		memcpy(&dest, &rt.rt_dest, rt.rt_dest.sa_len);
-		if (rt.rt_gateway.sa_family == AF_LINK)
-			memcpy(&sdl, &rt.rt_gateway, rt.rt_gateway.sa_len);
-		else
-			sdl.sdl_alen = 0;
-		ipv6nd_neighbour(ctx, &dest.sin6_addr,
-		    rtm->rtm_type != RTM_DELETE && sdl.sdl_alen ?
-		    IPV6ND_REACHABLE : 0);
-	}
+	if (rt.rt_dest.sa_family == AF_INET6 &&
+	    rt.rt_flags & RTF_HOST &&
+	    (rtm->rtm_type == RTM_DELETE || rt.rt_dflags & RTDF_GATELINK))
+		ipv6nd_neighbour(ctx, &rt.rt_ss_dest.sin6.sin6_addr,
+		    rtm->rtm_type != RTM_DELETE ? IPV6ND_REACHABLE : 0);
 #endif
 
 	rt_recvrt(rtm->rtm_type, &rt, rtm->rtm_pid);
--- a/src/route.h	Wed Aug 21 17:16:25 2019 +0100
+++ b/src/route.h	Fri Aug 23 18:01:24 2019 +0100
@@ -92,6 +92,7 @@
 #define	RTDF_RA			0x08		/* Router Advertisement */
 #define	RTDF_DHCP		0x10		/* DHCP route */
 #define	RTDF_STATIC		0x20		/* Configured in dhcpcd */
+#define	RTDF_GATELINK		0x40		/* Gateway is on link */
 	size_t			rt_order;
 	rb_node_t		rt_tree;
 };