Fix a problem that an interface unexpectedly becomes IFF_UP by

just doing "ifconfing inet6 -ifdisabled" when the interface has
ND6_IFF_AUTO_LINKLOCAL flag and no link-local address.
This commit is contained in:
Hiroki Sato 2011-10-16 19:46:52 +00:00
parent d13b008d74
commit 154d5f7321
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=226446

View File

@ -1364,7 +1364,8 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp)
" duplicate.\n");
} else {
ND_IFINFO(ifp)->flags &= ~ND6_IFF_IFDISABLED;
in6_if_up(ifp);
if (ifp->if_flags & IFF_UP)
in6_if_up(ifp);
}
} else if (!(ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) &&
(ND.flags & ND6_IFF_IFDISABLED)) {
@ -1382,35 +1383,37 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp)
IF_ADDR_UNLOCK(ifp);
}
if (!(ND_IFINFO(ifp)->flags & ND6_IFF_AUTO_LINKLOCAL) &&
(ND.flags & ND6_IFF_AUTO_LINKLOCAL)) {
/* auto_linklocal 0->1 transision */
if (ND.flags & ND6_IFF_AUTO_LINKLOCAL) {
if (!(ND_IFINFO(ifp)->flags & ND6_IFF_AUTO_LINKLOCAL)) {
/* auto_linklocal 0->1 transision */
/* If no link-local address on ifp, configure */
ND_IFINFO(ifp)->flags |= ND6_IFF_AUTO_LINKLOCAL;
in6_ifattach(ifp, NULL);
} else if ((ND_IFINFO(ifp)->flags & ND6_IFF_AUTO_LINKLOCAL) &&
!(ND.flags & ND6_IFF_IFDISABLED)) {
/*
* When the IF already has
* ND6_IFF_AUTO_LINKLOCAL and no link-local
* address is assigned, try to assign one.
*/
int haslinklocal = 0;
IF_ADDR_LOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family != AF_INET6)
continue;
ia = (struct in6_ifaddr *)ifa;
if (IN6_IS_ADDR_LINKLOCAL(IA6_IN6(ia))) {
haslinklocal = 1;
break;
}
}
IF_ADDR_UNLOCK(ifp);
if (!haslinklocal)
/* If no link-local address on ifp, configure */
ND_IFINFO(ifp)->flags |= ND6_IFF_AUTO_LINKLOCAL;
in6_ifattach(ifp, NULL);
} else if (!(ND.flags & ND6_IFF_IFDISABLED) &&
ifp->if_flags & IFF_UP) {
/*
* When the IF already has
* ND6_IFF_AUTO_LINKLOCAL, no link-local
* address is assigned, and IFF_UP, try to
* assign one.
*/
int haslinklocal = 0;
IF_ADDR_LOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family != AF_INET6)
continue;
ia = (struct in6_ifaddr *)ifa;
if (IN6_IS_ADDR_LINKLOCAL(IA6_IN6(ia))) {
haslinklocal = 1;
break;
}
}
IF_ADDR_UNLOCK(ifp);
if (!haslinklocal)
in6_ifattach(ifp, NULL);
}
}
}
ND_IFINFO(ifp)->flags = ND.flags;