DF-3377 / fix.diff
--- sys/netinet6/ip6_mroute.c.orig +++ sys/netinet6/ip6_mroute.c @@ -588,6 +588,39 @@ IFNAMSIZ); multicast_register_if.if_flags |= IFF_LOOPBACK; multicast_register_if.if_index = mifcp->mif6c_mifi; + /* + * The register "interface" is never if_attach()ed, + * but pim6_input() re-injects decapsulated PIM + * REGISTER packets through if_simloop(), which bumps + * per-CPU ifnet statistics through + * ifp->if_data_pcpu. Allocate the per-CPU stats + * block (as if_attach() would) so that path does + * not write through a NULL pointer. + */ + if (multicast_register_if.if_data_pcpu == NULL) { + multicast_register_if.if_data_pcpu = + kmalloc(ncpus * + sizeof(struct ifdata_pcpu), + M_DEVBUF, M_WAITOK | M_ZERO | + M_CACHEALIGN); + } + /* + * if_addrheads[] is iterated by in6_ifawithifp() + * from ip6_input() for packets "received" on this + * fake interface (if.c:550-553 does this in + * if_attach()). Empty lists are fine. + */ + if (multicast_register_if.if_addrheads == NULL) { + int _i; + + multicast_register_if.if_addrheads = + kmalloc(ncpus * + sizeof(struct ifaddrhead), + M_IFADDR, M_WAITOK | M_ZERO); + for (_i = 0; _i < ncpus; ++_i) + TAILQ_INIT( + &multicast_register_if.if_addrheads[_i]); + } reg_mif_num = mifcp->mif6c_mifi; } @@ -1417,9 +1450,18 @@ * For each mif, forward a copy of the packet if there are group * members downstream on the interface. */ - if (in6_addr2zoneid(ifp, &ip6->ip6_dst, &dscopein) || - in6_addr2zoneid(ifp, &ip6->ip6_src, &sscopein)) + /* + * XXX For packets arriving through the PIM register tunnel + * interface we believe the routing daemon (mirroring the + * output-side check below); the register "interface" has no + * scope6 data attached (never in6_ifattach()ed). + */ + if (mif6table[rt->mf6c_parent].m6_flags & MIFF_REGISTER) { + dscopein = sscopein = 0; + } else if (in6_addr2zoneid(ifp, &ip6->ip6_dst, &dscopein) || + in6_addr2zoneid(ifp, &ip6->ip6_src, &sscopein)) { return (EINVAL); + } for (mifp = mif6table, mifi = 0; mifi < nummifs; mifp++, mifi++) { if (IF_ISSET(mifi, &rt->mf6c_ifset)) { u_int32_t dscopeout, sscopeout; |