summaryrefslogtreecommitdiff
path: root/sbin/dhclient
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2021-03-24 16:04:11 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2021-03-24 16:04:11 +0000
commitbd9a9dadb69ca9b89f94dd8b9c5c79aa37e55498 (patch)
treec5aba3d9fa5f0f7dac1258c896323aed663a284f /sbin/dhclient
parent958fd07e91bd16e90966e472607c9061fb8783da (diff)
More timespec conversions. Less 'seconds' arithmetic.
Diffstat (limited to 'sbin/dhclient')
-rw-r--r--sbin/dhclient/dhclient.c129
-rw-r--r--sbin/dhclient/dhcpd.h4
2 files changed, 75 insertions, 58 deletions
diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c
index be1a5c0d749..8f9dc15c1c0 100644
--- a/sbin/dhclient/dhclient.c
+++ b/sbin/dhclient/dhclient.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dhclient.c,v 1.712 2021/03/16 20:21:54 krw Exp $ */
+/* $OpenBSD: dhclient.c,v 1.713 2021/03/24 16:04:10 krw Exp $ */
/*
* Copyright 2004 Henning Brauer <henning@openbsd.org>
@@ -137,8 +137,10 @@ void state_selecting(struct interface_info *);
void state_bound(struct interface_info *);
void state_panic(struct interface_info *);
-void set_interval(struct interface_info *, time_t);
-void set_secs(struct interface_info *, time_t);
+void set_interval(struct interface_info *, struct timespec *);
+void set_resend_timeout(struct interface_info *, struct timespec *,
+ void (*where)(struct interface_info *));
+void set_secs(struct interface_info *, struct timespec *);
void send_discover(struct interface_info *);
void send_request(struct interface_info *);
@@ -768,7 +770,6 @@ void
state_reboot(struct interface_info *ifi)
{
const struct timespec reboot_intvl = {config->reboot_interval, 0};
- struct timespec now;
struct client_lease *lease;
cancel_timeout(ifi);
@@ -792,9 +793,8 @@ state_reboot(struct interface_info *ifi)
make_request(ifi, ifi->active);
ifi->destination.s_addr = INADDR_BROADCAST;
- clock_gettime(CLOCK_REALTIME, &now);
- ifi->first_sending = now.tv_sec;
- timespecadd(&now, &reboot_intvl, &ifi->reboot_timeout);
+ clock_gettime(CLOCK_REALTIME, &ifi->first_sending);
+ timespecadd(&ifi->first_sending, &reboot_intvl, &ifi->reboot_timeout);
ifi->interval = 0;
send_request(ifi);
@@ -808,16 +808,14 @@ void
state_init(struct interface_info *ifi)
{
const struct timespec offer_intvl = {config->offer_interval, 0};
- struct timespec now;
ifi->xid = arc4random();
make_discover(ifi, ifi->active);
ifi->destination.s_addr = INADDR_BROADCAST;
ifi->state = S_SELECTING;
- clock_gettime(CLOCK_REALTIME, &now);
- ifi->first_sending = now.tv_sec;
- timespecadd(&now, &offer_intvl, &ifi->offer_timeout);
+ clock_gettime(CLOCK_REALTIME, &ifi->first_sending);
+ timespecadd(&ifi->first_sending, &offer_intvl, &ifi->offer_timeout);
ifi->select_timeout = ifi->offer_timeout;
ifi->interval = 0;
@@ -847,7 +845,7 @@ state_selecting(struct interface_info *ifi)
}
ifi->destination.s_addr = INADDR_BROADCAST;
- time(&ifi->first_sending);
+ clock_gettime(CLOCK_REALTIME, &ifi->first_sending);
ifi->interval = 0;
/*
@@ -899,7 +897,7 @@ process_offer(struct interface_info *ifi, struct option_data *options,
const char *src)
{
const struct timespec select_intvl = {config->select_interval, 0};
- struct timespec now, remaining;
+ struct timespec now;
struct client_lease *lease;
clock_gettime(CLOCK_REALTIME, &now);
@@ -934,12 +932,8 @@ process_offer(struct interface_info *ifi, struct option_data *options,
if (timespeccmp(&now, &ifi->select_timeout, >=))
state_selecting(ifi);
else {
- timespecsub(&ifi->select_timeout, &now, &remaining);
- if (remaining.tv_sec == 0 || remaining.tv_nsec > 500000000LL)
- remaining.tv_sec++;
- log_debug("%s: waiting %lld seconds for better offers",
- log_procname, (long long)remaining.tv_sec);
- set_timeout(ifi, remaining.tv_sec, state_selecting);
+ ifi->timeout = ifi->select_timeout;
+ ifi->timeout_func = state_selecting;
}
}
@@ -1178,7 +1172,7 @@ state_bound(struct interface_info *ifi)
else
dest->s_addr = INADDR_BROADCAST;
- time(&ifi->first_sending);
+ clock_gettime(CLOCK_REALTIME, &ifi->first_sending);
ifi->interval = 0;
ifi->state = S_RENEWING;
@@ -1372,53 +1366,85 @@ decline:
}
void
-set_interval(struct interface_info *ifi, time_t cur_time)
+set_interval(struct interface_info *ifi, struct timespec *now)
{
- time_t interval = ifi->interval;
+ struct timespec interval;
+
+ if (timespeccmp(now, &ifi->timeout, >))
+ ifi->interval = 1;
+ else {
+ timespecsub(&ifi->timeout, now, &interval);
+ if (interval.tv_sec == 0 || interval.tv_nsec > 500000000LL)
+ interval.tv_sec++;
+ ifi->interval = interval.tv_sec;
+ }
+}
- if (interval == 0) {
+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};
+ const struct timespec onesecond = {1, 0};
+ struct timespec interval, when;
+
+ if (timespeccmp(now, &ifi->link_timeout, <))
+ interval = onesecond;
+ else if (ifi->interval == 0) {
if (ifi->state == S_REBOOTING)
- interval = config->reboot_interval;
+ interval = reboot_intvl;
else
- interval = config->initial_interval;
+ interval = initial_intvl;
} else {
- interval += arc4random_uniform(2 * interval);
- if (interval > config->backoff_cutoff)
- interval = config->backoff_cutoff;
+ timespecclear(&interval);
+ interval.tv_sec = ifi->interval + arc4random_uniform(2 *
+ ifi->interval);
}
+ if (timespeccmp(&interval, &onesecond, <))
+ interval = onesecond;
+ else if (timespeccmp(&interval, &cutoff_intvl, >))
+ interval = cutoff_intvl;
+ timespecadd(now, &interval, &when);
switch (ifi->state) {
case S_REBOOTING:
case S_RENEWING:
- if (cur_time + interval > ifi->expiry)
- interval = ifi->expiry - cur_time;
+ if (timespeccmp(&when, &expiry, >))
+ when = expiry;
break;
case S_SELECTING:
- if (cur_time + interval > ifi->select_timeout.tv_sec)
- interval = ifi->select_timeout.tv_sec - cur_time;
+ if (timespeccmp(&when, &ifi->select_timeout, >))
+ when = ifi->select_timeout;
break;
case S_REQUESTING:
- if (cur_time + interval > ifi->offer_timeout.tv_sec)
- interval = ifi->offer_timeout.tv_sec - cur_time;
+ if (timespeccmp(&when, &ifi->offer_timeout, >))
+ when = ifi->offer_timeout;
break;
default:
break;
}
- ifi->interval = interval ? interval : 1;
+ ifi->timeout = when;
+ ifi->timeout_func = where;
}
void
-set_secs(struct interface_info *ifi, time_t cur_time)
+set_secs(struct interface_info *ifi, struct timespec *now)
{
- time_t secs;
+ struct timespec interval;
if (ifi->state != S_REQUESTING) {
/* Update the number of seconds since we started sending. */
- secs = cur_time - ifi->first_sending;
- if (secs > UINT16_MAX)
- secs = UINT16_MAX;
- ifi->secs = secs;
+ timespecsub(now, &ifi->first_sending, &interval);
+ if (interval.tv_nsec > 500000000LL)
+ interval.tv_sec++;
+ if (interval.tv_sec > UINT16_MAX)
+ ifi->secs = UINT16_MAX;
+ else
+ ifi->secs = interval.tv_sec;
}
ifi->sent_packet.secs = htons(ifi->secs);
@@ -1434,21 +1460,16 @@ send_discover(struct interface_info *ifi)
{
struct timespec now;
ssize_t rslt;
- time_t cur_time;
clock_gettime(CLOCK_REALTIME, &now);
- cur_time = now.tv_sec;
-
if (timespeccmp(&now, &ifi->offer_timeout, >=)) {
state_panic(ifi);
return;
}
- if (timespeccmp(&now, &ifi->link_timeout, <))
- ifi->interval = 1;
- else
- set_interval(ifi, cur_time);
- set_secs(ifi, cur_time);
+ set_resend_timeout(ifi, &now, send_discover);
+ set_interval(ifi, &now);
+ set_secs(ifi, &now);
rslt = send_packet(ifi, inaddr_any, inaddr_broadcast, "DHCPDISCOVER");
if (rslt != -1)
@@ -1456,7 +1477,6 @@ send_discover(struct interface_info *ifi)
(long long)ifi->interval);
tick_msg("lease", TICK_WAIT);
- set_timeout(ifi, ifi->interval, send_discover);
}
/*
@@ -1548,11 +1568,9 @@ send_request(struct interface_info *ifi)
return;
}
- if (timespeccmp(&now, &ifi->link_timeout, <))
- ifi->interval = 1;
- else
- set_interval(ifi, cur_time);
- set_secs(ifi, cur_time);
+ set_resend_timeout(ifi, &now, send_request);
+ set_interval(ifi, &now);
+ set_secs(ifi, &now);
rslt = send_packet(ifi, from, destination.sin_addr, "DHCPREQUEST");
if (rslt != -1)
@@ -1560,7 +1578,6 @@ send_request(struct interface_info *ifi)
inet_ntoa(destination.sin_addr));
tick_msg("lease", TICK_WAIT);
- set_timeout(ifi, ifi->interval, send_request);
}
void
diff --git a/sbin/dhclient/dhcpd.h b/sbin/dhclient/dhcpd.h
index 692a693cda1..e8993104843 100644
--- a/sbin/dhclient/dhcpd.h
+++ b/sbin/dhclient/dhcpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: dhcpd.h,v 1.297 2021/03/11 15:30:49 krw Exp $ */
+/* $OpenBSD: dhcpd.h,v 1.298 2021/03/24 16:04:10 krw Exp $ */
/*
* Copyright (c) 2004 Henning Brauer <henning@openbsd.org>
@@ -139,7 +139,7 @@ struct interface_info {
time_t expiry, rebind;
void (*timeout_func)(struct interface_info *);
uint16_t secs;
- time_t first_sending;
+ struct timespec first_sending;
struct timespec link_timeout;
struct timespec offer_timeout;
struct timespec select_timeout;