]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Add a reject route for the delegated prefix so that unassigned prefixes don't go...
authorRoy Marples <roy@marples.name>
Thu, 20 Mar 2014 16:36:03 +0000 (16:36 +0000)
committerRoy Marples <roy@marples.name>
Thu, 20 Mar 2014 16:36:03 +0000 (16:36 +0000)
dhcp6.c
if-bsd.c
if-linux.c
ipv6.c
ipv6.h

diff --git a/dhcp6.c b/dhcp6.c
index 9c1fbec13bd0f18ea3eb1736d0eb8dd7d7638ddb..2f40133aa54e41ed292a20be957305d1a9070d45 100644 (file)
--- a/dhcp6.c
+++ b/dhcp6.c
@@ -1425,7 +1425,7 @@ dhcp6_findpd(struct interface *ifp, const uint8_t *iaid,
                                break;
                        }
                        a->iface = ifp;
-                       a->flags = IPV6_AF_NEW;
+                       a->flags = IPV6_AF_NEW | IPV6_AF_DELEGATEDPFX;
                        a->dadcallback = dhcp6_dadcallback;
                        memcpy(a->iaid, iaid, sizeof(a->iaid));
                        memcpy(&a->prefix.s6_addr,
@@ -1852,6 +1852,8 @@ dhcp6_delegate_prefix(struct interface *ifp)
                k = 0;
                carrier_warned = 0;
                TAILQ_FOREACH(ap, &state->addrs, next) {
+                       if (!(ap->flags & IPV6_AF_DELEGATEDPFX))
+                               continue;
                        if (ap->flags & IPV6_AF_NEW) {
                                ap->flags &= ~IPV6_AF_NEW;
                                syslog(LOG_DEBUG, "%s: delegated prefix %s",
@@ -1946,12 +1948,12 @@ dhcp6_find_delegates(struct interface *ifp)
        k = 0;
        TAILQ_FOREACH(ifd, ifp->ctx->ifaces, next) {
                ifo = ifd->options;
-               if (ifo->ia_type != D6_OPTION_IA_PD)
-                       continue;
                state = D6_STATE(ifd);
                if (state == NULL || state->state != DH6S_BOUND)
                        continue;
                TAILQ_FOREACH(ap, &state->addrs, next) {
+                       if (!(ap->flags & IPV6_AF_DELEGATEDPFX))
+                               continue;
                        for (i = 0; i < ifo->ia_len; i++) {
                                ia = &ifo->ia[i];
                                if (memcmp(ia->iaid, ap->iaid,
index a39304edb3ebcf26b9738d2ca1e6d239d2e75bd3..650d1fcdac47cd0087f84bc337625a2c36df1d42 100644 (file)
--- a/if-bsd.c
+++ b/if-bsd.c
@@ -461,45 +461,42 @@ if_route6(const struct rt6 *rt, int action)
                rtm.hdr.rtm_type = RTM_ADD;
        else
                rtm.hdr.rtm_type = RTM_DELETE;
-       rtm.hdr.rtm_flags = RTF_UP;
+       rtm.hdr.rtm_flags = RTF_UP | rt->flags;
        rtm.hdr.rtm_addrs = RTA_DST | RTA_NETMASK;
 #ifdef SIOCGIFPRIORITY
        rtm.hdr.rtm_priority = rt->metric;
 #endif
        /* None interface subnet routes are static. */
-       if (IN6_IS_ADDR_UNSPECIFIED(&rt->dest) &&
-           IN6_IS_ADDR_UNSPECIFIED(&rt->net))
-               rtm.hdr.rtm_flags |= RTF_GATEWAY;
+       if (IN6_IS_ADDR_UNSPECIFIED(&rt->gate)) {
 #ifdef RTF_CLONING
-       else
                rtm.hdr.rtm_flags |= RTF_CLONING;
 #endif
+        } else
+               rtm.hdr.rtm_flags |= RTF_GATEWAY | RTF_STATIC;
 
-       if (action >= 0)
-               rtm.hdr.rtm_addrs |= RTA_GATEWAY | RTA_IFP | RTA_IFA;
+       if (action >= 0) {
+               rtm.hdr.rtm_addrs |= RTA_GATEWAY;
+               if (!(rtm.hdr.rtm_flags & RTF_REJECT))
+                       rtm.hdr.rtm_addrs |= RTA_IFP | RTA_IFA;
+       }
 
        ADDADDR(&rt->dest);
        lla = NULL;
        if (rtm.hdr.rtm_addrs & RTA_GATEWAY) {
-               if (!(rtm.hdr.rtm_flags & RTF_GATEWAY)) {
+               if (IN6_IS_ADDR_UNSPECIFIED(&rt->gate)) {
                        lla = ipv6_linklocal(rt->iface);
                        if (lla == NULL) /* unlikely */
                                return -1;
                        ADDADDRS(&lla->addr, rt->iface->index);
                } else {
-                       lla = NULL;
-                       ADDADDRS(&rt->gate, rt->iface->index);
+                       ADDADDRS(&rt->gate,
+                           IN6_ARE_ADDR_EQUAL(&rt->gate, &in6addr_loopback)
+                           ? 0 : rt->iface->index);
                }
        }
 
-       if (rtm.hdr.rtm_addrs & RTA_NETMASK) {
-               if (rtm.hdr.rtm_flags & RTF_GATEWAY) {
-                       memset(&su, 0, sizeof(su));
-                       su.sin.sin6_family = AF_INET6;
-                       ADDSU;
-               } else
-                       ADDADDR(&rt->net);
-       }
+       if (rtm.hdr.rtm_addrs & RTA_NETMASK)
+               ADDADDR(&rt->net);
 
        if (rtm.hdr.rtm_addrs & RTA_IFP) {
                /* Make us a link layer socket for the host gateway */
index 94c41f2e9788719dd67bdec1e13dd2f6c6be6634..13ace62be725428cf191df42d56a82518cbf50b5 100644 (file)
@@ -804,7 +804,10 @@ if_route6(const struct rt6 *rt, int action)
                        nlm.rt.rtm_scope = RT_SCOPE_LINK;
                } else
                        nlm.rt.rtm_protocol = RTPROT_BOOT;
-               nlm.rt.rtm_type = RTN_UNICAST;
+               if (rt->flags & RTF_REJECT)
+                       nlm.rt.rtm_type = RTN_UNREACHABLE;
+               else
+                       nlm.rt.rtm_type = RTN_UNICAST;
        }
 
        nlm.rt.rtm_dst_len = ipv6_prefixlen(&rt->net);
@@ -817,8 +820,10 @@ if_route6(const struct rt6 *rt, int action)
                add_attr_l(&nlm.hdr, sizeof(nlm), RTA_GATEWAY,
                    &rt->gate.s6_addr, sizeof(rt->gate.s6_addr));
 
-       add_attr_32(&nlm.hdr, sizeof(nlm), RTA_OIF, rt->iface->index);
-       add_attr_32(&nlm.hdr, sizeof(nlm), RTA_PRIORITY, rt->metric);
+       if (!(rt->flags & RTF_REJECT)) {
+               add_attr_32(&nlm.hdr, sizeof(nlm), RTA_OIF, rt->iface->index);
+               add_attr_32(&nlm.hdr, sizeof(nlm), RTA_PRIORITY, rt->metric);
+       }
 
        if (rt->mtu) {
                metrics->rta_type = RTA_METRICS;
diff --git a/ipv6.c b/ipv6.c
index 0efadae29df9c85f5592cef7da2703d7f356d697..37a35bb7e66fd9f4618526f36762ae15d4fd2922 100644 (file)
--- a/ipv6.c
+++ b/ipv6.c
@@ -786,7 +786,8 @@ desc_route(const char *cmd, const struct rt6 *rt)
        gate = inet_ntop(AF_INET6, &rt->gate.s6_addr,
            gatebuf, INET6_ADDRSTRLEN);
        if (IN6_ARE_ADDR_EQUAL(&rt->gate, &in6addr_any))
-               syslog(LOG_INFO, "%s: %s route to %s/%d", ifname, cmd,
+               syslog(LOG_INFO, "%s: %s %sroute to %s/%d", ifname, cmd,
+                   rt->flags & RTF_REJECT ? "reject " : "",
                    dest, ipv6_prefixlen(&rt->net));
        else if (IN6_ARE_ADDR_EQUAL(&rt->dest, &in6addr_any) &&
            IN6_ARE_ADDR_EQUAL(&rt->net, &in6addr_any))
@@ -862,16 +863,23 @@ make_prefix(const struct interface * ifp, const struct ra *rap,
                return NULL;
        }
 
-       /* There is no point in trying to manage a /128 prefix. */
-       if (addr->prefix_len == 128)
+       /* There is no point in trying to manage a /128 prefix,
+        * ones without a lifetime or ones not on link or delegated */
+       if (addr->prefix_len == 128 ||
+           addr->prefix_vltime == 0 ||
+           !(addr->flags & (IPV6_AF_ONLINK | IPV6_AF_DELEGATEDPFX)))
                return NULL;
 
        r = make_route(ifp, rap);
        if (r == NULL)
-               return r;
+               return NULL;
        r->dest = addr->prefix;
        ipv6_mask(&r->net, addr->prefix_len);
-       r->gate = in6addr_any;
+       if (addr->flags & IPV6_AF_DELEGATEDPFX) {
+               r->flags |= RTF_REJECT;
+               r->gate = in6addr_loopback;
+       } else
+               r->gate = in6addr_any;
        return r;
 }
 
@@ -944,9 +952,6 @@ 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 ||
-                                   (addr->flags & IPV6_AF_ONLINK) == 0)
-                                       continue;
                                rt = make_prefix(rap->iface, rap, addr);
                                if (rt)
                                        TAILQ_INSERT_TAIL(dnr, rt, next);
@@ -972,14 +977,9 @@ ipv6_build_dhcp_routes(struct dhcpcd_ctx *ctx,
        struct rt6 *rt;
 
        TAILQ_FOREACH(ifp, ctx->ifaces, next) {
-               if (!(ifp->options->options & DHCPCD_IPV6RA_OWN))
-                       continue;
                d6_state = D6_CSTATE(ifp);
                if (d6_state && d6_state->state == dstate) {
                        TAILQ_FOREACH(addr, &d6_state->addrs, next) {
-                               if ((addr->flags & IPV6_AF_ONLINK) == 0 ||
-                                   IN6_IS_ADDR_UNSPECIFIED(&addr->addr))
-                                       continue;
                                rt = make_prefix(ifp, NULL, addr);
                                if (rt)
                                        TAILQ_INSERT_TAIL(dnr, rt, next);
diff --git a/ipv6.h b/ipv6.h
index 4a89d85e36661d8402b3a09147c21ad9dd506af2..b602598f44695c2d47d88161da361f50d7fd9aa8 100644 (file)
--- a/ipv6.h
+++ b/ipv6.h
@@ -97,6 +97,7 @@ TAILQ_HEAD(ipv6_addrhead, ipv6_addr);
 #define IPV6_AF_DUPLICATED     0x0020
 #define IPV6_AF_DADCOMPLETED   0x0040
 #define IPV6_AF_DELEGATED      0x0080
+#define IPV6_AF_DELEGATEDPFX   0x0100
 
 struct rt6 {
        TAILQ_ENTRY(rt6) next;
@@ -104,6 +105,7 @@ struct rt6 {
        struct in6_addr net;
        struct in6_addr gate;
        const struct interface *iface;
+       unsigned int flags;
        int metric;
        unsigned int mtu;
 };