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:
parent
1e52914f2e
commit
8af6bee46d
27
ndhc/arp.c
27
ndhc/arp.c
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user