From: Roy Marples Date: Sat, 22 Feb 2025 13:21:17 +0000 (+0000) Subject: route lifetime behaviour should mirror other lifetimes X-Git-Tag: v10.2.1~5 X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=e7f90918a1c2d2aafef64a9eac3e8b0ce0548184;p=thirdparty%2Fdhcpcd.git route lifetime behaviour should mirror other lifetimes Each lifetime has a an aquistion time so we can compare to now to know how much of the lifetime is left. Apply the difference when adding/changing the route just as we do for addresses. This allow us to work out better when we need to update the route lifetime from a newer aquisition. Fixes #465. --- diff --git a/src/common.h b/src/common.h index a2ab05ea..12f9c1f4 100644 --- a/src/common.h +++ b/src/common.h @@ -67,6 +67,24 @@ #ifndef timespecclear #define timespecclear(tsp) (tsp)->tv_sec = (time_t)((tsp)->tv_nsec = 0L) #define timespecisset(tsp) ((tsp)->tv_sec || (tsp)->tv_nsec) +#define timespecadd(tsp, usp, vsp) \ + do { \ + (vsp)->tv_sec = (tsp)->tv_sec + (usp)->tv_sec; \ + (vsp)->tv_nsec = (tsp)->tv_nsec + (usp)->tv_nsec; \ + if ((vsp)->tv_nsec >= 1000000000L) { \ + (vsp)->tv_sec++; \ + (vsp)->tv_nsec -= 1000000000L; \ + } \ + } while (0) +#define timespecsub(tsp, usp, vsp) \ + do { \ + (vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec; \ + (vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec; \ + if ((vsp)->tv_nsec < 0) { \ + (vsp)->tv_sec--; \ + (vsp)->tv_nsec += 1000000000L; \ + } \ + } while (0) #endif #if __GNUC__ > 2 || defined(__INTEL_COMPILER) diff --git a/src/if-linux.c b/src/if-linux.c index 2a105a11..5a4a89c3 100644 --- a/src/if-linux.c +++ b/src/if-linux.c @@ -1770,8 +1770,12 @@ if_route(unsigned char cmd, const struct rt *rt) add_attr_32(&nlm.hdr, sizeof(nlm), RTA_OIF, rt->rt_ifp->index); #ifdef HAVE_ROUTE_LIFETIME - if (rt->rt_lifetime != 0) - add_attr_32(&nlm.hdr, sizeof(nlm), RTA_EXPIRES,rt->rt_lifetime); + if (rt->rt_lifetime != 0) { + uint32_t expires; + + expires = lifetime_left(rt->rt_lifetime, &rt->rt_aquired, NULL); + add_attr_32(&nlm.hdr, sizeof(nlm), RTA_EXPIRES, expires); + } #endif if (rt->rt_metric != 0) diff --git a/src/ipv6.c b/src/ipv6.c index 4561762b..934d5b24 100644 --- a/src/ipv6.c +++ b/src/ipv6.c @@ -709,9 +709,7 @@ ipv6_addaddr1(struct ipv6_addr *ia, struct timespec *now) * The saved times will be re-applied to the ia * before exiting this function. */ ia->prefix_vltime = ia->prefix_pltime = ND6_INFINITE_LIFETIME; - } - - if (timespecisset(&ia->acquired)) { + } else if (timespecisset(&ia->acquired)) { ia->prefix_pltime = lifetime_left(ia->prefix_pltime, &ia->acquired, now); ia->prefix_vltime = lifetime_left(ia->prefix_vltime, @@ -2274,13 +2272,10 @@ inet6_raroutes(rb_tree_t *routes, struct dhcpcd_ctx *ctx) const struct routeinfo *rinfo; const struct ipv6_addr *addr; struct in6_addr netmask; - struct timespec now; if (ctx->ra_routers == NULL) return 0; - timespecclear(&now); - TAILQ_FOREACH(rap, ctx->ra_routers, next) { if (rap->expired) continue; @@ -2302,8 +2297,8 @@ inet6_raroutes(rb_tree_t *routes, struct dhcpcd_ctx *ctx) rt->rt_pref = ipv6nd_rtpref(rinfo->flags); #endif #ifdef HAVE_ROUTE_LIFETIME - rt->rt_lifetime = lifetime_left(rinfo->lifetime, - &rinfo->acquired, &now); + rt->rt_aquired = rinfo->acquired; + rt->rt_lifetime = rinfo->lifetime, #endif rt_proto_add(routes, rt); } @@ -2319,9 +2314,8 @@ inet6_raroutes(rb_tree_t *routes, struct dhcpcd_ctx *ctx) rt->rt_pref = ipv6nd_rtpref(rap->flags); #endif #ifdef HAVE_ROUTE_LIFETIME - rt->rt_lifetime = - lifetime_left(addr->prefix_vltime, - &addr->acquired, &now); + rt->rt_aquired = addr->acquired; + rt->rt_lifetime = addr->prefix_vltime; #endif rt_proto_add(routes, rt); @@ -2356,8 +2350,8 @@ inet6_raroutes(rb_tree_t *routes, struct dhcpcd_ctx *ctx) rt->rt_pref = ipv6nd_rtpref(rap->flags); #endif #ifdef HAVE_ROUTE_LIFETIME - rt->rt_lifetime = lifetime_left(rap->lifetime, - &rap->acquired, &now); + rt->rt_aquired = rap->acquired; + rt->rt_lifetime = rap->lifetime; #endif rt_proto_add(routes, rt); @@ -2395,6 +2389,10 @@ inet6_dhcproutes(rb_tree_t *routes, struct dhcpcd_ctx *ctx, if (rt == NULL) continue; rt->rt_dflags |= RTDF_DHCP; +#ifdef HAVE_ROUTE_LIFETIME + rt->rt_aquired = ia->acquired; + rt->rt_lifetime = ia->prefix_vltime; +#endif rt_proto_add(routes, rt); } } diff --git a/src/ipv6nd.c b/src/ipv6nd.c index 4e1a536e..fe3423dd 100644 --- a/src/ipv6nd.c +++ b/src/ipv6nd.c @@ -148,6 +148,7 @@ __CTASSERT(sizeof(struct nd_opt_dnssl) == 8); static void ipv6nd_handledata(void *, unsigned short); static struct routeinfo *routeinfo_findalloc(struct ra *, const struct in6_addr *, uint8_t); static void routeinfohead_free(struct routeinfohead *); +static void ipv6nd_startrs2(void *); /* * Android ships buggy ICMP6 filter headers. @@ -1497,6 +1498,8 @@ nodhcp6: /* Expire should be called last as the rap object could be destroyed */ ipv6nd_expirera(ifp); #undef FREE_RAP + + eloop_timeout_add_sec(ifp->ctx->eloop, 5, ipv6nd_startrs2, ifp); } bool diff --git a/src/route.c b/src/route.c index bbc7bfd7..4d08da7e 100644 --- a/src/route.c +++ b/src/route.c @@ -521,12 +521,19 @@ rt_cmp_misc(struct rt *nrt, struct rt *ort) #endif #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. */ + * dhcpcd will expire the route regardless of route lifetime support. + */ + struct timespec ts; + uint32_t deviation; + + timespecsub(&nrt->rt_aquired, &ort->rt_aquired, &ts); + if (ts.tv_sec < 0) + ts.tv_sec = -ts.tv_sec; + if (ts.tv_sec > RTLIFETIME_DEV_MAX) + return false; if (nrt->rt_lifetime > ort->rt_lifetime) deviation = nrt->rt_lifetime - ort->rt_lifetime; else diff --git a/src/route.h b/src/route.h index 5c06d1da..2c85b90f 100644 --- a/src/route.h +++ b/src/route.h @@ -126,6 +126,7 @@ struct rt { 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 */ #define RTLIFETIME_DEV_MAX 2 /* max deviation for cmp */ #endif