From: Roy Marples Date: Fri, 2 May 2014 12:31:21 +0000 (+0000) Subject: Once reachability + randomisation has passed, wait DELAY_FIRST_PROBE_TIME X-Git-Tag: v6.4.0~79 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ae4f8bd77e8ae6d44c841df87cc9ba8a9a13d5ef;p=thirdparty%2Fdhcpcd.git Once reachability + randomisation has passed, wait DELAY_FIRST_PROBE_TIME seconds and then send MAX_UNICAST_SOLICIT probes at retranstimer intervals. If no confirmation and another retranstimer interval has passed, expire the address. More RFC4861 conformant. --- diff --git a/ipv6nd.c b/ipv6nd.c index d4875103..67db4aed 100644 --- a/ipv6nd.c +++ b/ipv6nd.c @@ -121,7 +121,7 @@ struct nd_opt_dnssl { /* DNSSL option RFC 6106 */ // static void ipv6nd_handledata(void *); -static void ipv6nd_proberouter(struct ra *); +static void ipv6nd_startproberouter(struct ra *); /* * Android ships buggy ICMP6 filter headers. @@ -933,7 +933,7 @@ ipv6nd_handlera(struct ipv6_ctx *ctx, struct interface *ifp, { rap->nsprobes = 0; if (rap->lifetime) - ipv6nd_proberouter(rap); + ipv6nd_startproberouter(rap); } handle_flag: @@ -1107,7 +1107,7 @@ ipv6nd_unreachable(void *arg) } static void -ipv6nd_proberouter1(void *arg) +ipv6nd_proberouter(void *arg) { struct ra *rap = arg; struct nd_neighbor_solicit *ns; @@ -1116,6 +1116,7 @@ ipv6nd_proberouter1(void *arg) struct cmsghdr *cm; struct in6_pktinfo pi; struct ipv6_ctx *ctx; + struct timeval tv; if (ipv6nd_open(rap->iface->ctx) == -1) { syslog(LOG_ERR, "%s: ipv6nd_open: %m", __func__); @@ -1175,41 +1176,48 @@ ipv6nd_proberouter1(void *arg) return; } - if (rap->nsprobes++ == 0) - eloop_timeout_add_sec(rap->iface->ctx->eloop, - DELAY_FIRST_PROBE_TIME, ipv6nd_unreachable, rap); + ms_to_tv(&tv, rap->retrans ? rap->retrans : RETRANS_TIMER); + eloop_timeout_add_tv(rap->iface->ctx->eloop, &tv, + ++rap->nsprobes < MAX_UNICAST_SOLICIT ? + ipv6nd_proberouter : ipv6nd_unreachable, + rap); +} - if (rap->nsprobes < MAX_UNICAST_SOLICIT) - ipv6nd_proberouter(rap); +static void +ipv6nd_stalerouter(void *arg) +{ + struct ra *rap = arg; + + rap->nsprobes = 0; + eloop_timeout_add_sec(rap->iface->ctx->eloop, DELAY_FIRST_PROBE_TIME, + ipv6nd_proberouter, rap); } static void -ipv6nd_proberouter(struct ra *rap) +ipv6nd_cancelproberouter(struct ra *rap) +{ + + eloop_timeout_delete(rap->iface->ctx->eloop, ipv6nd_proberouter, rap); + eloop_timeout_delete(rap->iface->ctx->eloop, ipv6nd_stalerouter, rap); + eloop_timeout_delete(rap->iface->ctx->eloop, ipv6nd_unreachable, rap); +} + + +static void +ipv6nd_startproberouter(struct ra *rap) { struct timeval tv, rtv; - if (rap->nsprobes == 0) { - ms_to_tv(&tv, rap->reachable ? rap->reachable : REACHABLE_TIME); - } else { - ms_to_tv(&tv, rap->retrans ? rap->retrans : RETRANS_TIMER); - } + ipv6nd_cancelproberouter(rap); + + ms_to_tv(&tv, rap->reachable ? rap->reachable : REACHABLE_TIME); ms_to_tv(&rtv, MIN_RANDOM_FACTOR); timeradd(&tv, &rtv, &tv); rtv.tv_sec = 0; rtv.tv_usec = arc4random() % (MAX_RANDOM_FACTOR_U -MIN_RANDOM_FACTOR_U); timeradd(&tv, &rtv, &tv); eloop_timeout_add_tv(rap->iface->ctx->eloop, - &tv, ipv6nd_proberouter1, rap); - - /* The unreachable timer starts AFTER first probe is actually send */ -} - -static void -ipv6nd_cancelproberouter(struct ra *rap) -{ - - eloop_timeout_delete(rap->iface->ctx->eloop, ipv6nd_proberouter1, rap); - eloop_timeout_delete(rap->iface->ctx->eloop, ipv6nd_unreachable, rap); + &tv, ipv6nd_stalerouter, rap); } void @@ -1405,10 +1413,7 @@ ipv6nd_handlena(struct ipv6_ctx *ctx, struct interface *ifp, ipv6_buildroutes(ifp->ctx); script_runreason(rap->iface, "ROUTERADVERT"); /* XXX */ } - eloop_timeout_delete(rap->iface->ctx->eloop, - ipv6nd_unreachable, rap); - rap->nsprobes = 0; - ipv6nd_proberouter(rap); + ipv6nd_startproberouter(rap); } } diff --git a/ipv6nd.h b/ipv6nd.h index 7c38e946..a5eff3be 100644 --- a/ipv6nd.h +++ b/ipv6nd.h @@ -77,7 +77,7 @@ struct rs_state { #define MAX_UNICAST_SOLICIT 3 /* 3 transmissions */ -#define MAX_REACHABLE_TIME 3600 /* seconds */ +#define MAX_REACHABLE_TIME 3600000 /* milliseconds */ #define REACHABLE_TIME 30000 /* milliseconds */ #define RETRANS_TIMER 1000 /* milliseconds */ #define DELAY_FIRST_PROBE_TIME 5 /* seconds */