if (netmask.s_addr == INADDR_BROADCAST)
rt->rt_flags = RTF_HOST;
- sa_in_init(&rt->rt_dest, &dest);
- sa_in_init(&rt->rt_netmask, &netmask);
- sa_in_init(&rt->rt_gateway, &gateway);
+ sa_in_init(rt->rt_dest, &dest);
+ sa_in_init(rt->rt_netmask, &netmask);
+ sa_in_init(rt->rt_gateway, &gateway);
if (rt_proto_add(routes, rt))
n = 1;
}
if (netmask.s_addr == INADDR_BROADCAST)
rt->rt_flags = RTF_HOST;
- sa_in_init(&rt->rt_dest, &dest);
- sa_in_init(&rt->rt_netmask, &netmask);
- sa_in_init(&rt->rt_gateway, &gateway);
+ sa_in_init(rt->rt_dest, &dest);
+ sa_in_init(rt->rt_netmask, &netmask);
+ sa_in_init(rt->rt_gateway, &gateway);
if (rt_proto_add(routes, rt))
n++;
}
return -1;
memcpy(&gateway.s_addr, p, sizeof(gateway.s_addr));
p += 4;
- sa_in_init(&rt->rt_dest, &dest);
- sa_in_init(&rt->rt_netmask, &netmask);
- sa_in_init(&rt->rt_gateway, &gateway);
+ sa_in_init(rt->rt_dest, &dest);
+ sa_in_init(rt->rt_netmask, &netmask);
+ sa_in_init(rt->rt_gateway, &gateway);
if (rt_proto_add(routes, rt))
n++;
}
ctx.ifc = argc - optind;
ctx.ifv = argv + optind;
- rt_init(&ctx);
+ rt_init_routes(&ctx);
ifo = read_config(&ctx, NULL, NULL, NULL);
if (ifo == NULL) {
rtm->rtm_flags |= RTF_PINNED;
#endif
- gateway_unspec = sa_is_unspecified(&rt->rt_gateway);
+ gateway_unspec = sa_is_unspecified(rt->rt_gateway);
if (cmd == RTM_ADD || cmd == RTM_CHANGE) {
- bool netmask_bcast = sa_is_allones(&rt->rt_netmask);
+ bool netmask_bcast = sa_is_allones(rt->rt_netmask);
rtm->rtm_flags |= RTF_UP;
rtm->rtm_addrs |= RTA_GATEWAY;
if (!(rtm->rtm_flags & RTF_REJECT) &&
- !sa_is_loopback(&rt->rt_gateway)) {
+ !sa_is_loopback(rt->rt_gateway)) {
rtm->rtm_index = (unsigned short)rt->rt_ifp->index;
/*
* OpenBSD rejects this for on-link routes when there is no default route
#ifdef __OpenBSD__
#warning kernel does not allow IPv6 address sharing
if (!gateway_unspec ||
- rt->rt_dest.sa_family != AF_INET6)
+ rt->rt_dest->sa_family != AF_INET6)
#endif
rtm->rtm_addrs |= RTA_IFP;
- if (!sa_is_unspecified(&rt->rt_ifa))
+ if (!sa_is_unspecified(rt->rt_ifa))
rtm->rtm_addrs |= RTA_IFA;
}
if (netmask_bcast)
if_linkaddr(&sdl, rt->rt_ifp);
- ADDSA(&rt->rt_dest);
+ ADDSA(rt->rt_dest);
if (rtm->rtm_addrs & RTA_GATEWAY) {
if (gateway_unspec)
ADDSA((struct sockaddr *)&sdl);
else {
- union sa_ss gateway;
+ struct sockaddr_storage gss;
+ struct sockaddr *gsa = (struct sockaddr *)&gss;
- if_copysa(&gateway.sa, &rt->rt_gateway);
+ if_copysa(gsa, rt->rt_gateway);
#ifdef INET6
- if (gateway.sa.sa_family == AF_INET6)
- ipv6_setscope(&gateway.sin6, rt->rt_ifp->index);
+ if (gss.ss_family == AF_INET6)
+ ipv6_setscope((struct sockaddr_in6 *)&gss, rt->rt_ifp->index);
#endif
- ADDSA(&gateway.sa);
+ ADDSA(gsa);
}
}
if (rtm->rtm_addrs & RTA_NETMASK)
- ADDSA(&rt->rt_netmask);
+ ADDSA(rt->rt_netmask);
if (rtm->rtm_addrs & RTA_IFP)
ADDSA((struct sockaddr *)&sdl);
if (rtm->rtm_addrs & RTA_IFA)
- ADDSA(&rt->rt_ifa);
+ ADDSA(rt->rt_ifa);
#undef ADDSA
if (get_addrs(rtm->rtm_addrs, (const char *)rtm + sizeof(*rtm),
rtm->rtm_msglen - sizeof(*rtm), rti_info) == -1)
return -1;
- memset(rt, 0, sizeof(*rt));
+ rt_init(rt);
rt->rt_flags = (unsigned int)rtm->rtm_flags;
- if_copysa(&rt->rt_dest, rti_info[RTAX_DST]);
+ if_copysa(rt->rt_dest, rti_info[RTAX_DST]);
if (rtm->rtm_addrs & RTA_NETMASK) {
- if_copysa(&rt->rt_netmask, rti_info[RTAX_NETMASK]);
+ if_copysa(rt->rt_netmask, rti_info[RTAX_NETMASK]);
/*
* Netmask family and length are ignored by traditional
* userland tools such as route and netstat and are assumed
*
* This is currently true for all BSD kernels.
*/
- rt->rt_netmask.sa_family = rt->rt_dest.sa_family;
- rt->rt_netmask.sa_len = rt->rt_dest.sa_len;
+ rt->rt_netmask->sa_family = rt->rt_dest->sa_family;
+ rt->rt_netmask->sa_len = rt->rt_dest->sa_len;
}
/* dhcpcd likes an unspecified gateway to indicate via the link.
if (sdl->sdl_alen != 0)
rt->rt_dflags |= RTDF_GATELINK;
} else if (rtm->rtm_flags & RTF_GATEWAY)
- if_copysa(&rt->rt_gateway, rti_info[RTAX_GATEWAY]);
+ if_copysa(rt->rt_gateway, rti_info[RTAX_GATEWAY]);
}
if (rtm->rtm_addrs & RTA_IFA)
- if_copysa(&rt->rt_ifa, rti_info[RTAX_IFA]);
+ if_copysa(rt->rt_ifa, rti_info[RTAX_IFA]);
rt->rt_mtu = (unsigned int)rtm->rtm_rmx.rmx_mtu;
logerr(__func__);
break;
}
- memcpy(rtn, &rt, sizeof(*rtn));
+ rt_copy(rtn, &rt);
if (rb_tree_insert_node(kroutes, rtn) != rtn)
rt_free(rtn);
}
* existance with a hardware address.
* Ensure we don't call this for a newly incomplete state.
*/
- if (rt.rt_dest.sa_family == AF_INET6 &&
+ if (rt.rt_dest->sa_family == AF_INET6 &&
(rt.rt_flags & RTF_HOST || rtm->rtm_type == RTM_MISS) &&
!(rtm->rtm_type == RTM_ADD && !(rt.rt_dflags & RTDF_GATELINK))) {
bool reachable;
+ struct sockaddr_in6 *dest = (struct sockaddr_in6 *)&rt.rt_ss_dest;
reachable = (rtm->rtm_type == RTM_ADD ||
rtm->rtm_type == RTM_CHANGE) &&
rt.rt_dflags & RTDF_GATELINK;
- ipv6nd_neighbour(ctx, &rt.rt_ss_dest.sin6.sin6_addr, reachable);
+ ipv6nd_neighbour(ctx, &dest->sin6_addr, reachable);
}
#endif
if (rtm->rtm_table != RT_TABLE_MAIN)
return -1;
- memset(rt, 0, sizeof(*rt));
+ rt_init(rt);
if (rtm->rtm_type == RTN_UNREACHABLE)
rt->rt_flags |= RTF_REJECT;
sa = NULL;
switch (rta->rta_type) {
case RTA_DST:
- sa = &rt->rt_dest;
+ sa = rt->rt_dest;
break;
case RTA_SRC: {
- union sa_ss ssa;
- struct sockaddr *psa = (struct sockaddr *)&ssa;
+ struct sockaddr_storage ss;
+ struct sockaddr *psa = (struct sockaddr *)&ss;
socklen_t salen;
psa->sa_family = rtm->rtm_family;
break;
}
case RTA_GATEWAY:
- sa = &rt->rt_gateway;
+ sa = rt->rt_gateway;
break;
case RTA_PREFSRC:
- sa = &rt->rt_ifa;
+ sa = rt->rt_ifa;
break;
case RTA_OIF:
ifindex = *(unsigned int *)RTA_DATA(rta);
sa->sa_family = rtm->rtm_family;
salen = sa_addrlen(sa);
- /* sa is a union where sockaddr_in6 is the biggest. */
- /* coverity[overrun-buffer-arg] */
memcpy((char *)sa + sa_addroffset(sa), RTA_DATA(rta),
MIN(salen, RTA_PAYLOAD(rta)));
}
}
/* If no RTA_DST set the unspecified address for the family. */
- if (rt->rt_dest.sa_family == AF_UNSPEC)
- rt->rt_dest.sa_family = rtm->rtm_family;
+ if (rt->rt_dest->sa_family == AF_UNSPEC)
+ rt->rt_dest->sa_family = rtm->rtm_family;
- rt->rt_netmask.sa_family = rtm->rtm_family;
- sa_fromprefix(&rt->rt_netmask, rtm->rtm_dst_len);
- if (sa_is_allones(&rt->rt_netmask))
+ rt->rt_netmask->sa_family = rtm->rtm_family;
+ sa_fromprefix(rt->rt_netmask, rtm->rtm_dst_len);
+ if (sa_is_allones(rt->rt_netmask))
rt->rt_flags |= RTF_HOST;
#if 0
break;
}
nlm.hdr.nlmsg_flags |= NLM_F_REQUEST;
- nlm.rt.rtm_family = (unsigned char)rt->rt_dest.sa_family;
+ nlm.rt.rtm_family = (unsigned char)rt->rt_dest->sa_family;
nlm.rt.rtm_table = RT_TABLE_MAIN;
- gateway_unspec = sa_is_unspecified(&rt->rt_gateway);
+ gateway_unspec = sa_is_unspecified(rt->rt_gateway);
if (cmd == RTM_DELETE) {
nlm.rt.rtm_scope = RT_SCOPE_NOWHERE;
add_attr_l(&nlm.hdr, sizeof(nlm), (type), \
(const char *)(sa) + sa_addroffset((sa)), \
(unsigned short)sa_addrlen((sa)));
- nlm.rt.rtm_dst_len = (unsigned char)sa_toprefix(&rt->rt_netmask);
- /* rt->rt_dest and rt->gateway are unions where sockaddr_in6
- * is the biggest member. However, we access them as the
- * generic sockaddr and coverity thinks this will overrun. */
- /* coverity[overrun-buffer-arg] */
- ADDSA(RTA_DST, &rt->rt_dest);
+ nlm.rt.rtm_dst_len = (unsigned char)sa_toprefix(rt->rt_netmask);
+ ADDSA(RTA_DST, rt->rt_dest);
if (cmd == RTM_ADD || cmd == RTM_CHANGE) {
if (!gateway_unspec) {
/* coverity[overrun-buffer-arg] */
- ADDSA(RTA_GATEWAY, &rt->rt_gateway);
+ ADDSA(RTA_GATEWAY, rt->rt_gateway);
}
/* Cannot add tentative source addresses.
* We don't know this here, so just skip INET6 ifa's.*/
- if (!sa_is_unspecified(&rt->rt_ifa) &&
- rt->rt_ifa.sa_family != AF_INET6)
- ADDSA(RTA_PREFSRC, &rt->rt_ifa);
+ if (!sa_is_unspecified(rt->rt_ifa) &&
+ rt->rt_ifa->sa_family != AF_INET6)
+ ADDSA(RTA_PREFSRC, rt->rt_ifa);
if (rt->rt_mtu) {
char metricsbuf[32];
struct rtattr *metrics = (void *)metricsbuf;
#endif
}
- if (!sa_is_loopback(&rt->rt_gateway))
+ if (!sa_is_loopback(rt->rt_gateway))
add_attr_32(&nlm.hdr, sizeof(nlm), RTA_OIF, rt->rt_ifp->index);
#ifdef HAVE_ROUTE_LIFETIME
logerr(__func__);
return 0;
}
- memcpy(rtn, &rt, sizeof(*rtn));
+ rt_copy(rtn, &rt);
if (rb_tree_insert_node(kroutes, rtn) != rtn)
rt_free(rtn);
return 0;
*fp = ' ';
if ((rt = rt_new0(ctx)) == NULL)
return -1;
- sa_in_init(&rt->rt_dest, &addr);
- sa_in_init(&rt->rt_netmask, &addr2);
- sa_in_init(&rt->rt_gateway, &addr3);
+ sa_in_init(rt->rt_dest, &addr);
+ sa_in_init(rt->rt_netmask, &addr2);
+ sa_in_init(rt->rt_gateway, &addr3);
if (rt_proto_add_ctx(&ifo->routes, rt, ctx))
add_environ(&ifo->config, arg, 0);
#else
if ((rt = rt_new0(ctx)) == NULL)
return -1;
addr2.s_addr = INADDR_ANY;
- sa_in_init(&rt->rt_dest, &addr2);
- sa_in_init(&rt->rt_netmask, &addr2);
- sa_in_init(&rt->rt_gateway, &addr);
+ sa_in_init(rt->rt_dest, &addr2);
+ sa_in_init(rt->rt_netmask, &addr2);
+ sa_in_init(rt->rt_gateway, &addr);
if (rt_proto_add_ctx(&ifo->routes, rt, ctx))
add_environ(&ifo->config, arg, 0);
#else
rtm->rtm_flags = rt->rt_flags;
rtm->rtm_addrs = RTA_DST | RTA_GATEWAY;
- gateway_unspec = sa_is_unspecified(&rt->rt_gateway);
+ gateway_unspec = sa_is_unspecified(rt->rt_gateway);
if (cmd == RTM_ADD || cmd == RTM_CHANGE) {
- bool netmask_bcast = sa_is_allones(&rt->rt_netmask);
+ bool netmask_bcast = sa_is_allones(rt->rt_netmask);
rtm->rtm_flags |= RTF_UP;
if (!(rtm->rtm_flags & RTF_REJECT) &&
- !sa_is_loopback(&rt->rt_gateway)) {
+ !sa_is_loopback(rt->rt_gateway)) {
rtm->rtm_addrs |= RTA_IFP;
/* RTA_IFA is currently ignored by the kernel.
* RTA_SRC and RTF_SETSRC look like what we want,
* but they don't work with RTF_GATEWAY.
* We set RTA_IFA just in the hope that the
* kernel will one day support this. */
- if (!sa_is_unspecified(&rt->rt_ifa))
+ if (!sa_is_unspecified(rt->rt_ifa))
rtm->rtm_addrs |= RTA_IFA;
}
if (!(rtm->rtm_flags & RTF_HOST))
rtm->rtm_addrs |= RTA_NETMASK;
- ADDSA(&rt->rt_dest);
+ ADDSA(rt->rt_dest);
if (gateway_unspec)
- ADDSA(&rt->rt_ifa);
+ ADDSA(rt->rt_ifa);
else
- ADDSA(&rt->rt_gateway);
+ ADDSA(rt->rt_gateway);
if (rtm->rtm_addrs & RTA_NETMASK)
- ADDSA(&rt->rt_netmask);
+ ADDSA(rt->rt_netmask);
if (rtm->rtm_addrs & RTA_IFP) {
struct sockaddr_dl sdl;
}
if (rtm->rtm_addrs & RTA_IFA)
- ADDSA(&rt->rt_ifa);
+ ADDSA(rt->rt_ifa);
#if 0
if (rtm->rtm_addrs & RTA_SRC)
- ADDSA(&rt->rt_ifa);
+ ADDSA(rt->rt_ifa);
#endif
rtm->rtm_msglen = (unsigned short)(bp - (char *)rtm);
rtm->rtm_msglen - sizeof(*rtm), rti_info) == -1)
return -1;
- memset(rt, 0, sizeof(*rt));
-
+ rt_init(rt);
rt->rt_flags = (unsigned int)rtm->rtm_flags;
- COPYSA(&rt->rt_dest, rti_info[RTAX_DST]);
+
+ COPYSA(rt->rt_dest, rti_info[RTAX_DST]);
if (rtm->rtm_addrs & RTA_NETMASK)
- COPYSA(&rt->rt_netmask, rti_info[RTAX_NETMASK]);
+ COPYSA(rt->rt_netmask, rti_info[RTAX_NETMASK]);
/* dhcpcd likes an unspecified gateway to indicate via the link.
* However we need to know if gateway was a link with an address. */
if (sdl->sdl_alen != 0)
rt->rt_dflags |= RTDF_GATELINK;
} else if (rtm->rtm_flags & RTF_GATEWAY)
- COPYSA(&rt->rt_gateway, rti_info[RTAX_GATEWAY]);
+ COPYSA(rt->rt_gateway, rti_info[RTAX_GATEWAY]);
}
if (rtm->rtm_addrs & RTA_SRC)
- COPYSA(&rt->rt_ifa, rti_info[RTAX_SRC]);
+ COPYSA(rt->rt_ifa, rti_info[RTAX_SRC]);
rt->rt_mtu = (unsigned int)rtm->rtm_rmx.rmx_mtu;
if (rtm->rtm_index)
* of the owning address.
* dhcpcd has a blank gateway here to indicate a
* subnet route. */
- if (!sa_is_unspecified(&rt->rt_dest) &&
- !sa_is_unspecified(&rt->rt_gateway)) {
- switch (rt->rt_gateway.sa_family) {
+ if (!sa_is_unspecified(rt->rt_dest) &&
+ !sa_is_unspecified(rt->rt_gateway)) {
+ switch (rt->rt_gateway->sa_family) {
#ifdef INET
case AF_INET: {
struct in_addr *in;
- in = &satosin(&rt->rt_gateway)->sin_addr;
+ in = &satosin(rt->rt_gateway)->sin_addr;
if (ipv4_findaddr(ctx, in))
in->s_addr = INADDR_ANY;
break;
case AF_INET6: {
struct in6_addr *in6;
- in6 = &satosin6(&rt->rt_gateway)->sin6_addr;
+ in6 = &satosin6(rt->rt_gateway)->sin6_addr;
if (ipv6_findaddr(ctx, in6, 0))
*in6 = in6addr_any;
break;
* existance with a hardware address.
* Ensure we don't call this for a newly incomplete state.
*/
- if (rt.rt_dest.sa_family == AF_INET6 &&
+ if (rt.rt_dest->sa_family == AF_INET6 &&
(rt.rt_flags & RTF_HOST || rtm->rtm_type == RTM_MISS) &&
!(rtm->rtm_type == RTM_ADD && !(rt.rt_dflags & RTDF_GATELINK))) {
bool reachable;
+ struct sockaddr_in6 *dest = (struct sockaddr_in6 *)rt.rt_dest;
reachable = (rtm->rtm_type == RTM_ADD ||
rtm->rtm_type == RTM_CHANGE) &&
rt.rt_dflags & RTDF_GATELINK;
- ipv6nd_neighbour(ctx, &rt.rt_ss_dest.sin6.sin6_addr, reachable);
+ ipv6nd_neighbour(ctx, &dest->sin6_addr, reachable);
}
#endif
break;
}
- memset(&rt, 0, sizeof(rt));
+ rt_init(&rt);
in.s_addr = re->ipRouteDest;
- sa_in_init(&rt.rt_dest, &in);
+ sa_in_init(rt.rt_dest, &in);
in.s_addr = re->ipRouteMask;
- sa_in_init(&rt.rt_netmask, &in);
+ sa_in_init(rt.rt_netmask, &in);
in.s_addr = re->ipRouteNextHop;
- sa_in_init(&rt.rt_gateway, &in);
+ sa_in_init(rt.rt_gateway, &in);
rt.rt_flags = re->ipRouteInfo.re_flags;
in.s_addr = re->ipRouteInfo.re_src_addr;
- sa_in_init(&rt.rt_ifa, &in);
+ sa_in_init(rt.rt_ifa, &in);
rt.rt_mtu = re->ipRouteInfo.re_max_frag;
if_octetstr(ifname, &re->ipRouteIfIndex, sizeof(ifname));
rt.rt_ifp = if_find(ctx->ifaces, ifname);
logerr(__func__);
break;
}
- memcpy(rtn, &rt, sizeof(*rtn));
+ rt_copy(rtn, &rt);
if (rb_tree_insert_node(routes, rtn) != rtn)
rt_free(rtn);
} while (++re < e);
break;
}
- memset(&rt, 0, sizeof(rt));
- sa_in6_init(&rt.rt_dest, &re->ipv6RouteDest);
+ rt_init(&rt);
+ sa_in6_init(rt.rt_dest, &re->ipv6RouteDest);
ipv6_mask(&in6, re->ipv6RoutePfxLength);
- sa_in6_init(&rt.rt_netmask, &in6);
- sa_in6_init(&rt.rt_gateway, &re->ipv6RouteNextHop);
- sa_in6_init(&rt.rt_ifa, &re->ipv6RouteInfo.re_src_addr);
+ sa_in6_init(rt.rt_netmask, &in6);
+ sa_in6_init(rt.rt_gateway, &re->ipv6RouteNextHop);
+ sa_in6_init(rt.rt_ifa, &re->ipv6RouteInfo.re_src_addr);
rt.rt_mtu = re->ipv6RouteInfo.re_max_frag;
if_octetstr(ifname, &re->ipv6RouteIfIndex, sizeof(ifname));
rt.rt_ifp = if_find(ctx->ifaces, ifname);
logerr(__func__);
break;
}
- memcpy(rtn, &rt, sizeof(*rtn));
+ rt_copy(rtn, &rt);
if (rb_tree_insert_node(routes, rtn) != rtn)
rt_free(rtn);
} while (++re < e);
return -1;
rt->rt_dflags |= RTDF_IFA_ROUTE;
in.s_addr = state->addr->addr.s_addr & state->addr->mask.s_addr;
- sa_in_init(&rt->rt_dest, &in);
+ sa_in_init(rt->rt_dest, &in);
in.s_addr = state->addr->mask.s_addr;
- sa_in_init(&rt->rt_netmask, &in);
+ sa_in_init(rt->rt_netmask, &in);
// in.s_addr = INADDR_ANY;
- // sa_in_init(&rt->rt_gateway, &in);
- rt->rt_gateway.sa_family = AF_UNSPEC;
+ // sa_in_init(rt->rt_gateway, &in);
+ rt->rt_gateway->sa_family = AF_UNSPEC;
rt_proto_add(&nroutes, rt);
}
if (RB_TREE_MIN(&ifp->options->routes)) {
RB_TREE_FOREACH(r, &ifp->options->routes)
{
- if (sa_is_unspecified(&r->rt_gateway))
+ if (sa_is_unspecified(r->rt_gateway))
break;
if ((rt = rt_new0(ifp->ctx)) == NULL)
return -1;
- memcpy(rt, r, sizeof(*rt));
+ rt_copy(rt, r);
rt_setif(rt, ifp);
rt->rt_dflags = RTDF_STATIC;
rt_proto_add(&nroutes, rt);
if ((rt = rt_new(ifp)) == NULL)
return -1;
in.s_addr = INADDR_ANY;
- sa_in_init(&rt->rt_dest, &in);
- sa_in_init(&rt->rt_netmask, &in);
- sa_in_init(&rt->rt_gateway, &state->addr->brd);
- sa_in_init(&rt->rt_ifa, &state->addr->addr);
+ sa_in_init(rt->rt_dest, &in);
+ sa_in_init(rt->rt_netmask, &in);
+ sa_in_init(rt->rt_gateway, &state->addr->brd);
+ sa_in_init(rt->rt_ifa, &state->addr->addr);
rt_proto_add(&nroutes, rt);
}
rt->rt_dflags |= RTDF_DHCP;
if (state->added & STATE_FAKE)
rt->rt_dflags |= RTDF_FAKE;
- sa_in_init(&rt->rt_ifa, &state->addr->addr);
+ sa_in_init(rt->rt_ifa, &state->addr->addr);
if (rb_tree_insert_node(routes, rt) != rt) {
rt_free(rt);
continue;
RB_TREE_FOREACH(rt, routes)
{
- if (rt->rt_dest.sa_family != AF_INET)
+ if (rt->rt_dest->sa_family != AF_INET)
continue;
- if (!sa_is_unspecified(&rt->rt_dest) ||
- sa_is_unspecified(&rt->rt_gateway))
+ if (!sa_is_unspecified(rt->rt_dest) ||
+ sa_is_unspecified(rt->rt_gateway))
continue;
- gateway = satosin(&rt->rt_gateway);
+ gateway = satosin(rt->rt_gateway);
/* Scan for a route to match */
RB_TREE_FOREACH(rth, routes)
{
if (rth == rt)
break;
/* match host */
- if (sa_cmp(&rth->rt_dest, &rt->rt_gateway) == 0)
+ if (sa_cmp(rth->rt_dest, rt->rt_gateway) == 0)
break;
/* match subnet */
/* XXX ADD TO RT_COMARE? XXX */
cp = (const char *)&gateway->sin_addr.s_addr;
- dest = satosin(&rth->rt_dest);
+ dest = satosin(rth->rt_dest);
cp2 = (const char *)&dest->sin_addr.s_addr;
- netmask = satosin(&rth->rt_netmask);
+ netmask = satosin(rth->rt_netmask);
cp3 = (const char *)&netmask->sin_addr.s_addr;
cplim = cp3 + sizeof(netmask->sin_addr.s_addr);
while (cp3 < cplim) {
logwarnx("%s: forcing router %s through "
"interface",
ifp->name,
- sa_addrtop(&rt->rt_gateway, buf,
+ sa_addrtop(rt->rt_gateway, buf,
sizeof(buf)));
}
gateway->sin_addr.s_addr = INADDR_ANY;
ifo->options |= DHCPCD_ROUTER_HOST_ROUTE_WARNED;
logwarnx("%s: router %s requires a host route",
ifp->name,
- sa_addrtop(&rt->rt_gateway, buf, sizeof(buf)));
+ sa_addrtop(rt->rt_gateway, buf, sizeof(buf)));
}
if ((rth = rt_new(ifp)) == NULL)
return -1;
rth->rt_flags |= RTF_HOST;
- sa_in_init(&rth->rt_dest, &gateway->sin_addr);
+ sa_in_init(rth->rt_dest, &gateway->sin_addr);
in.s_addr = INADDR_BROADCAST;
- sa_in_init(&rth->rt_netmask, &in);
+ sa_in_init(rth->rt_netmask, &in);
in.s_addr = INADDR_ANY;
- sa_in_init(&rth->rt_gateway, &in);
+ sa_in_init(rth->rt_gateway, &in);
rth->rt_mtu = dhcp_get_mtu(ifp);
if (state->addr != NULL)
- sa_in_init(&rth->rt_ifa, &state->addr->addr);
+ sa_in_init(rth->rt_ifa, &state->addr->addr);
else
- rth->rt_ifa.sa_family = AF_UNSPEC;
+ rth->rt_ifa->sa_family = AF_UNSPEC;
/* We need to insert the host route just before the router. */
while ((rtp = RB_TREE_MAX(routes)) != NULL) {
return -1;
in.s_addr = state->addr->addr.s_addr & state->addr->mask.s_addr;
- sa_in_init(&rt->rt_dest, &in);
+ sa_in_init(rt->rt_dest, &in);
in.s_addr = state->addr->mask.s_addr;
- sa_in_init(&rt->rt_netmask, &in);
+ sa_in_init(rt->rt_netmask, &in);
in.s_addr = INADDR_ANY;
- sa_in_init(&rt->rt_gateway, &in);
- sa_in_init(&rt->rt_ifa, &state->addr->addr);
+ sa_in_init(rt->rt_gateway, &in);
+ sa_in_init(rt->rt_ifa, &state->addr->addr);
rt->rt_dflags |= RTDF_IPV4LL;
return rt_proto_add(routes, rt) ? 1 : 0;
}
{
struct ipv4ll_state *state;
struct rt *rt;
- struct in_addr in;
+ struct in_addr in = { .s_addr = INADDR_ANY };
assert(ifp != NULL);
if ((state = IPV4LL_STATE(ifp)) == NULL || state->addr == NULL)
if ((rt = rt_new(ifp)) == NULL)
return -1;
- in.s_addr = INADDR_ANY;
- sa_in_init(&rt->rt_dest, &in);
- sa_in_init(&rt->rt_netmask, &in);
- sa_in_init(&rt->rt_gateway, &in);
- sa_in_init(&rt->rt_ifa, &state->addr->addr);
+ sa_in_init(rt->rt_dest, &in);
+ sa_in_init(rt->rt_netmask, &in);
+ sa_in_init(rt->rt_gateway, &in);
+ sa_in_init(rt->rt_ifa, &state->addr->addr);
rt->rt_dflags |= RTDF_IPV4LL;
#ifdef HAVE_ROUTE_METRIC
rt->rt_metric += RTMETRIC_IPV4LL;
struct interface *ifp;
/* Only interested in default route changes. */
- if (sa_is_unspecified(&rt->rt_dest))
+ if (!sa_is_unspecified(rt->rt_dest))
return 0;
/* If any interface is running IPv4LL, rebuild our routing table. */
if ((rt = inet6_makeroute(ifp, rap)) == NULL)
return NULL;
- sa_in6_init(&rt->rt_dest, &addr->prefix);
+ sa_in6_init(rt->rt_dest, &addr->prefix);
ipv6_mask(&netmask, addr->prefix_len);
- sa_in6_init(&rt->rt_netmask, &netmask);
+ sa_in6_init(rt->rt_netmask, &netmask);
if (addr->flags & IPV6_AF_PFXDELEGATION) {
rt->rt_flags |= RTF_REJECT;
/* Linux does not like a gateway for a reject route. */
#ifndef __linux__
- sa_in6_init(&rt->rt_gateway, &in6addr_loopback);
+ sa_in6_init(rt->rt_gateway, &in6addr_loopback);
#endif
} else if (!(addr->flags & IPV6_AF_ONLINK))
- sa_in6_init(&rt->rt_gateway, &rap->from);
+ sa_in6_init(rt->rt_gateway, &rap->from);
else
- rt->rt_gateway.sa_family = AF_UNSPEC;
- sa_in6_init(&rt->rt_ifa, &addr->addr);
+ rt->rt_gateway->sa_family = AF_UNSPEC;
+ sa_in6_init(rt->rt_ifa, &addr->addr);
return rt;
}
if ((rt = inet6_makeroute(rap->iface, rap)) == NULL)
return NULL;
- sa_in6_init(&rt->rt_dest, &in6addr_any);
- sa_in6_init(&rt->rt_netmask, &in6addr_any);
- sa_in6_init(&rt->rt_gateway, &rap->from);
+ sa_in6_init(rt->rt_dest, &in6addr_any);
+ sa_in6_init(rt->rt_netmask, &in6addr_any);
+ sa_in6_init(rt->rt_gateway, &rap->from);
return rt;
}
in6_addr_fromprefix(&netmask, rinfo->prefix_len);
- sa_in6_init(&rt->rt_dest, &rinfo->prefix);
- sa_in6_init(&rt->rt_netmask, &netmask);
- sa_in6_init(&rt->rt_gateway, &rap->from);
+ sa_in6_init(rt->rt_dest, &rinfo->prefix);
+ sa_in6_init(rt->rt_netmask, &netmask);
+ sa_in6_init(rt->rt_gateway, &rap->from);
rt->rt_dflags |= RTDF_RA;
#ifdef HAVE_ROUTE_PREF
rt->rt_pref = ipv6nd_rtpref(rinfo->flags);
{
if (rt1->rt_flags & RTF_HOST && rt2->rt_flags & RTF_HOST)
return 0;
- return sa_cmp(&rt1->rt_netmask, &rt2->rt_netmask);
+ return sa_cmp(rt1->rt_netmask, rt2->rt_netmask);
}
int
rt_cmp_dest(const struct rt *rt1, const struct rt *rt2)
{
- union sa_ss ma1 = { .sa.sa_family = AF_UNSPEC };
- union sa_ss ma2 = { .sa.sa_family = AF_UNSPEC };
+ struct sockaddr_storage ss1 = { .ss_family = AF_UNSPEC };
+ struct sockaddr_storage ss2 = { .ss_family = AF_UNSPEC };
+ struct sockaddr *ma1 = (struct sockaddr *)&ss1;
+ struct sockaddr *ma2 = (struct sockaddr *)&ss2;
int c;
- rt_maskedaddr(&ma1.sa, &rt1->rt_dest, &rt1->rt_netmask);
- rt_maskedaddr(&ma2.sa, &rt2->rt_dest, &rt2->rt_netmask);
- c = sa_cmp(&ma1.sa, &ma2.sa);
+ rt_maskedaddr(ma1, rt1->rt_dest, rt1->rt_netmask);
+ rt_maskedaddr(ma2, rt2->rt_dest, rt2->rt_netmask);
+ c = sa_cmp(ma1, ma2);
if (c != 0)
return c;
#endif
void
-rt_init(struct dhcpcd_ctx *ctx)
+rt_init_routes(struct dhcpcd_ctx *ctx)
{
rb_tree_init(&ctx->routes, &rt_compare_os_ops);
#ifdef RT_FREE_ROUTE_TABLE
bool
rt_is_default(const struct rt *rt)
{
- return sa_is_unspecified(&rt->rt_dest) &&
- sa_is_unspecified(&rt->rt_netmask);
+ return sa_is_unspecified(rt->rt_dest) &&
+ sa_is_unspecified(rt->rt_netmask);
}
static void
assert(cmd != NULL);
assert(rt != NULL);
- sa_addrtop(&rt->rt_dest, dest, sizeof(dest));
- prefix = sa_toprefix(&rt->rt_netmask);
- sa_addrtop(&rt->rt_gateway, gateway, sizeof(gateway));
- gateway_unspec = sa_is_unspecified(&rt->rt_gateway);
+ sa_addrtop(rt->rt_dest, dest, sizeof(dest));
+ prefix = sa_toprefix(rt->rt_netmask);
+ sa_addrtop(rt->rt_gateway, gateway, sizeof(gateway));
+ gateway_unspec = sa_is_unspecified(rt->rt_gateway);
ifname = rt->rt_ifp == NULL ? "(null)" : rt->rt_ifp->name;
if (rt->rt_flags & RTF_HOST) {
RB_TREE_FOREACH_SAFE(rt, rts, rtn)
{
- if (af != AF_UNSPEC && rt->rt_dest.sa_family != af &&
- rt->rt_gateway.sa_family != af)
+ if (af != AF_UNSPEC && rt->rt_dest->sa_family != af &&
+ rt->rt_gateway->sa_family != af)
continue;
rb_tree_remove_node(rts, rt);
rt_free(rt);
#endif
}
+static void
+rt_setup_sa(struct rt *rt)
+{
+ rt->rt_dest = (struct sockaddr *)&rt->rt_ss_dest;
+ rt->rt_netmask = (struct sockaddr *)&rt->rt_ss_netmask;
+ rt->rt_gateway = (struct sockaddr *)&rt->rt_ss_gateway;
+ rt->rt_ifa = (struct sockaddr *)&rt->rt_ss_ifa;
+}
+
+void
+rt_init(struct rt *rt)
+{
+ memset(rt, 0, sizeof(*rt));
+ rt_setup_sa(rt);
+}
+
+void
+rt_copy(struct rt *dst, const struct rt *src)
+{
+ memcpy(dst, src, sizeof(*dst));
+ rt_setup_sa(dst);
+}
+
struct rt *
rt_new0(struct dhcpcd_ctx *ctx)
{
logerr(__func__);
return NULL;
}
- memset(rt, 0, sizeof(*rt));
+ rt_init(rt);
return rt;
}
}
#if defined(IPV4LL) && defined(HAVE_ROUTE_METRIC)
- if (rt->rt_dest.sa_family == AF_INET)
+ if (rt->rt_dest->sa_family == AF_INET)
ipv4ll_recvrt(cmd, rt);
#endif
}
if (((nrt->rt_ifp->active &&
!(nrt->rt_ifp->options->options & DHCPCD_GATEWAY)) ||
(!nrt->rt_ifp->active && !(ctx->options & DHCPCD_GATEWAY))) &&
- sa_is_unspecified(&nrt->rt_dest) &&
- sa_is_unspecified(&nrt->rt_netmask))
+ sa_is_unspecified(nrt->rt_dest) &&
+ sa_is_unspecified(nrt->rt_netmask))
return false;
krt = rb_tree_find_node(kroutes, nrt);
#ifdef HAVE_ROUTE_METRIC
krt->rt_metric == nrt->rt_metric &&
#endif
- sa_cmp(&krt->rt_dest, &nrt->rt_dest) == 0 &&
+ sa_cmp(krt->rt_dest, nrt->rt_dest) == 0 &&
rt_cmp_netmask(krt, nrt) == 0 &&
- sa_cmp(&krt->rt_gateway, &nrt->rt_gateway) == 0 &&
+ sa_cmp(krt->rt_gateway, nrt->rt_gateway) == 0 &&
(nrt->rt_ifp->flags & IFF_LOOPBACK || rt_cmp_mtu(krt, nrt) == 0)) {
#ifdef HAVE_ROUTE_LIFETIME
if (rt_cmp_lifetime(krt, nrt) == 0) {
#ifdef HAVE_ROUTE_METRIC
r1->rt_metric == r2->rt_metric &&
#endif
- sa_cmp(&r1->rt_gateway, &r2->rt_gateway) == 0)
+ sa_cmp(r1->rt_gateway, r2->rt_gateway) == 0)
return 0;
return 1;
}
if (rt->rt_dflags & RTDF_FAKE)
return true;
if (or->rt_dflags & RTDF_FAKE || rt_cmp(rt, or) != 0 ||
- (rt->rt_ifa.sa_family != AF_UNSPEC &&
- sa_cmp(&or->rt_ifa, &rt->rt_ifa) != 0) ||
+ (rt->rt_ifa->sa_family != AF_UNSPEC &&
+ sa_cmp(or->rt_ifa, rt->rt_ifa) != 0) ||
#ifdef HAVE_ROUTE_LIFETIME
rt_cmp_lifetime(rt, or) != 0 ||
#endif
continue;
#ifdef BSD
if (rt_is_default(rt) &&
- if_missfilter(rt->rt_ifp, &rt->rt_gateway) == -1)
+ if_missfilter(rt->rt_ifp, rt->rt_gateway) == -1)
logerr("if_missfilter");
#endif
- if ((rt->rt_dest.sa_family != af &&
- rt->rt_dest.sa_family != AF_UNSPEC) ||
- (rt->rt_gateway.sa_family != af &&
- rt->rt_gateway.sa_family != AF_UNSPEC))
+ if ((rt->rt_dest->sa_family != af &&
+ rt->rt_dest->sa_family != AF_UNSPEC) ||
+ (rt->rt_gateway->sa_family != af &&
+ rt->rt_gateway->sa_family != AF_UNSPEC))
continue;
/* Is this route already in our table? */
if (rb_tree_find_node(&added, rt) != NULL)
/* Remove old routes we used to manage. */
RB_TREE_FOREACH_REVERSE_SAFE(rt, &ctx->routes, rtn)
{
- if ((rt->rt_dest.sa_family != af &&
- rt->rt_dest.sa_family != AF_UNSPEC) ||
- (rt->rt_gateway.sa_family != af &&
- rt->rt_gateway.sa_family != AF_UNSPEC))
+ if ((rt->rt_dest->sa_family != af &&
+ rt->rt_dest->sa_family != AF_UNSPEC) ||
+ (rt->rt_gateway->sa_family != af &&
+ rt->rt_gateway->sa_family != AF_UNSPEC))
continue;
rb_tree_remove_node(&ctx->routes, rt);
if (rb_tree_find_node(&added, rt) == NULL) {
#endif
struct rt {
- union sa_ss rt_ss_dest;
-#define rt_dest rt_ss_dest.sa
- union sa_ss rt_ss_netmask;
-#define rt_netmask rt_ss_netmask.sa
- union sa_ss rt_ss_gateway;
-#define rt_gateway rt_ss_gateway.sa
+ struct sockaddr *rt_dest;
+ struct sockaddr *rt_netmask;
+ struct sockaddr *rt_gateway;
struct interface *rt_ifp;
- union sa_ss rt_ss_ifa;
-#define rt_ifa rt_ss_ifa.sa
+ struct sockaddr *rt_ifa;
+
+ /* Storage for the above sockaddrs */
+ struct sockaddr_storage rt_ss_dest;
+ struct sockaddr_storage rt_ss_netmask;
+ struct sockaddr_storage rt_ss_gateway;
+ struct sockaddr_storage rt_ss_ifa;
+
unsigned int rt_flags;
unsigned int rt_mtu;
+
#ifdef HAVE_ROUTE_METRIC
unsigned int rt_metric;
#endif
#define RTMETRIC_WIRELESS 2000U
#define RTMETRIC_IPV4LL 1000000U
#define RTMETRIC_ROAM 2000000U
+
#ifdef HAVE_ROUTE_PREF
int rt_pref;
#endif
#define RTPREF_LOW (-1)
#define RTPREF_RESERVED (-2)
#define RTPREF_INVALID (-3) /* internal */
+
unsigned int rt_dflags;
#define RTDF_IFA_ROUTE 0x01 /* Address generated route */
#define RTDF_FAKE 0x02 /* Maybe us on lease reboot */
#define RTDF_DHCP 0x10 /* DHCP route */
#define RTDF_STATIC 0x20 /* Configured in dhcpcd */
#define RTDF_GATELINK 0x40 /* Gateway is on link */
+
size_t rt_order;
rb_node_t rt_tree;
+
#ifdef HAVE_ROUTE_LIFETIME
struct timespec rt_aquired; /* timestamp of aquisition */
uint32_t rt_lifetime; /* current lifetime of route */
extern const rb_tree_ops_t rt_compare_list_ops;
extern const rb_tree_ops_t rt_compare_proto_ops;
-void rt_init(struct dhcpcd_ctx *);
+void rt_init_routes(struct dhcpcd_ctx *);
void rt_dispose(struct dhcpcd_ctx *);
void rt_free(struct rt *);
void rt_freeif(struct interface *);
void rt_headclear0(struct dhcpcd_ctx *, rb_tree_t *, int);
void rt_headclear(rb_tree_t *, int);
void rt_headfreeif(rb_tree_t *);
+void rt_init(struct rt *);
+void rt_copy(struct rt *, const struct rt *);
struct rt *rt_new0(struct dhcpcd_ctx *);
void rt_setif(struct rt *, struct interface *);
struct rt *rt_new(struct interface *);
#ifndef NDEBUG
/* Ensure the calculation is correct */
if (!sa_inprefix) {
- union sa_ss ss = { .sa = { .sa_family = sa->sa_family } };
+ struct sockaddr_storage ss = { .ss_family = sa->sa_family };
+ struct sockaddr *ss_sa = (struct sockaddr *)&ss;
sa_inprefix = true;
- sa_fromprefix(&ss.sa, prefix);
- assert(sa_cmp(sa, &ss.sa) == 0);
+ sa_fromprefix(ss_sa, prefix);
+ assert(sa_cmp(sa, ss_sa) == 0);
sa_inprefix = false;
}
#endif
#include <netinet/in.h>
-union sa_ss {
- struct sockaddr sa;
- struct sockaddr_in sin;
- struct sockaddr_in6 sin6;
-// struct sockaddr_storage ss; /* avoids memory overrun */
-};
-
#ifdef BSD
#define HAVE_SA_LEN
#endif