summaryrefslogtreecommitdiffstats
path: root/sys/netkey/key.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/netkey/key.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/netkey/key.c')
-rw-r--r--sys/netkey/key.c63
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,
OpenPOWER on IntegriCloud