svn commit: r281693 - head/sys/netipsec
Andrey V. Elsukov
ae at FreeBSD.org
Sat Apr 18 16:46:32 UTC 2015
Author: ae
Date: Sat Apr 18 16:46:31 2015
New Revision: 281693
URL: https://svnweb.freebsd.org/changeset/base/281693
Log:
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
Modified:
head/sys/netipsec/ipsec_input.c
head/sys/netipsec/ipsec_output.c
head/sys/netipsec/key.c
Modified: head/sys/netipsec/ipsec_input.c
==============================================================================
--- head/sys/netipsec/ipsec_input.c Sat Apr 18 16:38:45 2015 (r281692)
+++ head/sys/netipsec/ipsec_input.c Sat Apr 18 16:46:31 2015 (r281693)
@@ -195,6 +195,13 @@ ipsec_common_input(struct mbuf *m, int s
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:
Modified: head/sys/netipsec/ipsec_output.c
==============================================================================
--- head/sys/netipsec/ipsec_output.c Sat Apr 18 16:38:45 2015 (r281692)
+++ head/sys/netipsec/ipsec_output.c Sat Apr 18 16:46:31 2015 (r281693)
@@ -503,7 +503,14 @@ ipsec_encap(struct mbuf **mp, struct sec
ip6->ip6_hlim = V_ip6_defhlim;
ip6->ip6_nxt = proto;
ip6->ip6_dst = saidx->dst.sin6.sin6_addr;
+ /* For link-local address embed scope zone id */
+ if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
+ ip6->ip6_dst.s6_addr16[1] =
+ htons(saidx->dst.sin6.sin6_scope_id & 0xffff);
ip6->ip6_src = saidx->src.sin6.sin6_addr;
+ if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
+ ip6->ip6_src.s6_addr16[1] =
+ htons(saidx->src.sin6.sin6_scope_id & 0xffff);
ip6->ip6_plen = htons((*mp)->m_pkthdr.len - sizeof(*ip6));
ip_ecn_ingress(V_ip6_ipsec_ecn, &proto, &itos);
ip6->ip6_flow |= htonl((uint32_t)proto << 20);
Modified: head/sys/netipsec/key.c
==============================================================================
--- head/sys/netipsec/key.c Sat Apr 18 16:38:45 2015 (r281692)
+++ head/sys/netipsec/key.c Sat Apr 18 16:46:31 2015 (r281693)
@@ -3856,48 +3856,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
-
- 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 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();
+ struct in6_addr in6;
- /* loopback, just for safety */
- if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
- return 1;
+ if (!IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
+ return (in6_localip(&sin6->sin6_addr));
- 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*/
More information about the svn-src-head
mailing list