]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Once reachability + randomisation has passed, wait DELAY_FIRST_PROBE_TIME
authorRoy Marples <roy@marples.name>
Fri, 2 May 2014 12:31:21 +0000 (12:31 +0000)
committerRoy Marples <roy@marples.name>
Fri, 2 May 2014 12:31:21 +0000 (12:31 +0000)
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.

ipv6nd.c
ipv6nd.h

index d4875103c5fa10d1015ba88637d4f3784550dd3b..67db4aed0eecf6c05b08b4253fb770b303cc8047 100644 (file)
--- 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);
        }
 }
 
index 7c38e9463639f1d3ce959aad1a02b9de3148aa2b..a5eff3bec7ba03785bed1ec49b9f4c9cba13d605 100644 (file)
--- 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 */