Only add delegated addresses once for each delegation.
When the kernel expires them we will see this via RTM_DELADDR and
remove the address from our list and thus the route.
/* Only drop the address if no other RAs have assigned it.
* This is safe because the RA is removed from the list
* before we are called. */
- if (drop && ap->onlink &&
+ if (drop && ap->flags & IPV6_AF_ONLINK &&
!dhcp6_addrexists(ap) &&
!ipv6rs_addrexists(ap))
{
struct dhcp6_state *state;
int wascompleted;
- wascompleted = ap->dadcompleted;
+ wascompleted = (ap->flags & IPV6_AF_DADCOMPLETED);
ipv6ns_cancelprobeaddr(ap);
- ap->dadcompleted = 1;
- if (ap->dad)
+ ap->flags |= IPV6_AF_DADCOMPLETED;
+ if (ap->flags & IPV6_AF_DUPLICATED)
/* XXX FIXME
* We should decline the address */
syslog(LOG_WARNING, "%s: DAD detected %s",
state->state == DH6S_DELEGATED)
{
TAILQ_FOREACH(ap, &state->addrs, next) {
- if (!ap->dadcompleted) {
+ if ((ap->flags & IPV6_AF_DADCOMPLETED) == 0) {
wascompleted = 1;
break;
}
break;
}
a->iface = ifp;
- a->new = 1;
- a->onlink = 1; /* XXX: suprised no DHCP opt for this */
+ a->flags = IPV6_AF_NEW | IPV6_AF_ONLINK;
a->dadcallback = dhcp6_dadcallback;
memcpy(a->iaid, iaid, sizeof(a->iaid));
memcpy(&a->addr.s6_addr, &in6.s6_addr,
iabuf, sizeof(iabuf));
snprintf(a->saddr, sizeof(a->saddr),
"%s/%d", ia, a->prefix_len);
- if (a->stale)
- a->stale = 0;
+ if (a->flags & IPV6_AF_STALE)
+ a->flags &= ~IPV6_AF_STALE;
else
TAILQ_INSERT_TAIL(&state->addrs, a, next);
i++;
break;
}
a->iface = ifp;
- a->new = 1;
- a->onlink = 0;
+ a->flags = IPV6_AF_NEW;
a->dadcallback = dhcp6_dadcallback;
memcpy(a->iaid, iaid, sizeof(a->iaid));
p = D6_COPTION_DATA(o);
}
} else {
TAILQ_FOREACH(ap, &state->addrs, next) {
- ap->stale = 1;
+ ap->flags |= IPV6_AF_STALE;
}
if (dhcp6_findna(ifp, iaid, p, ol) == 0) {
syslog(LOG_ERR,
return -1;
}
TAILQ_FOREACH_SAFE(ap, &state->addrs, next, nap) {
- if (ap->stale) {
+ if (ap->flags & IPV6_AF_STALE) {
TAILQ_REMOVE(&state->addrs, ap, next);
if (ap->dadcallback)
eloop_q_timeout_delete(0, NULL,
return NULL;
}
a->iface = ifp;
- a->new = 1;
- a->onlink = 1;
+ a->flags = IPV6_AF_NEW | IPV6_AF_ONLINK;
a->dadcallback = dhcp6_dadcallback;
a->delegating_iface = ifs;
memcpy(&a->iaid, &prefix->iaid, sizeof(a->iaid));
recv:
stale = 1;
TAILQ_FOREACH(ap, &state->addrs, next) {
- if (ap->new) {
+ if (ap->flags & IPV6_AF_NEW) {
stale = 0;
break;
}
len = 1;
/* If all addresses have completed DAD run the script */
TAILQ_FOREACH(ap, &state->addrs, next) {
- if (ap->onlink && ap->dadcompleted == 0) {
+ if (ap->flags & IPV6_AF_ONLINK &&
+ (ap->flags & IPV6_AF_DADCOMPLETED) == 0)
+ {
len = 0;
break;
}
ipv6_addaddr(struct ipv6_addr *ap)
{
- syslog(ap->new ? LOG_INFO : LOG_DEBUG,
+ syslog(ap->flags & IPV6_AF_NEW ? LOG_INFO : LOG_DEBUG,
"%s: adding address %s", ap->iface->name, ap->saddr);
if (add_address6(ap->iface, ap) == -1) {
syslog(LOG_ERR, "add_address6 %m");
return -1;
}
- ap->new = 0;
- ap->added = 1;
+ ap->flags &= ~IPV6_AF_NEW;
+ ap->flags |= IPV6_AF_ADDED;
+ if (ap->delegating_iface)
+ ap->flags |= IPV6_AF_DELEGATED;
if (ipv6_removesubnet(ap->iface, ap) == -1)
syslog(LOG_ERR,"ipv6_removesubnet %m");
syslog(LOG_DEBUG,
i = 0;
TAILQ_FOREACH(ap, addrs, next) {
if (ap->prefix_vltime == 0 ||
- IN6_IS_ADDR_UNSPECIFIED(&ap->addr))
+ IN6_IS_ADDR_UNSPECIFIED(&ap->addr) ||
+ ap->flags & IPV6_AF_DELEGATED)
continue;
if (ipv6_addaddr(ap) == 0)
i++;
found = 0;
TAILQ_FOREACH_SAFE(ap, addrs, next, apn) {
if (!IN6_ARE_ADDR_EQUAL(addr, &ap->addr)) {
- if (ap->dadcompleted == 0)
+ if ((ap->flags & IPV6_AF_DADCOMPLETED) == 0)
alldadcompleted = 0;
continue;
}
/* Safety - ignore tentative announcements */
if (flags & IN6_IFF_TENTATIVE)
break;
- if (!ap->dadcompleted) {
+ if ((ap->flags & IPV6_AF_DADCOMPLETED) == 0) {
found++;
- if (flags & IN6_IFF_DUPLICATED && ap->dad == 0)
- ap->dad = 1;
+ if (flags & IN6_IFF_DUPLICATED)
+ ap->flags |= IPV6_AF_DUPLICATED;
if (ap->dadcallback)
ap->dadcallback(ap);
/* We need to set this here in-case the
* dadcallback function checks it */
- ap->dadcompleted = 1;
+ ap->flags |= IPV6_AF_DADCOMPLETED;
}
break;
}
continue;
if (rap->iface->options->options & DHCPCD_IPV6RA_OWN) {
TAILQ_FOREACH(addr, &rap->addrs, next) {
- if (!addr->onlink)
+ if ((addr->flags & IPV6_AF_ONLINK) == 0)
continue;
rt = make_prefix(rap->iface, rap, addr);
if (rt)
d6_state->state == DH6S_DELEGATED))
{
TAILQ_FOREACH(addr, &d6_state->addrs, next) {
- if (!addr->onlink ||
+ if ((addr->flags & IPV6_AF_ONLINK) == 0 ||
IN6_IS_ADDR_UNSPECIFIED(&addr->addr))
continue;
rt = make_prefix(ifp, NULL, addr);
uint32_t prefix_vltime;
uint32_t prefix_pltime;
struct in6_addr addr;
- uint8_t onlink;
- uint8_t new;
- uint8_t stale;
+ short flags;
char saddr[INET6_ADDRSTRLEN];
- uint8_t added;
- uint8_t autoconf;
uint8_t iaid[4];
struct interface *delegating_iface;
void (*dadcallback)(void *);
- uint8_t dad;
- uint8_t dadcompleted;
uint8_t *ns;
size_t nslen;
int nsprobes;
};
TAILQ_HEAD(ipv6_addrhead, ipv6_addr);
+#define IPV6_AF_ONLINK 0x0001
+#define IPV6_AF_NEW 0x0002
+#define IPV6_AF_STALE 0x0004
+#define IPV6_AF_ADDED 0x0008
+#define IPV6_AF_AUTOCONF 0x0010
+#define IPV6_AF_DUPLICATED 0x0020
+#define IPV6_AF_DADCOMPLETED 0x0040
+#define IPV6_AF_DELEGATED 0x0080
+
struct rt6 {
TAILQ_ENTRY(rt6) next;
struct in6_addr dest;
#endif
if (ap->dadcallback &&
- (ap->new == 0 || ap->nsprobes >= ap->iface->options->dadtransmits))
+ ((ap->flags & IPV6_AF_NEW) == 0 ||
+ ap->nsprobes >= ap->iface->options->dadtransmits))
{
#ifdef IPV6_SEND_DAD
ap->dadcallback(ap);
if (ipv6ns_open() == -1)
return;
- ap->dadcompleted = 0;
+ ap->flags &= ~IPV6_AF_DADCOMPLETED;
#ifdef IPV6_SEND_DAD
if (!ap->ns) {
i = 0;
TAILQ_FOREACH(ap, addrs, next) {
if (ap->prefix_vltime == 0 ||
- IN6_IS_ADDR_UNSPECIFIED(&ap->addr))
+ IN6_IS_ADDR_UNSPECIFIED(&ap->addr) ||
+ ap->flags & IPV6_AF_DELEGATED)
continue;
ipv6ns_probeaddr(ap);
- if (ap->new)
+ if (ap->flags & IPV6_AF_NEW)
i++;
}
/* Only drop the address if no other RAs have assigned it.
* This is safe because the RA is removed from the list
* before we are called. */
- if (drop && ap->added &&
+ if (drop && ap->flags & IPV6_AF_ADDED &&
!IN6_IS_ADDR_UNSPECIFIED(&ap->addr) &&
!ipv6rs_addrexists(ap) && !dhcp6_addrexists(ap))
{
/* If all addresses have completed DAD run the script */
TAILQ_FOREACH(ap, &rap->addrs, next) {
- if (ap->dadcompleted == 0) {
+ if ((ap->flags & IPV6_AF_DADCOMPLETED) == 0) {
syslog(LOG_DEBUG,
"%s: waiting for Router Advertisement"
" DAD to complete",
struct ra *rap;
int wascompleted, found;
- wascompleted = ap->dadcompleted;
+ wascompleted = (ap->flags & IPV6_AF_DADCOMPLETED);
ipv6ns_cancelprobeaddr(ap);
- ap->dadcompleted = 1;
- if (ap->dad)
+ ap->flags |= IPV6_AF_DADCOMPLETED;
+ if (ap->flags & IPV6_AF_DUPLICATED)
/* No idea what how to try and make another address :( */
syslog(LOG_WARNING, "%s: DAD detected %s",
ap->iface->name, ap->saddr);
continue;
wascompleted = 1;
TAILQ_FOREACH(rapap, &rap->addrs, next) {
- if (!rapap->dadcompleted) {
+ if ((rapap->flags & IPV6_AF_DADCOMPLETED) == 0){
wascompleted = 0;
break;
}
break;
}
ap->iface = rap->iface;
- ap->new = 1;
- ap->onlink = 0;
- ap->autoconf = 1;
+ ap->flags = IPV6_AF_NEW | IPV6_AF_AUTOCONF;
ap->prefix_len = pi->nd_opt_pi_prefix_len;
memcpy(ap->prefix.s6_addr,
pi->nd_opt_pi_prefix.s6_addr,
ntohl(pi->nd_opt_pi_valid_time) ||
ap->prefix_pltime !=
ntohl(pi->nd_opt_pi_preferred_time) ||
- ap->dad)
+ ap->flags & IPV6_AF_DUPLICATED)
{
- ap->new = 1;
+ ap->flags |= IPV6_AF_NEW;
}
if (pi->nd_opt_pi_flags_reserved &
ND_OPT_PI_FLAG_ONLINK)
- ap->onlink = 1;
+ ap->flags |= IPV6_AF_ONLINK;
ap->prefix_vltime =
ntohl(pi->nd_opt_pi_valid_time);
ap->prefix_pltime =
ntohl(pi->nd_opt_pi_preferred_time);
ap->nsprobes = 0;
- ap->dad = 0;
+ ap->flags &= ~IPV6_AF_DUPLICATED;
if (opt) {
l = strlen(opt);
tmp = realloc(opt,