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,
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",
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,
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 */
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);
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;
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))
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;
}
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);
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);
#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;
struct in6_addr net;
struct in6_addr gate;
const struct interface *iface;
+ unsigned int flags;
int metric;
unsigned int mtu;
};