On 27 Oct 2014, at 16:15 , Andrey V. Elsukov <a...@freebsd.org> wrote:
> Author: ae > Date: Mon Oct 27 16:15:15 2014 > New Revision: 273742 > URL: https://svnweb.freebsd.org/changeset/base/273742 > > Log: > Do not automatically install routes to link-local and interface-local > multicast > addresses. Why? > > Obtained from: Yandex LLC > Sponsored by: Yandex LLC > > Modified: > head/sys/netinet6/in6.c > > Modified: head/sys/netinet6/in6.c > ============================================================================== > --- head/sys/netinet6/in6.c Mon Oct 27 16:13:51 2014 (r273741) > +++ head/sys/netinet6/in6.c Mon Oct 27 16:15:15 2014 (r273742) > @@ -782,27 +782,24 @@ in6_update_ifa_join_mc(struct ifnet *ifp > struct in6_ifaddr *ia, int flags, struct in6_multi **in6m_sol) > { > char ip6buf[INET6_ADDRSTRLEN]; > - struct sockaddr_in6 mltaddr, mltmask; > - struct in6_addr llsol; > + struct in6_addr mltaddr; > struct in6_multi_mship *imm; > - struct rtentry *rt; > int delay, error; > > KASSERT(in6m_sol != NULL, ("%s: in6m_sol is NULL", __func__)); > > /* Join solicited multicast addr for new host id. */ > - bzero(&llsol, sizeof(struct in6_addr)); > - llsol.s6_addr32[0] = IPV6_ADDR_INT32_MLL; > - llsol.s6_addr32[1] = 0; > - llsol.s6_addr32[2] = htonl(1); > - llsol.s6_addr32[3] = ifra->ifra_addr.sin6_addr.s6_addr32[3]; > - llsol.s6_addr8[12] = 0xff; > - if ((error = in6_setscope(&llsol, ifp, NULL)) != 0) { > + bzero(&mltaddr, sizeof(struct in6_addr)); > + mltaddr.s6_addr32[0] = IPV6_ADDR_INT32_MLL; > + mltaddr.s6_addr32[2] = htonl(1); > + mltaddr.s6_addr32[3] = ifra->ifra_addr.sin6_addr.s6_addr32[3]; > + mltaddr.s6_addr8[12] = 0xff; > + if ((error = in6_setscope(&mltaddr, ifp, NULL)) != 0) { > /* XXX: should not happen */ > log(LOG_ERR, "%s: in6_setscope failed\n", __func__); > goto cleanup; > } > - delay = 0; > + delay = error = 0; > if ((flags & IN6_IFAUPDATE_DADDELAY)) { > /* > * We need a random delay for DAD on the address being > @@ -812,62 +809,28 @@ in6_update_ifa_join_mc(struct ifnet *ifp > */ > delay = arc4random() % (MAX_RTR_SOLICITATION_DELAY * hz); > } > - imm = in6_joingroup(ifp, &llsol, &error, delay); > + imm = in6_joingroup(ifp, &mltaddr, &error, delay); > if (imm == NULL) { > - nd6log((LOG_WARNING, "%s: addmulti failed for %s on %s " > - "(errno=%d)\n", __func__, ip6_sprintf(ip6buf, &llsol), > + nd6log((LOG_WARNING, "%s: in6_joingroup failed for %s on %s " > + "(errno=%d)\n", __func__, ip6_sprintf(ip6buf, &mltaddr), > if_name(ifp), error)); > goto cleanup; > } > LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain); > *in6m_sol = imm->i6mm_maddr; > > - bzero(&mltmask, sizeof(mltmask)); > - mltmask.sin6_len = sizeof(struct sockaddr_in6); > - mltmask.sin6_family = AF_INET6; > - mltmask.sin6_addr = in6mask32; > -#define MLTMASK_LEN 4 /* mltmask's masklen (=32bit=4octet) */ > - > /* > * Join link-local all-nodes address. > */ > - bzero(&mltaddr, sizeof(mltaddr)); > - mltaddr.sin6_len = sizeof(struct sockaddr_in6); > - mltaddr.sin6_family = AF_INET6; > - mltaddr.sin6_addr = in6addr_linklocal_allnodes; > - if ((error = in6_setscope(&mltaddr.sin6_addr, ifp, NULL)) != 0) > + mltaddr = in6addr_linklocal_allnodes; > + if ((error = in6_setscope(&mltaddr, ifp, NULL)) != 0) > goto cleanup; /* XXX: should not fail */ > > - /* > - * XXX: do we really need this automatic routes? We should probably > - * reconsider this stuff. Most applications actually do not need the > - * routes, since they usually specify the outgoing interface. > - */ > - rt = in6_rtalloc1((struct sockaddr *)&mltaddr, 0, 0UL, RT_DEFAULT_FIB); > - if (rt != NULL) { > - /* XXX: only works in !SCOPEDROUTING case. */ > - if (memcmp(&mltaddr.sin6_addr, > - &((struct sockaddr_in6 *)rt_key(rt))->sin6_addr, > - MLTMASK_LEN)) { > - RTFREE_LOCKED(rt); > - rt = NULL; > - } > - } > - if (rt == NULL) { > - error = in6_rtrequest(RTM_ADD, (struct sockaddr *)&mltaddr, > - (struct sockaddr *)&ia->ia_addr, > - (struct sockaddr *)&mltmask, RTF_UP, > - (struct rtentry **)0, RT_DEFAULT_FIB); > - if (error) > - goto cleanup; > - } else > - RTFREE_LOCKED(rt); > - > - imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, 0); > + imm = in6_joingroup(ifp, &mltaddr, &error, 0); > if (imm == NULL) { > - nd6log((LOG_WARNING, "%s: addmulti failed for %s on %s " > - "(errno=%d)\n", __func__, ip6_sprintf(ip6buf, > - &mltaddr.sin6_addr), if_name(ifp), error)); > + nd6log((LOG_WARNING, "%s: in6_joingroup failed for %s on %s " > + "(errno=%d)\n", __func__, ip6_sprintf(ip6buf, &mltaddr), > + if_name(ifp), error)); > goto cleanup; > } > LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain); > @@ -883,24 +846,26 @@ in6_update_ifa_join_mc(struct ifnet *ifp > */ > delay = arc4random() % (MAX_RTR_SOLICITATION_DELAY * hz); > } > - if (in6_nigroup(ifp, NULL, -1, &mltaddr.sin6_addr) == 0) { > + if (in6_nigroup(ifp, NULL, -1, &mltaddr) == 0) { > /* XXX jinmei */ > - imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, delay); > + imm = in6_joingroup(ifp, &mltaddr, &error, delay); > if (imm == NULL) > - nd6log((LOG_WARNING, "%s: addmulti failed for %s on %s " > + nd6log((LOG_WARNING, > + "%s: in6_joingroup failed for %s on %s " > "(errno=%d)\n", __func__, ip6_sprintf(ip6buf, > - &mltaddr.sin6_addr), if_name(ifp), error)); > + &mltaddr), if_name(ifp), error)); > /* XXX not very fatal, go on... */ > else > LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain); > } > - if (V_icmp6_nodeinfo_oldmcprefix && > - in6_nigroup_oldmcprefix(ifp, NULL, -1, &mltaddr.sin6_addr) == 0) { > - imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, delay); > + if (V_icmp6_nodeinfo_oldmcprefix && > + in6_nigroup_oldmcprefix(ifp, NULL, -1, &mltaddr) == 0) { > + imm = in6_joingroup(ifp, &mltaddr, &error, delay); > if (imm == NULL) > - nd6log((LOG_WARNING, "%s: addmulti failed for %s on %s " > + nd6log((LOG_WARNING, > + "%s: in6_joingroup failed for %s on %s " > "(errno=%d)\n", __func__, ip6_sprintf(ip6buf, > - &mltaddr.sin6_addr), if_name(ifp), error)); > + &mltaddr), if_name(ifp), error)); > /* XXX not very fatal, go on... */ > else > LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain); > @@ -910,38 +875,18 @@ in6_update_ifa_join_mc(struct ifnet *ifp > * Join interface-local all-nodes address. > * (ff01::1%ifN, and ff01::%ifN/32) > */ > - mltaddr.sin6_addr = in6addr_nodelocal_allnodes; > - if ((error = in6_setscope(&mltaddr.sin6_addr, ifp, NULL)) != 0) > + mltaddr = in6addr_nodelocal_allnodes; > + if ((error = in6_setscope(&mltaddr, ifp, NULL)) != 0) > goto cleanup; /* XXX: should not fail */ > - /* XXX: again, do we really need the route? */ > - rt = in6_rtalloc1((struct sockaddr *)&mltaddr, 0, 0UL, RT_DEFAULT_FIB); > - if (rt != NULL) { > - if (memcmp(&mltaddr.sin6_addr, > - &((struct sockaddr_in6 *)rt_key(rt))->sin6_addr, > - MLTMASK_LEN)) { > - RTFREE_LOCKED(rt); > - rt = NULL; > - } > - } > - if (rt == NULL) { > - error = in6_rtrequest(RTM_ADD, (struct sockaddr *)&mltaddr, > - (struct sockaddr *)&ia->ia_addr, > - (struct sockaddr *)&mltmask, RTF_UP, > - (struct rtentry **)0, RT_DEFAULT_FIB); > - if (error) > - goto cleanup; > - } else > - RTFREE_LOCKED(rt); > > - imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, 0); > + imm = in6_joingroup(ifp, &mltaddr, &error, 0); > if (imm == NULL) { > - nd6log((LOG_WARNING, "%s: addmulti failed for %s on %s " > + nd6log((LOG_WARNING, "%s: in6_joingroup failed for %s on %s " > "(errno=%d)\n", __func__, ip6_sprintf(ip6buf, > - &mltaddr.sin6_addr), if_name(ifp), error)); > + &mltaddr), if_name(ifp), error)); > goto cleanup; > } > LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain); > -#undef MLTMASK_LEN > > cleanup: > return (error); > @@ -1343,135 +1288,17 @@ in6_broadcast_ifa(struct ifnet *ifp, str > } > > /* > - * Leave multicast groups. Factored out from in6_purgeaddr(). > - * This entire work should only be done once, for the default FIB. > + * Leave from multicast groups we have joined for the interface. > */ > static int > in6_purgeaddr_mc(struct ifnet *ifp, struct in6_ifaddr *ia, struct ifaddr > *ifa0) > { > - struct sockaddr_in6 mltaddr, mltmask; > struct in6_multi_mship *imm; > - struct rtentry *rt; > - struct sockaddr_in6 sin6; > - int error; > > - /* > - * Leave from multicast groups we have joined for the interface. > - */ > while ((imm = LIST_FIRST(&ia->ia6_memberships)) != NULL) { > LIST_REMOVE(imm, i6mm_chain); > in6_leavegroup(imm); > } > - > - /* > - * Remove the link-local all-nodes address. > - */ > - bzero(&mltmask, sizeof(mltmask)); > - mltmask.sin6_len = sizeof(struct sockaddr_in6); > - mltmask.sin6_family = AF_INET6; > - mltmask.sin6_addr = in6mask32; > - > - bzero(&mltaddr, sizeof(mltaddr)); > - mltaddr.sin6_len = sizeof(struct sockaddr_in6); > - mltaddr.sin6_family = AF_INET6; > - mltaddr.sin6_addr = in6addr_linklocal_allnodes; > - > - 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)); > - error = in6_setscope(&sin6.sin6_addr, ifa0->ifa_ifp, NULL); > - if (error != 0) > - return (error); > - } > - > - 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, > - &ia->ia_addr.sin6_addr, > - sizeof(ia->ia_addr.sin6_addr)) == 0)) { > - /* > - * If no more IPv6 address exists on this interface then > - * remove the multicast address route. > - */ > - if (ifa0 == NULL) { > - memcpy(&mltaddr.sin6_addr, > - &satosin6(rt_key(rt))->sin6_addr, > - sizeof(mltaddr.sin6_addr)); > - RTFREE_LOCKED(rt); > - error = in6_rtrequest(RTM_DELETE, > - (struct sockaddr *)&mltaddr, > - (struct sockaddr *)&ia->ia_addr, > - (struct sockaddr *)&mltmask, RTF_UP, > - (struct rtentry **)0, RT_DEFAULT_FIB); > - if (error) > - log(LOG_INFO, "%s: link-local all-nodes " > - "multicast address deletion error\n", > - __func__); > - } else { > - /* > - * Replace the gateway of the route. > - */ > - memcpy(rt->rt_gateway, &sin6, sizeof(sin6)); > - RTFREE_LOCKED(rt); > - } > - } else { > - if (rt != NULL) > - RTFREE_LOCKED(rt); > - } > - > - /* > - * Remove the node-local all-nodes address. > - */ > - mltaddr.sin6_addr = in6addr_nodelocal_allnodes; > - if ((error = in6_setscope(&mltaddr.sin6_addr, ifp, NULL)) != 0) > - return (error); > - > - 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, > - &ia->ia_addr.sin6_addr, > - sizeof(ia->ia_addr.sin6_addr)) == 0)) { > - /* > - * If no more IPv6 address exists on this interface then > - * remove the multicast address route. > - */ > - if (ifa0 == NULL) { > - memcpy(&mltaddr.sin6_addr, > - &satosin6(rt_key(rt))->sin6_addr, > - sizeof(mltaddr.sin6_addr)); > - > - RTFREE_LOCKED(rt); > - error = in6_rtrequest(RTM_DELETE, > - (struct sockaddr *)&mltaddr, > - (struct sockaddr *)&ia->ia_addr, > - (struct sockaddr *)&mltmask, RTF_UP, > - (struct rtentry **)0, RT_DEFAULT_FIB); > - if (error) > - log(LOG_INFO, "%s: node-local all-nodes" > - "multicast address deletion error\n", > - __func__); > - } else { > - /* > - * Replace the gateway of the route. > - */ > - memcpy(rt->rt_gateway, &sin6, sizeof(sin6)); > - RTFREE_LOCKED(rt); > - } > - } else { > - if (rt != NULL) > - RTFREE_LOCKED(rt); > - } > - > return (0); > } > > — Bjoern A. Zeeb "Come on. Learn, goddamn it.", WarGames, 1983 _______________________________________________ svn-src-head@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-head To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"