From: Roy Marples Date: Mon, 8 Aug 2022 15:47:55 +0000 (+0100) Subject: inet6: Support RFC 4862 5.5.3.e in regards to Valid Lifetime X-Git-Tag: v10.0.0~57 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=41b8ff0929f1c7ca9a270da24209a38271863e67;p=thirdparty%2Fdhcpcd.git inet6: Support RFC 4862 5.5.3.e in regards to Valid Lifetime 1. If the received Valid Lifetime is greater than 2 hours or greater than RemainingLifetime, set the valid lifetime of the corresponding address to the advertised Valid Lifetime. 2. If RemainingLifetime is less than or equal to 2 hours, ignore the Prefix Information option with regards to the valid lifetime. 3. Otherwise, reset the valid lifetime of the corresponding address to 2 hours. --- diff --git a/src/ipv6nd.c b/src/ipv6nd.c index 4b9c735d..94ffebd4 100644 --- a/src/ipv6nd.c +++ b/src/ipv6nd.c @@ -1314,6 +1314,9 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx, switch (ndo.nd_opt_type) { case ND_OPT_PREFIX_INFORMATION: + { + uint32_t vltime, pltime; + loglevel = new_data ? LOG_ERR : LOG_DEBUG; if (ndo.nd_opt_len != 4) { logmessage(loglevel, @@ -1337,9 +1340,10 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx, ifp->name); continue; } - if (ntohl(pi.nd_opt_pi_preferred_time) > - ntohl(pi.nd_opt_pi_valid_time)) - { + + vltime = ntohl(pi.nd_opt_pi_valid_time); + pltime = ntohl(pi.nd_opt_pi_preferred_time); + if (pltime > vltime) { logmessage(loglevel, "%s: pltime > vltime", ifp->name); continue; @@ -1364,10 +1368,15 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx, &pi_prefix, pi.nd_opt_pi_prefix_len, flags); if (ia == NULL) break; + ia->prefix = pi_prefix; + ia->created = ia->acquired = rap->acquired; + ia->prefix_vltime = vltime; + ia->prefix_pltime = pltime; + if (flags & IPV6_AF_AUTOCONF) ia->dadcallback = ipv6nd_dadcallback; - ia->created = ia->acquired = rap->acquired; + TAILQ_INSERT_TAIL(&rap->addrs, ia, next); #ifdef IPV6_MANAGETEMPADDR @@ -1384,18 +1393,58 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx, else new_ia = true; #endif + } else { -#ifdef IPV6_MANAGETEMPADDR - new_ia = false; -#endif + uint32_t rmtime; + + /* + * RFC 4862 5.5.3.e + * Don't terminate existing connections. + * This means that to actually remove the + * existing prefix, the RA needs to stop + * broadcasting the prefix and just let it + * expire in 2 hours. + * It might want to broadcast it to reduce + * the vltime if it was greater than 2 hours + * to start with/ + */ + ia->prefix_pltime = pltime; + if (ia->prefix_vltime) { + uint32_t elapsed; + + elapsed = (uint32_t)eloop_timespec_diff( + &rap->acquired, &ia->acquired, + NULL); + rmtime = ia->prefix_vltime - elapsed; + if (rmtime > ia->prefix_vltime) + rmtime = 0; + } else + rmtime = 0; + if (vltime > MIN_EXTENDED_VLTIME || + vltime > rmtime) + ia->prefix_vltime = vltime; + else if (rmtime <= MIN_EXTENDED_VLTIME) + /* No SEND support from RFC 3971 so + * leave vltime alone */ + ia->prefix_vltime = rmtime; + else + ia->prefix_vltime = MIN_EXTENDED_VLTIME; + + /* Ensure pltime still fits */ + if (pltime < ia->prefix_vltime) + ia->prefix_pltime = pltime; + else + ia->prefix_pltime = ia->prefix_vltime; + ia->flags |= flags; ia->flags &= ~IPV6_AF_STALE; ia->acquired = rap->acquired; + +#ifdef IPV6_MANAGETEMPADDR + new_ia = false; +#endif } - ia->prefix_vltime = - ntohl(pi.nd_opt_pi_valid_time); - ia->prefix_pltime = - ntohl(pi.nd_opt_pi_preferred_time); + if (ia->prefix_vltime != 0 && ia->flags & IPV6_AF_AUTOCONF) has_address = true; @@ -1418,6 +1467,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx, } #endif break; + } case ND_OPT_MTU: if (len < sizeof(mtu)) { diff --git a/src/ipv6nd.h b/src/ipv6nd.h index fd5990cf..2efc3536 100644 --- a/src/ipv6nd.h +++ b/src/ipv6nd.h @@ -98,6 +98,8 @@ struct rs_state { #define RETRANS_TIMER 1000 /* milliseconds */ #define DELAY_FIRST_PROBE_TIME 5 /* seconds */ +#define MIN_EXTENDED_VLTIME 7200 /* seconds */ + int ipv6nd_open(bool); #ifdef __sun int ipv6nd_openif(struct interface *);