Skip to content

Commit

Permalink
Make renew and rebinding directly track whether DHCPREQUEST was sent.
Browse files Browse the repository at this point in the history
Before it was inferred by examining timeouts.  Also, simplify
the associated timeout code so that there are no longer effectively
two redundant paths.
  • Loading branch information
niklata committed Oct 19, 2020
1 parent 4df035c commit f436589
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 36 deletions.
3 changes: 2 additions & 1 deletion src/ndhc.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ struct client_state_t {
uint32_t lease, xid;
uint8_t routerArp[6], serverArp[6];
enum arp_state server_arp_state, router_arp_state;
bool using_dhcp_bpf, arp_is_defense, check_fingerprint, program_init;
bool using_dhcp_bpf, arp_is_defense, check_fingerprint, program_init,
sent_renew_or_rebind;
bool sent_gw_query, sent_first_announce, sent_second_announce,
init_fingerprint_inprogress;
};
Expand Down
49 changes: 14 additions & 35 deletions src/state.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ static void reinit_shared_deconfig(struct client_state_t cs[static 1])
cs->server_arp_state = ARP_QUERY;
cs->router_arp_state = ARP_QUERY;
cs->check_fingerprint = false;
cs->sent_renew_or_rebind = false;
cs->sent_gw_query = false;
cs->sent_first_announce = false;
cs->sent_second_announce = false;
Expand Down Expand Up @@ -120,24 +121,10 @@ static int requesting_timeout(struct client_state_t cs[static 1],
return REQ_SUCCESS;
}

static bool is_renewing(struct client_state_t cs[static 1], long long nowts)
{
long long rnt = cs->leaseStartTime + cs->renewTime * 1000;
return nowts >= rnt;
}

static bool is_rebinding(struct client_state_t cs[static 1], long long nowts)
{
long long rbt = cs->leaseStartTime + cs->rebindTime * 1000;
return nowts >= rbt;
}

// 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.
// Called by renewing_timeout() to try to renew the lease. If all
// timeouts expire, then expire the lease and notify the caller.
static int rebinding_timeout(struct client_state_t cs[static 1],
long long nowts)
long long nowts)
{
long long elt = cs->leaseStartTime + cs->lease * 1000;
if (nowts >= elt) {
Expand All @@ -152,19 +139,15 @@ static int rebinding_timeout(struct client_state_t cs[static 1],
client_config.interface);
return BTO_HARDFAIL;
}
cs->sent_renew_or_rebind = true;
long long ts0 = nowts + (50 + nk_random_u32(&cs->rnd_state) % 20) * 1000;
cs->dhcp_wake_ts = ts0 < elt ? ts0 : elt;
return BTO_WAIT;
}

// 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
// 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
// a unicast DHCP renew packet. If it is not, then change to the REBINDING
// state to send broadcast queries.
// Called by bound_timeout() to try to renew the lease.
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;
if (nowts >= rbt)
Expand All @@ -175,13 +158,14 @@ static int renewing_timeout(struct client_state_t cs[static 1],
client_config.interface);
return BTO_HARDFAIL;
}
cs->sent_renew_or_rebind = true;
long long ts0 = nowts + (50 + nk_random_u32(&cs->rnd_state) % 20) * 1000;
cs->dhcp_wake_ts = ts0 < rbt ? ts0 : rbt;
return BTO_WAIT;
}

// Triggered when the lease has been held for a significant fraction of its
// total time, and it is time to renew the lease so that it is not lost.
// Called to handle dhcp state timeouts, such as when RENEW or REBIND
// DHCPREQUESTs must be sent. Can return BTO_(WAIT|EXPIRED|HARDFAIL).
static int bound_timeout(struct client_state_t cs[static 1], long long nowts)
{
long long rnt = cs->leaseStartTime + cs->renewTime * 1000;
Expand Down Expand Up @@ -245,6 +229,7 @@ static int extend_packet(struct client_state_t cs[static 1],
if (msgtype == DHCPACK) {
if (!validate_serverid(cs, packet, "a DHCP ACK"))
return ANP_IGNORE;
cs->sent_renew_or_rebind = false;
get_leasetime(cs, packet);

// Did we receive a lease with a different IP than we had before?
Expand All @@ -267,6 +252,7 @@ static int extend_packet(struct client_state_t cs[static 1],
} else if (msgtype == DHCPNAK) {
if (!validate_serverid(cs, packet, "a DHCP NAK"))
return ANP_IGNORE;
cs->sent_renew_or_rebind = false;
log_line("%s: Our request was rejected. Searching for a new lease...",
client_config.interface);
reinit_selecting(cs, 3000);
Expand Down Expand Up @@ -595,7 +581,7 @@ int dhcp_handle(struct client_state_t cs[static 1], long long nowts,
}
}
}
if (sev_dhcp && is_renewing(cs, nowts)) {
if (sev_dhcp && cs->sent_renew_or_rebind) {
int r = extend_packet(cs, dhcp_packet, dhcp_msgtype, dhcp_srcaddr);
if (r == ANP_SUCCESS || r == ANP_IGNORE) {
} else if (r == ANP_REJECTED) {
Expand Down Expand Up @@ -701,14 +687,7 @@ int dhcp_handle(struct client_state_t cs[static 1], long long nowts,
} else BAD_STATE();
}
if (dhcp_timeout) {
int r;
if (is_rebinding(cs, nowts)) {
r = rebinding_timeout(cs, nowts);
} else if (is_renewing(cs, nowts)) {
r = renewing_timeout(cs, nowts);
} else {
r = bound_timeout(cs, nowts);
}
int r = bound_timeout(cs, nowts);
if (r == BTO_WAIT) {
} else if (r == BTO_EXPIRED) {
sev_dhcp = false;
Expand Down

0 comments on commit f436589

Please sign in to comment.