]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Expire IPv6 RA Prefix routes.
authorRoy Marples <roy@marples.name>
Wed, 3 Aug 2016 20:38:31 +0000 (20:38 +0000)
committerRoy Marples <roy@marples.name>
Wed, 3 Aug 2016 20:38:31 +0000 (20:38 +0000)
ipv6.c
ipv6nd.c

diff --git a/ipv6.c b/ipv6.c
index 57eaffd5d31115b908da2e51721c4eb6514f18e8..3b8596dddae43eb2439412e609715698ee598ffe 100644 (file)
--- a/ipv6.c
+++ b/ipv6.c
@@ -2404,6 +2404,8 @@ ipv6_build_ra_routes(struct ipv6_ctx *ctx, struct rt6_head *dnr, int expired)
                        continue;
                if (rap->iface->options->options & DHCPCD_IPV6RA_OWN) {
                        TAILQ_FOREACH(addr, &rap->addrs, next) {
+                               if (addr->prefix_vltime == 0)
+                                       continue;
                                rt = make_prefix(rap->iface, rap, addr);
                                if (rt)
                                        TAILQ_INSERT_TAIL(dnr, rt, next);
index c839cecd46a9ea911513c6b2ff12212447d19492..71075002bd6e5f3afa03e394418a185e5e1878e6 100644 (file)
--- 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.