]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Add route lifetime from Router Advertisement (#429)
authorColin McInnes <colin.mcinnes@vecima.com>
Wed, 15 Jan 2025 10:29:14 +0000 (04:29 -0600)
committerGitHub <noreply@github.com>
Wed, 15 Jan 2025 10:29:14 +0000 (10:29 +0000)
Currently this is only for Linux and is fairly cosmetic as dhcpcd will
clean up expired routes itself as other OS's don't support route lifetimes.

src/common.c
src/common.h
src/if-linux.c
src/ipv6.c
src/route.h

index 0558ccbe3fb67e81e8b4fd05b4124e27b5b8f7a5..03bb33c158c65d80d4b5583a5357d98b3b8986bc 100644 (file)
@@ -38,6 +38,7 @@
 
 #include "common.h"
 #include "dhcpcd.h"
+#include "eloop.h"
 #include "if-options.h"
 
 const char *
@@ -214,3 +215,18 @@ is_root_local(void)
        return -1;
 #endif
 }
+
+uint32_t
+lifetime_left(uint32_t lifetime, const struct timespec *acquired, const struct timespec *now)
+{
+       uint32_t elapsed;
+
+       if (lifetime == INFINITE_LIFETIME)
+               return lifetime;
+
+       elapsed = (uint32_t)eloop_timespec_diff(now, acquired, NULL);
+       if (elapsed > lifetime)
+               return 0;
+
+       return lifetime - elapsed;
+}
index 97fffa5b5c3dcb308337763e3e327c78a8f49e60..096f6bd4f92a0323640596e05d089ee19019df05 100644 (file)
 # endif
 #endif
 
+#define INFINITE_LIFETIME (~0U)
+
 const char *hwaddr_ntoa(const void *, size_t, char *, size_t);
 size_t hwaddr_aton(uint8_t *, const char *);
 ssize_t readfile(const char *, void *, size_t);
@@ -148,4 +150,5 @@ ssize_t writefile(const char *, mode_t, const void *, size_t);
 int filemtime(const char *, time_t *);
 char *get_line(char ** __restrict, ssize_t * __restrict);
 int is_root_local(void);
+uint32_t lifetime_left(uint32_t, const struct timespec *, const struct timespec *);
 #endif
index 5980574b13004e0e561246cab0677c601c748ba4..96bcbbb971e79f45aa7b13717c3c60ff58d76c6d 100644 (file)
@@ -752,6 +752,11 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, struct nlmsghdr *nlm)
                        }
                        break;
                }
+               case RTA_EXPIRES:
+               {
+                       rt->rt_expires = *(uint32_t *)RTA_DATA(rta);
+                       break;
+               }
                }
 
                if (sa != NULL) {
@@ -1735,6 +1740,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);
+
        if (rt->rt_metric != 0)
                add_attr_32(&nlm.hdr, sizeof(nlm), RTA_PRIORITY,
                    rt->rt_metric);
index a4221a8c0a1ca66a6f4b1b6a4d50362afbbab385..c867626e80d38e9e4ef33edf7ae3698153e41493 100644 (file)
@@ -2301,10 +2301,13 @@ 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;
 
+       clock_gettime(CLOCK_MONOTONIC, &now);
+
        TAILQ_FOREACH(rap, ctx->ra_routers, next) {
                if (rap->expired)
                        continue;
@@ -2325,6 +2328,7 @@ 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, &rinfo->acquired, &now);
 
                        rt_proto_add(routes, rt);
                }
@@ -2339,6 +2343,8 @@ 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(addr->prefix_vltime, &addr->acquired, &now);
+
                                rt_proto_add(routes, rt);
                        }
                }
@@ -2370,6 +2376,8 @@ 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, &rap->acquired, &now);
+
                rt_proto_add(routes, rt);
        }
        return 0;
index b9b0dfd6473dbc7b5cb9e2358c0c6e29559e0572..6be2e1eaed69998c70efd01a46d649a40d57e8a6 100644 (file)
@@ -120,6 +120,7 @@ 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 */
 };
 
 extern const rb_tree_ops_t rt_compare_list_ops;