Author: delphij
Date: Mon Jun 25 20:56:32 2012
New Revision: 237571
URL: http://svn.freebsd.org/changeset/base/237571

Log:
  Fix a LOR acquiring the if_afdata lock while holding an rtentry lock.
  Possibly do some entra work in case we would not get into the
  ifa0 != NULL paths later as we already do for the mltaddr before.
  
  XXX We should possibly error in case in6_setscope fails.
  
  Reference: 
http://lists.freebsd.org/pipermail/freebsd-net/2011-September/029829.html
  
  Submitted by: bz
  MFC after:    1 week

Modified:
  head/sys/netinet6/in6.c

Modified: head/sys/netinet6/in6.c
==============================================================================
--- head/sys/netinet6/in6.c     Mon Jun 25 19:59:08 2012        (r237570)
+++ head/sys/netinet6/in6.c     Mon Jun 25 20:56:32 2012        (r237571)
@@ -1330,6 +1330,7 @@ in6_purgeaddr_mc(struct ifnet *ifp, stru
        struct sockaddr_in6 mltaddr, mltmask;
        struct in6_multi_mship *imm;
        struct rtentry *rt;
+       struct sockaddr_in6 sin6;
        int error;
 
        /*
@@ -1356,6 +1357,19 @@ in6_purgeaddr_mc(struct ifnet *ifp, stru
        if ((error = in6_setscope(&mltaddr.sin6_addr, ifp, NULL)) != 0)
                return (error);
 
+       /*
+        * As for the mltaddr above, proactively prepare the sin6 to avoid
+        * rtentry un- and re-locking.
+        */
+       if (ifa0 != NULL) {
+               bzero(&sin6, sizeof(sin6));
+               sin6.sin6_len = sizeof(sin6);
+               sin6.sin6_family = AF_INET6;
+               memcpy(&sin6.sin6_addr, &satosin6(ifa0->ifa_addr)->sin6_addr, 
+                   sizeof(sin6.sin6_addr));
+               in6_setscope(&sin6.sin6_addr, ifa0->ifa_ifp, NULL);
+       }
+
        rt = in6_rtalloc1((struct sockaddr *)&mltaddr, 0, 0UL, RT_DEFAULT_FIB);
        if (rt != NULL && rt->rt_gateway != NULL &&
            (memcmp(&satosin6(rt->rt_gateway)->sin6_addr, 
@@ -1382,15 +1396,7 @@ in6_purgeaddr_mc(struct ifnet *ifp, stru
                        /*
                         * Replace the gateway of the route.
                         */
-                       struct sockaddr_in6 sa;
-
-                       bzero(&sa, sizeof(sa));
-                       sa.sin6_len = sizeof(struct sockaddr_in6);
-                       sa.sin6_family = AF_INET6;
-                       memcpy(&sa.sin6_addr, 
&satosin6(ifa0->ifa_addr)->sin6_addr, 
-                              sizeof(sa.sin6_addr));
-                       in6_setscope(&sa.sin6_addr, ifa0->ifa_ifp, NULL);
-                       memcpy(rt->rt_gateway, &sa, sizeof(sa));
+                       memcpy(rt->rt_gateway, &sin6, sizeof(sin6));
                        RTFREE_LOCKED(rt);
                }
        } else {
@@ -1432,15 +1438,7 @@ in6_purgeaddr_mc(struct ifnet *ifp, stru
                        /*
                         * Replace the gateway of the route.
                         */
-                       struct sockaddr_in6 sa;
-
-                       bzero(&sa, sizeof(sa));
-                       sa.sin6_len = sizeof(struct sockaddr_in6);
-                       sa.sin6_family = AF_INET6;
-                       memcpy(&sa.sin6_addr, 
&satosin6(ifa0->ifa_addr)->sin6_addr, 
-                              sizeof(sa.sin6_addr));
-                       in6_setscope(&sa.sin6_addr, ifa0->ifa_ifp, NULL);
-                       memcpy(rt->rt_gateway, &sa, sizeof(sa));
+                       memcpy(rt->rt_gateway, &sin6, sizeof(sin6));
                        RTFREE_LOCKED(rt);
                }
        } else {
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to