From: Gabriel Valcazar Date: Mon, 5 Mar 2018 10:00:23 +0100 Subject: [PATCH] dhclient: Check if the rebind time has expired when renewing the lease If the system time suffers a big jump, the client will start the renewal process but it will end prematurely due to the expiry of the lease time. By adding this check, a time jump can be detected and the active lease can be updated with the correct expiry dates. https://jira.digi.com/browse/DEL-5233 Signed-off-by: Gabriel Valcazar --- client/dhclient.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/client/dhclient.c b/client/dhclient.c index dcf3f1a..9074373 100644 --- a/client/dhclient.c +++ b/client/dhclient.c @@ -101,6 +101,8 @@ char *mockup_relay = NULL; char *progname = NULL; +TIME time_of_binding; + void run_stateless(int exit_mode, u_int16_t port); static isc_result_t write_duid(struct data_string *duid); @@ -1440,6 +1442,9 @@ void bind_lease (client) client->active = client->new; client->new = NULL; + /* Save the time at which the binding occurred. */ + time_of_binding = cur_time; + /* Set up a timeout to start the renewal process. */ tv.tv_sec = client->active->renewal; tv.tv_usec = ((client->active->renewal - cur_tv.tv_sec) > 1) ? @@ -1472,6 +1477,30 @@ void state_bound (cpp) ASSERT_STATE(state, S_BOUND); + /* + * The T2 lease time for the active lease should never be expired when + * reaching this state. If so, it means there has been a time jump in + * the system's clock. In this case, update the lease with the correct + * times and create a new state_bound timeout. + */ + if (cur_time > client->active->rebind) { + struct timeval tv; + + TIME time_jump = cur_time - time_of_binding; + client->active->renewal += time_jump; + client->active->rebind += time_jump; + client->active->expiry += time_jump; + + rewrite_client_leases(); + + /* Set up a timeout to start the renewal process. */ + tv.tv_sec = client->active->renewal; + tv.tv_usec = ((client->active->renewal - cur_tv.tv_sec) > 1) ? + random() % 1000000 : cur_tv.tv_usec; + add_timeout(&tv, state_bound, client, 0, 0); + return; + } + /* T1 has expired. */ make_request (client, client -> active); client -> xid = client -> packet.xid;