diff options
| author | Roy Marples <roy@marples.name> | 2020-02-08 17:29:03 +0000 |
|---|---|---|
| committer | Roy Marples <roy@marples.name> | 2020-02-08 17:30:35 +0000 |
| commit | dd2d73d45140ac1aa9a4b85bdf87751f96766548 (patch) | |
| tree | 1dcca0db4bf0d062627349aba3b4004500b1a539 /src/if-bsd.c | |
| parent | 91b11be6dc29b3e3ff4ea50dd54e589d30b443c1 (diff) | |
| download | dhcpcd-dd2d73d45140ac1aa9a4b85bdf87751f96766548.tar.xz | |
BSD: Add support for RO_MISSFILTER route(4) socket option
This allows dhcpcd to only listen for RTM_MISS generated by
default routers dhcpcd *could* install so if one becomes
unreachable we can pick another.
Diffstat (limited to 'src/if-bsd.c')
| -rw-r--r-- | src/if-bsd.c | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/src/if-bsd.c b/src/if-bsd.c index 76ba114e..0e631819 100644 --- a/src/if-bsd.c +++ b/src/if-bsd.c @@ -1509,6 +1509,78 @@ if_dispatch(struct dhcpcd_ctx *ctx, const struct rt_msghdr *rtm) return 0; } +static int +if_missfilter0(struct dhcpcd_ctx *ctx, struct interface *ifp, + struct sockaddr *sa) +{ + size_t salen = (size_t)RT_ROUNDUP(sa->sa_len); + size_t newlen = ctx->rt_missfilterlen + salen; + size_t diff = salen - (sa->sa_len); + uint8_t *cp; + + if (ctx->rt_missfiltersize < newlen) { + void *n = realloc(ctx->rt_missfilter, newlen); + if (n == NULL) + return -1; + ctx->rt_missfilter = n; + ctx->rt_missfiltersize = newlen; + } + +#ifdef INET6 + if (sa->sa_family == AF_INET6) { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; + + ifa_setscope(sin6, ifp->index); + } +#endif + + cp = ctx->rt_missfilter + ctx->rt_missfilterlen; + memcpy(cp, sa, sa->sa_len); + if (diff != 0) + memset(cp + sa->sa_len, 0, diff); + ctx->rt_missfilterlen += salen; + +#ifdef INET6 + if (sa->sa_family == AF_INET6) { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; + + ifa_setscope(sin6, 0); + } +#endif + + return 0; +} + +int +if_missfilter(struct interface *ifp, struct sockaddr *sa) +{ + + return if_missfilter0(ifp->ctx, ifp, sa); +} + +int +if_missfilter_apply(struct dhcpcd_ctx *ctx) +{ +#ifdef RO_MISSFILTER + if (ctx->rt_missfilterlen == 0) { + struct sockaddr sa = { + .sa_family = AF_UNSPEC, + .sa_len = sizeof(sa), + }; + + if (if_missfilter0(ctx, NULL, &sa) == -1) + return -1; + } + + return setsockopt(ctx->link_fd, PF_ROUTE, RO_MISSFILTER, + ctx->rt_missfilter, (socklen_t)ctx->rt_missfilterlen); +#else +#warning kernel does not support RTM_MISS DST filtering + errno = ENOTSUP; + return -1; +#endif +} + __CTASSERT(offsetof(struct rt_msghdr, rtm_msglen) == 0); int if_handlelink(struct dhcpcd_ctx *ctx) |
