From: Roy Marples Date: Thu, 20 Mar 2014 16:36:03 +0000 (+0000) Subject: Add a reject route for the delegated prefix so that unassigned prefixes don't go... X-Git-Tag: v6.4.0~134 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=cda2f2a9c8a2c07baf33f97cc2a750bfe4e3e0dc;p=thirdparty%2Fdhcpcd.git Add a reject route for the delegated prefix so that unassigned prefixes don't go back upstream. --- diff --git a/dhcp6.c b/dhcp6.c index 9c1fbec1..2f40133a 100644 --- 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, diff --git a/if-bsd.c b/if-bsd.c index a39304ed..650d1fcd 100644 --- 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 */ diff --git a/if-linux.c b/if-linux.c index 94c41f2e..13ace62b 100644 --- a/if-linux.c +++ b/if-linux.c @@ -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 0efadae2..37a35bb7 100644 --- 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 4a89d85e..b602598f 100644 --- 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; };