summaryrefslogtreecommitdiffstats
path: root/src/if-bsd.c
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2019-09-01 21:29:46 +0100
committerRoy Marples <roy@marples.name>2019-09-01 21:29:46 +0100
commitfbb9b7c3b7714f02f857cdb5b9743ad0e1f10ee1 (patch)
tree01fcd6492189be33123346f5b2eadb8d7f6bdb16 /src/if-bsd.c
parent80bf495aa0748b75e6d6f3f3a0b616d6d71fa482 (diff)
downloaddhcpcd-fbb9b7c3b7714f02f857cdb5b9743ad0e1f10ee1.tar.xz
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.
Diffstat (limited to 'src/if-bsd.c')
-rw-r--r--src/if-bsd.c42
1 files changed, 27 insertions, 15 deletions
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 */