Commit 2aa8f155 authored by Alex Henrie's avatar Alex Henrie Committed by Paolo Abeni
Browse files

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: default avatarAlex Henrie <alexhenrie24@gmail.com>
Reviewed-by: default avatarDavid Ahern <dsahern@kernel.org>
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent ea578703
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -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.

+9 −6
Original line number Diff line number Diff line
@@ -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;