summaryrefslogtreecommitdiff
path: root/sbin/dhclient/dhclient.c
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2021-03-28 16:23:06 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2021-03-28 16:23:06 +0000
commit6bee891a0035796598928f5e22081472934c7fce (patch)
treea4b4097a6640defc8d06bb87b4feb90dd566bba3 /sbin/dhclient/dhclient.c
parentbf23ee514ad92d119a899918ef44a7805afc395a (diff)
Convert remaining timers (lease renew, rebind, expiry) to
timespec values. Translate from the epoch values in leases to timespec values in one place. Final step to allow CLOCK_REALTIME -> CLOCK_MONOTONIC time accounting for the active lease.
Diffstat (limited to 'sbin/dhclient/dhclient.c')
-rw-r--r--sbin/dhclient/dhclient.c108
1 files changed, 56 insertions, 52 deletions
diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c
index 8f9dc15c1c0..5043be023b0 100644
--- a/sbin/dhclient/dhclient.c
+++ b/sbin/dhclient/dhclient.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dhclient.c,v 1.713 2021/03/24 16:04:10 krw Exp $ */
+/* $OpenBSD: dhclient.c,v 1.714 2021/03/28 16:23:05 krw Exp $ */
/*
* Copyright 2004 Henning Brauer <henning@openbsd.org>
@@ -167,6 +167,7 @@ void append_statement(char *, size_t, char *, char *);
time_t lease_expiry(struct client_lease *);
time_t lease_renewal(struct client_lease *);
time_t lease_rebind(struct client_lease *);
+void get_lease_timeouts(struct interface_info *, struct client_lease *);
struct client_lease *packet_to_lease(struct interface_info *,
struct option_data *);
@@ -785,8 +786,7 @@ state_reboot(struct interface_info *ifi)
return;
}
lease = apply_defaults(ifi->active);
- ifi->expiry = lease_expiry(lease);
- ifi->rebind = lease_rebind(lease);
+ get_lease_timeouts(ifi, lease);
free_client_lease(lease);
ifi->xid = arc4random();
@@ -1016,32 +1016,18 @@ dhcpnak(struct interface_info *ifi, const char *src)
void
bind_lease(struct interface_info *ifi)
{
+ struct timespec now;
struct client_lease *lease, *pl, *ll;
struct proposal *effective_proposal = NULL;
struct unwind_info *unwind_info;
char *msg = NULL;
- time_t cur_time, renewal;
int rslt, seen;
- time(&cur_time);
tick_msg("lease", TICK_SUCCESS);
+ clock_gettime(CLOCK_REALTIME, &now);
lease = apply_defaults(ifi->offer);
-
- /*
- * Take the server-provided times if available. Otherwise
- * figure them out according to the spec.
- *
- * expiry == time to discard lease.
- * renewal == time to renew lease from server that provided it.
- * rebind == time to renew lease from any server.
- *
- * N.B.: renewal and/or rebind time could be < cur_time when the
- * lease was obtained from the leases file.
- */
- ifi->expiry = lease_expiry(lease);
- ifi->rebind = lease_rebind(lease);
- renewal = lease_renewal(lease);
+ get_lease_timeouts(ifi, lease);
/* Replace the old active lease with the accepted offer. */
ifi->active = ifi->offer;
@@ -1144,10 +1130,12 @@ newlease:
* leaseDB. Rather than immediately trying to contact a server,
* pause the configured time between attempts.
*/
- if (renewal < cur_time)
+ if (timespeccmp(&now, &ifi->renew, >=))
set_timeout(ifi, config->retry_interval, state_bound);
- else
- set_timeout(ifi, renewal - cur_time, state_bound);
+ else {
+ ifi->timeout = ifi->renew;
+ ifi->timeout_func = state_bound;
+ }
}
/*
@@ -1384,7 +1372,6 @@ void
set_resend_timeout(struct interface_info *ifi, struct timespec *now,
void (*where)(struct interface_info *))
{
- const struct timespec expiry = {ifi->expiry, 0};
const struct timespec reboot_intvl = {config->reboot_interval, 0};
const struct timespec initial_intvl = {config->initial_interval, 0};
const struct timespec cutoff_intvl = {config->backoff_cutoff, 0};
@@ -1412,8 +1399,8 @@ set_resend_timeout(struct interface_info *ifi, struct timespec *now,
switch (ifi->state) {
case S_REBOOTING:
case S_RENEWING:
- if (timespeccmp(&when, &expiry, >))
- when = expiry;
+ if (timespeccmp(&when, &ifi->expiry, >))
+ when = ifi->expiry;
break;
case S_SELECTING:
if (timespeccmp(&when, &ifi->select_timeout, >))
@@ -1517,11 +1504,9 @@ send_request(struct interface_info *ifi)
struct in_addr from;
struct timespec now;
ssize_t rslt;
- time_t cur_time;
cancel_timeout(ifi);
clock_gettime(CLOCK_REALTIME, &now);
- cur_time = now.tv_sec;
switch (ifi->state) {
case S_REBOOTING:
@@ -1536,10 +1521,10 @@ send_request(struct interface_info *ifi)
}
break;
case S_RENEWING:
- if (cur_time > ifi->expiry)
+ if (timespeccmp(&now, &ifi->expiry, >=))
ifi->state = S_INIT;
else {
- if (cur_time > ifi->rebind)
+ if (timespeccmp(&now, &ifi->rebind, >=))
destination.sin_addr.s_addr = INADDR_BROADCAST;
else
destination.sin_addr.s_addr = ifi->destination.s_addr;
@@ -1892,14 +1877,12 @@ free_client_lease(struct client_lease *lease)
void
write_lease_db(struct interface_info *ifi)
{
- struct timespec now;
struct client_lease_tq *lease_db = &ifi->lease_db;
struct client_lease *lp, *pl;
char *leasestr;
- clock_gettime(CLOCK_REALTIME, &now);
TAILQ_FOREACH_SAFE(lp, lease_db, next, pl) {
- if (lp != ifi->active && lease_expiry(lp) < now.tv_sec) {
+ if (lp != ifi->active && lease_expiry(lp) == 0) {
TAILQ_REMOVE(lease_db, lp, next);
free_client_lease(lp);
}
@@ -2115,19 +2098,19 @@ lease_as_string(char *type, struct client_lease *lease)
append_statement(string, sizeof(string), " epoch ", buf);
free(buf);
- t = lease_renewal(lease);
+ t = lease->epoch + lease_renewal(lease);
rslt = strftime(timebuf, sizeof(timebuf), DB_TIMEFMT, gmtime(&t));
if (rslt == 0)
return NULL;
append_statement(string, sizeof(string), " renew ", timebuf);
- t = lease_rebind(lease);
+ t = lease->epoch + lease_rebind(lease);
rslt = strftime(timebuf, sizeof(timebuf), DB_TIMEFMT, gmtime(&t));
if (rslt == 0)
return NULL;
append_statement(string, sizeof(string), " rebind ", timebuf);
- t = lease_expiry(lease);
+ t = lease->epoch + lease_expiry(lease);
rslt = strftime(timebuf, sizeof(timebuf), DB_TIMEFMT, gmtime(&t));
if (rslt == 0)
return NULL;
@@ -2612,8 +2595,10 @@ get_recorded_lease(struct interface_info *ifi)
time_t
lease_expiry(struct client_lease *lease)
{
+ time_t cur_time;
uint32_t expiry;
+ time(&cur_time);
expiry = 0;
if (lease->options[DHO_DHCP_LEASE_TIME].len == sizeof(expiry)) {
memcpy(&expiry, lease->options[DHO_DHCP_LEASE_TIME].data,
@@ -2622,53 +2607,72 @@ lease_expiry(struct client_lease *lease)
if (expiry < 60)
expiry = 60;
}
- if (expiry > LLONG_MAX - lease->epoch)
- expiry = LLONG_MAX - lease->epoch;
+ expiry = lease->epoch + expiry - cur_time;
- return lease->epoch + expiry;
+ return (expiry > 0) ? expiry : 0;
}
time_t
lease_renewal(struct client_lease *lease)
{
- time_t expiry;
+ time_t cur_time, expiry;
uint32_t renewal;
- expiry = lease_expiry(lease) - lease->epoch;
+ time(&cur_time);
+ expiry = lease_expiry(lease);
renewal = expiry / 2;
if (lease->options[DHO_DHCP_RENEWAL_TIME].len == sizeof(renewal)) {
memcpy(&renewal, lease->options[DHO_DHCP_RENEWAL_TIME].data,
sizeof(renewal));
renewal = ntohl(renewal);
- if (renewal > expiry)
- renewal = expiry;
}
+ renewal = lease->epoch + renewal - cur_time;
- return lease->epoch + renewal;
+ return (renewal > 0) ? renewal : 0;
}
time_t
lease_rebind(struct client_lease *lease)
{
- time_t expiry, renewal;
+ time_t cur_time, expiry;
uint32_t rebind;
- expiry = lease_expiry(lease) - lease->epoch;
- renewal = lease_renewal(lease) - lease->epoch;
+ time(&cur_time);
+ expiry = lease_expiry(lease);
rebind = (expiry / 8) * 7;
if (lease->options[DHO_DHCP_REBINDING_TIME].len == sizeof(rebind)) {
memcpy(&rebind, lease->options[DHO_DHCP_REBINDING_TIME].data,
sizeof(rebind));
rebind = ntohl(rebind);
- if (rebind > expiry)
- rebind = expiry;
}
- if (rebind < renewal)
- rebind = renewal;
+ rebind = lease->epoch + rebind - cur_time;
+
+ return (rebind > 0) ? rebind : 0;
+}
+
+void
+get_lease_timeouts(struct interface_info *ifi, struct client_lease *lease)
+{
+ struct timespec now, interval;
+
+ clock_gettime(CLOCK_REALTIME, &now);
+ timespecclear(&interval);
+
+ interval.tv_sec = lease_expiry(lease);
+ timespecadd(&now, &interval, &ifi->expiry);
+
+ interval.tv_sec = lease_rebind(lease);
+ timespecadd(&now, &interval, &ifi->rebind);
+
+ interval.tv_sec = lease_renewal(lease);
+ timespecadd(&now, &interval, &ifi->renew);
- return lease->epoch + rebind;
+ if (timespeccmp(&ifi->rebind, &ifi->expiry, >))
+ ifi->rebind = ifi->expiry;
+ if (timespeccmp(&ifi->renew, &ifi->rebind, >))
+ ifi->renew = ifi->rebind;
}
void