]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-dhcp-client: correct dhcpv4 renew/rebind retransmit timeouts
authorDan Streetman <ddstreet@canonical.com>
Tue, 8 Dec 2020 20:40:10 +0000 (15:40 -0500)
committerDan Streetman <ddstreet@canonical.com>
Mon, 14 Dec 2020 23:19:22 +0000 (18:19 -0500)
Use the request timeout algorithm specified in RFC2131 section 4.4.5 for
handling timed out RENEW and REBIND requests.

This changes behavior, as previously only 2 RENEW and 2 REBIND requests
were sent, no matter how long the lease lifetime. Now, requests are
send according to the RFC, which results in starting with a timeout
of 1/2 the t1 or t2 period, and halving the timeout for each retry
down to a minimum of 60 seconds.

Fixes: #17909
src/libsystemd-network/sd-dhcp-client.c

index 8c6affac81cb9d6cd94bc54dccd47ef2b36ecde2..4a693ba70605e913c394e9834edc0a052c14a889 100644 (file)
@@ -1227,7 +1227,6 @@ static int client_timeout_resend(
         DHCP_CLIENT_DONT_DESTROY(client);
         usec_t next_timeout;
         uint64_t time_now;
-        uint32_t time_left;
         int r;
 
         assert(s);
@@ -1241,19 +1240,11 @@ static int client_timeout_resend(
         switch (client->state) {
 
         case DHCP_STATE_RENEWING:
-                time_left = (client->lease->t2 - client->lease->t1) / 2;
-                if (time_left < 60)
-                        time_left = 60;
-
-                next_timeout = time_now + time_left * USEC_PER_SEC;
+                next_timeout = client_compute_reacquisition_timeout(time_now, client->t2_time);
                 break;
 
         case DHCP_STATE_REBINDING:
-                time_left = (client->lease->lifetime - client->lease->t2) / 2;
-                if (time_left < 60)
-                        time_left = 60;
-
-                next_timeout = time_now + time_left * USEC_PER_SEC;
+                next_timeout = client_compute_reacquisition_timeout(time_now, client->expire_time);
                 break;
 
         case DHCP_STATE_REBOOTING:
@@ -1279,6 +1270,7 @@ static int client_timeout_resend(
 
                 client->attempt++;
                 next_timeout = time_now + ((UINT64_C(1) << MIN(client->attempt, (uint64_t) 6)) - 1) * USEC_PER_SEC;
+                next_timeout += (random_u32() & 0x1fffff);
                 break;
 
         case DHCP_STATE_STOPPED:
@@ -1286,8 +1278,6 @@ static int client_timeout_resend(
                 goto error;
         }
 
-        next_timeout += (random_u32() & 0x1fffff);
-
         r = event_reset_time(client->event, &client->timeout_resend,
                              clock_boottime_or_monotonic(),
                              next_timeout, 10 * USEC_PER_MSEC,