summaryrefslogtreecommitdiffstats
path: root/ipv6nd.c
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2016-08-03 20:38:31 +0000
committerRoy Marples <roy@marples.name>2016-08-03 20:38:31 +0000
commit6d189cb65f5fbc8898841baf86f5288ae41b70b5 (patch)
treefb23f0fc5d8dd312a3cb8c08d2a4e177fb31752f /ipv6nd.c
parent518f8810294b409acd596079fa70a946a8025d86 (diff)
downloaddhcpcd-6d189cb65f5fbc8898841baf86f5288ae41b70b5.tar.xz
Expire IPv6 RA Prefix routes.
Diffstat (limited to 'ipv6nd.c')
-rw-r--r--ipv6nd.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/ipv6nd.c b/ipv6nd.c
index c839cecd..71075002 100644
--- a/ipv6nd.c
+++ b/ipv6nd.c
@@ -1329,6 +1329,7 @@ ipv6nd_expirera(void *arg)
struct ra *rap, *ran;
struct timespec now, lt, expire, next;
uint8_t expired, valid, validone;
+ struct ipv6_addr *ia;
ifp = arg;
clock_gettime(CLOCK_MONOTONIC, &now);
@@ -1362,6 +1363,39 @@ ipv6nd_expirera(void *arg)
}
}
+ /* Not every prefix is tied to an address which
+ * the kernel can expire, so we need to handle it ourself.
+ * Also, some OS don't support address lifetimes (Solaris). */
+ TAILQ_FOREACH(ia, &rap->addrs, next) {
+ if (ia->prefix_vltime == ND6_INFINITE_LIFETIME ||
+ ia->prefix_vltime == 0)
+ continue;
+ lt.tv_sec = (time_t)ia->prefix_vltime;
+ lt.tv_nsec = 0;
+ timespecadd(&ia->acquired, &lt, &expire);
+ if (timespeccmp(&now, &expire, >)) {
+ if (ia->flags & IPV6_AF_ADDED) {
+ logger(ia->iface->ctx, LOG_WARNING,
+ "%s: expired address %s",
+ ia->iface->name, ia->saddr);
+ if (if_address6(RTM_DELADDR, ia)== -1 &&
+ errno != EADDRNOTAVAIL &&
+ errno != ENXIO)
+ logger(ia->iface->ctx, LOG_ERR,
+ "if_address6: %m");
+ }
+ ia->prefix_vltime = ia->prefix_pltime = 0;
+ ia->flags &=
+ ~(IPV6_AF_ADDED | IPV6_AF_DADCOMPLETED);
+ expired = 1;
+ } else {
+ timespecsub(&expire, &now, &lt);
+ if (!timespecisset(&next) ||
+ timespeccmp(&next, &lt, >))
+ next = lt;
+ }
+ }
+
/* XXX FixMe!
* We need to extract the lifetime from each option and check
* if that has expired or not.