]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
BSD: Fix router reachability tests
authorRoy Marples <roy@marples.name>
Fri, 23 Aug 2019 17:01:24 +0000 (18:01 +0100)
committerRoy Marples <roy@marples.name>
Fri, 23 Aug 2019 17:01:24 +0000 (18:01 +0100)
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.

src/if-bsd.c
src/route.h

index 6d5531cb632634e479dfc327b93b48960e5f33c2..83a2f1694b840eb941e540eed66dc46d80e6864a 100644 (file)
@@ -674,9 +674,15 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, const struct rt_msghdr *rtm)
                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 @@ if_rtm(struct dhcpcd_ctx *ctx, const struct rt_msghdr *rtm)
         * 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);
index d1613943944adb021bb21eab2c6247622fb4a586..74570fa7940b6479bf9a1637d72a85240a4906a2 100644 (file)
@@ -92,6 +92,7 @@ struct rt {
 #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;
 };