return i;
}
+#ifndef SMALL
+static void
+dhcp6_deprecatedele(struct ipv6_addr *ia)
+{
+ struct ipv6_addr *da, *dan, *dda;
+ struct timespec now;
+ struct dhcp6_state *state;
+
+ timespecclear(&now);
+ TAILQ_FOREACH_SAFE(da, &ia->pd_pfxs, pd_next, dan) {
+ if (ia->prefix_vltime == 0) {
+ if (da->prefix_vltime != 0)
+ da->prefix_vltime = 0;
+ else
+ continue;
+ } else if (da->prefix_pltime != 0)
+ da->prefix_pltime = 0;
+ else
+ continue;
+
+ if (ipv6_doaddr(da, &now) != -1)
+ continue;
+
+ /* Delegation deleted, forget it. */
+ TAILQ_REMOVE(&ia->pd_pfxs, da, pd_next);
+
+ /* Delete it from the interface. */
+ state = D6_STATE(da->iface);
+ TAILQ_FOREACH(dda, &state->addrs, next) {
+ if (IN6_ARE_ADDR_EQUAL(&dda->addr, &da->addr))
+ break;
+ }
+ if (dda != NULL) {
+ TAILQ_REMOVE(&state->addrs, dda, next);
+ ipv6_freeaddr(dda);
+ }
+ }
+}
+#endif
+
static void
dhcp6_deprecateaddrs(struct ipv6_addrhead *addrs)
{
struct ipv6_addr *ia, *ian;
+ struct timespec now;
+ timespecclear(&now);
TAILQ_FOREACH_SAFE(ia, addrs, next, ian) {
if (ia->flags & IPV6_AF_EXTENDED)
;
#ifndef SMALL
/* If we delegated from this prefix, deprecate or remove
* the delegations. */
- if (ia->flags & IPV6_AF_DELEGATEDPFX) {
- struct ipv6_addr *da;
- bool touched = false;
-
- TAILQ_FOREACH(da, &ia->pd_pfxs, pd_next) {
- if (ia->prefix_vltime == 0) {
- if (da->prefix_vltime != 0) {
- da->prefix_vltime = 0;
- touched = true;
- }
- } else if (da->prefix_pltime != 0) {
- da->prefix_pltime = 0;
- touched = true;
- }
- }
- if (touched)
- ipv6_addaddrs(&ia->pd_pfxs);
- }
+ if (ia->flags & IPV6_AF_DELEGATEDPFX)
+ dhcp6_deprecatedele(ia);
#endif
if (ia->flags & IPV6_AF_REQUEST) {
#endif
}
+int
+ipv6_doaddr(struct ipv6_addr *ia, struct timespec *now)
+{
+
+ /* A delegated prefix is not an address. */
+ if (ia->flags & IPV6_AF_DELEGATEDPFX)
+ return 0;
+
+ if (ia->prefix_vltime == 0) {
+ if (ia->flags & IPV6_AF_ADDED)
+ ipv6_deleteaddr(ia);
+ eloop_q_timeout_delete(ia->iface->ctx->eloop,
+ 0, NULL, ia);
+ if (ia->flags & IPV6_AF_REQUEST) {
+ ia->flags &= ~IPV6_AF_ADDED;
+ return 0;
+ }
+ return -1;
+ }
+
+ if (ia->flags & IPV6_AF_STALE ||
+ IN6_IS_ADDR_UNSPECIFIED(&ia->addr))
+ return 0;
+
+ if (!timespecisset(now))
+ clock_gettime(CLOCK_MONOTONIC, now);
+ ipv6_addaddr(ia, now);
+ return ia->flags & IPV6_AF_NEW ? 1 : 0;
+}
+
ssize_t
-ipv6_addaddrs(struct ipv6_addrhead *addrs)
+ipv6_addaddrs(struct ipv6_addrhead *iaddrs)
{
- struct ipv6_addr *ap, *apn;
- ssize_t i;
struct timespec now;
+ struct ipv6_addr *ia, *ian;
+ ssize_t i, r;
i = 0;
timespecclear(&now);
- TAILQ_FOREACH_SAFE(ap, addrs, next, apn) {
- /* A delegated prefix is not an address. */
- if (ap->flags & IPV6_AF_DELEGATEDPFX)
- continue;
- if (ap->prefix_vltime == 0) {
- if (ap->flags & IPV6_AF_ADDED) {
- ipv6_deleteaddr(ap);
- i++;
- }
- eloop_q_timeout_delete(ap->iface->ctx->eloop,
- 0, NULL, ap);
- if (ap->flags & IPV6_AF_REQUEST) {
- ap->flags &= ~IPV6_AF_ADDED;
- } else {
-#ifndef SMALL
- if (ap->delegating_prefix != NULL &&
- addrs == &ap->delegating_prefix->pd_pfxs) {
- TAILQ_REMOVE(addrs, ap, pd_next);
- ap->delegating_prefix = NULL;
- } else
-#endif
- {
- TAILQ_REMOVE(addrs, ap, next);
- ipv6_freeaddr(ap);
- }
- }
- } else if (!(ap->flags & IPV6_AF_STALE) &&
- !IN6_IS_ADDR_UNSPECIFIED(&ap->addr))
- {
- if (ap->flags & IPV6_AF_NEW)
- i++;
- if (!timespecisset(&now))
- clock_gettime(CLOCK_MONOTONIC, &now);
- ipv6_addaddr(ap, &now);
+ TAILQ_FOREACH_SAFE(ia, iaddrs, next, ian) {
+ r = ipv6_doaddr(ia, &now);
+ if (r != 0)
+ i++;
+ if (r == -1) {
+ TAILQ_REMOVE(iaddrs, ia, next);
+ ipv6_freeaddr(ia);
}
}
-
return i;
}
void ipv6_markaddrsstale(struct interface *, unsigned int);
void ipv6_deletestaleaddrs(struct interface *);
int ipv6_addaddr(struct ipv6_addr *, const struct timespec *);
+int ipv6_doaddr(struct ipv6_addr *, struct timespec *);
ssize_t ipv6_addaddrs(struct ipv6_addrhead *addrs);
void ipv6_deleteaddr(struct ipv6_addr *);
void ipv6_freedrop_addrs(struct ipv6_addrhead *, int,