summaryrefslogtreecommitdiffstats
path: root/sys/netinet6/mld6.c
diff options
context:
space:
mode:
authorume <ume@FreeBSD.org>2005-07-25 12:31:43 +0000
committerume <ume@FreeBSD.org>2005-07-25 12:31:43 +0000
commitda2cf62b280b8450d5f8e0d810e810cdcc59a8c0 (patch)
tree5a678f63b25976c30f74f3bad9edb6f708c52930 /sys/netinet6/mld6.c
parent59bc7b0da19f008a39ee92249e92f8246f04394e (diff)
downloadFreeBSD-src-da2cf62b280b8450d5f8e0d810e810cdcc59a8c0.zip
FreeBSD-src-da2cf62b280b8450d5f8e0d810e810cdcc59a8c0.tar.gz
scope cleanup. with this change
- most of the kernel code will not care about the actual encoding of scope zone IDs and won't touch "s6_addr16[1]" directly. - similarly, most of the kernel code will not care about link-local scoped addresses as a special case. - scope boundary check will be stricter. For example, the current *BSD code allows a packet with src=::1 and dst=(some global IPv6 address) to be sent outside of the node, if the application do: s = socket(AF_INET6); bind(s, "::1"); sendto(s, some_global_IPv6_addr); This is clearly wrong, since ::1 is only meaningful within a single node, but the current implementation of the *BSD kernel cannot reject this attempt. Submitted by: JINMEI Tatuya <jinmei__at__isl.rdc.toshiba.co.jp> Obtained from: KAME
Diffstat (limited to 'sys/netinet6/mld6.c')
-rw-r--r--sys/netinet6/mld6.c93
1 files changed, 52 insertions, 41 deletions
diff --git a/sys/netinet6/mld6.c b/sys/netinet6/mld6.c
index 5cd7cf6..4f62181 100644
--- a/sys/netinet6/mld6.c
+++ b/sys/netinet6/mld6.c
@@ -82,6 +82,7 @@
#include <netinet/in_var.h>
#include <netinet/ip6.h>
#include <netinet6/ip6_var.h>
+#include <netinet6/scope6_var.h>
#include <netinet/icmp6.h>
#include <netinet6/mld6_var.h>
@@ -101,9 +102,6 @@
static struct ip6_pktopts ip6_opts;
static int mld6_timers_are_running;
-/* XXX: These are necessary for KAME's link-local hack */
-static struct in6_addr mld6_all_nodes_linklocal = IN6ADDR_LINKLOCAL_ALLNODES_INIT;
-static struct in6_addr mld6_all_routers_linklocal = IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
static void mld6_sendpkt(struct in6_multi *, int, const struct in6_addr *);
@@ -134,6 +132,7 @@ void
mld6_start_listening(in6m)
struct in6_multi *in6m;
{
+ struct in6_addr all_in6;
int s = splnet();
/*
@@ -143,10 +142,15 @@ mld6_start_listening(in6m)
* MLD messages are never sent for multicast addresses whose scope is 0
* (reserved) or 1 (node-local).
*/
- mld6_all_nodes_linklocal.s6_addr16[1] =
- htons(in6m->in6m_ifp->if_index); /* XXX */
- if (IN6_ARE_ADDR_EQUAL(&in6m->in6m_addr, &mld6_all_nodes_linklocal) ||
- IPV6_ADDR_MC_SCOPE(&in6m->in6m_addr) < IPV6_ADDR_SCOPE_LINKLOCAL) {
+ all_in6 = in6addr_linklocal_allnodes;
+ if (in6_setscope(&all_in6, in6m->in6m_ifp, NULL)) {
+ /* XXX: this should not happen! */
+ in6m->in6m_timer = 0;
+ in6m->in6m_state = MLD_OTHERLISTENER;
+ }
+ if (IN6_ARE_ADDR_EQUAL(&in6m->in6m_addr, &all_in6) ||
+ IPV6_ADDR_MC_SCOPE(&in6m->in6m_addr) <
+ IPV6_ADDR_SCOPE_LINKLOCAL) {
in6m->in6m_timer = 0;
in6m->in6m_state = MLD_OTHERLISTENER;
} else {
@@ -164,16 +168,24 @@ void
mld6_stop_listening(in6m)
struct in6_multi *in6m;
{
- mld6_all_nodes_linklocal.s6_addr16[1] =
- htons(in6m->in6m_ifp->if_index); /* XXX */
- mld6_all_routers_linklocal.s6_addr16[1] =
- htons(in6m->in6m_ifp->if_index); /* XXX: necessary when mrouting */
+ struct in6_addr allnode, allrouter;
+ allnode = in6addr_linklocal_allnodes;
+ if (in6_setscope(&allnode, in6m->in6m_ifp, NULL)) {
+ /* XXX: this should not happen! */
+ return;
+ }
+ allrouter = in6addr_linklocal_allrouters;
+ if (in6_setscope(&allrouter, in6m->in6m_ifp, NULL)) {
+ /* XXX impossible */
+ return;
+ }
if (in6m->in6m_state == MLD_IREPORTEDLAST &&
- (!IN6_ARE_ADDR_EQUAL(&in6m->in6m_addr, &mld6_all_nodes_linklocal)) &&
- IPV6_ADDR_MC_SCOPE(&in6m->in6m_addr) > IPV6_ADDR_SCOPE_INTFACELOCAL)
- mld6_sendpkt(in6m, MLD_LISTENER_DONE,
- &mld6_all_routers_linklocal);
+ !IN6_ARE_ADDR_EQUAL(&in6m->in6m_addr, &allnode) &&
+ IPV6_ADDR_MC_SCOPE(&in6m->in6m_addr) >
+ IPV6_ADDR_SCOPE_INTFACELOCAL) {
+ mld6_sendpkt(in6m, MLD_LISTENER_DONE, &allrouter);
+ }
}
void
@@ -185,6 +197,7 @@ mld6_input(m, off)
struct mld_hdr *mldh;
struct ifnet *ifp = m->m_pkthdr.rcvif;
struct in6_multi *in6m;
+ struct in6_addr mld_addr, all_in6;
struct in6_ifaddr *ia;
struct ifmultiaddr *ifma;
int timer; /* timer value in the MLD query header */
@@ -218,6 +231,16 @@ mld6_input(m, off)
}
/*
+ * make a copy for local work (in6_setscope() may modify the 1st arg)
+ */
+ mld_addr = mldh->mld_addr;
+ if (in6_setscope(&mld_addr, ifp, NULL)) {
+ /* XXX: this should not happen! */
+ m_free(m);
+ return;
+ }
+
+ /*
* In the MLD6 specification, there are 3 states and a flag.
*
* In Non-Listener state, we simply don't have a membership record.
@@ -233,12 +256,15 @@ mld6_input(m, off)
if (ifp->if_flags & IFF_LOOPBACK)
break;
- if (!IN6_IS_ADDR_UNSPECIFIED(&mldh->mld_addr) &&
- !IN6_IS_ADDR_MULTICAST(&mldh->mld_addr))
+ if (!IN6_IS_ADDR_UNSPECIFIED(&mld_addr) &&
+ !IN6_IS_ADDR_MULTICAST(&mld_addr))
break; /* print error or log stat? */
- if (IN6_IS_ADDR_MC_LINKLOCAL(&mldh->mld_addr))
- mldh->mld_addr.s6_addr16[1] =
- htons(ifp->if_index); /* XXX */
+
+ all_in6 = in6addr_linklocal_allnodes;
+ if (in6_setscope(&all_in6, ifp, NULL)) {
+ /* XXX: this should not happen! */
+ break;
+ }
/*
* - Start the timers in all of our membership records
@@ -263,24 +289,19 @@ mld6_input(m, off)
timer = ntohs(mldh->mld_maxdelay) * PR_FASTHZ / MLD_TIMER_SCALE;
if (timer == 0 && mldh->mld_maxdelay)
timer = 1;
- mld6_all_nodes_linklocal.s6_addr16[1] =
- htons(ifp->if_index); /* XXX */
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_INET6)
continue;
in6m = (struct in6_multi *)ifma->ifma_protospec;
- if (IN6_ARE_ADDR_EQUAL(&in6m->in6m_addr,
- &mld6_all_nodes_linklocal) ||
+ if (IN6_ARE_ADDR_EQUAL(&in6m->in6m_addr, &all_in6) ||
IPV6_ADDR_MC_SCOPE(&in6m->in6m_addr) <
IPV6_ADDR_SCOPE_LINKLOCAL)
continue;
- if (IN6_IS_ADDR_UNSPECIFIED(&mldh->mld_addr) ||
- IN6_ARE_ADDR_EQUAL(&mldh->mld_addr,
- &in6m->in6m_addr))
- {
+ if (IN6_IS_ADDR_UNSPECIFIED(&mld_addr) ||
+ IN6_ARE_ADDR_EQUAL(&mld_addr, &in6m->in6m_addr)) {
if (timer == 0) {
/* send a report immediately */
mld6_sendpkt(in6m, MLD_LISTENER_REPORT,
@@ -296,9 +317,6 @@ mld6_input(m, off)
}
}
}
-
- if (IN6_IS_ADDR_MC_LINKLOCAL(&mldh->mld_addr))
- mldh->mld_addr.s6_addr16[1] = 0; /* XXX */
break;
case MLD_LISTENER_REPORT:
@@ -314,24 +332,18 @@ mld6_input(m, off)
if (m->m_flags & M_LOOP) /* XXX: grotty flag, but efficient */
break;
- if (!IN6_IS_ADDR_MULTICAST(&mldh->mld_addr))
+ if (!IN6_IS_ADDR_MULTICAST(&mld_addr))
break;
- if (IN6_IS_ADDR_MC_LINKLOCAL(&mldh->mld_addr))
- mldh->mld_addr.s6_addr16[1] =
- htons(ifp->if_index); /* XXX */
/*
* If we belong to the group being reported, stop
* our timer for that group.
*/
- IN6_LOOKUP_MULTI(mldh->mld_addr, ifp, in6m);
+ IN6_LOOKUP_MULTI(mld_addr, ifp, in6m);
if (in6m) {
in6m->in6m_timer = 0; /* transit to idle state */
in6m->in6m_state = MLD_OTHERLISTENER; /* clear flag */
}
-
- if (IN6_IS_ADDR_MC_LINKLOCAL(&mldh->mld_addr))
- mldh->mld_addr.s6_addr16[1] = 0; /* XXX */
break;
default: /* this is impossible */
log(LOG_ERR, "mld6_input: illegal type(%d)", mldh->mld_type);
@@ -437,8 +449,7 @@ mld6_sendpkt(in6m, type, dst)
mldh->mld_maxdelay = 0;
mldh->mld_reserved = 0;
mldh->mld_addr = in6m->in6m_addr;
- if (IN6_IS_ADDR_MC_LINKLOCAL(&mldh->mld_addr))
- mldh->mld_addr.s6_addr16[1] = 0; /* XXX */
+ in6_clearscope(&mldh->mld_addr); /* XXX */
mldh->mld_cksum = in6_cksum(mh, IPPROTO_ICMPV6, sizeof(struct ip6_hdr),
sizeof(struct mld_hdr));
OpenPOWER on IntegriCloud