From 3205f823d93b13e44a7d00ea6baae003dbe84362 Mon Sep 17 00:00:00 2001 From: "Nicholas J. Kain" Date: Tue, 5 Jul 2011 15:57:11 -0400 Subject: [PATCH] Handle DS_REBINDING and DS_RENEWING states just like DS_BOUND when the hardware link returns after having been lost. Make the timeout action for DS_BOUND_GW_CHECK perform ARP retransmissions rather than just sending a single query. --- ndhc/arp.c | 24 +++++++++++++++--------- ndhc/arp.h | 3 +-- ndhc/state.c | 12 +++++++++--- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/ndhc/arp.c b/ndhc/arp.c index 8f5e643..95d9068 100644 --- a/ndhc/arp.c +++ b/ndhc/arp.c @@ -1,5 +1,5 @@ /* arp.c - arp ping checking - * Time-stamp: <2011-07-05 15:37:02 njk> + * Time-stamp: <2011-07-05 15:54:06 njk> * * Copyright 2010-2011 Nicholas J. Kain * @@ -408,17 +408,21 @@ static void arp_failed(struct client_state_t *cs) 0 : RATE_LIMIT_INTERVAL); } -void arp_gw_failed(struct client_state_t *cs) +static void arp_gw_failed(struct client_state_t *cs) +{ + log_line("arp: Gateway appears to have changed, getting new lease."); + arp_close_fd(cs); + cs->oldTimeout = 0; + reinit_selecting(cs, 0); +} + +static int act_if_arp_gw_failed(struct client_state_t *cs) { if (arp_send_stats[ASEND_GW_PING].count >= gw_check_init_pingcount + 3) { - log_line("arp: Gateway appears to have changed, getting new lease"); - arp_close_fd(cs); - cs->oldTimeout = 0; - reinit_selecting(cs, 0); - return; + arp_gw_failed(cs); + return 1; } - cs->timeout = ARP_RETRANS_DELAY + 250; - arp_retransmit(cs); + return 0; } void arp_success(struct client_state_t *cs) @@ -535,6 +539,8 @@ void arp_retransmit(struct client_state_t *cs) } } if (arpState == AS_GW_CHECK || arpState == AS_GW_QUERY) { + if (arpState == AS_GW_CHECK && act_if_arp_gw_failed(cs)) + return; long long cms = curms(); long long rtts = arp_send_stats[ASEND_GW_PING].ts + ARP_RETRANS_DELAY; if (cms < rtts) { diff --git a/ndhc/arp.h b/ndhc/arp.h index dcca3c0..3c8d1ab 100644 --- a/ndhc/arp.h +++ b/ndhc/arp.h @@ -1,5 +1,5 @@ /* arp.h - functions to call the interface change daemon - * Time-stamp: <2011-07-05 13:49:59 njk> + * Time-stamp: <2011-07-05 15:54:33 njk> * * Copyright 2010-2011 Nicholas J. Kain * @@ -52,7 +52,6 @@ int arp_close_fd(struct client_state_t *cs); int arp_check(struct client_state_t *cs, struct dhcpmsg *packet); int arp_gw_check(struct client_state_t *cs); void arp_success(struct client_state_t *cs); -void arp_gw_failed(struct client_state_t *cs); void arp_retransmit(struct client_state_t *cs); void handle_arp_response(struct client_state_t *cs); diff --git a/ndhc/state.c b/ndhc/state.c index ea8c2b1..ec46b6b 100644 --- a/ndhc/state.c +++ b/ndhc/state.c @@ -23,6 +23,7 @@ static void renewing_timeout(struct client_state_t *cs); static void rebinding_timeout(struct client_state_t *cs); static void released_timeout(struct client_state_t *cs); static void collision_check_timeout(struct client_state_t *cs); +static void bound_gw_check_timeout(struct client_state_t *cs); static void anfrelease(struct client_state_t *cs); static void nfrelease(struct client_state_t *cs); static void frelease(struct client_state_t *cs); @@ -42,7 +43,7 @@ dhcp_state_t dhcp_states[] = { { 0, bound_timeout, frenew, nfrelease}, // BOUND { an_packet, renewing_timeout, frenew, nfrelease}, // RENEWING { an_packet, rebinding_timeout, frenew, nfrelease}, // REBINDING - { 0, arp_gw_failed, frenew, anfrelease}, // BOUND_GW_CHECK + { 0, bound_gw_check_timeout, frenew, anfrelease}, // BOUND_GW_CHECK { 0, collision_check_timeout, frenew, anfrelease}, // COLLISION_CHECK { 0, released_timeout, frenew, frelease}, // RELEASED { 0, 0, 0, 0}, // NUM_STATES @@ -162,6 +163,11 @@ static void collision_check_timeout(struct client_state_t *cs) arp_retransmit(cs); } +static void bound_gw_check_timeout(struct client_state_t *cs) +{ + arp_retransmit(cs); +} + static void an_packet(struct client_state_t *cs, struct dhcpmsg *packet, uint8_t *message) { @@ -294,8 +300,8 @@ void ifup_action(struct client_state_t *cs) { // If we have a lease, check to see if our gateway is still valid via ARP. // If it fails, state -> SELECTING. - // XXX what about RENEWING and REBINDING?? - if (cs->dhcpState == DS_BOUND) { + if (cs->dhcpState == DS_BOUND || cs->dhcpState == DS_RENEWING || + cs->dhcpState == DS_REBINDING) { if (arp_gw_check(cs) == -1) log_warning("nl: arp_gw_check could not make arp socket, assuming lease is still OK"); else