state->raw_fd = -1;
/* Now is a good time to find IPv4 routes */
- if_initrt(ifp->ctx);
+ if_initrt(ifp->ctx, AF_INET);
}
state->state = DHS_INIT;
if (k && !carrier_warned) {
ifd_state = D6_STATE(ifd);
ipv6_addaddrs(&ifd_state->addrs);
- if_initrt(ifd->ctx);
+ if_initrt(ifd->ctx, AF_INET6);
rt_build(ifd->ctx, AF_INET6);
dhcp6_script_try_run(ifd, 1);
}
state = D6_STATE(ifp);
state->state = DH6S_DELEGATED;
ipv6_addaddrs(&state->addrs);
- if_initrt(ifp->ctx);
+ if_initrt(ifp->ctx, AF_INET6);
rt_build(ifp->ctx, AF_INET6);
dhcp6_script_try_run(ifp, 1);
}
else if (state->expire == 0)
logger(ifp->ctx, has_new ? LOG_INFO : LOG_DEBUG,
"%s: will expire", ifp->name);
- if_initrt(ifp->ctx);
+ if_initrt(ifp->ctx, AF_INET6);
rt_build(ifp->ctx, AF_INET6);
dhcp6_writelease(ifp);
#ifndef SMALL
}
int
-if_initrt(struct dhcpcd_ctx *ctx)
+if_initrt(struct dhcpcd_ctx *ctx, int af)
{
struct rt_msghdr *rtm;
int mib[6];
char *buf, *p, *end;
struct rt rt;
- rt_headclear(&ctx->kroutes);
+ rt_headclear(&ctx->kroutes, AF_UNSPEC);
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
mib[2] = 0;
- mib[3] = AF_UNSPEC;
+ mib[3] = af;
mib[4] = NET_RT_DUMP;
mib[5] = 0;
}
int
-if_initrt(struct dhcpcd_ctx *ctx)
+if_initrt(struct dhcpcd_ctx *ctx, int af)
{
struct nlmr nlm;
- rt_headclear(&ctx->kroutes);
+ rt_headclear(&ctx->kroutes, af);
memset(&nlm, 0, sizeof(nlm));
nlm.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
nlm.hdr.nlmsg_type = RTM_GETROUTE;
nlm.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_MATCH;
nlm.rt.rtm_table = RT_TABLE_MAIN;
- nlm.rt.rtm_family = AF_UNSPEC;
+ nlm.rt.rtm_family = af;
return send_netlink(ctx, NULL, NETLINK_ROUTE, &nlm.hdr, &_if_initrt);
}
free(ifo->config[i++]);
free(ifo->config);
}
- rt_headclear(&ifo->routes);
+ rt_headclear(&ifo->routes, AF_UNSPEC);
free(ifo->script);
free(ifo->arping);
free(ifo->blacklist);
int
-if_initrt(struct dhcpcd_ctx *ctx)
+if_initrt(struct dhcpcd_ctx *ctx, int af)
{
- rt_headclear(&ctx->kroutes);
+ rt_headclear(&ctx->kroutes, af);
#ifdef INET
- if (if_parsert(ctx, MIB2_IP,MIB2_IP_ROUTE, if_walkrt) == -1)
+ if ((af == AF_UNSPEC || af == AF_INET) &&
+ if_parsert(ctx, MIB2_IP,MIB2_IP_ROUTE, if_walkrt) == -1)
return -1;
#endif
#ifdef INET6
- if (if_parsert(ctx, MIB2_IP6, MIB2_IP6_ROUTE, if_walkrt6) == -1)
+ if ((af == AF_UNSPEC || af == AF_INET6) &&
+ if_parsert(ctx, MIB2_IP6, MIB2_IP6_ROUTE, if_walkrt6) == -1)
return -1;
#endif
return 0;
const char *);
int if_route(unsigned char, const struct rt *rt);
-int if_initrt(struct dhcpcd_ctx *);
+int if_initrt(struct dhcpcd_ctx *, int);
#endif
#ifdef INET6
/* Find any freshly added routes, such as the subnet route.
* We do this because we cannot rely on recieving the kernel
* notification right now via our link socket. */
- if_initrt(ifp->ctx);
+ if_initrt(ifp->ctx, AF_INET);
rt_build(ifp->ctx, AF_INET);
#ifdef ARP
ctx = rt->rt_ifp->ctx;
TAILQ_FOREACH(ifp, ctx->ifaces, next) {
if (IPV4LL_STATE_RUNNING(ifp)) {
- if_initrt(ctx);
+ if_initrt(ctx, AF_INET);
rt_build(ctx, AF_INET);
break;
}
ia->prefix_pltime = ND6_INFINITE_LIFETIME;
ia->dadcallback = ipv6_staticdadcallback;
ipv6_addaddr(ia, NULL);
- if_initrt(ifp->ctx);
+ if_initrt(ifp->ctx, AF_INET6);
rt_build(ifp->ctx, AF_INET6);
if (run_script)
script_runreason(ifp, "STATIC6");
}
/* Load existing routes */
- if_initrt(ifp->ctx);
+ if_initrt(ifp->ctx, AF_INET6);
return 0;
}
ipv6_freedrop_addrs(&state->addrs, drop ? 2 : 0, NULL);
if (drop) {
if (ifp->ctx->ipv6 != NULL) {
- if_initrt(ifp->ctx);
+ if_initrt(ifp->ctx, AF_INET6);
rt_build(ifp->ctx, AF_INET6);
}
} else {
/* Find any freshly added routes, such as the subnet route.
* We do this because we cannot rely on recieving the kernel
* notification right now via our link socket. */
- if_initrt(ifp->ctx);
+ if_initrt(ifp->ctx, AF_INET6);
rt_build(ifp->ctx, AF_INET6);
if (ipv6nd_scriptrun(rap))
}
void
-rt_headclear(struct rt_head *rts)
+rt_headclear(struct rt_head *rts, int af)
{
- struct rt *rt;
+ struct rt *rt, *rtn;
struct dhcpcd_ctx *ctx;
if (rts == NULL)
return;
- ctx = NULL;
- while ((rt = TAILQ_FIRST(rts))) {
+ if ((rt = TAILQ_FIRST(rts)) == NULL)
+ return;
+ ctx = rt->rt_ifp->ctx;
+ assert(&ctx->froutes != rts);
+
+ TAILQ_FOREACH_SAFE(rt, rts, rt_next, rtn) {
+ if (af != AF_UNSPEC &&
+ rt->rt_dest.sa_family != af &&
+ rt->rt_gateway.sa_family != af)
+ continue;
TAILQ_REMOVE(rts, rt, rt_next);
- if (ctx == NULL) {
- ctx = rt->rt_ifp->ctx;
- assert(&ctx->froutes != rts);
- }
TAILQ_INSERT_TAIL(&ctx->froutes, rt, rt_next);
}
}
TAILQ_INSERT_TAIL(&ctx->froutes, rt, rt_next);
}
- rt_headclear(&ctx->routes);
+ rt_headclear(&ctx->routes, af);
TAILQ_CONCAT(&ctx->routes, &added, rt_next);
- rt_headclear(&routes);
+ rt_headclear(&routes, AF_UNSPEC);
}
struct rt * rt_find(struct rt_head *, const struct rt *);
void rt_free(struct rt *);
void rt_freeif(struct interface *);
-void rt_headclear(struct rt_head *);
+void rt_headclear(struct rt_head *, int);
void rt_headfreeif(struct rt_head *);
struct rt * rt_new(struct interface *);
void rt_recvrt(int, const struct rt *);