diff options
author | hrs <hrs@FreeBSD.org> | 2014-10-09 23:25:57 +0000 |
---|---|---|
committer | hrs <hrs@FreeBSD.org> | 2014-10-09 23:25:57 +0000 |
commit | ca07cfe57d03fa85669d0ee973e22437cc6c5f24 (patch) | |
tree | 47779c24c81b557c5852d07fb0d3c95ae0b9dd3a /sys/netinet6 | |
parent | 90b42277dc21c65fc9805c42b5eddde0edb59b76 (diff) | |
download | FreeBSD-src-ca07cfe57d03fa85669d0ee973e22437cc6c5f24.zip FreeBSD-src-ca07cfe57d03fa85669d0ee973e22437cc6c5f24.tar.gz |
MFC r266248:
Cancel DAD for an ifa when the ifp has ND6_IFF_IFDISABLED as early as
possible and do not clear IN6_IFF_TENTATIVE. If IFDISABLED was accidentally
set after a DAD started, TENTATIVE could be cleared because no NA was
received due to IFDISABLED, and as a result it could prevent DAD when
manually clearing IFDISABLED after that.
Diffstat (limited to 'sys/netinet6')
-rw-r--r-- | sys/netinet6/nd6_nbr.c | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/sys/netinet6/nd6_nbr.c b/sys/netinet6/nd6_nbr.c index be81331..75ec443 100644 --- a/sys/netinet6/nd6_nbr.c +++ b/sys/netinet6/nd6_nbr.c @@ -1328,6 +1328,7 @@ nd6_dad_timer(struct dadq *dp) { CURVNET_SET(dp->dad_vnet); struct ifaddr *ifa = dp->dad_ifa; + struct ifnet *ifp = dp->dad_ifa->ifa_ifp; struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa; char ip6buf[INET6_ADDRSTRLEN]; @@ -1336,6 +1337,16 @@ nd6_dad_timer(struct dadq *dp) log(LOG_ERR, "nd6_dad_timer: called with null parameter\n"); goto done; } + if (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) { + /* Do not need DAD for ifdisabled interface. */ + TAILQ_REMOVE(&V_dadq, (struct dadq *)dp, dad_list); + log(LOG_ERR, "nd6_dad_timer: cancel DAD on %s because of " + "ND6_IFF_IFDISABLED.\n", ifp->if_xname); + free(dp, M_IP6NDP); + dp = NULL; + ifa_free(ifa); + goto done; + } if (ia->ia6_flags & IN6_IFF_DUPLICATED) { log(LOG_ERR, "nd6_dad_timer: called with duplicated address " "%s(%s)\n", @@ -1402,9 +1413,12 @@ nd6_dad_timer(struct dadq *dp) } else { /* * We are done with DAD. No NA came, no NS came. - * No duplicate address found. + * No duplicate address found. Check IFDISABLED flag + * again in case that it is changed between the + * beginning of this function and here. */ - ia->ia6_flags &= ~IN6_IFF_TENTATIVE; + if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) == 0) + ia->ia6_flags &= ~IN6_IFF_TENTATIVE; nd6log((LOG_DEBUG, "%s: DAD complete for %s - no duplicates found\n", |