Do not automatically install routes to link-local and interface-local multicast
addresses. Obtained from: Yandex LLC Sponsored by: Yandex LLC
This commit is contained in:
parent
219b3e3a0c
commit
c56173a626
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=273742
@ -782,27 +782,24 @@ in6_update_ifa_join_mc(struct ifnet *ifp, struct in6_aliasreq *ifra,
|
||||
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, struct in6_aliasreq *ifra,
|
||||
*/
|
||||
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, struct in6_aliasreq *ifra,
|
||||
*/
|
||||
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, struct in6_aliasreq *ifra,
|
||||
* 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, struct in6_aliasreq *ifra,
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user