]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Change the NS times so that we assume reachable until the reachable
authorRoy Marples <roy@marples.name>
Mon, 6 Aug 2012 19:32:15 +0000 (19:32 +0000)
committerRoy Marples <roy@marples.name>
Mon, 6 Aug 2012 19:32:15 +0000 (19:32 +0000)
time expires, then send probes at retrans intervals until
DELAY_FIRST_PROBE_TIME is reached at which point we expire the router.

common.h
ipv6ns.c
ipv6ns.h
ipv6rs.c
ipv6rs.h

index 411019832c0ac4a41b6c8d5c62d5086bd41d436c..e11cc5110a7c34b34c8cff52d1072e94213cb620 100644 (file)
--- a/common.h
+++ b/common.h
 #define UNCONST(a)             ((void *)(unsigned long)(const void *)(a))
 
 #define timeval_to_double(tv) ((tv)->tv_sec * 1.0 + (tv)->tv_usec * 1.0e-6)
+#define ms_to_tv(tv, ms)                                               \
+       do {                                                            \
+               (tv)->tv_sec = (ms / 1000);                             \
+               (tv)->tv_usec = ((ms % 1000) * 1000);                   \
+       } while (0 /* CONSTCOND */);
 #define timernorm(tvp)                                                 \
        do {                                                            \
                while ((tvp)->tv_usec >= 1000000) {                     \
index 14e1f5702367cf6bffb013dde46744500dd6a56a..c66770c258d5939d68ebae94faa413668a649b59 100644 (file)
--- a/ipv6ns.c
+++ b/ipv6ns.c
@@ -158,6 +158,20 @@ ipv6ns_makeprobe(struct ra *rap)
        return 0;
 }
 
+static void
+ipv6ns_unreachable(void *arg)
+{
+       struct ra *rap = arg;
+
+       /* 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_build_routes();
+       run_script_reason(rap->iface, "ROUTERADVERT"); /* XXX not RA */
+}
+
 void
 ipv6ns_sendprobe(void *arg)
 {
@@ -168,7 +182,7 @@ ipv6ns_sendprobe(void *arg)
        int hoplimit = HOPLIMIT;
        struct timeval tv, rtv;
 
-       if (!rap->nsprobes) {
+       if (!rap->ns) {
                if (ipv6ns_makeprobe(rap) == -1)
                        return;
        }
@@ -208,26 +222,18 @@ ipv6ns_sendprobe(void *arg)
        if (sendmsg(sock, &sndhdr, 0) == -1)
                syslog(LOG_ERR, "%s: sendmsg: %m", rap->iface->name);
 
-       tv.tv_sec = RETRANS_TIMER;
-       tv.tv_usec = MIN_RANDOM_FACTOR;
+
+       ms_to_tv(&tv, rap->retrans ? rap->retrans : RETRANS_TIMER);
+       ms_to_tv(&rtv, MIN_RANDOM_FACTOR);
+       timeradd(&tv, &rtv, &tv);
        rtv.tv_sec = 0;
        rtv.tv_usec = arc4random() % (MAX_RANDOM_FACTOR - MIN_RANDOM_FACTOR);
        timeradd(&tv, &rtv, &tv);
        add_timeout_tv(&tv, ipv6ns_sendprobe, rap);
-}
-
-void
-ipv6ns_unreachable(void *arg)
-{
-       struct ra *rap = arg;
 
-       /* 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_build_routes();
-       run_script_reason(rap->iface, "ROUTERADVERT"); /* XXX not RA */
+       if (rap->nsprobes++ == 0)
+               add_timeout_sec(DELAY_FIRST_PROBE_TIME,
+                   ipv6ns_unreachable, rap);
 }
 
 /* ARGSUSED */
@@ -244,6 +250,7 @@ ipv6ns_handledata(_unused void *arg)
        struct nd_neighbor_advert *nd_na;
        struct ra *rap;
        int is_router, is_solicited;
+       struct timeval tv;
 
        len = recvmsg(sock, &rcvhdr, 0);
        if (len == -1) {
@@ -340,8 +347,14 @@ ipv6ns_handledata(_unused void *arg)
        }
 
        if (is_solicited) {
-               rap->nsprobes = 1;
-               add_timeout_sec(REACHABLE_TIME, ipv6ns_unreachable, rap);
-               add_timeout_sec(DELAY_FIRST_PROBE_TIME, ipv6ns_sendprobe, rap);
+               rap->nsprobes = 0;
+               if (rap->reachable) {
+                       ms_to_tv(&tv, rap->reachable);
+               } else {
+                       tv.tv_sec = REACHABLE_TIME;
+                       tv.tv_usec = 0;
+               }
+               add_timeout_tv(&tv, ipv6ns_sendprobe, rap);
+               delete_timeout(ipv6ns_unreachable, rap);
        }
 }
index 05636c9e979765fb12dd2c0ad38a30727ccde22f..e71a6e790a1578b45374a93c19c4f97c43060578 100644 (file)
--- a/ipv6ns.h
+++ b/ipv6ns.h
 #include "dhcpcd.h"
 #include "ipv6rs.h"
 
+#define MAX_REACHABLE_TIME     3600    /* seconds */
 #define REACHABLE_TIME         30      /* seconds */
 #define RETRANS_TIMER          1       /* second */
 #define DELAY_FIRST_PROBE_TIME 5       /* seconds */
 
 int ipv6ns_open(void);
-void ipv6ns_unreachable(void *);
 void ipv6ns_sendprobe(void *);
 void ipv6ns_handledata(void *);
 #endif
index 3a837a1db56fa178ba804cc6614a0e64cecb7b2d..4d2bd2444e9c1c2a2c6ec178aa9652ce7d846e4b 100644 (file)
--- a/ipv6rs.c
+++ b/ipv6rs.c
@@ -447,6 +447,9 @@ ipv6rs_handledata(_unused void *arg)
                if (rap) {
                        free(rap->data);
                        rap->data_len = 0;
+                       free(rap->ns);
+                       rap->ns = NULL;
+                       rap->nslen = 0;
                }
                syslog(LOG_INFO, "%s: Router Advertisement from %s",
                    ifp->name, sfrom);
@@ -473,6 +476,13 @@ ipv6rs_handledata(_unused void *arg)
        nd_ra = (struct nd_router_advert *)icp;
        rap->flags = nd_ra->nd_ra_flags_reserved;
        rap->lifetime = ntohs(nd_ra->nd_ra_router_lifetime);
+       if (nd_ra->nd_ra_reachable) {
+               rap->reachable = ntohl(nd_ra->nd_ra_reachable);
+               if (rap->reachable > MAX_REACHABLE_TIME)
+                       rap->reachable = 0;
+       }
+       if (nd_ra->nd_ra_retransmit)
+               rap->retrans = ntohl(nd_ra->nd_ra_retransmit);
        rap->expired = 0;
 
        len -= sizeof(struct nd_router_advert);
@@ -706,8 +716,7 @@ ipv6rs_handledata(_unused void *arg)
            options & DHCPCD_IPV6RA_OWN_DEFAULT)
        {
                rap->nsprobes = 0;
-               add_timeout_sec(REACHABLE_TIME, ipv6ns_unreachable, rap);
-               add_timeout_sec(DELAY_FIRST_PROBE_TIME, ipv6ns_sendprobe, rap);
+               ipv6ns_sendprobe(rap);
        }
 }
 
index cae4058d41392f4efd2b4fc64201fb836c2f68ca..ef8b40680ee7b2c5dd87a730b1481873957079f2 100644 (file)
--- a/ipv6rs.h
+++ b/ipv6rs.h
@@ -52,6 +52,8 @@ struct ra {
        struct timeval received;
        unsigned char flags;
        uint32_t lifetime;
+       uint32_t reachable;
+       uint32_t retrans;
        uint32_t mtu;
        TAILQ_HEAD(, ipv6_addr) addrs;
        TAILQ_HEAD(, ra_opt) options;