const struct dhcp6_option *o;
const struct dhcp_opt *opt;
const struct if_options *ifo;
- const struct ipv6_addr *ap;
+ struct ipv6_addr *ap;
uint8_t has_new;
int error;
len = 1;
/* If all addresses have completed DAD run the script */
TAILQ_FOREACH(ap, &state->addrs, next) {
- if (ap->flags & IPV6_AF_ONLINK &&
- (ap->flags & IPV6_AF_DADCOMPLETED) == 0)
- {
- len = 0;
- break;
+ if (ap->flags & IPV6_AF_ONLINK) {
+ if (!(ap->flags & IPV6_AF_DADCOMPLETED) &&
+ ipv6_findaddr(ap->iface, &ap->addr))
+ ap->flags |= IPV6_AF_DADCOMPLETED;
+ if ((ap->flags & IPV6_AF_DADCOMPLETED) == 0) {
+ len = 0;
+ break;
+ }
}
}
if (len) {
struct interface *ifp;
struct dhcp6_state *state;
+ if (ifaces == NULL)
+ return;
+
TAILQ_FOREACH(ifp, ifaces, next) {
state = D6_STATE(ifp);
if (state == NULL || strcmp(ifp->name, ifname))
ipv6_makeaddr(struct in6_addr *addr, const struct interface *ifp,
const struct in6_addr *prefix, int prefix_len)
{
- const struct ipv6_state *state;
- const struct ll_addr *ap;
+ const struct ipv6_addr_l *ap;
#if 0
static u_int8_t allzero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
static u_int8_t allone[8] =
memcpy(addr, prefix, sizeof(*prefix));
/* Try and make the address from the first local-link address */
- state = IPV6_CSTATE(ifp);
- if (state) {
- ap = TAILQ_FIRST(&state->ll_addrs);
- if (ap) {
- addr->s6_addr32[2] = ap->addr.s6_addr32[2];
- addr->s6_addr32[3] = ap->addr.s6_addr32[3];
- return 0;
- }
+ ap = ipv6_linklocal(ifp);
+ if (ap) {
+ addr->s6_addr32[2] = ap->addr.s6_addr32[2];
+ addr->s6_addr32[3] = ap->addr.s6_addr32[3];
+ return 0;
}
/* Because we delay a few functions until we get a local-link address
syslog(ap->flags & IPV6_AF_NEW ? LOG_INFO : LOG_DEBUG,
"%s: adding address %s", ap->iface->name, ap->saddr);
+ if (!(ap->flags & IPV6_AF_DADCOMPLETED) &&
+ ipv6_findaddr(ap->iface, &ap->addr))
+ ap->flags |= IPV6_AF_DADCOMPLETED;
if (add_address6(ap) == -1) {
syslog(LOG_ERR, "add_address6 %m");
return -1;
syslog(LOG_ERR, "%s: %m", __func__);
return NULL;
}
- TAILQ_INIT(&state->ll_addrs);
+ TAILQ_INIT(&state->addrs);
TAILQ_INIT(&state->ll_callbacks);
}
return state;
{
struct interface *ifp;
struct ipv6_state *state;
- struct ll_addr *ap;
+ struct ipv6_addr_l *ap;
struct ll_callback *cb;
#if 0
return;
}
+ state = ipv6_getstate(ifp);
+ if (state == NULL)
+ return;
+
if (!IN6_IS_ADDR_LINKLOCAL(addr)) {
ipv6rs_handleifa(cmd, ifname, addr, flags);
dhcp6_handleifa(cmd, ifname, addr, flags);
- return;
}
- state = ipv6_getstate(ifp);
- if (state == NULL)
- return;
-
- /* We don't care about duplicated LL addresses, so remove them */
+ /* We don't care about duplicated addresses, so remove them */
if (flags & IN6_IFF_DUPLICATED)
cmd = RTM_DELADDR;
- TAILQ_FOREACH(ap, &state->ll_addrs, next) {
+ TAILQ_FOREACH(ap, &state->addrs, next) {
if (IN6_ARE_ADDR_EQUAL(&ap->addr, addr))
break;
}
switch (cmd) {
case RTM_DELADDR:
if (ap) {
- TAILQ_REMOVE(&state->ll_addrs, ap, next);
+ TAILQ_REMOVE(&state->addrs, ap, next);
free(ap);
}
break;
ap = calloc(1, sizeof(*ap));
memcpy(ap->addr.s6_addr, addr->s6_addr,
sizeof(ap->addr.s6_addr));
- TAILQ_INSERT_TAIL(&state->ll_addrs,
+ TAILQ_INSERT_TAIL(&state->addrs,
ap, next);
/* Now run any callbacks.
}
}
-const struct ll_addr *
+const struct ipv6_addr_l *
ipv6_linklocal(const struct interface *ifp)
{
const struct ipv6_state *state;
+ const struct ipv6_addr_l *ap;
state = IPV6_CSTATE(ifp);
- if (state)
- return TAILQ_FIRST(&state->ll_addrs);
+ if (state) {
+ TAILQ_FOREACH(ap, &state->addrs, next) {
+ if (IN6_IS_ADDR_LINKLOCAL(&ap->addr))
+ return ap;
+ }
+ }
+ return NULL;
+}
+
+const struct ipv6_addr_l *
+ipv6_findaddr(const struct interface *ifp, const struct in6_addr *addr)
+{
+ const struct ipv6_state *state;
+ const struct ipv6_addr_l *ap;
+
+ state = IPV6_CSTATE(ifp);
+ if (state) {
+ TAILQ_FOREACH(ap, &state->addrs, next) {
+ if (IN6_ARE_ADDR_EQUAL(&ap->addr, addr))
+ return ap;
+ }
+ }
return NULL;
}
}
}
}
+
void
ipv6_free(struct interface *ifp)
{
struct ipv6_state *state;
- struct ll_addr *ap;
+ struct ipv6_addr_l *ap;
ipv6_free_ll_callbacks(ifp);
state = IPV6_STATE(ifp);
if (state) {
- while ((ap = TAILQ_FIRST(&state->ll_addrs))) {
- TAILQ_REMOVE(&state->ll_addrs, ap, next);
+ while ((ap = TAILQ_FIRST(&state->addrs))) {
+ TAILQ_REMOVE(&state->addrs, ap, next);
free(ap);
}
free(state);
};
TAILQ_HEAD(rt6head, rt6);
-struct ll_addr {
- TAILQ_ENTRY(ll_addr) next;
+struct ipv6_addr_l {
+ TAILQ_ENTRY(ipv6_addr_l) next;
struct in6_addr addr;
};
-TAILQ_HEAD(ll_addr_head, ll_addr);
+TAILQ_HEAD(ipv6_addr_l_head, ipv6_addr_l);
struct ll_callback {
TAILQ_ENTRY(ll_callback) next;
TAILQ_HEAD(ll_callback_head, ll_callback);
struct ipv6_state {
- struct ll_addr_head ll_addrs;
+ struct ipv6_addr_l_head addrs;
struct ll_callback_head ll_callbacks;
};
const char *, const struct in6_addr *, int);
int ipv6_handleifa_addrs(int, struct ipv6_addrhead *,
const struct in6_addr *, int);
-const struct ll_addr *ipv6_linklocal(const struct interface *);
+const struct ipv6_addr_l *ipv6_linklocal(const struct interface *);
+const struct ipv6_addr_l *ipv6_findaddr(const struct interface *,
+ const struct in6_addr *);
int ipv6_addlinklocalcallback(struct interface *, void (*)(void *), void *);
void ipv6_free_ll_callbacks(struct interface *);
void ipv6_free(struct interface *);