Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update route if acquired time changes #441

Merged
merged 10 commits into from
Feb 5, 2025
34 changes: 29 additions & 5 deletions src/if-linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -752,11 +752,34 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, struct nlmsghdr *nlm)
}
break;
}
case RTA_EXPIRES:
#ifdef HAVE_ROUTE_LIFETIME
case RTA_CACHEINFO:
{
rt->rt_expires = *(uint32_t *)RTA_DATA(rta);
struct rta_cacheinfo ci;
static long hz;

if (hz == 0) {
hz = sysconf(_SC_CLK_TCK);
if (hz == -1)
hz = CLOCKS_PER_SEC;
}

memcpy(&ci, RTA_DATA(rta), sizeof(ci));
rt->rt_lifetime = (uint32_t)(ci.rta_expires / hz);
break;
}
#endif
#if 0
case RTA_EXPIRES:
/* Reading the kernel source, this is only
* emitted by IPv4 multicast routes as a UINT64.
* Although we can set it for IPv6 routes as a UINT32,
* the kernel will massage the value to HZ and put it
* into RTA_CACHINFO as read above.
* Gotta love that consistency! */
rt->rt_lifetime = (uint32_t)*(uint64_t *)RTA_DATA(rta);
break;
#endif
}

if (sa != NULL) {
Expand Down Expand Up @@ -1740,9 +1763,10 @@ if_route(unsigned char cmd, const struct rt *rt)
if (!sa_is_loopback(&rt->rt_gateway))
add_attr_32(&nlm.hdr, sizeof(nlm), RTA_OIF, rt->rt_ifp->index);

/* add route lifetime */
if (rt->rt_expires != 0)
add_attr_32(&nlm.hdr, sizeof(nlm), RTA_EXPIRES, rt->rt_expires);
#ifdef HAVE_ROUTE_LIFETIME
if (rt->rt_lifetime != 0)
add_attr_32(&nlm.hdr, sizeof(nlm), RTA_EXPIRES,rt->rt_lifetime);
#endif

if (rt->rt_metric != 0)
add_attr_32(&nlm.hdr, sizeof(nlm), RTA_PRIORITY,
Expand Down
13 changes: 9 additions & 4 deletions src/ipv6.c
Original file line number Diff line number Diff line change
Expand Up @@ -2301,9 +2301,10 @@ inet6_raroutes(rb_tree_t *routes, struct dhcpcd_ctx *ctx)
#ifdef HAVE_ROUTE_PREF
rt->rt_pref = ipv6nd_rtpref(rinfo->flags);
#endif
rt->rt_expires = lifetime_left(rinfo->lifetime,
#ifdef HAVE_ROUTE_LIFETIME
rt->rt_lifetime = lifetime_left(rinfo->lifetime,
&rinfo->acquired, &now);

#endif
rt_proto_add(routes, rt);
}

Expand All @@ -2317,9 +2318,11 @@ inet6_raroutes(rb_tree_t *routes, struct dhcpcd_ctx *ctx)
#ifdef HAVE_ROUTE_PREF
rt->rt_pref = ipv6nd_rtpref(rap->flags);
#endif
rt->rt_expires =
#ifdef HAVE_ROUTE_LIFETIME
rt->rt_lifetime =
lifetime_left(addr->prefix_vltime,
&addr->acquired, &now);
#endif

rt_proto_add(routes, rt);
}
Expand Down Expand Up @@ -2352,8 +2355,10 @@ inet6_raroutes(rb_tree_t *routes, struct dhcpcd_ctx *ctx)
#ifdef HAVE_ROUTE_PREF
rt->rt_pref = ipv6nd_rtpref(rap->flags);
#endif
rt->rt_expires = lifetime_left(rap->lifetime,
#ifdef HAVE_ROUTE_LIFETIME
rt->rt_lifetime = lifetime_left(rap->lifetime,
&rap->acquired, &now);
#endif

rt_proto_add(routes, rt);
}
Expand Down
32 changes: 29 additions & 3 deletions src/route.c
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,32 @@ rt_recvrt(int cmd, const struct rt *rt, pid_t pid)
#endif
}

/* Compare miscellaneous route details */
static bool
rt_cmp_misc(struct rt *nrt, struct rt *ort)
{
/* MTU changed */
if (ort->rt_mtu != nrt->rt_mtu)
return false;

#ifdef HAVE_ROUTE_LIFETIME
uint32_t deviation;

/* There might be a minor difference between kernel route
* lifetime and our lifetime due to processing times.
* We allow a small deviation to avoid needless route changes.
* dhcpcd will expire the route regardless of route lifetime support. */
if (nrt->rt_lifetime > ort->rt_lifetime)
deviation = nrt->rt_lifetime - ort->rt_lifetime;
else
deviation = ort->rt_lifetime - nrt->rt_lifetime;
if (deviation > RTLIFETIME_DEV_MAX)
return false;
#endif

return true;
}

static bool
rt_add(rb_tree_t *kroutes, struct rt *nrt, struct rt *ort)
{
Expand Down Expand Up @@ -540,7 +566,7 @@ rt_add(rb_tree_t *kroutes, struct rt *nrt, struct rt *ort)
#endif
sa_cmp(&ort->rt_gateway, &nrt->rt_gateway) == 0)))
{
if (ort->rt_mtu == nrt->rt_mtu)
if (rt_cmp_misc(nrt, ort))
return true;
change = true;
kroute = true;
Expand All @@ -555,7 +581,7 @@ rt_add(rb_tree_t *kroutes, struct rt *nrt, struct rt *ort)
rt_cmp_netmask(ort, nrt) == 0 &&
sa_cmp(&ort->rt_gateway, &nrt->rt_gateway) == 0)
{
if (ort->rt_mtu == nrt->rt_mtu)
if (rt_cmp_misc(nrt, ort))
return true;
change = true;
}
Expand Down Expand Up @@ -678,7 +704,7 @@ rt_doroute(rb_tree_t *kroutes, struct rt *rt)
!rt_cmp(rt, or) ||
(rt->rt_ifa.sa_family != AF_UNSPEC &&
sa_cmp(&or->rt_ifa, &rt->rt_ifa) != 0) ||
or->rt_mtu != rt->rt_mtu)
!rt_cmp_misc(rt, or))
{
if (!rt_add(kroutes, rt, or))
return false;
Expand Down
10 changes: 9 additions & 1 deletion src/route.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@
# define HAVE_ROUTE_METRIC 1
# endif
#endif
#ifndef HAVE_ROUTE_LIFETIME
# if defined(__linux__)
# define HAVE_ROUTE_LIFETIME 1 /* For IPv6 routes only */
# endif
#endif

#ifdef __linux__
# include <linux/version.h> /* RTA_PREF is only an enum.... */
Expand Down Expand Up @@ -120,7 +125,10 @@ struct rt {
#define RTDF_GATELINK 0x40 /* Gateway is on link */
size_t rt_order;
rb_node_t rt_tree;
uint32_t rt_expires; /* current lifetime of route */
#ifdef HAVE_ROUTE_LIFETIME
uint32_t rt_lifetime; /* current lifetime of route */
#define RTLIFETIME_DEV_MAX 2 /* max deviation for cmp */
#endif
};

extern const rb_tree_ops_t rt_compare_list_ops;
Expand Down
Loading