]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
- If the client had multiple addresses, and one expired (was not renewed
authorDavid Hankins <dhankins@isc.org>
Tue, 20 Nov 2007 18:33:07 +0000 (18:33 +0000)
committerDavid Hankins <dhankins@isc.org>
Tue, 20 Nov 2007 18:33:07 +0000 (18:33 +0000)
  by the server), the client would continue to attempt to renew the same
  old address over and over.  Now, the client will omit any expired
  addresses from future Confirm, Renew, or Rebind messages.  [ISC-Bugs #17266]
- dhclient -6 will now select renew/rebind timers based upon the longest
  address expiration time rather than the shortest expiration time, in
  order to avoid cascading renewals in the event a server elects not to
  extend one of multiple IAADDR leases.  [ISC-Bugs #17266]

RELNOTES
client/dhc6.c

index fa32799c4b5e097ad0e6082a237266a6e31f1f35..7c131c59c82426e4af9f87465dcee867fb37b081 100644 (file)
--- a/RELNOTES
+++ b/RELNOTES
@@ -53,6 +53,18 @@ may not work on other platforms. Please report any problems and
 suggested fixes to <dhcp-users@isc.org>.
 
 
+                       Changes since 4.0.0b3
+
+- If the client had multiple addresses, and one expired (was not renewed
+  by the server), the client would continue to attempt to renew the same
+  old address over and over.  Now, the client will omit any expired
+  addresses from future Confirm, Renew, or Rebind messages.
+
+- dhclient -6 will now select renew/rebind timers based upon the longest
+  address expiration time rather than the shortest expiration time, in
+  order to avoid cascading renewals in the event a server elects not to
+  extend one of multiple IAADDR leases.
+
                        Changes since 4.0.0b2
 
 - Clarified error message when lease limit exceeded
index 2731ba6b431b55e6b5b64cc73e26cefc4d7b88bc..33a5101e8bf7d44ccb4ef9e8c5151347ccd83870 100644 (file)
@@ -2186,6 +2186,14 @@ dhc6_add_ia(struct client_state *client, struct data_string *packet,
                 }
 
                for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
+                       /*
+                        * Do not confirm expired addresses, do not request
+                        * expired addresses (but we keep them around for
+                        * solicit).
+                        */
+                       if (addr->flags & DHC6_ADDR_EXPIRED)
+                               continue;
+
                        if (addr->address.len != 16) {
                                log_error("Illegal IPv6 address length (%d), "
                                          "ignoring.  (%s:%d)",
@@ -2455,6 +2463,11 @@ dhc6_check_times(struct client_state *client)
        cancel_timeout(do_expire, client);
 
        for(ia = lease->bindings ; ia != NULL ; ia = ia->next) {
+               TIME this_ia_lo_expire, this_ia_hi_expire, use_expire;
+
+               this_ia_lo_expire = MAX_TIME;
+               this_ia_hi_expire = 0;
+
                for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
                        if(!(addr->flags & DHC6_ADDR_DEPREFFED)) {
                                if (addr->preferred_life == 0xffffffff)
@@ -2468,27 +2481,41 @@ dhc6_check_times(struct client_state *client)
                        }
 
                        if (!(addr->flags & DHC6_ADDR_EXPIRED)) {
+                               /* Find EPOCH-relative expiration. */
                                if (addr->max_life == 0xffffffff)
                                        tmp = MAX_TIME;
                                else
                                        tmp = addr->starts + addr->max_life;
 
-                               if (tmp > hi_expire)
-                                       hi_expire = tmp;
-                               if (tmp < lo_expire)
-                                       lo_expire = tmp;
+                               /* Make the times ia->starts relative. */
+                               tmp -= ia->starts;
+
+                               if (tmp > this_ia_hi_expire)
+                                       this_ia_hi_expire = tmp;
+                               if (tmp < this_ia_lo_expire)
+                                       this_ia_lo_expire = tmp;
 
                                has_addrs = ISC_TRUE;
                        }
                }
 
-               if (ia->renew == 0) {
-                       if (lo_expire != MAX_TIME)
-                               tmp = (lo_expire - ia->starts) / 2;
-                       else
-                               tmp = client->config->requested_lease / 2;
+               /* These times are ia->starts relative. */
+               if (this_ia_lo_expire <= (this_ia_hi_expire / 2))
+                       use_expire = this_ia_hi_expire;
+               else
+                       use_expire = this_ia_lo_expire;
 
-                       tmp += ia->starts;
+               /*
+                * If the auto-selected expiration time is "infinite", or
+                * zero, assert a reasonable default.
+                */
+               if ((use_expire == MAX_TIME) || (use_expire <= 1))
+                       use_expire = client->config->requested_lease / 2;
+               else
+                       use_expire /= 2;
+
+               if (ia->renew == 0) {
+                       tmp = ia->starts + use_expire;
                } else if(ia->renew == 0xffffffff)
                        tmp = MAX_TIME;
                else
@@ -2498,12 +2525,8 @@ dhc6_check_times(struct client_state *client)
                        renew = tmp;
 
                if (ia->rebind == 0) {
-                       if (lo_expire != MAX_TIME)
-                               tmp = (lo_expire - ia->starts) / 2;
-                       else
-                               tmp = client->config->requested_lease / 2;
-
-                       tmp += ia->starts + (tmp / 2);
+                       /* Set rebind to 3/4 expiration interval. */
+                       tmp = ia->starts + use_expire + (use_expire / 2);
                } else if (ia->renew == 0xffffffff)
                        tmp = MAX_TIME;
                else
@@ -2511,6 +2534,18 @@ dhc6_check_times(struct client_state *client)
 
                if (tmp < rebind)
                        rebind = tmp;
+
+               /*
+                * Return expiration ranges to EPOCH relative for event
+                * scheduling (add_timeout()).
+                */
+               this_ia_hi_expire += ia->starts;
+               this_ia_lo_expire += ia->starts;
+
+               if (this_ia_hi_expire > hi_expire)
+                       hi_expire = this_ia_hi_expire;
+               if (this_ia_lo_expire < lo_expire)
+                       lo_expire = this_ia_lo_expire;
        }
 
        /* If there are no addresses, give up, go to INIT.