Instead of waiting the maximum amount of time to report DAD failure/completion, poll the address flags periodically.
/* If all addresses have completed DAD run the script */
TAILQ_FOREACH(ap, &state->addrs, next) {
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) &&
+// ipv6_findaddr(ap->iface, &ap->addr))
+// ap->flags |= IPV6_AF_DADCOMPLETED;
if ((ap->flags & IPV6_AF_DADCOMPLETED) == 0) {
len = 0;
break;
* them as some OS's will remove, mark tentative or
* do nothing. */
ipv6_free_ll_callbacks(ifp);
- dhcp_drop(ifp, "NOCARRIER");
+ dhcp_drop(ifp, "EXPIRE");
+ script_runreason(ifp, "NOCARRIER");
}
} else if (carrier == LINK_UP && ifp->flags & IFF_UP) {
if (ifp->carrier != LINK_UP) {
return 0;
}
+#ifdef LISTEN_DAD
+void
+ipv6_checkaddrflags(void *arg)
+{
+ struct ipv6_addr *ap;
+ int ifa_flags;
+
+ ap = arg;
+ ifa_flags = in6_addr_flags(ap->iface->name, &ap->addr);
+ if (ifa_flags == -1)
+ syslog(LOG_ERR, "%s: in6_addr_flags: %m", ap->iface->name);
+ else if (!(ifa_flags & IN6_IFF_TENTATIVE)) {
+ ipv6_handleifa(ap->iface->ctx, RTM_NEWADDR,
+ ap->iface->ctx->ifaces, ap->iface->name,
+ &ap->addr, ifa_flags);
+ } else {
+ struct timeval tv;
+
+ ms_to_tv(&tv, RETRANS_TIMER / 2);
+ eloop_timeout_add_tv(ap->iface->ctx->eloop, &tv,
+ ipv6_checkaddrflags, ap);
+ }
+}
+#endif
+
int
ipv6_addaddr(struct ipv6_addr *ap)
{
return r;
}
-
static struct rt6 *
make_router(const struct ra *rap)
{
int ipv6_prefixlen(const struct in6_addr *);
int ipv6_userprefix( const struct in6_addr *, short prefix_len,
uint64_t user_number, struct in6_addr *result, short result_len);
+void ipv6_checkaddrflags(void *);
int ipv6_addaddr(struct ipv6_addr *);
void ipv6_freedrop_addrs(struct ipv6_addrhead *, int,
const struct interface *);
if (ap->dadcallback)
eloop_timeout_delete(ap->iface->ctx->eloop, ap->dadcallback,ap);
}
+
#endif
void
struct cmsghdr *cm;
struct in6_pktinfo pi;
int hoplimit = HOPLIMIT;
+ struct timeval tv, rtv;
#else
#ifdef LISTEN_DAD
- struct timeval tv, rtv;
- struct timeval mtv;
- int i;
+ struct timeval tv;
#endif
#endif
#ifdef LISTEN_DAD
/* Let the kernel handle DAD.
- * We don't know the timings, so just wait for the max */
+ * We don't know the timings, so just poll the address flags */
if (ap->dadcallback) {
- mtv.tv_sec = 0;
- mtv.tv_usec = 0;
- for (i = 0; i < ap->iface->options->dadtransmits; i++) {
- ms_to_tv(&tv, RETRANS_TIMER);
- ms_to_tv(&rtv, MAX_RANDOM_FACTOR);
- timeradd(&tv, &rtv, &tv);
- timeradd(&mtv, &tv, &mtv);
- }
+ ms_to_tv(&tv, RETRANS_TIMER / 2);
eloop_timeout_add_tv(ap->iface->ctx->eloop,
- &mtv, ap->dadcallback, ap);
+ &tv, ipv6_checkaddrflags, ap);
}
#endif
#endif /* IPV6_SEND_DAD */