Make fingerprinting more robust with rapid carrier state changes.

The existing code tracked the fingerprinting completion state with
a bool, which is insufficient; what is required is a tristate
(none|inprogress|done) where the inprogress state reverts to
none on carrier down, but done state stays done on carrier down.
This commit is contained in:
Nicholas J. Kain 2020-10-27 14:14:18 -04:00
parent d07469a5fa
commit 918555219b
3 changed files with 14 additions and 7 deletions

View File

@ -553,7 +553,8 @@ int arp_query_gateway(struct client_state_t cs[static 1])
return ARPR_FAIL; return ARPR_FAIL;
} }
cs->sent_gw_query = true; cs->sent_gw_query = true;
cs->init_fingerprint_inprogress = true; if (cs->fp_state == FPRINT_NONE)
cs->fp_state = FPRINT_INPROGRESS;
garp.wake_ts[AS_QUERY_GW_SEND] = -1; garp.wake_ts[AS_QUERY_GW_SEND] = -1;
return ARPR_OK; return ARPR_OK;
} }

View File

@ -40,6 +40,12 @@ enum arp_state {
ARP_FAILED, ARP_FAILED,
}; };
enum fprint_state {
FPRINT_NONE = 0,
FPRINT_INPROGRESS,
FPRINT_DONE,
};
struct client_state_t { struct client_state_t {
struct nk_random_state rnd_state; struct nk_random_state rnd_state;
long long leaseStartTime, renewTime, rebindTime; long long leaseStartTime, renewTime, rebindTime;
@ -53,10 +59,10 @@ struct client_state_t {
uint32_t lease, xid; uint32_t lease, xid;
uint8_t routerArp[6], serverArp[6]; uint8_t routerArp[6], serverArp[6];
enum arp_state server_arp_state, router_arp_state; enum arp_state server_arp_state, router_arp_state;
enum fprint_state fp_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; sent_renew_or_rebind;
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 { struct client_config_t {

View File

@ -85,12 +85,12 @@ static void reinit_shared_deconfig(struct client_state_t cs[static 1])
cs->router_arp_sent = 0; cs->router_arp_sent = 0;
cs->server_arp_state = ARP_QUERY; cs->server_arp_state = ARP_QUERY;
cs->router_arp_state = ARP_QUERY; cs->router_arp_state = ARP_QUERY;
cs->fp_state = FPRINT_NONE;
cs->check_fingerprint = false; cs->check_fingerprint = false;
cs->sent_renew_or_rebind = false; cs->sent_renew_or_rebind = false;
cs->sent_gw_query = false; cs->sent_gw_query = false;
cs->sent_first_announce = false; cs->sent_first_announce = false;
cs->sent_second_announce = false; cs->sent_second_announce = false;
cs->init_fingerprint_inprogress = false;
memset(&cs->routerArp, 0, sizeof cs->routerArp); memset(&cs->routerArp, 0, sizeof cs->routerArp);
memset(&cs->serverArp, 0, sizeof cs->serverArp); memset(&cs->serverArp, 0, sizeof cs->serverArp);
arp_reset_state(cs); arp_reset_state(cs);
@ -394,9 +394,9 @@ static int ifup_action(struct client_state_t cs[static 1])
if (cs->routerAddr && cs->serverAddr) { if (cs->routerAddr && cs->serverAddr) {
const bool fp_server = cs->server_arp_state == ARP_FOUND; const bool fp_server = cs->server_arp_state == ARP_FOUND;
const bool fp_router = (cs->routerAddr != cs->serverAddr) ? (cs->router_arp_state == ARP_FOUND) : fp_server; const bool fp_router = (cs->routerAddr != cs->serverAddr) ? (cs->router_arp_state == ARP_FOUND) : fp_server;
if (!fp_server && !fp_router) if ((!fp_server && !fp_router) || cs->fp_state == FPRINT_NONE)
goto no_fingerprint; goto no_fingerprint;
if (cs->init_fingerprint_inprogress) { if (cs->fp_state == FPRINT_INPROGRESS) {
suicide("%s: Carrier lost during initial fingerprint. Forcing restart.", suicide("%s: Carrier lost during initial fingerprint. Forcing restart.",
client_config.interface); client_config.interface);
} }
@ -636,7 +636,7 @@ skip_to_requesting:
if (r == ARPR_OK) { if (r == ARPR_OK) {
} else if (r == ARPR_FREE) { } else if (r == ARPR_FREE) {
log_line("%s: Network fingerprinting complete.", client_config.interface); log_line("%s: Network fingerprinting complete.", client_config.interface);
cs->init_fingerprint_inprogress = false; cs->fp_state = FPRINT_DONE;
} else if (r == ARPR_FAIL) { } else if (r == ARPR_FAIL) {
ret = COR_ERROR; ret = COR_ERROR;
scrReturn(ret); scrReturn(ret);