]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
The unreachable timer should start AFTER the initial discovery packet is
authorRoy Marples <roy@marples.name>
Fri, 2 May 2014 10:16:00 +0000 (10:16 +0000)
committerRoy Marples <roy@marples.name>
Fri, 2 May 2014 10:16:00 +0000 (10:16 +0000)
sent, and that is first send after the retransmission timer has fired.

ipv6nd.c
ipv6nd.h

index 48deac7357f0bb3b49dbbcdaa1db80f9635be09c..043d708fed873b3349738f712f4df3f1a9ab7c4b 100644 (file)
--- a/ipv6nd.c
+++ b/ipv6nd.c
@@ -121,6 +121,7 @@ struct nd_opt_dnssl {               /* DNSSL option RFC 6106 */
 //
 
 static void ipv6nd_handledata(void *arg);
+static void ipv6nd_proberouter(void *arg);
 
 /*
  * Android ships buggy ICMP6 filter headers.
@@ -1091,6 +1092,133 @@ ipv6nd_handleifa(struct dhcpcd_ctx *ctx, int cmd, const char *ifname,
        }
 }
 
+static void
+ipv6nd_unreachable(void *arg)
+{
+       struct ra *rap = arg;
+       struct timeval tv;
+
+       /* We could add an unreachable flag and persist the information,
+        * but that is more effort than it's probably worth. */
+       syslog(LOG_WARNING, "%s: %s is unreachable, expiring it",
+           rap->iface->name, rap->sfrom);
+       rap->expired = 1;
+       ipv6_buildroutes(rap->iface->ctx);
+       script_runreason(rap->iface, "ROUTERADVERT"); /* XXX not RA */
+
+       /* We should still test if it's reachable or not so
+        * incase it comes back to life and it's preferable. */
+       if (rap->reachable) {
+               ms_to_tv(&tv, rap->reachable);
+       } else {
+               tv.tv_sec = REACHABLE_TIME;
+               tv.tv_usec = 0;
+       }
+       eloop_timeout_add_tv(rap->iface->ctx->eloop,
+           &tv, ipv6nd_proberouter, rap);
+}
+
+static void
+ipv6nd_proberouter1(struct ra *rap)
+{
+       struct nd_neighbor_solicit *ns;
+       struct nd_opt_hdr *nd;
+       struct sockaddr_in6 dst;
+       struct cmsghdr *cm;
+       struct in6_pktinfo pi;
+       struct ipv6_ctx *ctx;
+
+       if (ipv6nd_open(rap->iface->ctx) == -1) {
+               syslog(LOG_ERR, "%s: ipv6nd_open: %m", __func__);
+               return;
+       }
+
+       if (!rap->ns) {
+               rap->nslen = sizeof(*ns) + ROUNDUP8(rap->iface->hwlen + 2);
+               rap->ns = calloc(1, rap->nslen);
+               if (rap->ns == NULL) {
+                       syslog(LOG_ERR, "%s: %m", __func__);
+                       return;
+               }
+               ns = (struct nd_neighbor_solicit *)(void *)rap->ns;
+               ns->nd_ns_type = ND_NEIGHBOR_SOLICIT;
+               //ns->nd_ns_cksum = 0;
+               //ns->nd_ns_code = 0;
+               //ns->nd_ns_reserved = 0;
+               ns->nd_ns_target = rap->from;
+               nd = (struct nd_opt_hdr *)(rap->ns + sizeof(*ns));
+               nd->nd_opt_type = ND_OPT_SOURCE_LINKADDR;
+               nd->nd_opt_len = (ROUNDUP8(rap->iface->hwlen + 2)) >> 3;
+               memcpy(nd + 1, rap->iface->hwaddr, rap->iface->hwlen);
+       }
+
+       memset(&dst, 0, sizeof(dst));
+       dst.sin6_family = AF_INET6;
+#ifdef SIN6_LEN
+       dst.sin6_len = sizeof(dst);
+#endif
+       memcpy(&dst.sin6_addr, &rap->from, sizeof(dst.sin6_addr));
+       dst.sin6_scope_id = rap->iface->index;
+
+       ctx = rap->iface->ctx->ipv6;
+       ctx->sndhdr.msg_name = (caddr_t)&dst;
+       ctx->sndhdr.msg_iov[0].iov_base = rap->ns;
+       ctx->sndhdr.msg_iov[0].iov_len = rap->nslen;
+
+       /* Set the outbound interface */
+       cm = CMSG_FIRSTHDR(&ctx->sndhdr);
+       if (cm == NULL) /* unlikely */
+               return;
+       cm->cmsg_level = IPPROTO_IPV6;
+       cm->cmsg_type = IPV6_PKTINFO;
+       cm->cmsg_len = CMSG_LEN(sizeof(pi));
+       memset(&pi, 0, sizeof(pi));
+       pi.ipi6_ifindex = rap->iface->index;
+       memcpy(CMSG_DATA(cm), &pi, sizeof(pi));
+
+#ifdef DEBUG_NS
+       syslog(LOG_INFO, "%s: sending IPv6 NS for %s",
+           rap->iface->name, rap->sfrom);
+#endif
+       if (sendmsg(ctx->nd_fd, &ctx->sndhdr, 0) == -1) {
+               syslog(LOG_ERR, "%s: %s: sendmsg: %m",
+                   rap->iface->name, __func__);
+               return;
+       }
+
+       ipv6nd_proberouter(rap);
+
+       if (rap->nsprobes++ == 0)
+               eloop_timeout_add_sec(rap->iface->ctx->eloop,
+                   DELAY_FIRST_PROBE_TIME, ipv6nd_unreachable, rap);
+}
+
+static void
+ipv6nd_proberouter(void *arg)
+{
+       struct ra *rap = arg;
+       struct timeval tv, rtv;
+
+       ms_to_tv(&tv, rap->retrans == 0 ? RETRANS_TIMER : rap->retrans);
+       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_proberouter, rap);
+       eloop_timeout_delete(rap->iface->ctx->eloop, ipv6nd_unreachable, rap);
+}
+
 void
 ipv6nd_expirera(void *arg)
 {
@@ -1215,124 +1343,6 @@ ipv6nd_drop(struct interface *ifp)
        }
 }
 
-static void
-ipv6nd_unreachable(void *arg)
-{
-       struct ra *rap = arg;
-       struct timeval tv;
-
-       /* We could add an unreachable flag and persist the information,
-        * but that is more effort than it's probably worth. */
-       syslog(LOG_WARNING, "%s: %s is unreachable, expiring it",
-           rap->iface->name, rap->sfrom);
-       rap->expired = 1;
-       ipv6_buildroutes(rap->iface->ctx);
-       script_runreason(rap->iface, "ROUTERADVERT"); /* XXX not RA */
-
-       /* We should still test if it's reachable or not so
-        * incase it comes back to life and it's preferable. */
-       if (rap->reachable) {
-               ms_to_tv(&tv, rap->reachable);
-       } else {
-               tv.tv_sec = REACHABLE_TIME;
-               tv.tv_usec = 0;
-       }
-       eloop_timeout_add_tv(rap->iface->ctx->eloop,
-           &tv, ipv6nd_proberouter, rap);
-}
-
-void
-ipv6nd_proberouter(void *arg)
-{
-       struct ra *rap = arg;
-       struct nd_neighbor_solicit *ns;
-       struct nd_opt_hdr *nd;
-       struct sockaddr_in6 dst;
-       struct cmsghdr *cm;
-       struct in6_pktinfo pi;
-       struct timeval tv, rtv;
-       struct ipv6_ctx *ctx;
-
-       if (ipv6nd_open(rap->iface->ctx) == -1) {
-               syslog(LOG_ERR, "%s: ipv6nd_open: %m", __func__);
-               return;
-       }
-
-       if (!rap->ns) {
-               rap->nslen = sizeof(*ns) + ROUNDUP8(rap->iface->hwlen + 2);
-               rap->ns = calloc(1, rap->nslen);
-               if (rap->ns == NULL) {
-                       syslog(LOG_ERR, "%s: %m", __func__);
-                       return;
-               }
-               ns = (struct nd_neighbor_solicit *)(void *)rap->ns;
-               ns->nd_ns_type = ND_NEIGHBOR_SOLICIT;
-               //ns->nd_ns_cksum = 0;
-               //ns->nd_ns_code = 0;
-               //ns->nd_ns_reserved = 0;
-               ns->nd_ns_target = rap->from;
-               nd = (struct nd_opt_hdr *)(rap->ns + sizeof(*ns));
-               nd->nd_opt_type = ND_OPT_SOURCE_LINKADDR;
-               nd->nd_opt_len = (ROUNDUP8(rap->iface->hwlen + 2)) >> 3;
-               memcpy(nd + 1, rap->iface->hwaddr, rap->iface->hwlen);
-       }
-
-       memset(&dst, 0, sizeof(dst));
-       dst.sin6_family = AF_INET6;
-#ifdef SIN6_LEN
-       dst.sin6_len = sizeof(dst);
-#endif
-       memcpy(&dst.sin6_addr, &rap->from, sizeof(dst.sin6_addr));
-       dst.sin6_scope_id = rap->iface->index;
-
-       ctx = rap->iface->ctx->ipv6;
-       ctx->sndhdr.msg_name = (caddr_t)&dst;
-       ctx->sndhdr.msg_iov[0].iov_base = rap->ns;
-       ctx->sndhdr.msg_iov[0].iov_len = rap->nslen;
-
-       /* Set the outbound interface */
-       cm = CMSG_FIRSTHDR(&ctx->sndhdr);
-       if (cm == NULL) /* unlikely */
-               return;
-       cm->cmsg_level = IPPROTO_IPV6;
-       cm->cmsg_type = IPV6_PKTINFO;
-       cm->cmsg_len = CMSG_LEN(sizeof(pi));
-       memset(&pi, 0, sizeof(pi));
-       pi.ipi6_ifindex = rap->iface->index;
-       memcpy(CMSG_DATA(cm), &pi, sizeof(pi));
-
-#ifdef DEBUG_NS
-       syslog(LOG_INFO, "%s: sending IPv6 NS for %s",
-           rap->iface->name, rap->sfrom);
-#endif
-       if (sendmsg(ctx->nd_fd, &ctx->sndhdr, 0) == -1) {
-               syslog(LOG_ERR, "%s: %s: sendmsg: %m",
-                   rap->iface->name, __func__);
-               return;
-       }
-
-       ms_to_tv(&tv, rap->retrans == 0 ? RETRANS_TIMER : rap->retrans);
-       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_proberouter, rap);
-
-       if (rap->nsprobes++ == 0)
-               eloop_timeout_add_sec(rap->iface->ctx->eloop,
-                   DELAY_FIRST_PROBE_TIME, ipv6nd_unreachable, rap);
-}
-
-void
-ipv6nd_cancelproberouter(struct ra *rap)
-{
-
-       eloop_timeout_delete(rap->iface->ctx->eloop, ipv6nd_proberouter, rap);
-       eloop_timeout_delete(rap->iface->ctx->eloop, ipv6nd_unreachable, rap);
-}
-
 static void
 ipv6nd_handlena(struct ipv6_ctx *ctx, struct interface *ifp,
     struct icmp6_hdr *icp, size_t len)
index 3688a9899d9b99f054a0c64fba7bfba61d49053e..3f1a592e2991aa10922abcb288ddf6a43075b8b3 100644 (file)
--- a/ipv6nd.h
+++ b/ipv6nd.h
@@ -93,10 +93,6 @@ int ipv6nd_has_ra(const struct interface *);
 void ipv6nd_handleifa(struct dhcpcd_ctx *, int,
     const char *, const struct in6_addr *, int);
 void ipv6nd_drop(struct interface *);
-
-void ipv6nd_proberouter(void *);
-void ipv6nd_cancelproberouter(struct ra *);
-
 #else
 #define ipv6nd_startrs(a) {}
 #define ipv6nd_addrexists(a, b) (0)