diff --git a/sys/netinet6/in6_proto.c b/sys/netinet6/in6_proto.c --- a/sys/netinet6/in6_proto.c +++ b/sys/netinet6/in6_proto.c @@ -217,15 +217,19 @@ static int sysctl_ip6_temppltime(SYSCTL_HANDLER_ARGS) { - int error, val; + int error, val, ndf; val = V_ip6_temp_preferred_lifetime; error = sysctl_handle_int(oidp, &val, 0, req); if (error != 0 || !req->newptr) return (error); - if (val < V_ip6_desync_factor + V_ip6_temp_regen_advance) + ndf = TEMP_MAX_DESYNC_FACTOR_BASE + (val >> 2) + (val >> 3); + if (val < ndf + V_ip6_temp_regen_advance || + val > V_ip6_temp_valid_lifetime) return (EINVAL); V_ip6_temp_preferred_lifetime = val; + V_ip6_temp_max_desync_factor = ndf; + V_ip6_desync_factor = arc4random() % ndf; return (0); } diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c --- a/sys/netinet6/ip6_input.c +++ b/sys/netinet6/ip6_input.c @@ -173,6 +173,11 @@ CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_sav), true, "Drop incoming packets with source address that is a local address"); +SYSCTL_UINT(_net_inet6_ip6, OID_AUTO, temp_max_desync_factor, + CTLFLAG_RD | CTLFLAG_VNET, + &VNET_NAME(ip6_temp_max_desync_factor), 0, + "RFC 8981 max desync factor"); + #ifdef RSS static struct netisr_handler ip6_direct_nh = { .nh_name = "ip6_direct", @@ -262,7 +267,10 @@ nd6_init(); frag6_init(); - V_ip6_desync_factor = arc4random() % MAX_TEMP_DESYNC_FACTOR; + V_ip6_temp_max_desync_factor = TEMP_MAX_DESYNC_FACTOR_BASE + + (V_ip6_temp_preferred_lifetime >> 2) + + (V_ip6_temp_preferred_lifetime >> 3); + V_ip6_desync_factor = arc4random() % V_ip6_temp_max_desync_factor; /* Skip global initialization stuff for non-default instances. */ #ifdef VIMAGE diff --git a/sys/netinet6/nd6.h b/sys/netinet6/nd6.h --- a/sys/netinet6/nd6.h +++ b/sys/netinet6/nd6.h @@ -187,7 +187,7 @@ #define DEF_TEMP_VALID_LIFETIME 172800 /* 2 days */ #define DEF_TEMP_PREFERRED_LIFETIME 86400 /* 1 day */ #define TEMPADDR_REGEN_ADVANCE 5 /* sec */ -#define MAX_TEMP_DESYNC_FACTOR 600 /* 10 min */ +#define TEMP_MAX_DESYNC_FACTOR_BASE 300 /* 5 min */ #define ND_COMPUTE_RTIME(x) \ (((MIN_RANDOM_FACTOR * (x >> 10)) + (arc4random() & \ ((MAX_RANDOM_FACTOR - MIN_RANDOM_FACTOR) * (x >> 10)))) /1000) @@ -292,11 +292,13 @@ /* nd6_rtr.c */ VNET_DECLARE(int, nd6_defifindex); VNET_DECLARE(int, ip6_desync_factor); /* seconds */ +VNET_DECLARE(uint32_t, ip6_temp_max_desync_factor); /* seconds */ VNET_DECLARE(u_int32_t, ip6_temp_preferred_lifetime); /* seconds */ VNET_DECLARE(u_int32_t, ip6_temp_valid_lifetime); /* seconds */ VNET_DECLARE(int, ip6_temp_regen_advance); /* seconds */ #define V_nd6_defifindex VNET(nd6_defifindex) #define V_ip6_desync_factor VNET(ip6_desync_factor) +#define V_ip6_temp_max_desync_factor VNET(ip6_temp_max_desync_factor) #define V_ip6_temp_preferred_lifetime VNET(ip6_temp_preferred_lifetime) #define V_ip6_temp_valid_lifetime VNET(ip6_temp_valid_lifetime) #define V_ip6_temp_regen_advance VNET(ip6_temp_regen_advance) diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c --- a/sys/netinet6/nd6_rtr.c +++ b/sys/netinet6/nd6_rtr.c @@ -94,6 +94,7 @@ VNET_DEFINE(int, ip6_use_tempaddr) = 0; VNET_DEFINE(int, ip6_desync_factor); +VNET_DEFINE(uint32_t, ip6_temp_max_desync_factor) = TEMP_MAX_DESYNC_FACTOR_BASE; VNET_DEFINE(u_int32_t, ip6_temp_preferred_lifetime) = DEF_TEMP_PREFERRED_LIFETIME; VNET_DEFINE(u_int32_t, ip6_temp_valid_lifetime) = DEF_TEMP_VALID_LIFETIME; @@ -2229,7 +2230,7 @@ /* * Get a randomized interface identifier for a temporary address - * , Section 3.3.1. + * Based on RFC 8981, Section 3.3.1. */ static int in6_get_tmp_ifid(struct in6_aliasreq *ifra)