https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=298533
Bug ID: 298533
Summary: netinet6: temporary addresses are regenerated for
prefixes in detached state
Product: Base System
Version: 15.1-RELEASE
Hardware: Any
OS: Any
Status: New
Severity: Affects Many People
Priority: ---
Component: kern
Assignee: [email protected]
Reporter: [email protected]
Version: FreeBSD 15.1-RELEASE-p3 releng/15.1-n283611-88e7371d9dc2 GENERIC amd64
Description:
When an on-link prefix becomes detached (the router stops advertising it), the
kernel keeps generating new RFC 8981 temporary addresses for that prefix. Each
regeneration produces a fresh address with a full lifetime, so addresses of a
dead prefix accumulate on the interface and never age out naturally.
Observed on wlan0 connected to a tethering hotspot, which changed the delegated
prefix from 2001:db8:a::/64 (prefix A) to 2001:db8:b::/64 (prefix B). Addresses
below are anonymized (RFC 3849); flags and lifetimes are verbatim.
inet6 2001:db8:a::200:ff:fe00:1 prefixlen 64 detached autoconf
inet6 2001:db8:a::1:1 prefixlen 64 detached deprecated autoconf temporary
pltime 0 vltime 42441
inet6 2001:db8:a::1:2 prefixlen 64 detached deprecated autoconf temporary
pltime 28650 vltime 115050
inet6 2001:db8:b::200:ff:fe00:1 prefixlen 64 autoconf
inet6 2001:db8:b::2:1 prefixlen 64 autoconf temporary pltime 32275 vltime
118675
inet6 2001:db8:a::1:3 prefixlen 64 detached autoconf temporary pltime 72609
vltime 172800
The temporary address 2001:db8:a::1:3 belongs to the detached prefix A. Its
remaining pltime (72609) is larger than that of the temporary address on the
live prefix B (2001:db8:b::2:1, 32275). This shows it was created after the
prefix change, when prefix A was already detached.
This is not a one-off: I observe it systematically after every prefix change on
this link. Without intervention, new temporary addresses for the detached
prefix keep appearing at each regeneration interval for as long as the old
prefix remains on the interface.
Analysis:
In sys/netinet6/nd6.c:
nd6_timer() calls regen_tmpaddr() for a temporary address whose preferred
lifetime is about to expire. It does not check IN6_IFF_DETACHED.
regen_tmpaddr() looks for a non-deprecated autoconf public address with the
same ia6_ndpr and calls in6_tmpifadd() for it. The public address of a detached
prefix is detached but not deprecated, because IFA6_IS_DEPRECATED() checks only
the flag and pltime. That address therefore qualifies, and a new temporary
address is created.
Neither the IN6_IFF_DETACHED address flag nor the NDPRF_DETACHED prefix state
is considered. RFC 8981 ยง3.4 expects new temporary addresses to be generated
only for prefixes that are still usable on the link.
How to repeat:
1. sysctl net.inet6.ip6.use_tempaddr=1
2. Connect to a router advertising prefix A and wait for temporary addresses to
be configured.
3. Make the router switch to prefix B (tethering hotspots do this on
reconnect).
4. Wait for net.inet6.ip6.temppltime minus the regeneration advance.
5. Run ifconfig <if>: new temporary addresses keep appearing for prefix A,
marked detached, with full lifetimes.
Expected behavior:
No new temporary addresses are generated for a detached prefix. Existing ones
deprecate and expire.
Proposed fix (untested sketch):
diff
--- a/sys/netinet6/nd6.c
+++ b/sys/netinet6/nd6.c
@@ nd6_timer()
if ((ia6->ia6_flags & IN6_IFF_TEMPORARY) != 0 &&
+ (ia6->ia6_flags & IN6_IFF_DETACHED) == 0 &&
(ia6->ia6_lifetime.ia6t_pltime - time_uptime)
V_ip6_temp_regen_advance) {
@@ regen_tmpaddr()
if ((it6->ia6_flags & IN6_IFF_AUTOCONF) == 0)
continue;
+ if ((it6->ia6_flags & IN6_IFF_DETACHED) != 0)
+ continue;
+ if (it6->ia6_ndpr == NULL ||
+ (it6->ia6_ndpr->ndpr_stateflags & NDPRF_DETACHED) != 0)
+ continue;
Workaround:
sysctl net.inet6.ip6.use_tempaddr=0 avoids the problem entirely. As a less
invasive measure, after each prefix change I delete all detached addresses so
they do not accumulate:
sh
ifconfig wlan0 inet6 | awk '$5 == "detached" {print $1, $2}' | \
sudo sh -c 'while read ip6; do ifconfig wlan0 $ip6 delete; echo
"Detached $ip6 deleted"; done'
Deleting the detached public address also stops further regeneration. This is
consistent with the analysis above: regen_tmpaddr() no longer finds a matching
public address for the prefix.
--
You are receiving this mail because:
You are the assignee for the bug.