summaryrefslogtreecommitdiffstats
path: root/ipv6nd.c
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2014-05-03 19:53:22 +0000
committerRoy Marples <roy@marples.name>2014-05-03 19:53:22 +0000
commit6e6e06af143ff0533ee481852a7b28e67bfd9eae (patch)
tree94bf65ed93b4a26bbde453bfa01282e94b917179 /ipv6nd.c
parent17d810346d07744bb8ec8d5adadd31ddb87140ea (diff)
downloaddhcpcd-6e6e06af143ff0533ee481852a7b28e67bfd9eae.tar.xz
Respect RFC4861 MAX_RTR_SOLICITATION_DELAY as specified in section 6.3.7.
Diffstat (limited to 'ipv6nd.c')
-rw-r--r--ipv6nd.c29
1 files changed, 23 insertions, 6 deletions
diff --git a/ipv6nd.c b/ipv6nd.c
index 09b7ccc2..fade521a 100644
--- 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;
}