#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))
struct rt rt;
#endif
#ifdef INET6
+ struct rt6 rt6;
struct in6_addr ia6;
struct sockaddr_in6 *sin6;
int ifa_flags;
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
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;
{
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))
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