]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Don't actually remove unreachable routers and prefixes from the routing table.
authorRoy Marples <roy@marples.name>
Tue, 21 May 2013 09:24:49 +0000 (09:24 +0000)
committerRoy Marples <roy@marples.name>
Tue, 21 May 2013 09:24:49 +0000 (09:24 +0000)
Instead we just change the interface if they are reachable via another one.

ipv6.c
ipv6ns.c

diff --git a/ipv6.c b/ipv6.c
index 9fb159eae936fc12069c1d0a14a37ff1f9aa57fd..cae5c96f80876f734363da31e75d6c9e4ed1621b 100644 (file)
--- a/ipv6.c
+++ b/ipv6.c
@@ -641,12 +641,36 @@ ipv6_removesubnet(const struct interface *ifp, struct ipv6_addr *addr)
        (IN6_ARE_ADDR_EQUAL(&((rtp)->dest), &in6addr_any) &&                  \
            IN6_ARE_ADDR_EQUAL(&((rtp)->net), &in6addr_any))
 
+static void
+ipv6_buildroutes1(struct rt6head *dnr, int expired)
+{
+       struct rt6 *rt;
+       struct ra *rap;
+       struct ipv6_addr *addr;
+
+       TAILQ_FOREACH(rap, &ipv6_routers, next) {
+               if (rap->expired != expired)
+                       continue;
+               if (options & DHCPCD_IPV6RA_OWN) {
+                       TAILQ_FOREACH(addr, &rap->addrs, next) {
+                               if (!addr->onlink)
+                                       continue;
+                               rt = make_prefix(rap->iface, rap, addr);
+                               if (rt)
+                                       TAILQ_INSERT_TAIL(dnr, rt, next);
+                       }
+               }
+               rt = make_router(rap);
+               if (rt)
+                       TAILQ_INSERT_TAIL(dnr, rt, next);
+       }
+}
+
 void
 ipv6_buildroutes(void)
 {
        struct rt6head dnr, *nrs;
        struct rt6 *rt, *rtn, *or;
-       struct ra *rap;
        struct ipv6_addr *addr;
        const struct interface *ifp;
        const struct dhcp6_state *d6_state;
@@ -656,6 +680,12 @@ ipv6_buildroutes(void)
                return;
 
        TAILQ_INIT(&dnr);
+
+       /* First add reachable routers and their prefixes */
+       ipv6_buildroutes1(&dnr, 0);
+
+       /* We have no way of knowing if prefixes added by DHCP are reachable
+        * or not, so we have to assume they are */
        TAILQ_FOREACH(ifp, ifaces, next) {
                d6_state = D6_CSTATE(ifp);
                if (d6_state &&
@@ -671,22 +701,11 @@ ipv6_buildroutes(void)
                        }
                }
        }
-       TAILQ_FOREACH(rap, &ipv6_routers, next) {
-               if (options & DHCPCD_IPV6RA_OWN) {
-                       TAILQ_FOREACH(addr, &rap->addrs, next) {
-                               if (!addr->onlink)
-                                       continue;
-                               rt = make_prefix(rap->iface, rap, addr);
-                               if (rt)
-                                       TAILQ_INSERT_TAIL(&dnr, rt, next);
-                       }
-               }
-               if (!rap->expired) {
-                       rt = make_router(rap);
-                       if (rt)
-                               TAILQ_INSERT_TAIL(&dnr, rt, next);
-               }
-       }
+
+       /* Add our non-reachable routers and prefixes
+        * Unsure if this is needed, but it's a close match to kernel
+        * behaviour */
+       ipv6_buildroutes1(&dnr, 1);
 
        nrs = malloc(sizeof(*nrs));
        if (nrs == NULL) {
index 5a182f82bd6af35622b096dbe9fe1f5d776c5382..a0f238430e96375a4861a8cb20d24505b3191bc4 100644 (file)
--- a/ipv6ns.c
+++ b/ipv6ns.c
@@ -209,6 +209,7 @@ static void
 ipv6ns_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. */
@@ -217,6 +218,16 @@ ipv6ns_unreachable(void *arg)
        rap->expired = 1;
        ipv6_buildroutes();
        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(&tv, ipv6ns_proberouter, rap);
 }
 
 #ifdef LISTEN_DAD
@@ -626,6 +637,13 @@ ipv6ns_handledata(__unused void *arg)
        }
 
        if (is_solicited) {
+               if (rap->expired) {
+                       rap->expired = 0;
+                       syslog(LOG_INFO, "%s: %s is reachable again",
+                               ifp->name, sfrom);
+                       ipv6_buildroutes();
+                       script_runreason(rap->iface, "ROUTERADVERT"); /* XXX */
+               }
                rap->nsprobes = 0;
                if (rap->reachable) {
                        ms_to_tv(&tv, rap->reachable);