From 55b1dfff23a3db9080e2d5525ece165f024e6cfb Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Thu, 27 Aug 2026 19:18:13 +0000 Subject: [PATCH 1/4] DHCP6: Improve which facility DHCP replies are sent to on RENEW Some DHCP6 servers send a unstable vltime even when configured to send a static one (hello Kea). We only really care if the address is going away or is new, so only set NEW for this. When binding addresses, ignore ones marked NEW+STALE+REQUEST when they are a Prefix Delegation as these are never added to an interface and as such we don't want to promote the log level to LOG_INFO when renewing. Fixes #558. --- src/dhcp6.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/dhcp6.c b/src/dhcp6.c index 07ffeb50..66d2b1be 100644 --- a/src/dhcp6.c +++ b/src/dhcp6.c @@ -2276,7 +2276,8 @@ dhcp6_findna(struct interface *ifp, uint16_t ot, const uint8_t *iaid, a->acquired = *acquired; a->prefix_pltime = ia.pltime; if (a->prefix_vltime != ia.vltime) { - a->flags |= IPV6_AF_NEW; + if (ia.vltime == 0) + a->flags |= IPV6_AF_NEW; a->prefix_vltime = ia.vltime; } if (a->prefix_pltime && a->prefix_pltime < state->lowpl) @@ -2365,7 +2366,7 @@ dhcp6_findpd(struct interface *ifp, const uint8_t *iaid, uint8_t *d, size_t l, if (!(a->flags & IPV6_AF_PFXDELEGATION)) a->flags |= IPV6_AF_NEW | IPV6_AF_PFXDELEGATION; a->flags &= ~(IPV6_AF_STALE | IPV6_AF_EXTENDED); - if (a->prefix_vltime != pdp_vltime) + if (pdp_vltime == 0 && a->prefix_vltime != pdp_vltime) a->flags |= IPV6_AF_NEW; } @@ -3156,6 +3157,10 @@ dhcp6_bind(struct interface *ifp, const char *op, const char *sfrom) loglevel = LOG_DEBUG; TAILQ_FOREACH(ia, &state->addrs, next) { if (ia->flags & IPV6_AF_NEW) { + if (ia->ia_type == D6_OPTION_IA_PD && + ia->flags & IPV6_AF_STALE && + ia->flags & IPV6_AF_REQUEST) + continue; loglevel = LOG_INFO; break; } From dd5f05c2ab0226e846767c1b24da163b019f6a12 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Fri, 28 Aug 2026 08:11:40 +0000 Subject: [PATCH 2/4] Don't just limit to PD. Add a comment to explain the rationale for future self. --- src/dhcp6.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/dhcp6.c b/src/dhcp6.c index 66d2b1be..66c4455c 100644 --- a/src/dhcp6.c +++ b/src/dhcp6.c @@ -3157,8 +3157,15 @@ dhcp6_bind(struct interface *ifp, const char *op, const char *sfrom) loglevel = LOG_DEBUG; TAILQ_FOREACH(ia, &state->addrs, next) { if (ia->flags & IPV6_AF_NEW) { - if (ia->ia_type == D6_OPTION_IA_PD && - ia->flags & IPV6_AF_STALE && + /* + * Ignore unfulfilled requested addresses + * and Prefix Delegations. + * This can be normal behaviour if you hint + * at a property such as an address or prefix + * length and get something slightly different + * back. + */ + if (ia->flags & IPV6_AF_STALE && ia->flags & IPV6_AF_REQUEST) continue; loglevel = LOG_INFO; From 97c47b835287b707efe8beb15a81c25f542d1dcd Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Fri, 28 Aug 2026 12:31:24 +0000 Subject: [PATCH 3/4] Improve commentry and code flow. --- src/dhcp6.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/dhcp6.c b/src/dhcp6.c index 66c4455c..732a8e95 100644 --- a/src/dhcp6.c +++ b/src/dhcp6.c @@ -3154,23 +3154,23 @@ dhcp6_bind(struct interface *ifp, const char *op, const char *sfrom) struct timespec now; if (state->state == DH6S_RENEW) { + /* + * Ignore unfulfilled requested addresses + * and Prefix Delegations. + * As most requests will be the unspecified address and + * optionally prefix length, this is expected behaviour. + */ loglevel = LOG_DEBUG; TAILQ_FOREACH(ia, &state->addrs, next) { - if (ia->flags & IPV6_AF_NEW) { - /* - * Ignore unfulfilled requested addresses - * and Prefix Delegations. - * This can be normal behaviour if you hint - * at a property such as an address or prefix - * length and get something slightly different - * back. - */ - if (ia->flags & IPV6_AF_STALE && - ia->flags & IPV6_AF_REQUEST) - continue; - loglevel = LOG_INFO; - break; - } + if (!(ia->flags & IPV6_AF_NEW)) + continue; + if (ia->flags & IPV6_AF_STALE && + ia->flags & IPV6_AF_REQUEST) + continue; + /* This address is either coming or going, so promote + * the priority. */ + loglevel = LOG_INFO; + break; } } else if (state->state == DH6S_INFORM) loglevel = state->new_start ? LOG_INFO : LOG_DEBUG; From dc0f199427766d19b9ec054864103586cff27c9c Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Tue, 1 Sep 2026 09:14:44 +0000 Subject: [PATCH 4/4] Requested addresses are still added. Don't consider vltime when searching for an address. --- src/ipv6.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/ipv6.c b/src/ipv6.c index 80ee4ad3..37078bcd 100644 --- a/src/ipv6.c +++ b/src/ipv6.c @@ -925,8 +925,7 @@ ipv6_findaddrmatch(const struct ipv6_addr *addr, const struct in6_addr *match, if ((addr->flags & (IPV6_AF_ADDED | IPV6_AF_DADCOMPLETED)) == (IPV6_AF_ADDED | IPV6_AF_DADCOMPLETED)) return 1; - } else if (addr->prefix_vltime && - IN6_ARE_ADDR_EQUAL(&addr->addr, match) && + } else if (IN6_ARE_ADDR_EQUAL(&addr->addr, match) && (!flags || addr->flags & flags)) return 1; @@ -971,11 +970,7 @@ ipv6_doaddr(struct ipv6_addr *ia, struct timespec *now) ipv6_deleteaddr(ia); eloop_q_timeout_delete(ia->iface->ctx->eloop, ELOOP_QUEUE_ALL, NULL, ia); - if (ia->flags & IPV6_AF_REQUEST) { - ia->flags &= ~IPV6_AF_ADDED; - return 0; - } - return -1; + return ia->flags & IPV6_AF_REQUEST ? 0 : -1; } if (ia->flags & IPV6_AF_STALE || IN6_IS_ADDR_UNSPECIFIED(&ia->addr))