{
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))
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);
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;
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;
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;
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;
break;
}
if (dhcp6_ifdelegateaddr(ifd, ap,
- NULL, ia, ifp))
+ NULL, ia))
k++;
}
for (j = 0; j < ia->sla_len; j++) {
break;
}
if (dhcp6_ifdelegateaddr(ifd, ap,
- sla, ia, ifp))
+ sla, ia))
k++;
}
if (carrier_warned ||abrt)
return 1;
}
if (dhcp6_ifdelegateaddr(ifp, ap,
- sla, ia, ifd))
+ sla, ia))
k++;
}
}
return;
}
- if (drop && options & DHCPCD_RELEASE) {
+ if (drop && options & DHCPCD_RELEASE &&
+ state->state != DH6S_DELEGATED)
+ {
if (ifp->carrier == LINK_UP &&
state->state != DH6S_RELEASED)
{
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;
}
}
}
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;
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)) {
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
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);
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);
#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;
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;
size_t nslen;
int nsprobes;
};
-TAILQ_HEAD(ipv6_addrhead, ipv6_addr);
#define IPV6_AF_ONLINK 0x0001
#define IPV6_AF_NEW 0x0002