--- sys/netinet6/mld6.c (svn+ssh://svn.freebsd.org/base/head) (revision 261548) +++ sys/netinet6/mld6.c (working copy) @@ -163,33 +163,10 @@ static int sysctl_mld_ifinfo(SYSCTL_HANDLER_ARGS); * per-link state iterators. * * XXX LOR PREVENTION - * A special case for IPv6 is the in6_setscope() routine. ip6_output() - * will not accept an ifp; it wants an embedded scope ID, unlike - * ip_output(), which happily takes the ifp given to it. The embedded - * scope ID is only used by MLD to select the outgoing interface. * * During interface attach and detach, MLD will take MLD_LOCK *after* * the IF_AFDATA_LOCK. - * As in6_setscope() takes IF_AFDATA_LOCK then SCOPE_LOCK, we can't call - * it with MLD_LOCK held without triggering an LOR. A netisr with indirect - * dispatch could work around this, but we'd rather not do that, as it - * can introduce other races. * - * As such, we exploit the fact that the scope ID is just the interface - * index, and embed it in the IPv6 destination address accordingly. - * This is potentially NOT VALID for MLDv1 reports, as they - * are always sent to the multicast group itself; as MLDv2 - * reports are always sent to ff02::16, this is not an issue - * when MLDv2 is in use. - * - * This does not however eliminate the LOR when ip6_output() itself - * calls in6_setscope() internally whilst MLD_LOCK is held. This will - * trigger a LOR warning in WITNESS when the ifnet is detached. - * - * The right answer is probably to make IF_AFDATA_LOCK an rwlock, given - * how it's used across the network stack. Here we're simply exploiting - * the fact that MLD runs at a similar layer in the stack to scope6.c. - * * VIMAGE: * * Each in6_multi corresponds to an ifp, and each ifp corresponds * to a vnet in ifp->if_vnet. @@ -197,11 +174,6 @@ static int sysctl_mld_ifinfo(SYSCTL_HANDLER_ARGS); static struct mtx mld_mtx; static MALLOC_DEFINE(M_MLD, "mld", "mld state"); -#define MLD_EMBEDSCOPE(pin6, zoneid) \ - if (IN6_IS_SCOPE_LINKLOCAL(pin6) || \ - IN6_IS_ADDR_MC_INTFACELOCAL(pin6)) \ - (pin6)->s6_addr16[1] = htons((zoneid) & 0xFFFF) \ - /* * VIMAGE-wide globals. */ @@ -427,11 +399,7 @@ mld_dispatch_queue(struct ifqueue *ifq, int limit) * Filter outgoing MLD report state by group. * * Reports are ALWAYS suppressed for ALL-HOSTS (ff02::1) - * and node-local addresses. However, kernel and socket consumers - * always embed the KAME scope ID in the address provided, so strip it - * when performing comparison. - * Note: This is not the same as the *multicast* scope. - * + * and node-local addresses. * Return zero if the given group is one for which MLD reports * should be suppressed, or non-zero if reports should be issued. */ @@ -441,16 +409,9 @@ mld_is_addr_reported(const struct in6_addr *addr) KASSERT(IN6_IS_ADDR_MULTICAST(addr), ("%s: not multicast", __func__)); - if (IPV6_ADDR_MC_SCOPE(addr) == IPV6_ADDR_SCOPE_NODELOCAL) + if (IPV6_ADDR_MC_SCOPE(addr) == IPV6_ADDR_SCOPE_NODELOCAL || + IN6_ARE_ADDR_EQUAL(addr, &in6addr_linklocal_allnodes)) return (0); - - if (IPV6_ADDR_MC_SCOPE(addr) == IPV6_ADDR_SCOPE_LINKLOCAL) { - struct in6_addr tmp = *addr; - in6_clearscope(&tmp); - if (IN6_ARE_ADDR_EQUAL(&tmp, &in6addr_linklocal_allnodes)) - return (0); - } - return (1); } @@ -620,9 +581,6 @@ mli_delete_locked(const struct ifnet *ifp) /* * Process a received MLDv1 general or address-specific query. * Assumes that the query header has been pulled up to sizeof(mld_hdr). - * - * NOTE: Can't be fully const correct as we temporarily embed scope ID in - * mld_addr. This is OK as we own the mbuf chain. */ static int mld_v1_input_query(struct ifnet *ifp, const struct ip6_hdr *ip6, @@ -666,19 +624,10 @@ mld_v1_input_query(struct ifnet *ifp, const struct * MLDv1 General Query. * If this was not sent to the all-nodes group, ignore it. */ - struct in6_addr dst; - - dst = ip6->ip6_dst; - in6_clearscope(&dst); - if (!IN6_ARE_ADDR_EQUAL(&dst, &in6addr_linklocal_allnodes)) + if (!IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, + &in6addr_linklocal_allnodes)) return (EINVAL); is_general_query = 1; - } else { - /* - * Embed scope ID of receiving interface in MLD query for - * lookup whilst we don't hold other locks. - */ - in6_setscope(&mld->mld_addr, ifp, NULL); } IN6_MULTI_LOCK(); @@ -723,8 +672,6 @@ mld_v1_input_query(struct ifnet *ifp, const struct ifp, if_name(ifp)); mld_v1_update_group(inm, timer); } - /* XXX Clear embedded scope ID as userland won't expect it. */ - in6_clearscope(&mld->mld_addr); } IF_ADDR_RUNLOCK(ifp); @@ -874,13 +821,6 @@ mld_v2_input_query(struct ifnet *ifp, const struct if (nsrc > 0) return (EINVAL); is_general_query = 1; - } else { - /* - * Embed scope ID of receiving interface in MLD query for - * lookup whilst we don't hold other locks (due to KAME - * locking lameness). We own this mbuf chain just now. - */ - in6_setscope(&mld->mld_addr, ifp, NULL); } IN6_MULTI_LOCK(); @@ -959,8 +899,6 @@ mld_v2_input_query(struct ifnet *ifp, const struct if (mli->mli_v2_timer == 0 || mli->mli_v2_timer >= timer) mld_v2_process_group_query(inm, mli, timer, m, off); - /* XXX Clear embedded scope ID as userland won't expect it. */ - in6_clearscope(&mld->mld_addr); IF_ADDR_RUNLOCK(ifp); } @@ -1087,15 +1025,11 @@ mld_v2_process_group_query(struct in6_multi *inm, /* * Process a received MLDv1 host membership report. * Assumes mld points to mld_hdr in pulled up mbuf chain. - * - * NOTE: Can't be fully const correct as we temporarily embed scope ID in - * mld_addr. This is OK as we own the mbuf chain. */ static int mld_v1_input_report(struct ifnet *ifp, const struct ip6_hdr *ip6, /*const*/ struct mld_hdr *mld) { - struct in6_addr src, dst; struct in6_ifaddr *ia; struct in6_multi *inm; #ifdef KTR @@ -1116,9 +1050,8 @@ mld_v1_input_report(struct ifnet *ifp, const struc * MLDv1 reports must originate from a host's link-local address, * or the unspecified address (when booting). */ - src = ip6->ip6_src; - in6_clearscope(&src); - if (!IN6_IS_SCOPE_LINKLOCAL(&src) && !IN6_IS_ADDR_UNSPECIFIED(&src)) { + if (!IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src) && + !IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) { CTR3(KTR_MLD, "ignore v1 query src %s on ifp %p(%s)", ip6_sprintf(ip6tbuf, &ip6->ip6_src), ifp, if_name(ifp)); @@ -1129,10 +1062,8 @@ mld_v1_input_report(struct ifnet *ifp, const struc * RFC2710 Section 4: MLDv1 reports must pertain to a multicast * group, and must be directed to the group itself. */ - dst = ip6->ip6_dst; - in6_clearscope(&dst); if (!IN6_IS_ADDR_MULTICAST(&mld->mld_addr) || - !IN6_ARE_ADDR_EQUAL(&mld->mld_addr, &dst)) { + !IN6_ARE_ADDR_EQUAL(&mld->mld_addr, &ip6->ip6_dst)) { CTR3(KTR_MLD, "ignore v1 query dst %s on ifp %p(%s)", ip6_sprintf(ip6tbuf, &ip6->ip6_dst), ifp, if_name(ifp)); @@ -1151,7 +1082,7 @@ mld_v1_input_report(struct ifnet *ifp, const struc */ ia = in6ifa_ifpforlinklocal(ifp, IN6_IFF_NOTREADY|IN6_IFF_ANYCAST); if ((ia && IN6_ARE_ADDR_EQUAL(&ip6->ip6_src, IA6_IN6(ia))) || - (ia == NULL && IN6_IS_ADDR_UNSPECIFIED(&src))) { + (ia == NULL && IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src))) { if (ia != NULL) ifa_free(&ia->ia_ifa); return (0); @@ -1162,13 +1093,6 @@ mld_v1_input_report(struct ifnet *ifp, const struc CTR3(KTR_MLD, "process v1 report %s on ifp %p(%s)", ip6_sprintf(ip6tbuf, &mld->mld_addr), ifp, if_name(ifp)); - /* - * Embed scope ID of receiving interface in MLD query for lookup - * whilst we don't hold other locks (due to KAME locking lameness). - */ - if (!IN6_IS_ADDR_UNSPECIFIED(&mld->mld_addr)) - in6_setscope(&mld->mld_addr, ifp, NULL); - IN6_MULTI_LOCK(); MLD_LOCK(); IF_ADDR_RLOCK(ifp); @@ -1222,10 +1146,6 @@ out_locked: IF_ADDR_RUNLOCK(ifp); MLD_UNLOCK(); IN6_MULTI_UNLOCK(); - - /* XXX Clear embedded scope ID as userland won't expect it. */ - in6_clearscope(&mld->mld_addr); - return (0); } @@ -1840,7 +1760,6 @@ mld_v1_transmit_report(struct in6_multi *in6m, con mld->mld_maxdelay = 0; mld->mld_reserved = 0; mld->mld_addr = in6m->in6m_addr; - in6_clearscope(&mld->mld_addr); mld->mld_cksum = in6_cksum(mh, IPPROTO_ICMPV6, sizeof(struct ip6_hdr), sizeof(struct mld_hdr)); @@ -2467,7 +2386,6 @@ mld_v2_enqueue_group_record(struct ifqueue *ifq, s mr.mr_datalen = 0; mr.mr_numsrc = 0; mr.mr_addr = inm->in6m_addr; - in6_clearscope(&mr.mr_addr); if (!m_append(m, sizeof(struct mldv2_record), (void *)&mr)) { if (m != m0) m_freem(m); @@ -2753,7 +2671,6 @@ mld_v2_enqueue_filter_change(struct ifqueue *ifq, */ memset(&mr, 0, sizeof(mr)); mr.mr_addr = inm->in6m_addr; - in6_clearscope(&mr.mr_addr); if (!m_append(m, sizeof(mr), (void *)&mr)) { if (m != m0) m_freem(m); @@ -3052,7 +2969,6 @@ mld_dispatch_packet(struct mbuf *m) struct ifnet *oifp; struct mbuf *m0; struct mbuf *md; - struct ip6_hdr *ip6; struct mld_hdr *mld; int error; int off; @@ -3102,19 +3018,7 @@ mld_dispatch_packet(struct mbuf *m) m_clrprotoflags(m); m0->m_pkthdr.rcvif = V_loif; - ip6 = mtod(m0, struct ip6_hdr *); -#if 0 - (void)in6_setscope(&ip6->ip6_dst, ifp, NULL); /* XXX LOR */ -#else /* - * XXX XXX Break some KPI rules to prevent an LOR which would - * occur if we called in6_setscope() at transmission. - * See comments at top of file. - */ - MLD_EMBEDSCOPE(&ip6->ip6_dst, ifp->if_index); -#endif - - /* * Retrieve the ICMPv6 type before handoff to ip6_output(), * so we can bump the stats. */