From: Roy Marples Date: Mon, 22 Sep 2014 09:33:29 +0000 (+0000) Subject: Detect removal of IPv6 routes on BSD X-Git-Tag: v6.4.6~21 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3e4fb0bfdc541e49b66d9b6c312333dbe9519784;p=thirdparty%2Fdhcpcd.git Detect removal of IPv6 routes on BSD --- diff --git a/if-bsd.c b/if-bsd.c index 08825a19..52fecc86 100644 --- a/if-bsd.c +++ b/if-bsd.c @@ -85,12 +85,12 @@ #endif #define COPYOUT(sin, sa) \ - sin.s_addr = ((sa) != NULL) ? \ - (((struct sockaddr_in *)(void *)sa)->sin_addr).s_addr : 0 + if ((sa) && (sa)->sa_family == AF_INET) \ + (sin) = ((struct sockaddr_in*)(void *)(sa))->sin_addr #define COPYOUT6(sin, sa) \ - sin.s6_addr = ((sa) != NULL) ? \ - (((struct sockaddr_in6 *)(void *)sa)->sin6_addr).s6_addr : 0 + if ((sa) && (sa)->sa_family == AF_INET6) \ + (sin) = ((struct sockaddr_in6*)(void *)(sa))->sin6_addr #ifndef CLLADDR # define CLLADDR(s) ((const char *)((s)->sdl_data + (s)->sdl_nlen)) @@ -783,6 +783,7 @@ if_managelink(struct dhcpcd_ctx *ctx) struct rt rt; #endif #ifdef INET6 + struct rt6 rt6; struct in6_addr ia6; struct sockaddr_in6 *sin6; int ifa_flags; @@ -846,18 +847,29 @@ if_managelink(struct dhcpcd_ctx *ctx) break; cp = (char *)(void *)(rtm + 1); sa = (struct sockaddr *)(void *)cp; - if (sa->sa_family != AF_INET) - break; -#ifdef INET get_addrs(rtm->rtm_addrs, cp, rti_info); - memset(&rt, 0, sizeof(rt)); - rt.iface = NULL; - COPYOUT(rt.dest, rti_info[RTAX_DST]); - COPYOUT(rt.net, rti_info[RTAX_NETMASK]); - COPYOUT(rt.gate, rti_info[RTAX_GATEWAY]); - ipv4_routedeleted(ctx, &rt); + switch (sa->sa_family) { +#ifdef INET + case AF_INET: + memset(&rt, 0, sizeof(rt)); + rt.iface = NULL; + COPYOUT(rt.dest, rti_info[RTAX_DST]); + COPYOUT(rt.net, rti_info[RTAX_NETMASK]); + COPYOUT(rt.gate, rti_info[RTAX_GATEWAY]); + ipv4_routedeleted(ctx, &rt); + break; #endif - break; +#ifdef INET6 + case AF_INET6: + memset(&rt6, 0, sizeof(rt6)); + rt6.iface = NULL; + COPYOUT6(rt6.dest, rti_info[RTAX_DST]); + COPYOUT6(rt6.net, rti_info[RTAX_NETMASK]); + COPYOUT6(rt6.gate, rti_info[RTAX_GATEWAY]); + ipv6_routedeleted(ctx, &rt6); + break; +#endif + } #ifdef RTM_CHGADDR case RTM_CHGADDR: /* FALLTHROUGH */ #endif diff --git a/ipv6.c b/ipv6.c index 5986a18a..3ccc30bb 100644 --- a/ipv6.c +++ b/ipv6.c @@ -1097,7 +1097,8 @@ find_route6(struct rt6_head *rts, const struct rt6 *r) TAILQ_FOREACH(rt, rts, next) { if (IN6_ARE_ADDR_EQUAL(&rt->dest, &r->dest) && #if HAVE_ROUTE_METRIC - rt->iface->metric == r->iface->metric && + (r->iface == NULL || rt->iface == NULL || + rt->iface->metric == r->iface->metric) #endif IN6_ARE_ADDR_EQUAL(&rt->net, &r->net)) return rt; @@ -1110,8 +1111,9 @@ desc_route(const char *cmd, const struct rt6 *rt) { char destbuf[INET6_ADDRSTRLEN]; char gatebuf[INET6_ADDRSTRLEN]; - const char *ifname = rt->iface->name, *dest, *gate; + const char *ifname, *dest, *gate; + ifname = rt->iface ? rt->iface->name : "(no iface)"; dest = inet_ntop(AF_INET6, &rt->dest, destbuf, INET6_ADDRSTRLEN); gate = inet_ntop(AF_INET6, &rt->gate, gatebuf, INET6_ADDRSTRLEN); if (IN6_ARE_ADDR_EQUAL(&rt->gate, &in6addr_any)) @@ -1127,6 +1129,22 @@ desc_route(const char *cmd, const struct rt6 *rt) dest, ipv6_prefixlen(&rt->net), gate); } +/* If something other than dhcpcd removes a route, + * we need to remove it from our internal table. */ +int +ipv6_routedeleted(struct dhcpcd_ctx *ctx, const struct rt6 *rt) +{ + struct rt6 *f; + + f = find_route6(ctx->ipv6->routes, rt); + if (f == NULL) + return 0; + desc_route("removing", f); + TAILQ_REMOVE(ctx->ipv6->routes, f, next); + free(f); + return 1; +} + #define n_route(a) nc_route(1, a, a) #define c_route(a, b) nc_route(0, a, b) static int diff --git a/ipv6.h b/ipv6.h index 5c932aa2..fac9458a 100644 --- a/ipv6.h +++ b/ipv6.h @@ -199,6 +199,7 @@ void ipv6_free_ll_callbacks(struct interface *); int ipv6_start(struct interface *); void ipv6_free(struct interface *); void ipv6_ctxfree(struct dhcpcd_ctx *); +int ipv6_routedeleted(struct dhcpcd_ctx *, const struct rt6 *); int ipv6_removesubnet(struct interface *, struct ipv6_addr *); void ipv6_buildroutes(struct dhcpcd_ctx *);