]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Respect RFC4861 MAX_RTR_SOLICITATION_DELAY as specified in section 6.3.7.
authorRoy Marples <roy@marples.name>
Sat, 3 May 2014 19:53:22 +0000 (19:53 +0000)
committerRoy Marples <roy@marples.name>
Sat, 3 May 2014 19:53:22 +0000 (19:53 +0000)
ipv6nd.c
ipv6nd.h

index 09b7ccc21202e2a4b617a004c07a24cfc73ddff6..fade521a082ebbfe7057d6a5f2c36d4dabf1d953 100644 (file)
--- a/ipv6nd.c
+++ b/ipv6nd.c
@@ -1494,15 +1494,17 @@ ipv6nd_handledata(void *arg)
            icp->icmp6_type, icp->icmp6_code, ctx->sfrom);
 }
 
-int
-ipv6nd_startrs(struct interface *ifp)
+static int
+ipv6nd_startrs1(void *arg)
 {
+       struct interface *ifp = arg;
        struct rs_state *state;
+       struct timeval tv;
 
        syslog(LOG_INFO, "%s: soliciting an IPv6 router", ifp->name);
        if (ipv6nd_open(ifp->ctx) == -1) {
                syslog(LOG_ERR, "%s: ipv6nd_open: %m", __func__);
-               return -1;
+               return;
        }
 
        eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
@@ -1513,7 +1515,7 @@ ipv6nd_startrs(struct interface *ifp)
                state = RS_STATE(ifp);
                if (state == NULL) {
                        syslog(LOG_ERR, "%s: %m", __func__);
-                       return -1;
+                       return;
                }
        }
 
@@ -1522,10 +1524,25 @@ ipv6nd_startrs(struct interface *ifp)
        ipv6nd_makersprobe(ifp);
        if (state->rs == NULL) {
                syslog(LOG_ERR, "%s: ipv6ns_makersprobe: %m", __func__);
-               return -1;
+               return;
        }
 
        state->rsprobes = 0;
        ipv6nd_sendrsprobe(ifp);
-       return 0;
+}
+
+void
+ipv6nd_startrs(struct interface *ifp)
+{
+       struct timeval tv;
+
+       tv.tv_sec = 0;
+       tv.tv_usec = (suseconds_t)(arc4random() %
+           (MAX_RTR_SOLICITATION_DELAY * 1000000));
+       timernorm(&tv);
+       syslog(LOG_DEBUG,
+           "%s: delaying IPv6 router solictation for %0.1f seconds",
+           ifp->name, timeval_to_double(&tv));
+       eloop_timeout_add_tv(ifp->ctx->eloop, &tv, ipv6nd_startrs1, ifp);
+       return;
 }
index a5eff3bec7ba03785bed1ec49b9f4c9cba13d605..8c606919bcf6f031ab2ae12b0634b856f82bb714 100644 (file)
--- a/ipv6nd.h
+++ b/ipv6nd.h
@@ -75,15 +75,16 @@ struct rs_state {
 
 #define RS_STATE(a) ((struct rs_state *)(ifp)->if_data[IF_DATA_IPV6ND])
 
-#define MAX_UNICAST_SOLICIT    3       /* 3 transmissions */
+#define MAX_RTR_SOLICITATION_DELAY     1       /* seconds */
+#define MAX_UNICAST_SOLICIT            3       /* 3 transmissions */
 
-#define MAX_REACHABLE_TIME     3600000 /* milliseconds */
-#define REACHABLE_TIME         30000   /* milliseconds */
-#define RETRANS_TIMER          1000    /* milliseconds */
-#define DELAY_FIRST_PROBE_TIME 5       /* seconds */
+#define MAX_REACHABLE_TIME             3600000 /* milliseconds */
+#define REACHABLE_TIME                 30000   /* milliseconds */
+#define RETRANS_TIMER                  1000    /* milliseconds */
+#define DELAY_FIRST_PROBE_TIME         5       /* seconds */
 
 #ifdef INET6
-int ipv6nd_startrs(struct interface *);
+void ipv6nd_startrs(struct interface *);
 ssize_t ipv6nd_env(char **, const char *, const struct interface *);
 int ipv6nd_addrexists(struct dhcpcd_ctx *, const struct ipv6_addr *);
 void ipv6nd_freedrop_ra(struct ra *, int);