From nobody Tue Jan 27 14:11:12 2026 X-Original-To: dev-commits-src-branches@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4f0nPr6dmqz6Pt8b for ; Tue, 27 Jan 2026 14:11:12 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R13" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4f0nPr3tH7z3s2l for ; Tue, 27 Jan 2026 14:11:12 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1769523072; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=7rFklPRlW1Bu3VpeHv8TP0jOaRNiS0Vz0iZlNG3e/ZQ=; b=b1IAxM0IneVbp+qFOrI9dJc6Mz64a9DuaGznZvYekKoTMfLwar2XQCJ9kbNiYp0GIqU/Rv 38TsmlTyKZuBnYRDk4sXEAMy4PMIYmjT2cAIaAirPKIlCxW6AdIPifMFjMP6IGa5Ud8reB 42w0caJKRSVDaNm/gBwH7KCpjQSBqD6SWbg9XbGYfB7ImfZvs42SltUxXNXEdLazzYAvfb wXNLclvMaN8A0cfLgHC9lnfXR6iLNiEj3o64mY9UbgQVvz4odPyGsmZ5AC3ZiM1svvxlHv yWCz7XOl15U/GbcZER+menq8Wr/fS6W8naYXOvJf3eL2us+m7rqaKZbZimIXmw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1769523072; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=7rFklPRlW1Bu3VpeHv8TP0jOaRNiS0Vz0iZlNG3e/ZQ=; b=G5HaIa0m3BAlLnlb7NNePoKtQ43d9aVewH3NXi8droPz96RRF1pG9wzmWOxcWPW2MVrIL3 JsP66egLTXJ3Tp5ECPl46IQATZm8A7zIR0VoDuEdmSwJa+XmUkIM9/VozhpVzbj8GTPPBe D9ZYLdhyNmcqxGPHbCSetxIgplCTEZfzGcog/pqv7l3nRa4pV5tXzYgroNm30OBlLmjUVp +QhL1KSdc9cKFqTkQf+MleHR8FJOnwL4FLnlSxugkslG0DOcjT9iqLlZNPnYnfaTLYe2av uX4ma+mONK2IDQS9f1IsFpQTCzCHGGW2r0JvWLWiM1KDYvszKpBfgPLFnYegHg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1769523072; a=rsa-sha256; cv=none; b=tyGQoqTwXn+ri0o5st1QGsOmNc9UXpsFRpZBcEReLrLoQV8aWxOA/xkh+U5ZGedtOa1h5Z 14kadcfLN6YOxge8zGb8u4iezalf9fwo2W5/WsX+fpJotrVEJAwZ53qI/c47r260dK7Y+L 971GwNYSs3wnVoOv6HOgbmDOjtDdrcJD8cW353gsBDzYzvnlxoRCKgkt2pJSn1+jaQuZeP GgGXy1zgopwlE5mWMJN0rEPpZ9Krarn0lnDluAjv80AZGr7RCQqLK09w/+JIQcO4OCJ8y9 iuunUbpg+bH0hmyaoFi5IwY9dz2G5yokW4gA+PGIULQaXtl00OJJ4glFemFdsQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4f0nPr34phz18gf for ; Tue, 27 Jan 2026 14:11:12 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 23cda by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Tue, 27 Jan 2026 14:11:12 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Mark Johnston Subject: git: a30def1e98a2 - stable/15 - in6: Modify address prefix lifetimes when updating address lifetimes List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-branches@freebsd.org Sender: owner-dev-commits-src-branches@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: markj X-Git-Repository: src X-Git-Refname: refs/heads/stable/15 X-Git-Reftype: branch X-Git-Commit: a30def1e98a2c49fe0318cac414ccccdf5ab79bb Auto-Submitted: auto-generated Date: Tue, 27 Jan 2026 14:11:12 +0000 Message-Id: <6978c780.23cda.3bf9a09e@gitrepo.freebsd.org> The branch stable/15 has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=a30def1e98a2c49fe0318cac414ccccdf5ab79bb commit a30def1e98a2c49fe0318cac414ccccdf5ab79bb Author: Mark Johnston AuthorDate: 2026-01-12 13:49:54 +0000 Commit: Mark Johnston CommitDate: 2026-01-27 14:10:47 +0000 in6: Modify address prefix lifetimes when updating address lifetimes When one uses SIOCAIFADDR_IN6 to add a v6 address, it's possible to set the preferred and valid lifetimes of the address. If the address already exists, this ioctl will recalculate and update the expiry times based on the provided timestamps. When adding a new address, the lifetimes are inherited by the prefix as well, but only if we create a new prefix. If the prefix already exists, as it will in the case where an address is being updated rather than being added, we do not touch the prefix lifetimes at all. This means that the original address lifetime still applies to the route associated with that prefix, so when the prefix expires, the route goes away. This behaviour doesn't make a lot of sense: if the admin updates an address lifetime, we should ensure that the prefix lifetime is updated too. Make that change, ensuring that we do not shorten the prefix lifetime, as the prefix might be shared among multiple interface addresses. Add a regression test. Co-authored by: Franco Fichtner Reviewed by: pouria, zlei, ae MFC after: 2 weeks Sponsored by: OPNsense Sponsored by: Klara, Inc. Differential Revision: https://reviews.freebsd.org/D54562 (cherry picked from commit 74999aac5effb9b32d12f413ef51e87b15c8a0d8) --- sys/netinet6/in6.c | 22 ++++++++++++++ tests/sys/netinet6/ndp.sh | 76 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index cd75d22fa527..bdee1eefaa3f 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -1333,6 +1333,28 @@ in6_addifaddr(struct ifnet *ifp, struct in6_aliasreq *ifra, struct in6_ifaddr *i (*carp_detach_p)(&ia->ia_ifa, false); goto out; } + } else if (pr->ndpr_raf_onlink) { + time_t expiry; + + /* + * If the prefix already exists, update lifetimes, but avoid + * shortening them. + */ + ND6_WLOCK(); + expiry = in6_expire_time(pr0.ndpr_pltime); + if (pr->ndpr_preferred != 0 && + (pr->ndpr_preferred < expiry || expiry == 0)) { + pr->ndpr_pltime = pr0.ndpr_pltime; + pr->ndpr_preferred = expiry; + } + expiry = in6_expire_time(pr0.ndpr_vltime); + if (pr->ndpr_expire != 0 && + (pr->ndpr_expire < expiry || expiry == 0)) { + pr->ndpr_vltime = pr0.ndpr_vltime; + pr->ndpr_expire = expiry; + } + pr->ndpr_lastupdate = time_uptime; + ND6_WUNLOCK(); } /* relate the address to the prefix */ diff --git a/tests/sys/netinet6/ndp.sh b/tests/sys/netinet6/ndp.sh index 1c9a0d0b6473..433dd81a121b 100755 --- a/tests/sys/netinet6/ndp.sh +++ b/tests/sys/netinet6/ndp.sh @@ -249,10 +249,86 @@ ndp_prefix_lifetime_cleanup() { vnet_cleanup } +atf_test_case "ndp_prefix_lifetime_extend" +ndp_prefix_lifetime_extend_head() { + atf_set descr 'Test prefix lifetime updates via ifconfig' + atf_set require.user root + atf_set require.progs jq +} + +get_prefix_attr() { + local prefix=$1 + local attr=$2 + + ndp -p --libxo json | \ + jq -r '.ndp.["prefix-list"][] | + select(.prefix == "'${prefix}'") | .["'${attr}'"]' +} + +# Given a prefix, return its expiry time in seconds. +prefix_expiry() { + get_prefix_attr $1 "expires_sec" +} + +# Given a prefix, return its valid and preferred lifetimes. +prefix_lifetimes() { + local p v + + v=$(get_prefix_attr $1 "valid-lifetime") + p=$(get_prefix_attr $1 "preferred-lifetime") + echo $v $p +} + +ndp_prefix_lifetime_extend_body() { + local epair ex1 ex2 ex3 prefix pltime vltime + + atf_check -o save:epair ifconfig epair create + epair=$(cat epair) + atf_check ifconfig ${epair} up + + prefix="2001:db8:ffff:1000::" + + atf_check ifconfig ${epair} inet6 ${prefix}1/64 pltime 5 vltime 10 + t=$(prefix_lifetimes ${prefix}/64) + if [ "${t}" != "10 5" ]; then + atf_fail "Unexpected lifetimes: ${t}" + fi + ex1=$(prefix_expiry ${prefix}/64) + if [ "${ex1}" -gt 10 ]; then + atf_fail "Unexpected expiry time: ${ex1}" + fi + + # Double the address lifetime and verify that the prefix is + # updated. + atf_check ifconfig ${epair} inet6 ${prefix}1/64 pltime 10 vltime 20 + t=$(prefix_lifetimes ${prefix}/64) + if [ "${t}" != "20 10" ]; then + atf_fail "Unexpected lifetimes: ${t}" + fi + ex2=$(prefix_expiry ${prefix}/64) + if [ "${ex2}" -le "${ex1}" ]; then + atf_fail "Expiry time was not extended: ${ex1} <= ${ex2}" + fi + + # Add a second address from the same prefix with a shorter + # lifetime, and make sure that the prefix lifetime is not + # shortened. + atf_check ifconfig ${epair} inet6 ${prefix}2/64 pltime 5 vltime 10 + t=$(prefix_lifetimes ${prefix}/64) + if [ "${t}" != "20 10" ]; then + atf_fail "Unexpected lifetimes: ${t}" + fi + ex3=$(prefix_expiry ${prefix}/64) + if [ "${ex3}" -lt "${ex2}" ]; then + atf_fail "Expiry time was shortened: ${ex2} <= ${ex3}" + fi +} + atf_init_test_cases() { atf_add_test_case "ndp_add_gu_success" atf_add_test_case "ndp_del_gu_success" atf_add_test_case "ndp_slaac_default_route" atf_add_test_case "ndp_prefix_lifetime" + atf_add_test_case "ndp_prefix_lifetime_extend" }