From: Roy Marples Date: Sat, 7 May 2016 20:40:40 +0000 (+0000) Subject: When removing delegated addresses, ensure the reject route is restored. X-Git-Tag: v6.11.0~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8f849e773a6cdb6bb2fa398399a88181918b41d4;p=thirdparty%2Fdhcpcd.git When removing delegated addresses, ensure the reject route is restored. --- diff --git a/dhcp6.c b/dhcp6.c index 3270a8df..6c15e86f 100644 --- a/dhcp6.c +++ b/dhcp6.c @@ -1273,7 +1273,7 @@ dhcp6_dadcallback(void *arg) { struct ipv6_addr *ap2; - valid = (ap->delegating_iface == NULL); + valid = (ap->delegating_prefix == NULL); TAILQ_FOREACH(ap2, &state->addrs, next) { if (ap2->flags & IPV6_AF_ADDED && !(ap2->flags & IPV6_AF_DADCOMPLETED)) @@ -1286,7 +1286,7 @@ dhcp6_dadcallback(void *arg) logger(ap->iface->ctx, LOG_DEBUG, "%s: DHCPv6 DAD completed", ifp->name); script_runreason(ifp, - ap->delegating_iface ? + ap->delegating_prefix ? "DELEGATED6" : state->reason); if (valid) dhcpcd_daemonise(ifp->ctx); @@ -1878,10 +1878,13 @@ dhcp6_findpd(struct interface *ifp, const uint8_t *iaid, iabuf, sizeof(iabuf)); snprintf(a->saddr, sizeof(a->saddr), "%s/%d", ia, a->prefix_len); + TAILQ_INIT(&a->pd_pfxs); TAILQ_INSERT_TAIL(&state->addrs, a, next); } else { - if (!(a->flags & IPV6_AF_DELEGATEDPFX)) + if (!(a->flags & IPV6_AF_DELEGATEDPFX)) { a->flags |= IPV6_AF_NEW | IPV6_AF_DELEGATEDPFX; + TAILQ_INIT(&a->pd_pfxs); + } a->flags &= ~(IPV6_AF_STALE | IPV6_AF_REQUEST); if (a->prefix_vltime != ntohl(pdp->vltime)) a->flags |= IPV6_AF_NEW; @@ -2321,7 +2324,7 @@ dhcp6_startinit(struct interface *ifp) static struct ipv6_addr * dhcp6_ifdelegateaddr(struct interface *ifp, struct ipv6_addr *prefix, - const struct if_sla *sla, struct if_ia *if_ia, struct interface *ifs) + const struct if_sla *sla, struct if_ia *if_ia) { struct dhcp6_state *state; struct in6_addr addr, daddr; @@ -2388,12 +2391,13 @@ dhcp6_ifdelegateaddr(struct interface *ifp, struct ipv6_addr *prefix, ia->dadcallback = dhcp6_dadcallback; memcpy(&ia->iaid, &prefix->iaid, sizeof(ia->iaid)); ia->created = ia->acquired = prefix->acquired; - ia->prefix = addr; - ia->prefix_len = (uint8_t)pfxlen; + ia->addr = daddr; TAILQ_INSERT_TAIL(&state->addrs, ia, next); + TAILQ_INSERT_TAIL(&prefix->pd_pfxs, ia, pd_next); } - ia->delegating_iface = ifs; + ia->delegating_prefix = prefix; + ia->prefix = addr; ia->prefix_len = (uint8_t)pfxlen; ia->prefix_pltime = prefix->prefix_pltime; ia->prefix_vltime = prefix->prefix_vltime; @@ -2429,8 +2433,8 @@ dhcp6_script_try_run(struct interface *ifp, int delegated) ipv6_iffindaddr(ap->iface, &ap->addr, IN6_IFF_TENTATIVE)) ap->flags |= IPV6_AF_DADCOMPLETED; if ((ap->flags & IPV6_AF_DADCOMPLETED) == 0 && - ((delegated && ap->delegating_iface) || - (!delegated && !ap->delegating_iface))) + ((delegated && ap->delegating_prefix) || + (!delegated && !ap->delegating_prefix))) { completed = 0; break; @@ -2492,7 +2496,7 @@ dhcp6_delegate_prefix(struct interface *ifp) break; } if (dhcp6_ifdelegateaddr(ifd, ap, - NULL, ia, ifp)) + NULL, ia)) k++; } for (j = 0; j < ia->sla_len; j++) { @@ -2508,7 +2512,7 @@ dhcp6_delegate_prefix(struct interface *ifp) break; } if (dhcp6_ifdelegateaddr(ifd, ap, - sla, ia, ifp)) + sla, ia)) k++; } if (carrier_warned ||abrt) @@ -2574,7 +2578,7 @@ dhcp6_find_delegates(struct interface *ifp) return 1; } if (dhcp6_ifdelegateaddr(ifp, ap, - sla, ia, ifd)) + sla, ia)) k++; } } @@ -3356,7 +3360,9 @@ dhcp6_freedrop(struct interface *ifp, int drop, const char *reason) return; } - if (drop && options & DHCPCD_RELEASE) { + if (drop && options & DHCPCD_RELEASE && + state->state != DH6S_DELEGATED) + { if (ifp->carrier == LINK_UP && state->state != DH6S_RELEASED) { @@ -3550,7 +3556,7 @@ delegated: state = D6_CSTATE(ifp); i = 0; TAILQ_FOREACH(ap, &state->addrs, next) { - if (ap->delegating_iface) { + if (ap->delegating_prefix) { i += strlen(ap->saddr) + 1; } } @@ -3563,7 +3569,7 @@ delegated: } v += snprintf(val, i, "%s_delegated_dhcp6_prefix=", prefix); TAILQ_FOREACH(ap, &state->addrs, next) { - if (ap->delegating_iface) { + if (ap->delegating_prefix) { /* Can't use stpcpy(3) due to "security" */ const char *sap = ap->saddr; diff --git a/ipv6.c b/ipv6.c index eebc790f..1c4ffefa 100644 --- a/ipv6.c +++ b/ipv6.c @@ -593,6 +593,13 @@ ipv6_deleteaddr(struct ipv6_addr *ia) errno != EADDRNOTAVAIL && errno != ENXIO && errno != ENODEV) logger(ia->iface->ctx, LOG_ERR, "if_deladdress6: :%m"); + /* NOREJECT is set if we delegated exactly the prefix to another + * address. + * This can only be one address, so just clear the flag. + * This should ensure the reject route will be restored. */ + if (ia->delegating_prefix != NULL) + ia->delegating_prefix->flags &= ~IPV6_AF_NOREJECT; + state = IPV6_STATE(ia->iface); TAILQ_FOREACH(ap, &state->addrs, next) { if (IN6_ARE_ADDR_EQUAL(&ap->addr, &ia->addr)) { @@ -720,7 +727,7 @@ ipv6_addaddr(struct ipv6_addr *ap, const struct timespec *now) ap->flags &= ~IPV6_AF_NEW; ap->flags |= IPV6_AF_ADDED; - if (ap->delegating_iface) + if (ap->delegating_prefix != NULL) ap->flags |= IPV6_AF_DELEGATED; #ifdef IPV6_POLLADDRFLAG @@ -839,6 +846,16 @@ ipv6_addaddrs(struct ipv6_addrhead *addrs) void ipv6_freeaddr(struct ipv6_addr *ap) { + struct ipv6_addr *ia; + + /* Forget the reference */ + if (ap->flags & IPV6_AF_DELEGATEDPFX) { + TAILQ_FOREACH(ia, &ap->pd_pfxs, pd_next) { + ia->delegating_prefix = NULL; + } + } else if (ap->delegating_prefix != NULL) { + TAILQ_REMOVE(&ap->delegating_prefix->pd_pfxs, ap, pd_next); + } eloop_q_timeout_delete(ap->iface->ctx->eloop, 0, NULL, ap); free(ap); @@ -853,7 +870,9 @@ ipv6_freedrop_addrs(struct ipv6_addrhead *addrs, int drop, timespecclear(&now); TAILQ_FOREACH_SAFE(ap, addrs, next, apn) { - if (ifd && ap->delegating_iface != ifd) + if (ifd != NULL && + (ap->delegating_prefix == NULL || + ap->delegating_prefix->iface != ifd)) continue; if (drop != 2) TAILQ_REMOVE(addrs, ap, next); diff --git a/ipv6.h b/ipv6.h index d20f9435..5ae8426b 100644 --- a/ipv6.h +++ b/ipv6.h @@ -138,6 +138,7 @@ #define IN6_IFF_NOTUSEABLE \ (IN6_IFF_TENTATIVE | IN6_IFF_DUPLICATED | IN6_IFF_DETACHED) +TAILQ_HEAD(ipv6_addrhead, ipv6_addr); struct ipv6_addr { TAILQ_ENTRY(ipv6_addr) next; struct interface *iface; @@ -153,7 +154,11 @@ struct ipv6_addr { char saddr[INET6_ADDRSTRLEN]; uint8_t iaid[4]; uint16_t ia_type; - struct interface *delegating_iface; + + struct ipv6_addr *delegating_prefix; + struct ipv6_addrhead pd_pfxs; + TAILQ_ENTRY(ipv6_addr) pd_next; + uint8_t prefix_exclude_len; struct in6_addr prefix_exclude; @@ -163,7 +168,6 @@ struct ipv6_addr { size_t nslen; int nsprobes; }; -TAILQ_HEAD(ipv6_addrhead, ipv6_addr); #define IPV6_AF_ONLINK 0x0001 #define IPV6_AF_NEW 0x0002