From a4ebe438df322757a92b4225658b6ede0bed590e Mon Sep 17 00:00:00 2001 From: Giuseppe Piscitelli Date: Thu, 13 Aug 2026 16:08:08 +0100 Subject: [PATCH] radv: explicit lease time as a floor for constructed-prefix RA lifetimes. If upstream gives short lifetimes, local clients using RA for address leasing can lose address access. This gives the ability to stretch RAs to reasonable lifetimes. --- man/dnsmasq.8 | 5 ++++- src/radv.c | 17 ++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 index c557553..2ec9b66 100644 --- a/man/dnsmasq.8 +++ b/man/dnsmasq.8 @@ -1047,7 +1047,10 @@ options. If the lease time is given, then leases will be given for that length of time. The lease time is in seconds, or minutes (eg 45m) or hours (eg 1h) or days (2d) or weeks (1w) or "infinite". If not given, the default lease time is one hour for IPv4 and one day for IPv6. The -minimum lease time is two minutes. For IPv6 ranges, the lease time +minimum lease time is two minutes. An explicitly configured lease time also +affects IPv6 router advertisements: it acts as a ceiling on the advertised +prefix lifetimes. For constructed ranges it also acts as a floor, unless the +prefix is being deprecated. For IPv6 ranges, the lease time maybe "deprecated"; this sets the preferred lifetime sent in a DHCP lease or router advertisement to zero, which causes clients to use other addresses, if available, for new connections as a prelude to renumbering. diff --git a/src/radv.c b/src/radv.c index 00c2aa7..e31bc25 100644 --- a/src/radv.c +++ b/src/radv.c @@ -608,6 +608,7 @@ static int add_prefixes(struct in6_addr *local, int prefix, int do_slaac = 0; int deprecate = 0; int constructed = 0; + int have_lease = 0; int adv_router = 0; int off_link = 0; unsigned int time = 0xffffffff; @@ -660,6 +661,8 @@ static int add_prefixes(struct in6_addr *local, int prefix, if (time < ((unsigned int)(3 * param->adv_interval))) time = 3 * param->adv_interval; } + if (context->flags & CONTEXT_SETLEASE) + have_lease = 1; if (context->flags & CONTEXT_DEPRECATE) deprecate = 1; @@ -697,7 +700,19 @@ static int add_prefixes(struct in6_addr *local, int prefix, /* configured time is ceiling */ if (!constructed || valid > time) valid = time; - + + /* For CONSTRUCTED prefixes an explicitly configured lease time is + also a floor: an upstream delegating with very short lifetimes + (mobile links) would otherwise churn the addresses of any client + that sleeps through a few RAs. Deprecation still wins below. */ + if (constructed && have_lease && !deprecate && !(flags & IFACE_DEPRECATED)) + { + if (valid < time) + valid = time; + if (preferred < time) + preferred = time; + } + if (flags & IFACE_DEPRECATED) preferred = 0;