mirror of
https://gitlab.isc.org/isc-projects/dhcp
synced 2025-09-01 14:55:30 +00:00
[master] Altered v4 lease time handling better handle infinite and large times
Merged in rt41976
This commit is contained in:
7
RELNOTES
7
RELNOTES
@@ -187,6 +187,13 @@ by Eric Young (eay@cryptsoft.com).
|
|||||||
Mritunjaykumar Dubey at Nokia for reporting the issue.
|
Mritunjaykumar Dubey at Nokia for reporting the issue.
|
||||||
[ISC-Bugs #41473]
|
[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.3.0 (bug fixes)
|
Changes since 4.3.0 (bug fixes)
|
||||||
|
|
||||||
- Tidy up several small tickets.
|
- Tidy up several small tickets.
|
||||||
|
@@ -1588,6 +1588,7 @@ typedef unsigned char option_mask [16];
|
|||||||
#define DHCPD_LOG_FACILITY LOG_DAEMON
|
#define DHCPD_LOG_FACILITY LOG_DAEMON
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define INFINITE_TIME 0xffffffff
|
||||||
#define MAX_TIME 0x7fffffff
|
#define MAX_TIME 0x7fffffff
|
||||||
#define MIN_TIME 0
|
#define MIN_TIME 0
|
||||||
|
|
||||||
|
@@ -85,6 +85,8 @@ const int dhcp_type_name_max = ((sizeof dhcp_type_names) / sizeof (char *));
|
|||||||
# define send_packet trace_packet_send
|
# define send_packet trace_packet_send
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static TIME leaseTimeCheck(TIME calculated, TIME alternate);
|
||||||
|
|
||||||
void
|
void
|
||||||
dhcp (struct packet *packet) {
|
dhcp (struct packet *packet) {
|
||||||
int ms_nulltp = 0;
|
int ms_nulltp = 0;
|
||||||
@@ -2878,8 +2880,15 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
|
|||||||
* the desired lease time upon renewal.
|
* the desired lease time upon renewal.
|
||||||
*/
|
*/
|
||||||
if (offer == DHCPACK) {
|
if (offer == DHCPACK) {
|
||||||
lt->tstp = cur_time + lease_time +
|
if (lease_time == INFINITE_TIME) {
|
||||||
(new_lease_time / 2);
|
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,
|
/* If we reduced the potential expiry time,
|
||||||
* make sure we don't offer an old-expiry-time
|
* make sure we don't offer an old-expiry-time
|
||||||
@@ -2896,12 +2905,16 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
|
|||||||
}
|
}
|
||||||
#endif /* FAILOVER_PROTOCOL */
|
#endif /* FAILOVER_PROTOCOL */
|
||||||
|
|
||||||
|
if (lease_time == INFINITE_TIME) {
|
||||||
|
state->offered_expiry = MAX_TIME;
|
||||||
|
} else {
|
||||||
/* If the lease duration causes the time value to wrap,
|
/* If the lease duration causes the time value to wrap,
|
||||||
use the maximum expiry time. */
|
use the maximum expiry time. */
|
||||||
if (cur_time + lease_time < cur_time)
|
state->offered_expiry
|
||||||
state -> offered_expiry = MAX_TIME - 1;
|
= leaseTimeCheck(cur_time + lease_time,
|
||||||
else
|
MAX_TIME - 1);
|
||||||
state -> offered_expiry = cur_time + lease_time;
|
}
|
||||||
|
|
||||||
if (when)
|
if (when)
|
||||||
lt -> ends = when;
|
lt -> ends = when;
|
||||||
else
|
else
|
||||||
@@ -5670,3 +5683,29 @@ reuse_lease (struct packet* packet,
|
|||||||
lease->cannot_reuse = (!reusable && offer == DHCPOFFER);
|
lease->cannot_reuse = (!reusable && offer == DHCPOFFER);
|
||||||
return (reusable);
|
return (reusable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* \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);
|
||||||
|
}
|
||||||
|
@@ -2090,7 +2090,7 @@ reply_process_ia_na(struct reply_state *reply, struct option_cache *ia) {
|
|||||||
* A not included IA ("cleanup" below) could give a Renew/Rebind.
|
* A not included IA ("cleanup" below) could give a Renew/Rebind.
|
||||||
*/
|
*/
|
||||||
oc = lookup_option(&dhcpv6_universe, packet_ia, D6O_IAADDR);
|
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;
|
reply->client_valid = reply->client_prefer = 0;
|
||||||
for (; oc != NULL ; oc = oc->next) {
|
for (; oc != NULL ; oc = oc->next) {
|
||||||
status = reply_process_addr(reply, oc);
|
status = reply_process_addr(reply, oc);
|
||||||
@@ -2845,7 +2845,7 @@ reply_process_ia_ta(struct reply_state *reply, struct option_cache *ia) {
|
|||||||
* Deal with an IAADDR for lifetimes.
|
* Deal with an IAADDR for lifetimes.
|
||||||
* For all or none, process IAADDRs as hints.
|
* For all or none, process IAADDRs as hints.
|
||||||
*/
|
*/
|
||||||
reply->min_valid = reply->min_prefer = 0xffffffff;
|
reply->min_valid = reply->min_prefer = INFINITE_TIME;
|
||||||
reply->client_valid = reply->client_prefer = 0;
|
reply->client_valid = reply->client_prefer = 0;
|
||||||
oc = lookup_option(&dhcpv6_universe, packet_ia, D6O_IAADDR);
|
oc = lookup_option(&dhcpv6_universe, packet_ia, D6O_IAADDR);
|
||||||
for (; oc != NULL; oc = oc->next) {
|
for (; oc != NULL; oc = oc->next) {
|
||||||
@@ -3567,10 +3567,10 @@ reply_process_is_addressed(struct reply_state *reply,
|
|||||||
* The following doesn't work on at least some systems:
|
* The following doesn't work on at least some systems:
|
||||||
* (cur_time + reply->send_valid < cur_time)
|
* (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;
|
time_t test_time = cur_time + reply->send_valid;
|
||||||
if (test_time < cur_time)
|
if (test_time < cur_time)
|
||||||
reply->send_valid = 0xFFFFFFFF;
|
reply->send_valid = INFINITE_TIME;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reply->client_prefer == 0)
|
if (reply->client_prefer == 0)
|
||||||
@@ -3579,7 +3579,7 @@ reply_process_is_addressed(struct reply_state *reply,
|
|||||||
reply->send_prefer = reply->client_prefer;
|
reply->send_prefer = reply->client_prefer;
|
||||||
|
|
||||||
if ((reply->send_prefer >= reply->send_valid) &&
|
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_prefer = (reply->send_valid / 2) +
|
||||||
(reply->send_valid / 8);
|
(reply->send_valid / 8);
|
||||||
|
|
||||||
@@ -3634,7 +3634,7 @@ reply_process_is_addressed(struct reply_state *reply,
|
|||||||
* when connecting to the lease file MAX_TIME is
|
* when connecting to the lease file MAX_TIME is
|
||||||
*/
|
*/
|
||||||
if (reply->buf.reply.msg_type == DHCPV6_REPLY) {
|
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;
|
reply->lease->soft_lifetime_end_time = MAX_TIME;
|
||||||
} else {
|
} else {
|
||||||
reply->lease->soft_lifetime_end_time =
|
reply->lease->soft_lifetime_end_time =
|
||||||
@@ -3921,7 +3921,7 @@ reply_process_ia_pd(struct reply_state *reply, struct option_cache *ia) {
|
|||||||
* For each prefix in this IA_PD, decide what to do about it.
|
* For each prefix in this IA_PD, decide what to do about it.
|
||||||
*/
|
*/
|
||||||
oc = lookup_option(&dhcpv6_universe, packet_ia, D6O_IAPREFIX);
|
oc = lookup_option(&dhcpv6_universe, packet_ia, D6O_IAPREFIX);
|
||||||
reply->min_valid = reply->min_prefer = 0xffffffff;
|
reply->min_valid = reply->min_prefer = INFINITE_TIME;
|
||||||
reply->client_valid = reply->client_prefer = 0;
|
reply->client_valid = reply->client_prefer = 0;
|
||||||
reply->preflen = -1;
|
reply->preflen = -1;
|
||||||
for (; oc != NULL ; oc = oc->next) {
|
for (; oc != NULL ; oc = oc->next) {
|
||||||
@@ -4813,10 +4813,10 @@ reply_process_is_prefixed(struct reply_state *reply,
|
|||||||
* The following doesn't work on at least some systems:
|
* The following doesn't work on at least some systems:
|
||||||
* (cur_time + reply->send_valid < cur_time)
|
* (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;
|
time_t test_time = cur_time + reply->send_valid;
|
||||||
if (test_time < cur_time)
|
if (test_time < cur_time)
|
||||||
reply->send_valid = 0xFFFFFFFF;
|
reply->send_valid = INFINITE_TIME;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reply->client_prefer == 0)
|
if (reply->client_prefer == 0)
|
||||||
@@ -4825,7 +4825,7 @@ reply_process_is_prefixed(struct reply_state *reply,
|
|||||||
reply->send_prefer = reply->client_prefer;
|
reply->send_prefer = reply->client_prefer;
|
||||||
|
|
||||||
if ((reply->send_prefer >= reply->send_valid) &&
|
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_prefer = (reply->send_valid / 2) +
|
||||||
(reply->send_valid / 8);
|
(reply->send_valid / 8);
|
||||||
|
|
||||||
@@ -4865,7 +4865,7 @@ reply_process_is_prefixed(struct reply_state *reply,
|
|||||||
* when connecting to the lease file MAX_TIME is
|
* when connecting to the lease file MAX_TIME is
|
||||||
*/
|
*/
|
||||||
if (reply->buf.reply.msg_type == DHCPV6_REPLY) {
|
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;
|
reply->lease->soft_lifetime_end_time = MAX_TIME;
|
||||||
} else {
|
} else {
|
||||||
reply->lease->soft_lifetime_end_time =
|
reply->lease->soft_lifetime_end_time =
|
||||||
@@ -8089,8 +8089,10 @@ set_reply_tee_times(struct reply_state* reply, unsigned ia_cursor)
|
|||||||
} else if (set_tee_times) {
|
} else if (set_tee_times) {
|
||||||
/* Setting them is enabled so T1 is either infinite or
|
/* Setting them is enabled so T1 is either infinite or
|
||||||
* 0.5 * the shortest preferred lifetime in the IA_XX */
|
* 0.5 * the shortest preferred lifetime in the IA_XX */
|
||||||
reply->renew = (reply->min_prefer == 0xFFFFFFFF ? 0xFFFFFFFF
|
if (reply->min_prefer == INFINITE_TIME)
|
||||||
: reply->min_prefer / 2);
|
reply->renew = INFINITE_TIME;
|
||||||
|
else
|
||||||
|
reply->renew = reply->min_prefer / 2;
|
||||||
} else {
|
} else {
|
||||||
/* Default is to let the client choose */
|
/* Default is to let the client choose */
|
||||||
reply->renew = 0;
|
reply->renew = 0;
|
||||||
@@ -8122,8 +8124,10 @@ set_reply_tee_times(struct reply_state* reply, unsigned ia_cursor)
|
|||||||
} else if (set_tee_times) {
|
} else if (set_tee_times) {
|
||||||
/* Setting them is enabled so T2 is either infinite or
|
/* Setting them is enabled so T2 is either infinite or
|
||||||
* 0.8 * the shortest preferred lifetime in the reply */
|
* 0.8 * the shortest preferred lifetime in the reply */
|
||||||
reply->rebind = (reply->min_prefer == 0xFFFFFFFF ? 0xFFFFFFFF
|
if (reply->min_prefer == INFINITE_TIME)
|
||||||
: (reply->min_prefer / 5) * 4);
|
reply->rebind = INFINITE_TIME;
|
||||||
|
else
|
||||||
|
reply->rebind = (reply->min_prefer / 5) * 4;
|
||||||
} else {
|
} else {
|
||||||
/* Default is to let the client choose */
|
/* Default is to let the client choose */
|
||||||
reply->rebind = 0;
|
reply->rebind = 0;
|
||||||
|
Reference in New Issue
Block a user