summaryrefslogtreecommitdiffstats
path: root/sys/netinet6/ip6_input.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_input.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_input.c')
-rw-r--r--sys/netinet6/ip6_input.c80
1 files changed, 18 insertions, 62 deletions
diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c
index d23a447..9c5ff4a 100644
--- a/sys/netinet6/ip6_input.c
+++ b/sys/netinet6/ip6_input.c
@@ -236,8 +236,6 @@ ip6_input(m)
u_int32_t rtalert = ~0;
int nxt, ours = 0;
struct ifnet *deliverifp = NULL;
- struct sockaddr_in6 sa6;
- u_int32_t srczone, dstzone;
struct in6_addr odst;
int srcrt = 0;
@@ -401,23 +399,23 @@ ip6_input(m)
#endif
/*
- * Drop packets if the link ID portion is already filled.
- * XXX: this is technically not a good behavior. But, we internally
- * use the field to disambiguate link-local addresses, so we cannot
- * be generous against those a bit strange addresses.
+ * Disambiguate address scope zones (if there is ambiguity).
+ * We first make sure that the original source or destination address
+ * is not in our internal form for scoped addresses. Such addresses
+ * are not necessarily invalid spec-wise, but we cannot accept them due
+ * to the usage conflict.
+ * in6_setscope() then also checks and rejects the cases where src or
+ * dst are the loopback address and the receiving interface
+ * is not loopback.
*/
- if ((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0) {
- if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src) &&
- ip6->ip6_src.s6_addr16[1]) {
- ip6stat.ip6s_badscope++;
- goto bad;
- }
- if ((IN6_IS_ADDR_MC_INTFACELOCAL(&ip6->ip6_dst) ||
- IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) &&
- ip6->ip6_dst.s6_addr16[1]) {
- ip6stat.ip6s_badscope++;
- goto bad;
- }
+ if (in6_clearscope(&ip6->ip6_src) || in6_clearscope(&ip6->ip6_dst)) {
+ ip6stat.ip6s_badscope++; /* XXX */
+ goto bad;
+ }
+ if (in6_setscope(&ip6->ip6_src, m->m_pkthdr.rcvif, NULL) ||
+ in6_setscope(&ip6->ip6_dst, m->m_pkthdr.rcvif, NULL)) {
+ ip6stat.ip6s_badscope++;
+ goto bad;
}
/*
@@ -457,49 +455,6 @@ passin:
}
/*
- * construct source and destination address structures with
- * disambiguating their scope zones (if there is ambiguity).
- * XXX: sin6_family and sin6_len will NOT be referred to, but we fill
- * in these fields just in case.
- */
- if (in6_addr2zoneid(m->m_pkthdr.rcvif, &ip6->ip6_src, &srczone) ||
- in6_addr2zoneid(m->m_pkthdr.rcvif, &ip6->ip6_dst, &dstzone)) {
- /*
- * Note that these generic checks cover cases that src or
- * dst are the loopback address and the receiving interface
- * is not loopback.
- */
- ip6stat.ip6s_badscope++;
- goto bad;
- }
-
- bzero(&sa6, sizeof(sa6));
- sa6.sin6_family = AF_INET6;
- sa6.sin6_len = sizeof(struct sockaddr_in6);
-
- sa6.sin6_addr = ip6->ip6_src;
- sa6.sin6_scope_id = srczone;
- if (in6_embedscope(&ip6->ip6_src, &sa6, NULL, NULL)) {
- /* XXX: should not happen */
- ip6stat.ip6s_badscope++;
- goto bad;
- }
-
- sa6.sin6_addr = ip6->ip6_dst;
- sa6.sin6_scope_id = dstzone;
- if (in6_embedscope(&ip6->ip6_dst, &sa6, NULL, NULL)) {
- /* XXX: should not happen */
- ip6stat.ip6s_badscope++;
- goto bad;
- }
-
- /* XXX: ff01::%ifN awareness is not merged, yet. */
- if (IN6_IS_ADDR_MC_INTFACELOCAL(&ip6->ip6_src))
- ip6->ip6_src.s6_addr16[1] = 0;
- if (IN6_IS_ADDR_MC_INTFACELOCAL(&ip6->ip6_dst))
- ip6->ip6_dst.s6_addr16[1] = 0;
-
- /*
* Multicast check
*/
if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
@@ -1363,7 +1318,8 @@ ip6_notify_pmtu(in6p, dst, mtu)
bzero(&mtuctl, sizeof(mtuctl)); /* zero-clear for safety */
mtuctl.ip6m_mtu = *mtu;
mtuctl.ip6m_addr = *dst;
- in6_recoverscope(&mtuctl.ip6m_addr, &mtuctl.ip6m_addr.sin6_addr, NULL);
+ if (sa6_recoverscope(&mtuctl.ip6m_addr))
+ return;
if ((m_mtu = sbcreatecontrol((caddr_t)&mtuctl, sizeof(mtuctl),
IPV6_PATHMTU, IPPROTO_IPV6)) == NULL)
OpenPOWER on IntegriCloud