]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Respect AUTO and ONLINK flags for each prefix in the RA.
authorRoy Marples <roy@marples.name>
Tue, 11 Dec 2012 08:45:33 +0000 (08:45 +0000)
committerRoy Marples <roy@marples.name>
Tue, 11 Dec 2012 08:45:33 +0000 (08:45 +0000)
ipv6.c
ipv6.h
ipv6rs.c

diff --git a/ipv6.c b/ipv6.c
index 793cf6b84712ac6e57a70a19ed8fcf7bb2e9e4d3..c20d98adfad19449ba9c3f8d43d89fd8ead25ffc 100644 (file)
--- a/ipv6.c
+++ b/ipv6.c
@@ -384,7 +384,11 @@ ipv6_remove_subnet(struct ra *rap, struct ipv6_addr *addr)
 #else
                if (!find_route6(routes, rt))
 #endif
+               {
                        r = del_route6(rt);
+                       if (r == -1 && errno == ESRCH)
+                               r = 0;
+               }
                free(rt);
        }
        return r;
@@ -410,6 +414,8 @@ ipv6_build_routes(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, addr);
                                if (rt)
                                        TAILQ_INSERT_TAIL(&dnr, rt, next);
diff --git a/ipv6.h b/ipv6.h
index ef3b2352c3c48663e5600bad5be9fe570f30e9fc..7f889bc2302caeae88bc4efd60b9e4a970b74b05 100644 (file)
--- a/ipv6.h
+++ b/ipv6.h
@@ -46,7 +46,8 @@ struct ipv6_addr {
        uint32_t prefix_vltime;
        uint32_t prefix_pltime;
        struct in6_addr addr;
-       int new;
+       uint8_t onlink;
+       uint8_t new;
        char saddr[INET6_ADDRSTRLEN];
 };
 
index f48d01c7877dff66614510d2b39c6d18b559402e..d4877a9c169ca2976871b360a142afa480cc7920 100644 (file)
--- a/ipv6rs.c
+++ b/ipv6rs.c
@@ -291,6 +291,7 @@ ipv6rs_freedrop_addrs(struct ra *rap, int drop)
                 * This is safe because the RA is removed from the list
                 * before we are called. */
                if (drop && (options & DHCPCD_IPV6RA_OWN) &&
+                   !IN6_IS_ADDR_UNSPECIFIED(&ap->addr) &&
                    !ipv6rs_addrexists(ap))
                {
                        syslog(LOG_INFO, "%s: deleting address %s",
@@ -568,21 +569,41 @@ ipv6rs_handledata(_unused void *arg)
                                    sizeof(ap->prefix.s6_addr)) == 0)
                                        break;
                        if (ap == NULL) {
+                               /* As we haven't added the prefix before
+                                * check if we can make an address with it */
+                               if (!(pi->nd_opt_pi_flags_reserved &
+                                   ND_OPT_PI_FLAG_AUTO) &&
+                                   !(pi->nd_opt_pi_flags_reserved &
+                                   ND_OPT_PI_FLAG_ONLINK))
+                                       break;
                                ap = xmalloc(sizeof(*ap));
                                ap->new = 1;
+                               ap->onlink = 0;
                                ap->prefix_len = pi->nd_opt_pi_prefix_len;
                                memcpy(ap->prefix.s6_addr,
                                   pi->nd_opt_pi_prefix.s6_addr,
                                   sizeof(ap->prefix.s6_addr));
-                               ipv6_makeaddr(&ap->addr, ifp->name,
-                                   &ap->prefix, pi->nd_opt_pi_prefix_len);
-                               cbp = inet_ntop(AF_INET6, ap->addr.s6_addr,
-                                   ntopbuf, INET6_ADDRSTRLEN);
-                               if (cbp)
-                                       snprintf(ap->saddr, sizeof(ap->saddr),
-                                           "%s/%d", cbp, ap->prefix_len);
-                               else
+                               if (pi->nd_opt_pi_flags_reserved &
+                                   ND_OPT_PI_FLAG_AUTO)
+                               {
+                                       ipv6_makeaddr(&ap->addr, ifp->name,
+                                           &ap->prefix,
+                                           pi->nd_opt_pi_prefix_len);
+                                       cbp = inet_ntop(AF_INET6,
+                                           ap->addr.s6_addr,
+                                           ntopbuf, INET6_ADDRSTRLEN);
+                                       if (cbp)
+                                               snprintf(ap->saddr,
+                                                   sizeof(ap->saddr),
+                                                   "%s/%d",
+                                                   cbp, ap->prefix_len);
+                                       else
+                                               ap->saddr[0] = '\0';
+                               } else {
+                                       memset(ap->addr.s6_addr, 0,
+                                           sizeof(ap->addr.s6_addr));
                                        ap->saddr[0] = '\0';
+                               }
                                TAILQ_INSERT_TAIL(&rap->addrs, ap, next);
                        } else if (ap->prefix_vltime !=
                            ntohl(pi->nd_opt_pi_valid_time) ||
@@ -591,6 +612,10 @@ ipv6rs_handledata(_unused void *arg)
                                ap->new = 1;
                        else
                                ap->new = 0;
+                       /* onlink should not change from on to off */
+                       if (pi->nd_opt_pi_flags_reserved &
+                           ND_OPT_PI_FLAG_ONLINK)
+                               ap->onlink = 1;
                        ap->prefix_vltime =
                            ntohl(pi->nd_opt_pi_valid_time);
                        ap->prefix_pltime =
@@ -722,7 +747,8 @@ ipv6rs_handledata(_unused void *arg)
                add_router(rap);
        if (options & DHCPCD_IPV6RA_OWN && !(options & DHCPCD_TEST)) {
                TAILQ_FOREACH(ap, &rap->addrs, next) {
-                       if (ap->prefix_vltime == 0)
+                       if (ap->prefix_vltime == 0 ||
+                           IN6_IS_ADDR_UNSPECIFIED(&ap->addr))
                                continue;
                        syslog(ap->new ? LOG_INFO : LOG_DEBUG,
                            "%s: adding address %s",