diff options
author | ume <ume@FreeBSD.org> | 2005-07-25 12:31:43 +0000 |
---|---|---|
committer | ume <ume@FreeBSD.org> | 2005-07-25 12:31:43 +0000 |
commit | da2cf62b280b8450d5f8e0d810e810cdcc59a8c0 (patch) | |
tree | 5a678f63b25976c30f74f3bad9edb6f708c52930 /sys/netkey | |
parent | 59bc7b0da19f008a39ee92249e92f8246f04394e (diff) | |
download | FreeBSD-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/netkey')
-rw-r--r-- | sys/netkey/key.c | 63 |
1 files changed, 35 insertions, 28 deletions
diff --git a/sys/netkey/key.c b/sys/netkey/key.c index 1a26c95..03cb075 100644 --- a/sys/netkey/key.c +++ b/sys/netkey/key.c @@ -69,6 +69,7 @@ __FBSDID("$FreeBSD$"); #include <netinet/ip6.h> #include <netinet6/in6_var.h> #include <netinet6/ip6_var.h> +#include <netinet6/scope6_var.h> #endif /* INET6 */ #ifdef INET @@ -955,6 +956,13 @@ key_allocsa(family, src, dst, proto, spi) arraysize = _ARRAYLEN(saorder_state_valid_prefer_new); } + bzero(&sin, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_len = sizeof(sin); + bzero(&sin6, sizeof(sin6)); + sin6.sin6_family = AF_INET6; + sin6.sin6_len = sizeof(sin6); + /* * searching SAD. * XXX: to be checked internal IP header somewhere. Also when @@ -991,27 +999,17 @@ key_allocsa(family, src, dst, proto, spi) /* check src address */ switch (family) { case AF_INET: - bzero(&sin, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_len = sizeof(sin); - bcopy(src, &sin.sin_addr, - sizeof(sin.sin_addr)); + bcopy(src, &sin.sin_addr, sizeof(sin.sin_addr)); if (key_sockaddrcmp((struct sockaddr*)&sin, (struct sockaddr *)&sav->sah->saidx.src, 0) != 0) continue; break; case AF_INET6: - bzero(&sin6, sizeof(sin6)); - sin6.sin6_family = AF_INET6; - sin6.sin6_len = sizeof(sin6); bcopy(src, &sin6.sin6_addr, sizeof(sin6.sin6_addr)); - if (IN6_IS_SCOPE_LINKLOCAL(&sin6.sin6_addr)) { - /* kame fake scopeid */ - sin6.sin6_scope_id = - ntohs(sin6.sin6_addr.s6_addr16[1]); - sin6.sin6_addr.s6_addr16[1] = 0; - } + sin6.sin6_scope_id = 0; + if (sa6_recoverscope(&sin6)) + continue; if (key_sockaddrcmp((struct sockaddr *)&sin6, (struct sockaddr *)&sav->sah->saidx.src, 0) != 0) continue; @@ -1027,27 +1025,17 @@ key_allocsa(family, src, dst, proto, spi) /* check dst address */ switch (family) { case AF_INET: - bzero(&sin, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_len = sizeof(sin); - bcopy(dst, &sin.sin_addr, - sizeof(sin.sin_addr)); + bcopy(dst, &sin.sin_addr, sizeof(sin.sin_addr)); if (key_sockaddrcmp((struct sockaddr*)&sin, (struct sockaddr *)&sav->sah->saidx.dst, 0) != 0) continue; break; case AF_INET6: - bzero(&sin6, sizeof(sin6)); - sin6.sin6_family = AF_INET6; - sin6.sin6_len = sizeof(sin6); bcopy(dst, &sin6.sin6_addr, sizeof(sin6.sin6_addr)); - if (IN6_IS_SCOPE_LINKLOCAL(&sin6.sin6_addr)) { - /* kame fake scopeid */ - sin6.sin6_scope_id = - ntohs(sin6.sin6_addr.s6_addr16[1]); - sin6.sin6_addr.s6_addr16[1] = 0; - } + sin6.sin6_scope_id = 0; + if (sa6_recoverscope(&sin6)) + continue; if (key_sockaddrcmp((struct sockaddr *)&sin6, (struct sockaddr *)&sav->sah->saidx.dst, 0) != 0) continue; @@ -3975,6 +3963,9 @@ key_ismyaddr6(sin6) struct in6_ifaddr *ia; struct in6_multi *in6m; + if (sa6_embedscope(sin6, 0) != 0) + return 0; + for (ia = in6_ifaddr; ia; ia = ia->ia_next) { if (key_sockaddrcmp((struct sockaddr *)&sin6, (struct sockaddr *)&ia->ia_addr, 0) == 0) @@ -6899,6 +6890,9 @@ key_parse(m, so) u_int orglen; int error; int target; +#ifdef INET6 + struct sockaddr_in6 *sin6; +#endif /* sanity check */ if (m == NULL || so == NULL) @@ -7087,6 +7081,19 @@ key_parse(m, so) error = EINVAL; goto senderror; } +#ifdef INET6 + /* + * Check validity of the scope zone ID of the + * addresses, and embed the zone ID into the address + * if necessary. + */ + sin6 = (struct sockaddr_in6 *)PFKEY_ADDR_SADDR(src0); + if ((error = sa6_embedscope(sin6, 0)) != 0) + goto senderror; + sin6 = (struct sockaddr_in6 *)PFKEY_ADDR_SADDR(dst0); + if ((error = sa6_embedscope(sin6, 0)) != 0) + goto senderror; +#endif break; default: ipseclog((LOG_DEBUG, |