net: ipv6/addrconf: ensure that regen_advance is at least 2 seconds

RFC 8981 defines REGEN_ADVANCE as follows:

REGEN_ADVANCE = 2 + (TEMP_IDGEN_RETRIES * DupAddrDetectTransmits * RetransTimer / 1000)

Thus, allowing it to be less than 2 seconds is technically a protocol
violation.

Link: https://datatracker.ietf.org/doc/html/rfc8981#name-defined-protocol-parameters
Signed-off-by: Alex Henrie <alexhenrie24@gmail.com>
Reviewed-by: David Ahern <dsahern@kernel.org>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
Alex Henrie 2024-02-13 23:26:30 -07:00 committed by Paolo Abeni
parent ea578703b0
commit 2aa8f155b0
2 changed files with 11 additions and 8 deletions

View file

@ -2503,7 +2503,7 @@ use_tempaddr - INTEGER
temp_valid_lft - INTEGER
valid lifetime (in seconds) for temporary addresses. If less than the
minimum required lifetime (typically 5 seconds), temporary addresses
minimum required lifetime (typically 5-7 seconds), temporary addresses
will not be created.
Default: 172800 (2 days)
@ -2511,7 +2511,7 @@ temp_valid_lft - INTEGER
temp_prefered_lft - INTEGER
Preferred lifetime (in seconds) for temporary addresses. If
temp_prefered_lft is less than the minimum required lifetime (typically
5 seconds), temporary addresses will not be created. If
5-7 seconds), temporary addresses will not be created. If
temp_prefered_lft is greater than temp_valid_lft, the preferred lifetime
is temp_valid_lft.

View file

@ -1339,6 +1339,13 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
in6_ifa_put(ifp);
}
static unsigned long ipv6_get_regen_advance(struct inet6_dev *idev)
{
return 2 + idev->cnf.regen_max_retry *
idev->cnf.dad_transmits *
max(NEIGH_VAR(idev->nd_parms, RETRANS_TIME), HZ/100) / HZ;
}
static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, bool block)
{
struct inet6_dev *idev = ifp->idev;
@ -1380,9 +1387,7 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, bool block)
age = (now - ifp->tstamp) / HZ;
regen_advance = idev->cnf.regen_max_retry *
idev->cnf.dad_transmits *
max(NEIGH_VAR(idev->nd_parms, RETRANS_TIME), HZ/100) / HZ;
regen_advance = ipv6_get_regen_advance(idev);
/* recalculate max_desync_factor each time and update
* idev->desync_factor if it's larger
@ -4595,9 +4600,7 @@ static void addrconf_verify_rtnl(struct net *net)
!ifp->regen_count && ifp->ifpub) {
/* This is a non-regenerated temporary addr. */
unsigned long regen_advance = ifp->idev->cnf.regen_max_retry *
ifp->idev->cnf.dad_transmits *
max(NEIGH_VAR(ifp->idev->nd_parms, RETRANS_TIME), HZ/100) / HZ;
unsigned long regen_advance = ipv6_get_regen_advance(ifp->idev);
if (age + regen_advance >= ifp->prefered_lft) {
struct inet6_ifaddr *ifpub = ifp->ifpub;