diff options
author | Luiz Otavio O Souza <luiz@netgate.com> | 2015-09-15 15:22:37 -0500 |
---|---|---|
committer | Luiz Otavio O Souza <luiz@netgate.com> | 2015-10-20 12:01:14 -0500 |
commit | 16636d7a65a723c72f597d46931c31fdd4993205 (patch) | |
tree | 85eba7a9c22d8fa1366d1720a5d3cf434d36ac60 /sys/netipsec/key.c | |
parent | c3560c4520f486ebf25e8ca725a7f77c559cb589 (diff) | |
download | FreeBSD-src-16636d7a65a723c72f597d46931c31fdd4993205.zip FreeBSD-src-16636d7a65a723c72f597d46931c31fdd4993205.tar.gz |
MFC r281693:
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
TAG: IPSEC-HEAD
Issue: #4841
Diffstat (limited to 'sys/netipsec/key.c')
-rw-r--r-- | sys/netipsec/key.c | 43 |
1 files changed, 7 insertions, 36 deletions
diff --git a/sys/netipsec/key.c b/sys/netipsec/key.c index c19dd47..6ab3f64 100644 --- a/sys/netipsec/key.c +++ b/sys/netipsec/key.c @@ -3854,48 +3854,19 @@ key_ismyaddr(struct sockaddr *sa) * compare my own address for IPv6. * 1: ours * 0: other - * NOTE: derived ip6_input() in KAME. This is necessary to modify more. */ -#include <netinet6/in6_var.h> - static int key_ismyaddr6(struct sockaddr_in6 *sin6) { - struct in6_ifaddr *ia; -#if 0 - struct in6_multi *in6m; -#endif + struct in6_addr in6; - IN6_IFADDR_RLOCK(); - TAILQ_FOREACH(ia, &V_in6_ifaddrhead, ia_link) { - if (key_sockaddrcmp((struct sockaddr *)sin6, - (struct sockaddr *)&ia->ia_addr, 0) == 0) { - IN6_IFADDR_RUNLOCK(); - return 1; - } + if (!IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) + return (in6_localip(&sin6->sin6_addr)); -#if 0 - /* - * XXX Multicast - * XXX why do we care about multlicast here while we don't care - * about IPv4 multicast?? - * XXX scope - */ - in6m = NULL; - IN6_LOOKUP_MULTI(sin6->sin6_addr, ia->ia_ifp, in6m); - if (in6m) { - IN6_IFADDR_RUNLOCK(); - return 1; - } -#endif - } - IN6_IFADDR_RUNLOCK(); - - /* loopback, just for safety */ - if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr)) - return 1; - - return 0; + /* Convert address into kernel-internal form */ + in6 = sin6->sin6_addr; + in6.s6_addr16[1] = htons(sin6->sin6_scope_id & 0xffff); + return (in6_localip(&in6)); } #endif /*INET6*/ |