From: Roy Marples Date: Mon, 6 Aug 2012 19:32:15 +0000 (+0000) Subject: Change the NS times so that we assume reachable until the reachable X-Git-Tag: v5.6.2~8 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ea112ab290d35fe4df41df4f77be50b005934402;p=thirdparty%2Fdhcpcd.git Change the NS times so that we assume reachable until the reachable time expires, then send probes at retrans intervals until DELAY_FIRST_PROBE_TIME is reached at which point we expire the router. --- diff --git a/common.h b/common.h index 41101983..e11cc511 100644 --- a/common.h +++ b/common.h @@ -37,6 +37,11 @@ #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) { \ diff --git a/ipv6ns.c b/ipv6ns.c index 14e1f570..c66770c2 100644 --- 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); } } diff --git a/ipv6ns.h b/ipv6ns.h index 05636c9e..e71a6e79 100644 --- a/ipv6ns.h +++ b/ipv6ns.h @@ -31,12 +31,12 @@ #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 diff --git a/ipv6rs.c b/ipv6rs.c index 3a837a1d..4d2bd244 100644 --- 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); } } diff --git a/ipv6rs.h b/ipv6rs.h index cae4058d..ef8b4068 100644 --- 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;