changeset 2468:ec51834c005f draft

Respect RFC4861 MAX_RTR_SOLICITATION_DELAY as specified in section 6.3.7.
author Roy Marples <roy@marples.name>
date Sat, 03 May 2014 19:53:22 +0000
parents 56b4420b0d71
children 5fc737832999
files ipv6nd.c ipv6nd.h
diffstat 2 files changed, 30 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/ipv6nd.c	Sat May 03 10:17:48 2014 +0000
+++ b/ipv6nd.c	Sat May 03 19:53:22 2014 +0000
@@ -1494,15 +1494,17 @@
 	    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 @@
 		state = RS_STATE(ifp);
 		if (state == NULL) {
 			syslog(LOG_ERR, "%s: %m", __func__);
-			return -1;
+			return;
 		}
 	}
 
@@ -1522,10 +1524,25 @@
 	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;
+}
--- a/ipv6nd.h	Sat May 03 10:17:48 2014 +0000
+++ b/ipv6nd.h	Sat May 03 19:53:22 2014 +0000
@@ -75,15 +75,16 @@
 
 #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);