diff options
author | ae <ae@FreeBSD.org> | 2015-04-18 16:46:31 +0000 |
---|---|---|
committer | ae <ae@FreeBSD.org> | 2015-04-18 16:46:31 +0000 |
commit | 0e635affcb1c17159cb21d85b42dbd79cc5b2faf (patch) | |
tree | 0e5523427571594a2ab2b573e2c32b8ff11753f1 /sys/netipsec/ipsec_input.c | |
parent | 76eadbeca7623488eb5425c74644ec3e01a5ae50 (diff) | |
download | FreeBSD-src-0e635affcb1c17159cb21d85b42dbd79cc5b2faf.zip FreeBSD-src-0e635affcb1c17159cb21d85b42dbd79cc5b2faf.tar.gz |
Fix handling of scoped IPv6 addresses in IPSec code.
* in ipsec_encap() embed scope zone ids into link-local addresses
in the new IPv6 header, this helps ip6_output() disambiguate the
scope;
* teach key_ismyaddr6() use in6_localip(). in6_localip() is less
strict than key_sockaddrcmp(). It doesn't compare all fileds of
struct sockaddr_in6, but it is faster and it should be safe,
because all SA's data was checked for correctness. Also, since
IPv6 link-local addresses in the &V_in6_ifaddrhead are stored in
kernel-internal form, we need to embed scope zone id from SA into
the address before calling in6_localip.
* in ipsec_common_input() take scope zone id embedded in the address
and use it to initialize sin6_scope_id, then use this sockaddr
structure to lookup SA, because we keep addresses in the SADB without
embedded scope zone id.
Differential Revision: https://reviews.freebsd.org/D2304
Reviewed by: gnn
Sponsored by: Yandex LLC
Diffstat (limited to 'sys/netipsec/ipsec_input.c')
-rw-r--r-- | sys/netipsec/ipsec_input.c | 7 |
1 files changed, 7 insertions, 0 deletions
diff --git a/sys/netipsec/ipsec_input.c b/sys/netipsec/ipsec_input.c index 86cc5b5..1eac8db 100644 --- a/sys/netipsec/ipsec_input.c +++ b/sys/netipsec/ipsec_input.c @@ -195,6 +195,13 @@ ipsec_common_input(struct mbuf *m, int skip, int protoff, int af, int sproto) m_copydata(m, offsetof(struct ip6_hdr, ip6_dst), sizeof(struct in6_addr), (caddr_t) &dst_address.sin6.sin6_addr); + /* We keep addresses in SADB without embedded scope id */ + if (IN6_IS_SCOPE_LINKLOCAL(&dst_address.sin6.sin6_addr)) { + /* XXX: sa6_recoverscope() */ + dst_address.sin6.sin6_scope_id = + ntohs(dst_address.sin6.sin6_addr.s6_addr16[1]); + dst_address.sin6.sin6_addr.s6_addr16[1] = 0; + } break; #endif /* INET6 */ default: |