On Thu, Dec 29, 2011 at 03:27:26PM -0500, John Baldwin wrote: J> - if_addr_uses.patch This changes callers of the existing macros to use J> either read or write locks. This is the patch that J> could use the most review.
Reviewing your patch I've found several problems not introduced by it, but already existing, and somewhat related to your patch: 1) Unneeded use of _SAFE version of TAILQ: igmp.c:3338 in6.c:1339 mld6.c:2993 2) Potential race when dropping a lock inside FOREACH loop: igmp.c:2058 mld6.c:1419 mld6.c:1704 (this one isn't even a SAFE, so would crash earlier) 3) I've found that in6_ifawithifp() doesn't do what it is supposed to, as well as uses incorrect locking during this. As last resort it should run through global list of addresses, not run throgh the ifp one again. Patch attached. -- Totus tuus, Glebius.
Index: in6.c =================================================================== --- in6.c (revision 228971) +++ in6.c (working copy) @@ -2188,10 +2188,10 @@ { int dst_scope = in6_addrscope(dst), blen = -1, tlen; struct ifaddr *ifa; - struct in6_ifaddr *besta = 0; + struct in6_ifaddr *ia; struct in6_ifaddr *dep[2]; /* last-resort: deprecated */ - dep[0] = dep[1] = NULL; + ia = dep[0] = dep[1] = NULL; /* * We first look for addresses in the same scope. @@ -2219,45 +2219,43 @@ /* * call in6_matchlen() as few as possible */ - if (besta) { + if (ia) { if (blen == -1) - blen = in6_matchlen(&besta->ia_addr.sin6_addr, dst); + blen = in6_matchlen(&ia->ia_addr.sin6_addr, dst); tlen = in6_matchlen(IFA_IN6(ifa), dst); if (tlen > blen) { blen = tlen; - besta = (struct in6_ifaddr *)ifa; + ia = (struct in6_ifaddr *)ifa; } } else - besta = (struct in6_ifaddr *)ifa; + ia = (struct in6_ifaddr *)ifa; } } - if (besta) { - ifa_ref(&besta->ia_ifa); + if (ia) { + ifa_ref(&ia->ia_ifa); IF_ADDR_UNLOCK(ifp); - return (besta); + return (ia); } IF_ADDR_UNLOCK(ifp); IN6_IFADDR_RLOCK(); - TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { - if (ifa->ifa_addr->sa_family != AF_INET6) - continue; - if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST) + TAILQ_FOREACH(ia, &V_in6_ifaddrhead, ia_link) { + if (ia->ia6_flags & IN6_IFF_ANYCAST) continue; /* XXX: is there any case to allow anycast? */ - if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY) + if (ia->ia6_flags & IN6_IFF_NOTREADY) continue; /* don't use this interface */ - if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED) + if (ia->ia6_flags & IN6_IFF_DETACHED) continue; - if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) { + if (ia->ia6_flags & IN6_IFF_DEPRECATED) { if (V_ip6_use_deprecated) dep[1] = (struct in6_ifaddr *)ifa; continue; } - if (ifa != NULL) - ifa_ref(ifa); + if (ia != NULL) + ifa_ref(&ia->ia_ifa); IN6_IFADDR_RUNLOCK(); - return (struct in6_ifaddr *)ifa; + return (ia); } IN6_IFADDR_RUNLOCK();
_______________________________________________ freebsd-net@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-net To unsubscribe, send any mail to "freebsd-net-unsubscr...@freebsd.org"