Author: hrs
Date: Mon Jun  6 02:37:38 2011
New Revision: 222730
URL: http://svn.freebsd.org/changeset/base/222730

Log:
  - 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

Modified:
  head/sys/netinet6/in6.c
  head/sys/netinet6/nd6.c

Modified: head/sys/netinet6/in6.c
==============================================================================
--- head/sys/netinet6/in6.c     Mon Jun  6 02:25:53 2011        (r222729)
+++ head/sys/netinet6/in6.c     Mon Jun  6 02:37:38 2011        (r222730)
@@ -652,8 +652,32 @@ in6_control(struct socket *so, u_long cm
                 * 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;
        }
 

Modified: head/sys/netinet6/nd6.c
==============================================================================
--- head/sys/netinet6/nd6.c     Mon Jun  6 02:25:53 2011        (r222729)
+++ head/sys/netinet6/nd6.c     Mon Jun  6 02:37:38 2011        (r222730)
@@ -1322,6 +1322,15 @@ nd6_ioctl(u_long cmd, caddr_t data, stru
                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, stru
                        /* 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;
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to