diff options
author | Kenneth R Westerback <krw@cvs.openbsd.org> | 2021-03-11 15:30:50 +0000 |
---|---|---|
committer | Kenneth R Westerback <krw@cvs.openbsd.org> | 2021-03-11 15:30:50 +0000 |
commit | 3cf9d7c6fe48b6295f47d43dfcca911053585553 (patch) | |
tree | 0efc2f275c9f8cf795c8264f1ce9c7f4608788e2 /sbin/dhclient | |
parent | 57f7bbe27566731f97de2222cb8a307893193342 (diff) |
Use timespec timers to determine when select-timeout and timeout intervals
are exceeded.
Feedback from otto@, cheloha@
Diffstat (limited to 'sbin/dhclient')
-rw-r--r-- | sbin/dhclient/dhclient.c | 45 | ||||
-rw-r--r-- | sbin/dhclient/dhcpd.h | 4 |
2 files changed, 35 insertions, 14 deletions
diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c index b45dc868f6c..8ec981d57bd 100644 --- a/sbin/dhclient/dhclient.c +++ b/sbin/dhclient/dhclient.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dhclient.c,v 1.710 2021/03/09 14:32:24 krw Exp $ */ +/* $OpenBSD: dhclient.c,v 1.711 2021/03/11 15:30:49 krw Exp $ */ /* * Copyright 2004 Henning Brauer <henning@openbsd.org> @@ -807,12 +807,18 @@ state_reboot(struct interface_info *ifi) 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; - time(&ifi->first_sending); + clock_gettime(CLOCK_REALTIME, &now); + ifi->first_sending = now.tv_sec; + timespecadd(&now, &offer_intvl, &ifi->offer_timeout); + ifi->select_timeout = ifi->offer_timeout; ifi->interval = 0; send_discover(ifi); @@ -892,10 +898,11 @@ void 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 client_lease *lease; - time_t cur_time, stop_selecting; - time(&cur_time); + clock_gettime(CLOCK_REALTIME, &now); lease = packet_to_lease(ifi, options); if (lease != NULL) { @@ -903,6 +910,10 @@ process_offer(struct interface_info *ifi, struct option_data *options, ifi->offer = lease; free(ifi->offer_src); ifi->offer_src = strdup(src); /* NULL is OK */ + timespecadd(&now, &select_intvl, &ifi->select_timeout); + if (timespeccmp(&ifi->select_timeout, + &ifi->offer_timeout, >)) + ifi->select_timeout = ifi->offer_timeout; } else if (lease->address.s_addr == ifi->offer->address.s_addr) { /* Decline duplicate offers. */ @@ -920,12 +931,16 @@ process_offer(struct interface_info *ifi, struct option_data *options, } } - /* Figure out when we're supposed to stop selecting. */ - stop_selecting = ifi->first_sending + config->select_interval; - if (stop_selecting <= cur_time) + if (timespeccmp(&now, &ifi->select_timeout, >=)) state_selecting(ifi); - else - set_timeout(ifi, stop_selecting - cur_time, state_selecting); + 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); + } } void @@ -1378,9 +1393,13 @@ set_interval(struct interface_info *ifi, time_t cur_time) if (cur_time + interval > ifi->expiry) interval = ifi->expiry - cur_time; break; + case S_SELECTING: + if (cur_time + interval > ifi->select_timeout.tv_sec) + interval = ifi->select_timeout.tv_sec - cur_time; + break; case S_REQUESTING: - if (cur_time + interval > ifi->first_sending + config->offer_interval) - interval = (ifi->first_sending + config->offer_interval) - cur_time; + if (cur_time + interval > ifi->offer_timeout.tv_sec) + interval = ifi->offer_timeout.tv_sec - cur_time; break; default: break; @@ -1420,7 +1439,7 @@ send_discover(struct interface_info *ifi) clock_gettime(CLOCK_REALTIME, &now); cur_time = now.tv_sec; - if (cur_time > ifi->first_sending + config->offer_interval) { + if (timespeccmp(&now, &ifi->offer_timeout, >=)) { state_panic(ifi); return; } @@ -1514,7 +1533,7 @@ send_request(struct interface_info *ifi) } break; case S_REQUESTING: - if (interval > config->offer_interval) + if (timespeccmp(&now, &ifi->offer_timeout, >=)) ifi->state = S_INIT; else { destination.sin_addr.s_addr = INADDR_BROADCAST; diff --git a/sbin/dhclient/dhcpd.h b/sbin/dhclient/dhcpd.h index 08ac22f3ddd..692a693cda1 100644 --- a/sbin/dhclient/dhcpd.h +++ b/sbin/dhclient/dhcpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: dhcpd.h,v 1.296 2021/03/09 14:32:24 krw Exp $ */ +/* $OpenBSD: dhcpd.h,v 1.297 2021/03/11 15:30:49 krw Exp $ */ /* * Copyright (c) 2004 Henning Brauer <henning@openbsd.org> @@ -141,6 +141,8 @@ struct interface_info { uint16_t secs; time_t first_sending; struct timespec link_timeout; + struct timespec offer_timeout; + struct timespec select_timeout; enum dhcp_state state; struct in_addr destination; time_t interval; |