- Make the code more proactively clear an ND6_IFF_IFDISABLED flag when

an explicit action for INET6 configuration happens.  The changes are:

  1. When an ND6 flag is changed via SIOCSIFINFO_FLAGS ioctl,
     setting ND6_IFF_ACCEPT_RTADV and/or ND6_IFF_AUTO_LINKLOCAL now triggers
     an attempt to clear the ND6_IFF_IFDISABLED flag.

  2. When an AF_INET6 address is added successfully to an interface and
     it is marked as ND6_IFF_IFDISABLED, an attempt to clear the
     ND6_IFF_IFDISABLED happens.

  This simplifies ND6_IFF_IFDISABLED flag manipulation by users via ifconfig(8);
  in most cases manual configuration is no longer needed.

- When ND6_IFF_AUTO_LINKLOCAL is set and no link-local address is assigned to
  an interface, SIOCSIFINFO_FLAGS ioctl now calls in6_ifattach() to configure
  a link-local address.

  This change ensures link-local address configuration when "ifconfig IF inet6"
  command is invoked.  For example, "ifconfig IF inet6 auto_linklocal" now
  always try to configure an LL addr even if ND6_IFF_AUTO_LINKLOCAL is already
  set to 1 (i.e. down/up cycle is no longer needed).

Reviewed by:	bz
This commit is contained in:
hrs 2011-06-06 02:37:38 +00:00
parent 4c2206b625
commit acbda2ccc1
2 changed files with 55 additions and 1 deletions

View File

@ -652,8 +652,32 @@ in6_control(struct socket *so, u_long cmd, caddr_t data,
* that is, this address might make other addresses detached.
*/
pfxlist_onlink_check();
if (error == 0 && ia)
if (error == 0 && ia) {
if (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) {
/*
* Try to clear the flag when a new
* IPv6 address is added onto an
* IFDISABLED interface and it
* succeeds.
*/
struct in6_ndireq nd;
memset(&nd, 0, sizeof(nd));
nd.ndi.flags = ND_IFINFO(ifp)->flags;
nd.ndi.flags &= ~ND6_IFF_IFDISABLED;
if (nd6_ioctl(SIOCSIFINFO_FLAGS,
(caddr_t)&nd, ifp) < 0)
log(LOG_NOTICE, "SIOCAIFADDR_IN6: "
"SIOCSIFINFO_FLAGS for -ifdisabled "
"failed.");
/*
* Ignore failure of clearing the flag
* intentionally. The failure means
* address duplication was detected.
*/
}
EVENTHANDLER_INVOKE(ifaddr_event, ifp);
}
break;
}

View File

@ -1322,6 +1322,15 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp)
struct ifaddr *ifa;
struct in6_ifaddr *ia;
/*
* Try to clear ifdisabled flag when enabling
* accept_rtadv or auto_linklocal.
*/
if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) &&
(ND.flags & (ND6_IFF_ACCEPT_RTADV |
ND6_IFF_AUTO_LINKLOCAL)))
ND.flags &= ~ND6_IFF_IFDISABLED;
if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) &&
!(ND.flags & ND6_IFF_IFDISABLED)) {
/* ifdisabled 1->0 transision */
@ -1379,6 +1388,27 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp)
/* 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) {
/*
* 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)
in6_ifattach(ifp, NULL);
}
}
ND_IFINFO(ifp)->flags = ND.flags;