From nobody Wed Apr 23 04:51:00 2025 X-Original-To: dev-commits-src-branches@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4Zj6BF2Msrz5skkQ; Wed, 23 Apr 2025 04:51:01 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R11" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4Zj6BF0ZTBz3dwY; Wed, 23 Apr 2025 04:51:01 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1745383861; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=0NQYnbE8ygxWWEI8hkiwwGwQqvj3FBjNBNQvYKT3mvs=; b=pcpdCIU62TF2bJ8jM9PzB601CA8cjqn0aX0+Ihlm080L2PcWG/4dBPD+CyiXF4uQ/5oFtZ b4SZuoQ73pVDpe4rWyFCMKfadbAIhkkwUpKXQ8vQ/j8yljiD7VM1a3ViyQu/XCo8dFy0JE X41uk5XB2A2j2BTRZtL5WKsun3toGVIPs/jTFYHTrw/OEw68nwJPDnb6rVsFgb1Cl6BTPC piiju3T+PmX71DVyi9RbQxgm68unzQDKK4sb5Gh9Uf9MKxPKQqJi8eiUUi4XcD5gDni9bX vboqBCngcxITFauodM6e4T1nk0jIa9WedM4UrLGloWSzwv7GNBqF9TONTNxWTQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1745383861; a=rsa-sha256; cv=none; b=nKxgxhPzPWQ96Z7Bgpaa9NeQRMFdiPkuah/jFthVi27aj31kQO3CLAS52iQ6ijoCHHfzT0 i81w28QA32niTRZbYCQ7WhiR7lYJpGy6bpWXq7WE/HFi3Iy0amYRCavGgtXy929B8vH1zW D6EhaMC5RYv8+Ju6Zah8J0svkqulB8qABdyvNbUONffHvRfWwQGLCIGsmdQ/vWB2jVyp0Z tKmC9cb2J3GSkaudXc6zQ/UnVVNkOQoMxd7JwUBMVhy6SdrlE3kt/7IQmwb5S2b4AGGnZK 5pdA8htedsJmdsNNkd+vSX7j0Eu7BJHLCUWxyw7pTHgSGznR47oks5aExFsegg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1745383861; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=0NQYnbE8ygxWWEI8hkiwwGwQqvj3FBjNBNQvYKT3mvs=; b=KuI0WFRTd7Yf5oQbx/Y6AwCw9naXXlAx9y/qEftV2pVI3ywRCWEei1Ze8gW/n3qiBqD+r/ wWpj+FUHCI+rMJMLk3EhKpiTwpIi6xFM6ItbaXDvZGWQk+nTi1EH8w3t9PkT6ITcNcc/mK 4OEcUwgve91zoSdZqEQiqr1eDYVx/PK0Ak7QLz6Kl28qdpEXw0AAH+xO+s5b8+V0zJkZgS hhsTzA9mpC3TcIlEx8At8rZmp48ig2d3b9eeRF0j2rw4uapL7SjxC6pPWQjL39GQUfd0VY xM81hhvZkUxI2tWdVybhM2i2E8xjkhRquzAyApO7Q+j80HfcX0a8/HgKe9q7zA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4Zj6BD74RGzq7w; Wed, 23 Apr 2025 04:51:00 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 53N4p03i081532; Wed, 23 Apr 2025 04:51:00 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 53N4p06b081529; Wed, 23 Apr 2025 04:51:00 GMT (envelope-from git) Date: Wed, 23 Apr 2025 04:51:00 GMT Message-Id: <202504230451.53N4p06b081529@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Colin Percival Subject: git: c8c624de57b0 - stable/13 - dhclient: Keep two clocks List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-branches@freebsd.org Sender: owner-dev-commits-src-branches@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: cperciva X-Git-Repository: src X-Git-Refname: refs/heads/stable/13 X-Git-Reftype: branch X-Git-Commit: c8c624de57b072d14c1ab23167880a069ef51f11 Auto-Submitted: auto-generated The branch stable/13 has been updated by cperciva: URL: https://cgit.FreeBSD.org/src/commit/?id=c8c624de57b072d14c1ab23167880a069ef51f11 commit c8c624de57b072d14c1ab23167880a069ef51f11 Author: Colin Percival AuthorDate: 2025-04-08 22:50:01 +0000 Commit: Colin Percival CommitDate: 2025-04-23 04:50:55 +0000 dhclient: Keep two clocks Until July 2024, dhclient kept track of time as seconds-since-epoch as a time_t. This was a problem because (a) we wanted sub-second timeouts and (b) timeouts didn't always do the right thing if the system clock changed. Switching to using CLOCK_MONOTONIC and struct timespec fixed those issues but introduced a new problem: CLOCK_MONOTONIC values were being intepreted as seconds-since-epoch and written to the dhclient.leases file, causing confusion with DHCP leases expiring in early 1970. Attempt to compromise between these by keeping track of both times; any type within dhclient which is a time_t now refers to seconds past the epoch, while any struct timespec value is a CLOCK_MONOTONIC time. PR: 283256 Reviewed by: dch Fixes: f0a38976b01e ("dhclient: Use clock_gettime() instead of time()") Sponsored by: Amazon Differential Revision: https://reviews.freebsd.org/D49720 (cherry picked from commit 43d19e6a4c42ade0f276ceca18a09e2e3829fce4) --- sbin/dhclient/dhclient.c | 50 +++++++++++++++++++++--------------------------- sbin/dhclient/dhcpd.h | 4 ++-- sbin/dhclient/dispatch.c | 14 +++++++++----- 3 files changed, 33 insertions(+), 35 deletions(-) diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c index 141403d8c86b..0ac2a493a94f 100644 --- a/sbin/dhclient/dhclient.c +++ b/sbin/dhclient/dhclient.c @@ -90,8 +90,8 @@ cap_channel_t *capsyslog; -time_t cur_time; -struct timespec time_now; +time_t cur_time; /* Seconds since epoch. */ +struct timespec time_now; /* CLOCK_MONOTONIC. */ static time_t default_lease_time = 43200; /* 12 hours... */ const char *path_dhclient_conf = _PATH_DHCLIENT_CONF; @@ -450,7 +450,7 @@ main(int argc, char *argv[]) tzset(); clock_gettime(CLOCK_MONOTONIC, &time_now); - cur_time = time_now.tv_sec; + cur_time = time(NULL); inaddr_broadcast.s_addr = INADDR_BROADCAST; inaddr_any.s_addr = INADDR_ANY; @@ -1030,13 +1030,13 @@ dhcpoffer(struct packet *packet) struct client_lease *lease, *lp; int i; struct timespec arp_timeout_needed; - struct timespec stop_selecting = { .tv_sec = 0, .tv_nsec = 0 }; - time_now.tv_sec = cur_time; - time_now.tv_nsec = 0; - + time_t stop_selecting; + struct timespec stop_time; const char *name = packet->options[DHO_DHCP_MESSAGE_TYPE].len ? "DHCPOFFER" : "BOOTREPLY"; + clock_gettime(CLOCK_MONOTONIC, &time_now); + /* If we're not receptive to an offer right now, or if the offer has an unrecognizable transaction id, then just drop it. */ if (ip->client->state != S_SELECTING || @@ -1096,7 +1096,7 @@ dhcpoffer(struct packet *packet) arp_timeout_needed = arp_timeout; /* Figure out when we're supposed to stop selecting. */ - stop_selecting.tv_sec = + stop_selecting = ip->client->first_sending + ip->client->config->select_interval; /* If this is the lease we asked for, put it at the head of the @@ -1117,7 +1117,7 @@ dhcpoffer(struct packet *packet) timespecadd(&time_now, &arp_timeout_needed, &interm_struct); if (ip->client->offered_leases && - timespeccmp(&interm_struct, &stop_selecting, >)) + interm_struct.tv_sec >= stop_selecting) arp_timeout_needed = zero_timespec; /* Put the lease at the end of the list. */ @@ -1132,27 +1132,21 @@ dhcpoffer(struct packet *packet) } } - /* If we're supposed to stop selecting before we've had time - to wait for the ARPREPLY, add some delay to wait for - the ARPREPLY. */ - struct timespec time_left; - timespecsub(&stop_selecting, &time_now, &time_left); - + /* + * Wait until stop_selecting seconds past the epoch, or until + * arp_timeout_needed past now, whichever is longer. Note that + * the first case only occurs if select-timeout is set to nonzero + * in dhclient.conf. + */ + struct timespec time_left = + {.tv_sec = stop_selecting - cur_time, .tv_nsec = 0}; if (timespeccmp(&time_left, &arp_timeout_needed, <)) { - timespecadd(&time_now, &arp_timeout_needed, &stop_selecting); - } - - /* If the selecting interval has expired, go immediately to - state_selecting(). Otherwise, time out into - state_selecting at the select interval. */ - - - if (timespeccmp(&stop_selecting, &zero_timespec, <=)) - state_selecting(ip); - else { - add_timeout_timespec(stop_selecting, state_selecting, ip); - cancel_timeout(send_discover, ip); + timespecadd(&time_now, &arp_timeout_needed, &stop_time); + } else { + timespecadd(&time_now, &time_left, &stop_time); } + add_timeout_timespec(stop_time, state_selecting, ip); + cancel_timeout(send_discover, ip); } /* Allocate a client_lease structure and initialize it from the parameters diff --git a/sbin/dhclient/dhcpd.h b/sbin/dhclient/dhcpd.h index abe652c06fec..13c748c3f83f 100644 --- a/sbin/dhclient/dhcpd.h +++ b/sbin/dhclient/dhcpd.h @@ -361,8 +361,8 @@ char *piaddr(struct iaddr); extern cap_channel_t *capsyslog; extern const char *path_dhclient_conf; extern char *path_dhclient_db; -extern struct timespec time_now; -extern time_t cur_time; +extern struct timespec time_now; /* CLOCK_MONOTONIC */ +extern time_t cur_time; /* Seconds since epoch */ extern int log_priority; extern int log_perror; diff --git a/sbin/dhclient/dispatch.c b/sbin/dhclient/dispatch.c index 78d94804468b..bfa96b391bf8 100644 --- a/sbin/dhclient/dispatch.c +++ b/sbin/dhclient/dispatch.c @@ -171,8 +171,8 @@ dispatch(void) struct protocol *l; struct pollfd *fds; struct timespec howlong; - time_now.tv_sec = cur_time; - time_now.tv_nsec = 0; + + clock_gettime(CLOCK_MONOTONIC, &time_now); for (l = protocols; l; l = l->next) nfds++; @@ -236,7 +236,7 @@ another: if (count == -1) { if (errno == EAGAIN || errno == EINTR) { clock_gettime(CLOCK_MONOTONIC, &time_now); - cur_time = time_now.tv_sec; + cur_time = time(NULL); continue; } else error("poll: %m"); @@ -244,7 +244,7 @@ another: /* Get the current time... */ clock_gettime(CLOCK_MONOTONIC, &time_now); - cur_time = time_now.tv_sec; + cur_time = time(NULL); i = 0; for (l = protocols; l; l = l->next) { @@ -377,7 +377,11 @@ active: void add_timeout(time_t when_s, void (*where)(void *), void *what) { - struct timespec when = { .tv_sec = when_s, .tv_nsec = 0 }; + struct timespec when; + + cur_time = time(NULL); + clock_gettime(CLOCK_MONOTONIC, &when); + when.tv_sec += when_s - cur_time; add_timeout_timespec(when, where, what); }