diff options
| author | Roy Marples <roy@marples.name> | 2019-04-02 13:35:51 +0100 |
|---|---|---|
| committer | Roy Marples <roy@marples.name> | 2019-04-02 13:35:51 +0100 |
| commit | cf924ee8a31557387b2e4f399ec3f3cf3c221ee9 (patch) | |
| tree | 23eafecc2e484448b5e4f7aac23bd2e5849f9311 /src/if-bsd.c | |
| parent | 885986d6b9b32d37ccf8dccda05f4c79c639a6fa (diff) | |
| download | dhcpcd-cf924ee8a31557387b2e4f399ec3f3cf3c221ee9.tar.xz | |
BSD: Fix detecting the interface for scoped routes
dhcpcd will now detect the IPv6 default route being deleted
by a third party, for example.
Diffstat (limited to 'src/if-bsd.c')
| -rw-r--r-- | src/if-bsd.c | 51 |
1 files changed, 40 insertions, 11 deletions
diff --git a/src/if-bsd.c b/src/if-bsd.c index 5c6347e4..7d5c7806 100644 --- a/src/if-bsd.c +++ b/src/if-bsd.c @@ -99,8 +99,8 @@ #endif #ifdef INET6 -static void -ifa_scope(struct sockaddr_in6 *, unsigned int); +static void ifa_setscope(struct sockaddr_in6 *, unsigned int); +static unsigned int ifa_getscope(const struct sockaddr_in6 *); #endif struct priv { @@ -418,9 +418,13 @@ if_findsa(struct dhcpcd_ctx *ctx, const struct sockaddr *sa) case AF_INET6: { const struct sockaddr_in6 *sin; + unsigned int scope; struct ipv6_addr *ia; sin = (const void *)sa; + scope = ifa_getscope(sin); + if (scope != 0) + return if_findindex(ctx->ifaces, scope); if ((ia = ipv6_findmaskaddr(ctx, &sin->sin6_addr))) return ia->iface; break; @@ -577,7 +581,7 @@ if_route(unsigned char cmd, const struct rt *rt) if_copysa(&gateway.sa, &rt->rt_gateway); #ifdef INET6 if (gateway.sa.sa_family == AF_INET6) - ifa_scope(&gateway.sin6, rt->rt_ifp->index); + ifa_setscope(&gateway.sin6, rt->rt_ifp->index); #endif ADDSA(&gateway.sa); } @@ -605,19 +609,27 @@ 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 | RTA_GATEWAY)) { + errno = EINVAL; return -1; + } #ifdef RTF_CLONED - if (rtm->rtm_flags & RTF_CLONED) + if (rtm->rtm_flags & RTF_CLONED) { + errno = ENOTSUP; return -1; + } #endif #ifdef RTF_LOCAL - if (rtm->rtm_flags & RTF_LOCAL) + if (rtm->rtm_flags & RTF_LOCAL) { + errno = ENOTSUP; return -1; + } #endif #ifdef RTF_BROADCAST - if (rtm->rtm_flags & RTF_BROADCAST) + if (rtm->rtm_flags & RTF_BROADCAST) { + errno = ENOTSUP; return -1; + } #endif get_addrs(rtm->rtm_addrs, rtm + 1, rti_info); @@ -751,7 +763,7 @@ if_addrflags(const struct interface *ifp, const struct in_addr *addr, #ifdef INET6 static void -ifa_scope(struct sockaddr_in6 *sin, unsigned int ifindex) +ifa_setscope(struct sockaddr_in6 *sin, unsigned int ifindex) { #ifdef __KAME__ @@ -771,6 +783,23 @@ ifa_scope(struct sockaddr_in6 *sin, unsigned int ifindex) #endif } +static unsigned int +ifa_getscope(const struct sockaddr_in6 *sin) +{ +#ifdef __KAME__ + uint16_t scope; +#endif + + if (!IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr)) + return 0; +#ifdef __KAME__ + memcpy(&scope, &sin->sin6_addr.s6_addr[2], sizeof(scope)); + return (unsigned int)ntohs(scope); +#else + return (unsigned int)sin->sin6_scope_id; +#endif +} + int if_address6(unsigned char cmd, const struct ipv6_addr *ia) { @@ -810,7 +839,7 @@ if_address6(unsigned char cmd, const struct ipv6_addr *ia) } ADDADDR(&ifa.ifra_addr, &ia->addr); - ifa_scope(&ifa.ifra_addr, ia->iface->index); + ifa_setscope(&ifa.ifra_addr, ia->iface->index); ipv6_mask(&mask, ia->prefix_len); ADDADDR(&ifa.ifra_prefixmask, &mask); @@ -887,7 +916,7 @@ if_addrflags6(const struct interface *ifp, const struct in6_addr *addr, strlcpy(ifr6.ifr_name, ifp->name, sizeof(ifr6.ifr_name)); ifr6.ifr_addr.sin6_family = AF_INET6; ifr6.ifr_addr.sin6_addr = *addr; - ifa_scope(&ifr6.ifr_addr, ifp->index); + ifa_setscope(&ifr6.ifr_addr, ifp->index); priv = (struct priv *)ifp->ctx->priv; if (ioctl(priv->pf_inet6_fd, SIOCGIFAFLAG_IN6, &ifr6) != -1) flags = ifr6.ifr_ifru.ifru_flags6; @@ -908,7 +937,7 @@ if_getlifetime6(struct ipv6_addr *ia) strlcpy(ifr6.ifr_name, ia->iface->name, sizeof(ifr6.ifr_name)); ifr6.ifr_addr.sin6_family = AF_INET6; ifr6.ifr_addr.sin6_addr = ia->addr; - ifa_scope(&ifr6.ifr_addr, ia->iface->index); + ifa_setscope(&ifr6.ifr_addr, ia->iface->index); priv = (struct priv *)ia->iface->ctx->priv; if (ioctl(priv->pf_inet6_fd, SIOCGIFALIFETIME_IN6, &ifr6) == -1) return -1; |
