Make the renew and rebind timeouts more strictly rfc compliant, and also

take into account the possiblity of renew times being ridiculously deferred
such that the current time is within lease expiration time.
This commit is contained in:
Nicholas J. Kain
2011-06-30 02:48:58 -04:00
parent 8fffc5721f
commit 339804856b

View File

@ -75,43 +75,61 @@ static void bound_timeout(struct client_state_t *cs)
renewing_timeout(cs); renewing_timeout(cs);
} }
static void lease_timedout(struct client_state_t *cs)
{
cs->dhcpState = DS_SELECTING;
log_line("Lease lost, entering init state.");
ifchange(NULL, IFCHANGE_DECONFIG);
cs->timeout = 0;
cs->packetNum = 0;
change_listen_mode(cs, LM_RAW);
}
// Triggered when a DHCP renew request has been sent and no reply has been // Triggered when a DHCP renew request has been sent and no reply has been
// received within the response wait time. This function is also directly // received within the response wait time. This function is also directly
// called by bound_timeout() when it is time to renew a lease before it // called by bound_timeout() when it is time to renew a lease before it
// expires. Check to see if the lease is still valid, and if it is, send // expires. Check to see if the lease is still valid, and if it is, send
// a unicast DHCP renew packet. If it is not, then change to the REBINDING // a unicast DHCP renew packet. If it is not, then change to the REBINDING
// state to get a new lease. // state to send broadcast queries.
static void renewing_timeout(struct client_state_t *cs) static void renewing_timeout(struct client_state_t *cs)
{ {
if ((cs->rebindTime - cs->renewTime) <= (cs->lease / 14400 + 1)) { long long ct = curms();
cs->dhcpState = DS_REBINDING; long long rbt = cs->leaseStartTime + cs->rebindTime * 1000;
cs->timeout = (cs->rebindTime - cs->renewTime) * 1000; if (ct < rbt) {
log_line("Entering rebinding state."); long long wt = (rbt - ct) / 2;
} else { if (wt >= 30000)
send_renew(cs->xid, cs->serverAddr, cs->requestedIP); send_renew(cs->xid, cs->serverAddr, cs->requestedIP);
cs->renewTime = ((cs->rebindTime - cs->renewTime) >> 1) + cs->renewTime; else
cs->timeout = (cs->renewTime * 1000) - (curms() - cs->leaseStartTime); wt = rbt - ct;
cs->timeout = wt;
return;
} }
long long elt = cs->leaseStartTime + cs->lease * 1000;
if (ct < elt) {
cs->dhcpState = DS_REBINDING;
cs->timeout = elt - ct / 2;
log_line("Entering rebinding state.");
} else
lease_timedout(cs);
} }
// Triggered when a DHCP rebind request has been sent and no reply has been
// received within the response wait time. Check to see if the lease is still
// valid, and if it is, send a broadcast DHCP renew packet. If it is not, then
// change to the SELECTING state to get a new lease.
static void rebinding_timeout(struct client_state_t *cs) static void rebinding_timeout(struct client_state_t *cs)
{ {
/* Either set a new rebindTime, or enter INIT state */ long long ct = curms();
if ((cs->lease - cs->rebindTime) <= (cs->lease / 14400 + 1)) { long long elt = cs->leaseStartTime + cs->lease * 1000;
/* timed out, enter init state */ if (ct < elt) {
cs->dhcpState = DS_SELECTING; long long wt = (elt - ct) / 2;
log_line("Lease lost, entering init state."); if (wt >= 30000)
ifchange(NULL, IFCHANGE_DECONFIG); send_renew(cs->xid, 0, cs->requestedIP);
cs->timeout = 0; else
cs->packetNum = 0; wt = elt - ct;
change_listen_mode(cs, LM_RAW); cs->timeout = wt;
} else { } else
/* send a request packet */ lease_timedout(cs);
send_renew(cs->xid, 0, cs->requestedIP); /* broadcast */
cs->rebindTime = ((cs->lease - cs->rebindTime) >> 1) + cs->rebindTime;
cs->timeout = (cs->rebindTime * 1000) - (curms() - cs->leaseStartTime);
}
} }
static void released_timeout(struct client_state_t *cs) static void released_timeout(struct client_state_t *cs)