From 55b1dfff23a3db9080e2d5525ece165f024e6cfb Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Thu, 27 Aug 2026 19:18:13 +0000 Subject: [PATCH 1/6] 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/6] 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/6] 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/6] 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)) From aaf5f930ec8e76019cfc46462f40bd9a3c611d73 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Thu, 3 Sep 2026 11:00:40 +0000 Subject: [PATCH 5/6] Address review comments. --- src/ipv6.c | 13 +++++++++++-- src/ipv6.h | 3 ++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/ipv6.c b/src/ipv6.c index 37078bcd..173bc07c 100644 --- a/src/ipv6.c +++ b/src/ipv6.c @@ -679,6 +679,7 @@ ipv6_deleteaddr(struct ipv6_addr *ia) errno != ESRCH && errno != ENXIO && errno != ENODEV) logerr(__func__); + ia->flags &= ~IPV6_AF_ADDED; ipv6_deletedaddr(ia); state = IPV6_STATE(ia->iface); @@ -921,12 +922,20 @@ int ipv6_findaddrmatch(const struct ipv6_addr *addr, const struct in6_addr *match, unsigned int flags) { + bool vltime = false; + + if (flags & IPV6_AF_USEABLE) { + vltime = true; + flags &= ~IPV6_AF_USEABLE; + } + if (match == NULL) { if ((addr->flags & (IPV6_AF_ADDED | IPV6_AF_DADCOMPLETED)) == (IPV6_AF_ADDED | IPV6_AF_DADCOMPLETED)) return 1; } else if (IN6_ARE_ADDR_EQUAL(&addr->addr, match) && - (!flags || addr->flags & flags)) + (!flags || addr->flags & flags) && + (!vltime || addr->prefix_vltime)) return 1; return 0; @@ -1061,7 +1070,7 @@ ipv6_freedrop_addrs(struct ipv6_addrhead *addrs, int drop, TAILQ_REMOVE(addrs, ap, next); /* Find the same address somewhere else */ apf = ipv6_findaddr(ap->iface->ctx, &ap->addr, - 0); + IPV6_AF_USEABLE); if ((apf == NULL || (apf->iface != ap->iface))) ipv6_deleteaddr(ap); if (!(ap->iface->options->options & diff --git a/src/ipv6.h b/src/ipv6.h index 1b78532f..9d4ef998 100644 --- a/src/ipv6.h +++ b/src/ipv6.h @@ -227,8 +227,9 @@ struct ipv6_addr { #define IPV6_AF_REGEN (1U << 14) #define IPV6_AF_ROUTER (1U << 15) #define IPV6_AF_ADVERTISED (1U << 16) +#define IPV6_AF_USEABLE (1U << 17) #ifdef IPV6_MANAGETEMPADDR -#define IPV6_AF_TEMPORARY (1U << 17) +#define IPV6_AF_TEMPORARY (1U << 18) #endif struct ll_callback { From 7c09fc481eb61dc0fcf55ba828601ed77a7c06ad Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Thu, 3 Sep 2026 11:06:49 +0000 Subject: [PATCH 6/6] Format --- src/ipv6.c | 3 +-- src/ipv6.h | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/ipv6.c b/src/ipv6.c index 173bc07c..3997dafe 100644 --- a/src/ipv6.c +++ b/src/ipv6.c @@ -934,8 +934,7 @@ ipv6_findaddrmatch(const struct ipv6_addr *addr, const struct in6_addr *match, (IPV6_AF_ADDED | IPV6_AF_DADCOMPLETED)) return 1; } else if (IN6_ARE_ADDR_EQUAL(&addr->addr, match) && - (!flags || addr->flags & flags) && - (!vltime || addr->prefix_vltime)) + (!flags || addr->flags & flags) && (!vltime || addr->prefix_vltime)) return 1; return 0; diff --git a/src/ipv6.h b/src/ipv6.h index 9d4ef998..f09205cc 100644 --- a/src/ipv6.h +++ b/src/ipv6.h @@ -227,7 +227,7 @@ struct ipv6_addr { #define IPV6_AF_REGEN (1U << 14) #define IPV6_AF_ROUTER (1U << 15) #define IPV6_AF_ADVERTISED (1U << 16) -#define IPV6_AF_USEABLE (1U << 17) +#define IPV6_AF_USEABLE (1U << 17) #ifdef IPV6_MANAGETEMPADDR #define IPV6_AF_TEMPORARY (1U << 18) #endif