From: Roy Marples Date: Sun, 1 Sep 2019 20:29:46 +0000 (+0100) Subject: BSD: Handle RTM_MISS X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fbb9b7c3b7714f02f857cdb5b9743ad0e1f10ee1;p=thirdparty%2Fdhcpcd.git BSD: Handle RTM_MISS RTM_MISS is sent when an address is not resolvable. This means that we want to use it but don't know how to reach it and thus is neighbour unreachable. If it's the address a RA came from and we don't have any others on that interface, solicit a new RA. We still handle RTM_DELETE as RTM_MISS as the address llentry could have been gc'ed or manually deleted and is thus unreachable. --- diff --git a/src/if-bsd.c b/src/if-bsd.c index ced065a1..2a7d677d 100644 --- a/src/if-bsd.c +++ b/src/if-bsd.c @@ -141,7 +141,7 @@ if_opensockets_os(struct dhcpcd_ctx *ctx) #ifdef RTM_IFANNOUNCE RTM_IFANNOUNCE, #endif - RTM_ADD, RTM_CHANGE, RTM_DELETE, + RTM_ADD, RTM_CHANGE, RTM_DELETE, RTM_MISS, #ifdef RTM_CHGADDR RTM_CHGADDR, #endif @@ -639,7 +639,11 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, const struct rt_msghdr *rtm) { const struct sockaddr *rti_info[RTAX_MAX]; - if (~rtm->rtm_addrs & (RTA_DST | RTA_GATEWAY)) { + if (!(rtm->rtm_addrs & RTA_DST)) { + errno = EINVAL; + return -1; + } + if (rtm->rtm_type != RTM_MISS && !(rtm->rtm_addrs & RTA_GATEWAY)) { errno = EINVAL; return -1; } @@ -674,19 +678,24 @@ 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. * 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; + if (rtm->rtm_addrs & RTA_GATEWAY) { + if (rti_info[RTAX_GATEWAY]->sa_family == AF_LINK) { + const struct sockaddr_dl *sdl; + + sdl = (const struct sockaddr_dl*) + (const void *)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]); + } - sdl = (const struct sockaddr_dl*) - (const void *)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]); + rt->rt_mtu = (unsigned int)rtm->rtm_rmx.rmx_mtu; if (rtm->rtm_index) @@ -1077,7 +1086,7 @@ if_rtm(struct dhcpcd_ctx *ctx, const struct rt_msghdr *rtm) return 0; if (if_copyrt(ctx, &rt, rtm) == -1) - return -1; + return errno == ENOTSUP ? 0 : -1; #ifdef INET6 /* @@ -1087,18 +1096,20 @@ if_rtm(struct dhcpcd_ctx *ctx, const struct rt_msghdr *rtm) * Ensure we don't call this for a newly incomplete state. */ if (rt.rt_dest.sa_family == AF_INET6 && - rt.rt_flags & RTF_HOST && + (rt.rt_flags & RTF_HOST || rtm->rtm_type == RTM_MISS) && !(rtm->rtm_type == RTM_ADD && !(rt.rt_dflags & RTDF_GATELINK))) { bool reachable; - reachable = rtm->rtm_type != RTM_DELETE && + reachable = (rtm->rtm_type == RTM_ADD || + rtm->rtm_type == RTM_CHANGE) && rt.rt_dflags & RTDF_GATELINK; ipv6nd_neighbour(ctx, &rt.rt_ss_dest.sin6.sin6_addr, reachable); } #endif - rt_recvrt(rtm->rtm_type, &rt, rtm->rtm_pid); + if (rtm->rtm_type != RTM_MISS) + rt_recvrt(rtm->rtm_type, &rt, rtm->rtm_pid); return 0; } @@ -1304,7 +1315,8 @@ if_dispatch(struct dhcpcd_ctx *ctx, const struct rt_msghdr *rtm) return if_ifinfo(ctx, (const void *)rtm); case RTM_ADD: /* FALLTHROUGH */ case RTM_CHANGE: /* FALLTHROUGH */ - case RTM_DELETE: + case RTM_DELETE: /* FALLTHROUGH */ + case RTM_MISS: return if_rtm(ctx, (const void *)rtm); #ifdef RTM_CHGADDR case RTM_CHGADDR: /* FALLTHROUGH */