]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
inet6: Support RFC 4862 5.5.3.e in regards to Valid Lifetime
authorRoy Marples <roy@marples.name>
Mon, 8 Aug 2022 15:47:55 +0000 (16:47 +0100)
committerRoy Marples <roy@marples.name>
Mon, 8 Aug 2022 15:47:55 +0000 (16:47 +0100)
      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.

src/ipv6nd.c
src/ipv6nd.h

index 4b9c735df44d3442007665ed95732958e079b4b0..94ffebd468fe5692c0d63caf81e37f385775308a 100644 (file)
@@ -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)) {
index fd5990cfea973ba313ebc5fc88e80df99168cb12..2efc3536cb1e1b15063de8cf55e0c50a6f95a097 100644 (file)
@@ -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 *);