- Schedule DAD for IN6_IFF_TENTATIVE addresses in nd6_timer(). This
catches cases that DAD probes cannot be sent because of IFF_UP && !IFF_DRV_RUNNING. - nd6_dad_starttimer() now calls nd6_dad_ns_output(), instead of calling it before nd6_dad_starttimer(). - Do not release an entry in dadq when a duplicate entry is being added.
This commit is contained in:
parent
ec5a8cf7c0
commit
6401c828ce
@ -810,7 +810,30 @@ nd6_timer(void *arg)
|
||||
goto addrloop;
|
||||
}
|
||||
}
|
||||
} else if ((ia6->ia6_flags & IN6_IFF_TENTATIVE) != 0) {
|
||||
/*
|
||||
* Schedule DAD for a tentative address. This happens
|
||||
* if the interface was down or not running
|
||||
* when the address was configured.
|
||||
*/
|
||||
int delay;
|
||||
|
||||
delay = arc4random() %
|
||||
(MAX_RTR_SOLICITATION_DELAY * hz);
|
||||
nd6_dad_start((struct ifaddr *)ia6, delay);
|
||||
} else {
|
||||
/*
|
||||
* Check status of the interface. If it is down,
|
||||
* mark the address as tentative for future DAD.
|
||||
*/
|
||||
if ((ia6->ia_ifp->if_flags & IFF_UP) == 0 ||
|
||||
(ia6->ia_ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
== 0 ||
|
||||
(ND_IFINFO(ia6->ia_ifp)->flags &
|
||||
ND6_IFF_IFDISABLED) != 0) {
|
||||
ia6->ia6_flags &= ~IN6_IFF_DUPLICATED;
|
||||
ia6->ia6_flags |= IN6_IFF_TENTATIVE;
|
||||
}
|
||||
/*
|
||||
* A new RA might have made a deprecated address
|
||||
* preferred.
|
||||
@ -1452,7 +1475,8 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp)
|
||||
/* Mark all IPv6 address as tentative. */
|
||||
|
||||
ND_IFINFO(ifp)->flags |= ND6_IFF_IFDISABLED;
|
||||
if ((ND_IFINFO(ifp)->flags & ND6_IFF_NO_DAD) == 0) {
|
||||
if (V_ip6_dad_count > 0 &&
|
||||
(ND_IFINFO(ifp)->flags & ND6_IFF_NO_DAD) == 0) {
|
||||
IF_ADDR_RLOCK(ifp);
|
||||
TAILQ_FOREACH(ifa, &ifp->if_addrhead,
|
||||
ifa_link) {
|
||||
|
@ -85,11 +85,11 @@ static struct dadq *nd6_dad_find(struct ifaddr *, struct nd_opt_nonce *);
|
||||
static void nd6_dad_add(struct dadq *dp);
|
||||
static void nd6_dad_del(struct dadq *dp);
|
||||
static void nd6_dad_rele(struct dadq *);
|
||||
static void nd6_dad_starttimer(struct dadq *, int);
|
||||
static void nd6_dad_starttimer(struct dadq *, int, int);
|
||||
static void nd6_dad_stoptimer(struct dadq *);
|
||||
static void nd6_dad_timer(struct dadq *);
|
||||
static void nd6_dad_duplicated(struct ifaddr *, struct dadq *);
|
||||
static void nd6_dad_ns_output(struct dadq *, struct ifaddr *);
|
||||
static void nd6_dad_ns_output(struct dadq *);
|
||||
static void nd6_dad_ns_input(struct ifaddr *, struct nd_opt_nonce *);
|
||||
static void nd6_dad_na_input(struct ifaddr *);
|
||||
static void nd6_na_output_fib(struct ifnet *, const struct in6_addr *,
|
||||
@ -1199,9 +1199,11 @@ nd6_dad_find(struct ifaddr *ifa, struct nd_opt_nonce *n)
|
||||
}
|
||||
|
||||
static void
|
||||
nd6_dad_starttimer(struct dadq *dp, int ticks)
|
||||
nd6_dad_starttimer(struct dadq *dp, int ticks, int send_ns)
|
||||
{
|
||||
|
||||
if (send_ns != 0)
|
||||
nd6_dad_ns_output(dp);
|
||||
callout_reset(&dp->dad_timer_ch, ticks,
|
||||
(void (*)(void *))nd6_dad_timer, (void *)dp);
|
||||
}
|
||||
@ -1240,6 +1242,7 @@ nd6_dad_start(struct ifaddr *ifa, int delay)
|
||||
struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
|
||||
struct dadq *dp;
|
||||
char ip6buf[INET6_ADDRSTRLEN];
|
||||
int send_ns;
|
||||
|
||||
/*
|
||||
* If we don't need DAD, don't do it.
|
||||
@ -1276,8 +1279,10 @@ nd6_dad_start(struct ifaddr *ifa, int delay)
|
||||
return;
|
||||
}
|
||||
if ((dp = nd6_dad_find(ifa, NULL)) != NULL) {
|
||||
/* DAD already in progress */
|
||||
nd6_dad_rele(dp);
|
||||
/*
|
||||
* DAD already in progress. Let the existing entry
|
||||
* to finish it.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1310,13 +1315,12 @@ nd6_dad_start(struct ifaddr *ifa, int delay)
|
||||
dp->dad_ns_lcount = dp->dad_loopbackprobe = 0;
|
||||
refcount_init(&dp->dad_refcnt, 1);
|
||||
nd6_dad_add(dp);
|
||||
send_ns = 0;
|
||||
if (delay == 0) {
|
||||
nd6_dad_ns_output(dp, ifa);
|
||||
nd6_dad_starttimer(dp,
|
||||
(long)ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000);
|
||||
} else {
|
||||
nd6_dad_starttimer(dp, delay);
|
||||
send_ns = 1;
|
||||
delay = (long)ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000;
|
||||
}
|
||||
nd6_dad_starttimer(dp, delay, send_ns);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1386,7 +1390,8 @@ nd6_dad_timer(struct dadq *dp)
|
||||
if ((dp->dad_ns_tcount > V_dad_maxtry) &&
|
||||
(((ifp->if_flags & IFF_UP) == 0) ||
|
||||
((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0))) {
|
||||
nd6log((LOG_INFO, "%s: could not run DAD, driver problem?\n",
|
||||
nd6log((LOG_INFO, "%s: could not run DAD "
|
||||
"because the interface was down or not running.\n",
|
||||
if_name(ifa->ifa_ifp)));
|
||||
goto err;
|
||||
}
|
||||
@ -1396,9 +1401,8 @@ nd6_dad_timer(struct dadq *dp)
|
||||
/*
|
||||
* We have more NS to go. Send NS packet for DAD.
|
||||
*/
|
||||
nd6_dad_ns_output(dp, ifa);
|
||||
nd6_dad_starttimer(dp,
|
||||
(long)ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000);
|
||||
(long)ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000, 1);
|
||||
goto done;
|
||||
} else {
|
||||
/*
|
||||
@ -1426,11 +1430,11 @@ nd6_dad_timer(struct dadq *dp)
|
||||
* Send an NS immediately and increase dad_count by
|
||||
* V_nd6_mmaxtries - 1.
|
||||
*/
|
||||
nd6_dad_ns_output(dp, ifa);
|
||||
dp->dad_count =
|
||||
dp->dad_ns_ocount + V_nd6_mmaxtries - 1;
|
||||
nd6_dad_starttimer(dp,
|
||||
(long)ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000);
|
||||
(long)ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000,
|
||||
1);
|
||||
goto done;
|
||||
} else {
|
||||
/*
|
||||
@ -1517,10 +1521,10 @@ nd6_dad_duplicated(struct ifaddr *ifa, struct dadq *dp)
|
||||
}
|
||||
|
||||
static void
|
||||
nd6_dad_ns_output(struct dadq *dp, struct ifaddr *ifa)
|
||||
nd6_dad_ns_output(struct dadq *dp)
|
||||
{
|
||||
struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
|
||||
struct ifnet *ifp = ifa->ifa_ifp;
|
||||
struct in6_ifaddr *ia = (struct in6_ifaddr *)dp->dad_ifa;
|
||||
struct ifnet *ifp = dp->dad_ifa->ifa_ifp;
|
||||
int i;
|
||||
|
||||
dp->dad_ns_tcount++;
|
||||
|
Loading…
Reference in New Issue
Block a user