summaryrefslogtreecommitdiffstats
path: root/sys/netinet6/ip6_forward.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/ip6_forward.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/ip6_forward.c')
-rw-r--r--sys/netinet6/ip6_forward.c45
1 files changed, 36 insertions, 9 deletions
diff --git a/sys/netinet6/ip6_forward.c b/sys/netinet6/ip6_forward.c
index f0b1cf0..e003452 100644
--- a/sys/netinet6/ip6_forward.c
+++ b/sys/netinet6/ip6_forward.c
@@ -59,6 +59,7 @@
#include <netinet6/in6_var.h>
#include <netinet/ip6.h>
#include <netinet6/ip6_var.h>
+#include <netinet6/scope6_var.h>
#include <netinet/icmp6.h>
#include <netinet6/nd6.h>
@@ -111,7 +112,8 @@ ip6_forward(m, srcrt)
int error, type = 0, code = 0;
struct mbuf *mcopy = NULL;
struct ifnet *origifp; /* maybe unnecessary */
- u_int32_t srczone, dstzone;
+ u_int32_t inzone, outzone;
+ struct in6_addr src_in6, dst_in6;
#ifdef IPSEC
struct secpolicy *sp = NULL;
int ipsecrt = 0;
@@ -400,21 +402,29 @@ ip6_forward(m, srcrt)
#endif
/*
- * Scope check: if a packet can't be delivered to its destination
- * for the reason that the destination is beyond the scope of the
- * source address, discard the packet and return an icmp6 destination
- * unreachable error with Code 2 (beyond scope of source address).
- * [draft-ietf-ipngwg-icmp-v3-02.txt, Section 3.1]
+ * Source scope check: if a packet can't be delivered to its
+ * destination for the reason that the destination is beyond the scope
+ * of the source address, discard the packet and return an icmp6
+ * destination unreachable error with Code 2 (beyond scope of source
+ * address). We use a local copy of ip6_src, since in6_setscope()
+ * will possibly modify its first argument.
+ * [draft-ietf-ipngwg-icmp-v3-04.txt, Section 3.1]
*/
- if (in6_addr2zoneid(m->m_pkthdr.rcvif, &ip6->ip6_src, &srczone) ||
- in6_addr2zoneid(rt->rt_ifp, &ip6->ip6_src, &dstzone)) {
+ src_in6 = ip6->ip6_src;
+ if (in6_setscope(&src_in6, rt->rt_ifp, &outzone)) {
/* XXX: this should not happen */
ip6stat.ip6s_cantforward++;
ip6stat.ip6s_badscope++;
m_freem(m);
return;
}
- if (srczone != dstzone
+ if (in6_setscope(&src_in6, m->m_pkthdr.rcvif, &inzone)) {
+ ip6stat.ip6s_cantforward++;
+ ip6stat.ip6s_badscope++;
+ m_freem(m);
+ return;
+ }
+ if (inzone != outzone
#ifdef IPSEC
&& !ipsecrt
#endif
@@ -440,6 +450,23 @@ ip6_forward(m, srcrt)
return;
}
+ /*
+ * Destination scope check: if a packet is going to break the scope
+ * zone of packet's destination address, discard it. This case should
+ * usually be prevented by appropriately-configured routing table, but
+ * we need an explicit check because we may mistakenly forward the
+ * packet to a different zone by (e.g.) a default route.
+ */
+ dst_in6 = ip6->ip6_dst;
+ if (in6_setscope(&dst_in6, m->m_pkthdr.rcvif, &inzone) != 0 ||
+ in6_setscope(&dst_in6, rt->rt_ifp, &outzone) != 0 ||
+ inzone != outzone) {
+ ip6stat.ip6s_cantforward++;
+ ip6stat.ip6s_badscope++;
+ m_freem(m);
+ return;
+ }
+
if (m->m_pkthdr.len > IN6_LINKMTU(rt->rt_ifp)) {
in6_ifstat_inc(rt->rt_ifp, ifs6_in_toobig);
if (mcopy) {
OpenPOWER on IntegriCloud