state: Faster recovery when carrier lost during DHCP init.

If carrier is lost before network fingerprinting is complete, we
have a few problems; first, we don't know whether the network has
changed underneath us.  Second, we've not yet configured the
interface properties, and it is not unlikely that doing so will
fail as the underlying network device may have been destroyed
and recreated during this time (eg, if ethtool has been run at
start-up time).

Thus, the safest reaction is to terminate and force a supervisor
respawn.  It is best to do this once carrier recovers, not when
the carrier is lost, as it is more likely to minimize delays.
This commit is contained in:
Nicholas J. Kain 2017-04-10 09:57:52 -04:00
parent 369ff59cab
commit ed44a90114
3 changed files with 10 additions and 2 deletions

View File

@ -558,6 +558,7 @@ int arp_query_gateway(struct client_state_t cs[static 1])
return ARPR_FAIL;
}
cs->sent_gw_query = true;
cs->init_fingerprint_inprogress = true;
garp.wake_ts[AS_QUERY_GW_SEND] = -1;
return ARPR_OK;
}

View File

@ -47,7 +47,8 @@ struct client_state_t {
uint8_t routerArp[6], serverArp[6];
bool using_dhcp_bpf, got_router_arp, got_server_arp, arp_is_defense,
check_fingerprint, program_init;
bool sent_gw_query, sent_first_announce, sent_second_announce;
bool sent_gw_query, sent_first_announce, sent_second_announce,
init_fingerprint_inprogress;
};
struct client_config_t {

View File

@ -83,6 +83,7 @@ static void reinit_shared_deconfig(struct client_state_t cs[static 1])
cs->sent_gw_query = false;
cs->sent_first_announce = false;
cs->sent_second_announce = false;
cs->init_fingerprint_inprogress = false;
memset(&cs->routerArp, 0, sizeof cs->routerArp);
memset(&cs->serverArp, 0, sizeof cs->serverArp);
arp_reset_state(cs);
@ -416,6 +417,10 @@ static int frenew(struct client_state_t cs[static 1], bool is_bound)
static int ifup_action(struct client_state_t cs[static 1])
{
if (cs->routerAddr && cs->serverAddr) {
if (cs->init_fingerprint_inprogress) {
suicide("%s: Carrier lost during initial fingerprint. Forcing restart.",
client_config.interface);
}
if (arp_gw_check(cs) >= 0) {
log_line("%s: Interface is back. Revalidating lease...",
client_config.interface);
@ -621,7 +626,8 @@ skip_to_requesting:
r = arp_do_gw_query(cs);
if (r == ARPR_OK) {
} else if (r == ARPR_FREE) {
// We got both ARP addresses.
log_line("%s: Network fingerprinting complete.", client_config.interface);
cs->init_fingerprint_inprogress = false;
} else if (r == ARPR_FAIL) {
ret = COR_ERROR;
scrReturn(ret);