]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
[v4_1_esv] Altered v4 lease time handling better handle infinite and large times
authorThomas Markwalder <tmark@isc.org>
Wed, 10 May 2017 18:11:14 +0000 (14:11 -0400)
committerThomas Markwalder <tmark@isc.org>
Wed, 10 May 2017 18:11:14 +0000 (14:11 -0400)
        Merged in rt41976

RELNOTES
includes/dhcpd.h
server/dhcp.c
server/dhcpv6.c

index 7c38dc3fc0ce5d83414cc30dd7a3a5f03c182569..08cb43a6bb956e97f8aad9b635a1c9081bf89eb2 100644 (file)
--- a/RELNOTES
+++ b/RELNOTES
@@ -117,6 +117,13 @@ by Eric Young (eay@cryptsoft.com).
   Mritunjaykumar Dubey at Nokia for reporting the issue.
   [ISC-Bugs #41473]
 
+- Altered DHCPv4 lease time calculation to avoid roll over errors on 64-bit
+  OS systems when using -1 or large values for default-lease-time.  Rollover
+  values will be replaced with 0x7FFFFFFF - 1.  This alleviates unintentionally
+  short expiration times being handed out when infinite lease times (-1) in
+  conjuction with failover.
+  [ISC-Bugs #41976]
+
                        Changes since 4.1-ESV-R14b1
 - None
 
index 06c80a4059d0497492d59ede61c56bb9341b858a..1e3c2011de18bbdfade1f6cd5556770a812fae96 100644 (file)
@@ -1354,6 +1354,7 @@ typedef unsigned char option_mask [16];
 #define DHCPD_LOG_FACILITY     LOG_DAEMON
 #endif
 
+#define INFINITE_TIME 0xffffffff
 #define MAX_TIME 0x7fffffff
 #define MIN_TIME 0
 
index bbcb3cb93db4a727311c7dae015fc69a7aa336d0..9fd17e2d940f71f1aa004c6bf7b18c6c9296156f 100644 (file)
@@ -75,6 +75,8 @@ const int dhcp_type_name_max = ((sizeof dhcp_type_names) / sizeof (char *));
 # define send_packet trace_packet_send
 #endif
 
+static TIME leaseTimeCheck(TIME calculated, TIME alternate);
+
 void
 dhcp (struct packet *packet) {
        int ms_nulltp = 0;
@@ -2289,8 +2291,15 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
                         * the desired lease time upon renewal.
                         */
                        if (offer == DHCPACK) {
-                               lt->tstp = cur_time + lease_time +
-                                               (new_lease_time / 2);
+                               if (lease_time == INFINITE_TIME) {
+                                       lt->tstp = MAX_TIME;
+                               } else {
+                                       lt->tstp =
+                                               leaseTimeCheck(
+                                                       (cur_time + lease_time
+                                                        + (new_lease_time / 2))
+                                                        , MAX_TIME - 1);
+                               }
 
                                /* If we reduced the potential expiry time,
                                 * make sure we don't offer an old-expiry-time
@@ -2307,12 +2316,16 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
                }
 #endif /* FAILOVER_PROTOCOL */
 
-               /* If the lease duration causes the time value to wrap,
-                  use the maximum expiry time. */
-               if (cur_time + lease_time < cur_time)
-                       state -> offered_expiry = MAX_TIME - 1;
-               else
-                       state -> offered_expiry = cur_time + lease_time;
+               if (lease_time == INFINITE_TIME) {
+                       state->offered_expiry = MAX_TIME;
+               } else {
+                       /* If the lease duration causes the time value to wrap,
+                        * use the maximum expiry time. */
+                       state->offered_expiry
+                               = leaseTimeCheck(cur_time + lease_time,
+                                                MAX_TIME - 1);
+               }
+
                if (when)
                        lt -> ends = when;
                else
@@ -4634,3 +4647,30 @@ void use_host_decl_name(struct packet* packet,
                 }
         }
 }
+
+
+/* \brief Validates a proposed value for use as a lease time
+ *
+ * Convenience function used for catching calculeated lease
+ * times that overflow 4-byte times used in v4 protocol.
+ *
+ * We use variables of type TIME in lots of places, which on
+ * 64-bit systems is 8 bytes while on 32-bit OSs it is int32_t,
+ * so we have all sorts of fun places to mess things up.
+ * This function checks a calculated lease time for and if it
+ * is unsuitable for use as a lease time, the given alternate
+ * value is returned.
+ * \param calculated
+ * \param alternate
+ *
+ * \returen either the calculated value if it is valid, or
+ * the alternate value supplied
+ */
+TIME leaseTimeCheck(TIME calculated, TIME alternate) {
+       if ((sizeof(TIME) > 4 && calculated >= INFINITE_TIME) ||
+           (calculated < cur_time)) {
+               return (alternate);
+       }
+
+       return (calculated);
+}
index 68080a4bdab9e02df4d97ee58038cb9960e4a0da..9099e06777b752932682a20d77df72ac68219364 100644 (file)
@@ -1700,7 +1700,7 @@ reply_process_ia_na(struct reply_state *reply, struct option_cache *ia) {
         * A not included IA ("cleanup" below) could give a Renew/Rebind.
         */
        oc = lookup_option(&dhcpv6_universe, packet_ia, D6O_IAADDR);
-       reply->min_valid = reply->min_prefer = 0xffffffff;
+       reply->min_valid = reply->min_prefer = INFINITE_TIME;
        reply->client_valid = reply->client_prefer = 0;
        for (; oc != NULL ; oc = oc->next) {
                status = reply_process_addr(reply, oc);
@@ -2965,10 +2965,10 @@ reply_process_is_addressed(struct reply_state *reply,
         * The following doesn't work on at least some systems:
         * (cur_time + reply->send_valid < cur_time)
         */
-       if (reply->send_valid != 0xFFFFFFFF) {
+       if (reply->send_valid != INFINITE_TIME) {
                time_t test_time = cur_time + reply->send_valid;
                if (test_time < cur_time)
-                       reply->send_valid = 0xFFFFFFFF;
+                       reply->send_valid = INFINITE_TIME;
         }
 
        if (reply->client_prefer == 0)
@@ -2977,7 +2977,7 @@ reply_process_is_addressed(struct reply_state *reply,
                reply->send_prefer = reply->client_prefer;
 
        if ((reply->send_prefer >= reply->send_valid) &&
-           (reply->send_valid != 0xFFFFFFFF))
+           (reply->send_valid != INFINITE_TIME))
                reply->send_prefer = (reply->send_valid / 2) +
                                     (reply->send_valid / 8);
 
@@ -3032,7 +3032,7 @@ reply_process_is_addressed(struct reply_state *reply,
                 * when connecting to the lease file MAX_TIME is
                 */
                if (reply->buf.reply.msg_type == DHCPV6_REPLY) {
-                       if (reply->send_valid == 0xFFFFFFFF) {
+                       if (reply->send_valid == INFINITE_TIME) {
                                reply->lease->soft_lifetime_end_time = MAX_TIME;
                        } else {
                                reply->lease->soft_lifetime_end_time =
@@ -4004,10 +4004,10 @@ reply_process_is_prefixed(struct reply_state *reply,
         * The following doesn't work on at least some systems:
         * (cur_time + reply->send_valid < cur_time)
         */
-       if (reply->send_valid != 0xFFFFFFFF) {
+       if (reply->send_valid != INFINITE_TIME) {
                time_t test_time = cur_time + reply->send_valid;
                if (test_time < cur_time)
-                       reply->send_valid = 0xFFFFFFFF;
+                       reply->send_valid = INFINITE_TIME;
         }
 
        if (reply->client_prefer == 0)
@@ -4016,7 +4016,7 @@ reply_process_is_prefixed(struct reply_state *reply,
                reply->send_prefer = reply->client_prefer;
 
        if ((reply->send_prefer >= reply->send_valid) &&
-           (reply->send_valid != 0xFFFFFFFF))
+           (reply->send_valid != INFINITE_TIME))
                reply->send_prefer = (reply->send_valid / 2) +
                                     (reply->send_valid / 8);
 
@@ -4056,7 +4056,7 @@ reply_process_is_prefixed(struct reply_state *reply,
                 * when connecting to the lease file MAX_TIME is
                 */
                if (reply->buf.reply.msg_type == DHCPV6_REPLY) {
-                       if (reply->send_valid == 0xFFFFFFFF) {
+                       if (reply->send_valid == INFINITE_TIME) {
                                reply->lease->soft_lifetime_end_time = MAX_TIME;
                        } else {
                                reply->lease->soft_lifetime_end_time =
@@ -6505,8 +6505,8 @@ set_reply_tee_times(struct reply_state* reply, unsigned ia_cursor)
        } else if (set_tee_times) {
                /* Setting them is enabled so T1 is either infinite or
                 * 0.5 * the shortest preferred lifetime in the IA_XX  */
-               reply->renew = (reply->min_prefer == 0xFFFFFFFF ? 0xFFFFFFFF
-                                : reply->min_prefer / 2);
+               reply->renew = (reply->min_prefer == INFINITE_TIME 
+                               ? INFINITE_TIME : reply->min_prefer / 2);
        } else {
                /* Default is to let the client choose */
                reply->renew = 0;
@@ -6538,8 +6538,8 @@ set_reply_tee_times(struct reply_state* reply, unsigned ia_cursor)
        } else if (set_tee_times) {
                /* Setting them is enabled so T2 is either infinite or
                 * 0.8 * the shortest preferred lifetime in the reply */
-               reply->rebind = (reply->min_prefer == 0xFFFFFFFF ? 0xFFFFFFFF
-                                : (reply->min_prefer / 5) * 4);
+               reply->rebind = (reply->min_prefer == INFINITE_TIME 
+                                ? INFINITE_TIME : (reply->min_prefer / 5) * 4);
        } else {
                /* Default is to let the client choose */
                reply->rebind = 0;