arp_switch_state() was far too confusing and buggy. Pass the target state as

an argument, and only switch the global state after a change is successfully
made.
This commit is contained in:
Nicholas J. Kain 2014-04-06 05:51:52 -04:00
parent 1e52914f2e
commit 8af6bee46d

View File

@ -158,12 +158,18 @@ static int get_arp_defense_socket(struct client_state_t *cs)
return fd; return fd;
} }
static int arp_open_fd(struct client_state_t *cs) static int arp_open_fd(struct client_state_t *cs, arp_state_t state)
{ {
if (cs->arpFd != -1) if (cs->arpFd >= 0) {
log_warning("%s: (%s) called but fd already exists",
client_config.interface, __func__);
return 0;
}
switch (state) {
default:
log_warning("%s: (%s) called for 'default' state",
client_config.interface, __func__);
return 0; return 0;
switch (arpState) {
default: cs->arpFd = -1; arpState = AS_NONE; return -1;
case AS_COLLISION_CHECK: case AS_COLLISION_CHECK:
case AS_GW_QUERY: case AS_GW_QUERY:
case AS_GW_CHECK: cs->arpFd = get_arp_basic_socket(); break; case AS_GW_CHECK: cs->arpFd = get_arp_basic_socket(); break;
@ -190,22 +196,21 @@ static void arp_min_close_fd(struct client_state_t *cs)
static void arp_switch_state(struct client_state_t *cs, arp_state_t state) static void arp_switch_state(struct client_state_t *cs, arp_state_t state)
{ {
arp_state_t prev_state = arpState;
if (arpState == state || arpState >= AS_MAX) if (arpState == state || arpState >= AS_MAX)
return; return;
arpState = state; if (state == AS_NONE) {
if (arpState == AS_NONE) {
arp_close_fd(cs); arp_close_fd(cs);
return; return;
} }
bool force_reopen = arpState == AS_DEFENSE || prev_state == AS_DEFENSE; bool force_reopen = state == AS_DEFENSE || arpState == AS_DEFENSE;
if (force_reopen) if (force_reopen)
arp_min_close_fd(cs); arp_min_close_fd(cs);
if (cs->arpFd == -1 || force_reopen) { if (cs->arpFd < 0 || force_reopen) {
if (arp_open_fd(cs) == -1) if (arp_open_fd(cs, state) < 0)
suicide("arp: Failed to open arpFd when changing state %u -> %u", suicide("arp: Failed to open arpFd when changing state %u -> %u",
prev_state, arpState); arpState, state);
} }
arpState = state;
} }
void arp_close_fd(struct client_state_t *cs) void arp_close_fd(struct client_state_t *cs)