Add a heuristic to detect when server ignores dhcp renews.
If we get no response to three renews (unicast), switch to sending rebinds (broadcast). Servers are supposed to always reply with a DHCPACK or DHCPNAK even if the server doesn't update its internal lease duration database, so this behavior should be RFC compliant.
This commit is contained in:
parent
f4365897bc
commit
32bc422d0e
@ -48,7 +48,7 @@ struct client_state_t {
|
|||||||
int epollFd, signalFd, listenFd, arpFd, nlFd, rfkillFd;
|
int epollFd, signalFd, listenFd, arpFd, nlFd, rfkillFd;
|
||||||
int server_arp_sent, router_arp_sent;
|
int server_arp_sent, router_arp_sent;
|
||||||
uint32_t nlPortId;
|
uint32_t nlPortId;
|
||||||
unsigned int num_dhcp_requests;
|
unsigned int num_dhcp_requests, num_dhcp_renews;
|
||||||
uint32_t clientAddr, serverAddr, srcAddr, routerAddr;
|
uint32_t clientAddr, serverAddr, srcAddr, routerAddr;
|
||||||
uint32_t lease, xid;
|
uint32_t lease, xid;
|
||||||
uint8_t routerArp[6], serverArp[6];
|
uint8_t routerArp[6], serverArp[6];
|
||||||
|
@ -43,6 +43,8 @@
|
|||||||
#include "netlink.h"
|
#include "netlink.h"
|
||||||
#include "coroutine.h"
|
#include "coroutine.h"
|
||||||
|
|
||||||
|
#define IGNORED_RENEWS_BEFORE_REBIND 3
|
||||||
|
|
||||||
#define SEL_SUCCESS 0
|
#define SEL_SUCCESS 0
|
||||||
#define SEL_FAIL -1
|
#define SEL_FAIL -1
|
||||||
|
|
||||||
@ -78,6 +80,7 @@ static void reinit_shared_deconfig(struct client_state_t cs[static 1])
|
|||||||
cs->xid = nk_random_u32(&cs->rnd_state);
|
cs->xid = nk_random_u32(&cs->rnd_state);
|
||||||
cs->clientAddr = 0;
|
cs->clientAddr = 0;
|
||||||
cs->num_dhcp_requests = 0;
|
cs->num_dhcp_requests = 0;
|
||||||
|
cs->num_dhcp_renews = 0;
|
||||||
cs->server_arp_sent = 0;
|
cs->server_arp_sent = 0;
|
||||||
cs->router_arp_sent = 0;
|
cs->router_arp_sent = 0;
|
||||||
cs->server_arp_state = ARP_QUERY;
|
cs->server_arp_state = ARP_QUERY;
|
||||||
@ -150,7 +153,7 @@ static int renewing_timeout(struct client_state_t cs[static 1],
|
|||||||
long long nowts)
|
long long nowts)
|
||||||
{
|
{
|
||||||
long long rbt = cs->leaseStartTime + cs->rebindTime * 1000;
|
long long rbt = cs->leaseStartTime + cs->rebindTime * 1000;
|
||||||
if (nowts >= rbt)
|
if (nowts >= rbt || cs->num_dhcp_renews >= IGNORED_RENEWS_BEFORE_REBIND)
|
||||||
return rebinding_timeout(cs, nowts);
|
return rebinding_timeout(cs, nowts);
|
||||||
start_dhcp_listen(cs);
|
start_dhcp_listen(cs);
|
||||||
if (send_renew(cs) < 0) {
|
if (send_renew(cs) < 0) {
|
||||||
@ -159,6 +162,7 @@ static int renewing_timeout(struct client_state_t cs[static 1],
|
|||||||
return BTO_HARDFAIL;
|
return BTO_HARDFAIL;
|
||||||
}
|
}
|
||||||
cs->sent_renew_or_rebind = true;
|
cs->sent_renew_or_rebind = true;
|
||||||
|
++cs->num_dhcp_renews;
|
||||||
long long ts0 = nowts + (50 + nk_random_u32(&cs->rnd_state) % 20) * 1000;
|
long long ts0 = nowts + (50 + nk_random_u32(&cs->rnd_state) % 20) * 1000;
|
||||||
cs->dhcp_wake_ts = ts0 < rbt ? ts0 : rbt;
|
cs->dhcp_wake_ts = ts0 < rbt ? ts0 : rbt;
|
||||||
return BTO_WAIT;
|
return BTO_WAIT;
|
||||||
@ -230,6 +234,7 @@ static int extend_packet(struct client_state_t cs[static 1],
|
|||||||
if (!validate_serverid(cs, packet, "a DHCP ACK"))
|
if (!validate_serverid(cs, packet, "a DHCP ACK"))
|
||||||
return ANP_IGNORE;
|
return ANP_IGNORE;
|
||||||
cs->sent_renew_or_rebind = false;
|
cs->sent_renew_or_rebind = false;
|
||||||
|
cs->num_dhcp_renews = 0;
|
||||||
get_leasetime(cs, packet);
|
get_leasetime(cs, packet);
|
||||||
|
|
||||||
// Did we receive a lease with a different IP than we had before?
|
// Did we receive a lease with a different IP than we had before?
|
||||||
@ -253,6 +258,7 @@ static int extend_packet(struct client_state_t cs[static 1],
|
|||||||
if (!validate_serverid(cs, packet, "a DHCP NAK"))
|
if (!validate_serverid(cs, packet, "a DHCP NAK"))
|
||||||
return ANP_IGNORE;
|
return ANP_IGNORE;
|
||||||
cs->sent_renew_or_rebind = false;
|
cs->sent_renew_or_rebind = false;
|
||||||
|
cs->num_dhcp_renews = 0;
|
||||||
log_line("%s: Our request was rejected. Searching for a new lease...",
|
log_line("%s: Our request was rejected. Searching for a new lease...",
|
||||||
client_config.interface);
|
client_config.interface);
|
||||||
reinit_selecting(cs, 3000);
|
reinit_selecting(cs, 3000);
|
||||||
|
Loading…
Reference in New Issue
Block a user