Folks,

Attached you'll find a patch for slaacd(8) that implements RFC 8981 (a
revision of RFC 4941, IPv6 Temporary Address Extensions), just published. 

slacd(8) had most of it already. The remaining bit was to have each 
temporary address employ a randomized Preferred Lifetime.

I've also found a bug in the current implementation, which I fixed while 
implementing RFC 8981:
Consider the case where you receive a PIO with a small preferred lifetime 
(say 4 seconds), and desync_factor was 0. The existing code would regenerate
a temporary address. But a temporary address should only be generated when 
its *total elapsed time* is >= (PRIV_PREFERRED_TIME - desync_factor - 
PRIV_REGEN_ADVANCE). The patch below fixes this bug as part of the 
implementation of RFC 8981.

P.S.: Patch also available at: 
https://www.gont.com.ar/files/fgont-patch-rfc8981-v0.2.diff

Thanks,
Fernando


 

diff --git engine.c engine.c
index 4160d798261..6e2d38c5fab 100644
--- engine.c
+++ engine.c
@@ -88,10 +88,14 @@
 #define        RTR_SOLICITATION_INTERVAL       4
 #define        MAX_RTR_SOLICITATIONS           3
 
-/* constants for RFC 4941 autoconf privacy extension */
-#define PRIV_MAX_DESYNC_FACTOR 600     /* 10 minutes */
+/*
+ * Constants for RFC 8981 autoconf privacy extensions
+ *
+ * PRIV_PREFERRED_LIFETIME > (PRIV_MAX_DESYNC_FACTOR + PRIV_REGEN_ADVANCE)
+ */
 #define PRIV_VALID_LIFETIME    172800  /* 2 days */
 #define PRIV_PREFERRED_LIFETIME        86400   /* 1 day */
+#define PRIV_MAX_DESYNC_FACTOR PRIV_PREFERRED_LIFETIME * 0.4   /* 9.6 hours */
 #define        PRIV_REGEN_ADVANCE      5       /* 5 seconds */
 
 enum if_state {
@@ -198,6 +202,7 @@ struct address_proposal {
        uint8_t                          prefix_len;
        uint32_t                         vltime;
        uint32_t                         pltime;
+       uint32_t                         desync_factor;
        uint8_t                          soiikey[SLAACD_SOIIKEY_LEN];
        uint32_t                         mtu;
 };
@@ -327,8 +332,6 @@ static struct imsgev        *iev_frontend;
 static struct imsgev   *iev_main;
 int64_t                         proposal_id;
 
-uint32_t                desync_factor;
-
 void
 engine_sig_handler(int sig, short event, void *arg)
 {
@@ -399,8 +402,6 @@ engine(int debug, int verbose)
 
        LIST_INIT(&slaacd_interfaces);
 
-       desync_factor = arc4random_uniform(PRIV_MAX_DESYNC_FACTOR);
-
        event_dispatch();
 
        engine_shutdown();
@@ -1858,14 +1859,18 @@ update_iface_ra_prefix(struct slaacd_iface *iface, 
struct radv *ra,
 
                if (addr_proposal->privacy) {
                        struct timespec now;
-                       int64_t         ltime;
+                       int64_t         ltime, mtime;
 
                        if (clock_gettime(CLOCK_MONOTONIC, &now))
                                fatal("clock_gettime");
 
-                       ltime = MINIMUM(addr_proposal->created.tv_sec +
-                           PRIV_PREFERRED_LIFETIME - desync_factor,
-                           now.tv_sec + prefix->pltime) - now.tv_sec;
+                       mtime = addr_proposal->created.tv_sec +
+                           PRIV_PREFERRED_LIFETIME -
+                           addr_proposal->desync_factor;
+
+                       ltime = MINIMUM(mtime, now.tv_sec + prefix->pltime) -
+                           now.tv_sec;
+
                        pltime = ltime > 0 ? ltime : 0;
 
                        ltime = MINIMUM(addr_proposal->created.tv_sec +
@@ -1873,7 +1878,7 @@ update_iface_ra_prefix(struct slaacd_iface *iface, struct 
radv *ra,
                            now.tv_sec;
                        vltime = ltime > 0 ? ltime : 0;
 
-                       if (pltime > PRIV_REGEN_ADVANCE)
+                       if ((mtime - now.tv_sec) > PRIV_REGEN_ADVANCE)
                                found_privacy = 1;
                } else {
                        pltime = prefix->pltime;
@@ -1919,11 +1924,11 @@ update_iface_ra_prefix(struct slaacd_iface *iface, 
struct radv *ra,
 
        /* privacy addresses do not depend on eui64 */
        if (!found_privacy && iface->autoconfprivacy) {
-               if (prefix->pltime < desync_factor) {
+               if (prefix->pltime < PRIV_REGEN_ADVANCE) {
                        log_warnx("%s: pltime from %s is too small: %d < %d; "
                            "not generating privacy address", __func__,
                            sin6_to_str(&ra->from), prefix->pltime,
-                           desync_factor);
+                           PRIV_REGEN_ADVANCE);
                } else
                        /* new privacy proposal */
                        gen_address_proposal(iface, ra, prefix, 1);
@@ -2055,8 +2060,11 @@ gen_address_proposal(struct slaacd_iface *iface, struct 
radv *ra, struct
        if (privacy) {
                addr_proposal->vltime = MINIMUM(prefix->vltime,
                    PRIV_VALID_LIFETIME);
+               addr_proposal->desync_factor =
+                   arc4random_uniform(PRIV_MAX_DESYNC_FACTOR);
+
                addr_proposal->pltime = MINIMUM(prefix->pltime,
-                   PRIV_PREFERRED_LIFETIME - desync_factor);
+                   PRIV_PREFERRED_LIFETIME - addr_proposal->desync_factor);
        } else {
                addr_proposal->vltime = prefix->vltime;
                addr_proposal->pltime = prefix->pltime;
diff --git slaacd.8 slaacd.8
index fb9bb3d0c60..44057ea4785 100644
--- slaacd.8
+++ slaacd.8
@@ -110,15 +110,6 @@ socket used for communication with
 .Re
 .Pp
 .Rs
-.%A T. Narten
-.%A R. Draves
-.%A S. Krishnan
-.%D September 2007
-.%R RFC 4941
-.%T Privacy Extensions for Stateless Address Autoconfiguration in IPv6
-.Re
-.Pp
-.Rs
 .%A F. Gont
 .%D April 2014
 .%R RFC 7217
@@ -152,6 +143,16 @@ socket used for communication with
 .%R RFC 8106
 .%T IPv6 Router Advertisement Options for DNS Configuration
 .Re
+.Pp
+.Rs
+.%A F. Gont
+.%A S. Krishnan
+.%A T. Narten
+.%A R. Draves
+.%D February 2021
+.%R RFC 8981
+.%T Temporary Address Extensions for Stateless Address Autoconfiguration in 
IPv6
+.Re
 .Sh HISTORY
 The
 .Nm

Reply via email to