summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Markwalder <tmark@isc.org>2017-05-10 14:11:14 -0400
committerThomas Markwalder <tmark@isc.org>2017-05-10 14:11:14 -0400
commit27bcd88f807b424a6539850c39ccd335fd3f61ad (patch)
tree03d08a02d4f6ce2f6a8b378d9112a51dd6abc82d
parenta0ba59ad2a3a2ec4705ce1aa69933fbb92232cd1 (diff)
downloadisc-dhcp-27bcd88f807b424a6539850c39ccd335fd3f61ad.tar.gz
[v4_1_esv] Altered v4 lease time handling better handle infinite and large times
Merged in rt41976
-rw-r--r--RELNOTES7
-rw-r--r--includes/dhcpd.h1
-rw-r--r--server/dhcp.c56
-rw-r--r--server/dhcpv6.c26
4 files changed, 69 insertions, 21 deletions
diff --git a/RELNOTES b/RELNOTES
index 7c38dc3f..08cb43a6 100644
--- 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
diff --git a/includes/dhcpd.h b/includes/dhcpd.h
index 06c80a40..1e3c2011 100644
--- a/includes/dhcpd.h
+++ b/includes/dhcpd.h
@@ -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
diff --git a/server/dhcp.c b/server/dhcp.c
index bbcb3cb9..9fd17e2d 100644
--- a/server/dhcp.c
+++ b/server/dhcp.c
@@ -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);
+}
diff --git a/server/dhcpv6.c b/server/dhcpv6.c
index 68080a4b..9099e067 100644
--- a/server/dhcpv6.c
+++ b/server/dhcpv6.c
@@ -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;