From: Roy Marples Date: Fri, 23 Aug 2019 17:01:24 +0000 (+0100) Subject: BSD: Fix router reachability tests X-Git-Tag: v8.0.4~52 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9996285f1c23d1e62b93c48f7fc84fd5939990fc;p=thirdparty%2Fdhcpcd.git 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. --- diff --git a/src/if-bsd.c b/src/if-bsd.c index 6d5531cb..83a2f169 100644 --- a/src/if-bsd.c +++ b/src/if-bsd.c @@ -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); diff --git a/src/route.h b/src/route.h index d1613943..74570fa7 100644 --- a/src/route.h +++ b/src/route.h @@ -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; };