DHCP: fix timeout handling

We allowed a delay only for few DHCP states. As a result, DHCP requests
would timeout immediately after sending the initial discover, and
moreover the code would then switch to "renew" state, trying to renew
without an assigned address.

The result is a quick succession of DISCOVER and empty REQUEST messages.
Eventually, the server could send us an OFFER as reply to our DISCOVER,
unless it decided that the empty REQUEST means "I'm requesting from
another server", which would lead it to cancelling its lease.

This would only work by luck on unbusy networks unlike the one I'm using
today.

Change-Id: I86905b341dc70f7dbcc780b954005e39e7c39ee0
Reviewed-on: https://review.haiku-os.org/c/1296
Reviewed-by: waddlesplash <waddlesplash@gmail.com>
This commit is contained in:
Adrien Destugues 2019-03-15 23:09:13 +01:00 committed by waddlesplash
parent e2c7bb900c
commit 9fef538b5b
1 changed files with 14 additions and 0 deletions

View File

@ -949,10 +949,24 @@ DHCPClient::_TimeoutShift(int socket, dhcp_state& state,
socket_timeout& timeout)
{
bigtime_t stateMaxTime = -1;
// Compute the date at which we must consider the DHCP negociation failed.
// This varies depending on the current state. In renewing and rebinding
// states, it is based on the lease expiration.
// We can stay for up to 1 minute in the selecting and requesting states
// (these correspond to sending DHCP_DISCOVER and DHCP_REQUEST,
// respectively).
// All other states time out immediately after a single try.
// If this timeout expires, the DHCP negociation is aborted and starts
// over. As long as the timeout is not expired, we repeat the message with
// increasing delays (the delay is computed in timeout.shift below, and is
// at most equal to the timeout, but usually much shorter).
if (state == RENEWING)
stateMaxTime = fRebindingTime;
else if (state == REBINDING)
stateMaxTime = fLeaseTime;
else if (state == SELECTING || state == REQUESTING)
stateMaxTime = fRequestTime + AS_USECS(MAX_TIMEOUT);
if (system_time() > stateMaxTime) {
state = state == REBINDING ? INIT : REBINDING;