diff options
Diffstat (limited to 'usr/src/uts/common/inet/ip/ip_sadb.c')
-rw-r--r-- | usr/src/uts/common/inet/ip/ip_sadb.c | 62 |
1 files changed, 58 insertions, 4 deletions
diff --git a/usr/src/uts/common/inet/ip/ip_sadb.c b/usr/src/uts/common/inet/ip/ip_sadb.c index 7a7614159f..6a4f1cffb9 100644 --- a/usr/src/uts/common/inet/ip/ip_sadb.c +++ b/usr/src/uts/common/inet/ip/ip_sadb.c @@ -28,6 +28,7 @@ #include <sys/types.h> #include <sys/stream.h> #include <sys/sunddi.h> +#include <sys/ddi.h> #include <sys/strlog.h> #include <inet/common.h> @@ -100,9 +101,9 @@ ipsec_match_outbound_ids(ipsec_latch_t *ipl, ipsa_t *sa) /* * Look up a security association based on the unique ID generated by IP and - * transport information, such as ports and upper-layer protocol, and the - * address(es). Used for uniqueness testing and outbound packets. The - * source address may be ignored. + * transport or tunnel information, such as ports and upper-layer protocol, + * and the inner and outer address(es). Used for uniqueness testing and + * outbound packets. The outer source address may be ignored. * * I expect an SA hash bucket, and that its per-bucket mutex is held. * The SA ptr I return will have its reference count incremented by one. @@ -114,6 +115,7 @@ ipsec_getassocbyconn(isaf_t *bucket, ipsec_out_t *io, uint32_t *src, ipsa_t *retval, *candidate; ipsec_action_t *candact; boolean_t need_unique; + boolean_t tunnel_mode = io->ipsec_out_tunnel; uint64_t unique_id; uint32_t old_flags, excludeflags; ipsec_policy_t *pp = io->ipsec_out_policy; @@ -121,10 +123,22 @@ ipsec_getassocbyconn(isaf_t *bucket, ipsec_out_t *io, uint32_t *src, ipsec_action_t *act; ipsec_latch_t *ipl = io->ipsec_out_latch; ipsa_ref_t *ipr = NULL; + sa_family_t inaf = io->ipsec_out_inaf; + uint32_t *insrc = io->ipsec_out_insrc; + uint32_t *indst = io->ipsec_out_indst; + uint8_t insrcpfx = io->ipsec_out_insrcpfx; + uint8_t indstpfx = io->ipsec_out_indstpfx; ASSERT(MUTEX_HELD(&bucket->isaf_lock)); /* + * Caller must set ipsec_out_t structure such that we know + * whether this is tunnel mode or transport mode based on + * io->ipsec_out_tunnel. If this flag is set, we assume that + * there are valid inner src and destination addresses to compare. + */ + + /* * Fast path: do we have a latch structure, is it for this bucket, * and does the generation number match? If so, refhold and return. */ @@ -175,6 +189,8 @@ ipsec_getassocbyconn(isaf_t *bucket, ipsec_out_t *io, uint32_t *src, * - destination * - source * - algorithms + * - inner dst + * - inner src * - <MORE TBD> * * Make sure that wildcard sources are inserted at the end of the hash @@ -203,12 +219,48 @@ ipsec_getassocbyconn(isaf_t *bucket, ipsec_out_t *io, uint32_t *src, mutex_enter(&retval->ipsa_lock); /* My apologies for the use of goto instead of continue. */ + + /* Outer destination address */ if (!IPSA_ARE_ADDR_EQUAL(dst, retval->ipsa_dstaddr, af)) goto next_ipsa; /* Destination mismatch. */ + + /* Outer source address */ if (!IPSA_ARE_ADDR_EQUAL(src, retval->ipsa_srcaddr, af) && !IPSA_IS_ADDR_UNSPEC(retval->ipsa_srcaddr, af)) goto next_ipsa; /* Specific source and not matched. */ + if (tunnel_mode) { + /* Check tunnel mode */ + if (!(retval->ipsa_flags & IPSA_F_TUNNEL)) + goto next_ipsa; /* Not tunnel mode SA */ + + /* Inner destination address */ + if (!IPSA_IS_ADDR_UNSPEC(retval->ipsa_innerdst, inaf)) { + if (!ip_addr_match((uint8_t *)indst, + min(indstpfx, retval->ipsa_innerdstpfx), + (in6_addr_t *)retval->ipsa_innerdst)) + goto next_ipsa; /* not matched. */ + } + + /* Inner source address */ + if (!IPSA_IS_ADDR_UNSPEC(retval->ipsa_innersrc, inaf)) { + if (!ip_addr_match((uint8_t *)insrc, + min(insrcpfx, retval->ipsa_innersrcpfx), + (in6_addr_t *)retval->ipsa_innersrc)) + goto next_ipsa; /* not matched. */ + } + } else { + /* Check transport mode */ + if (retval->ipsa_flags & IPSA_F_TUNNEL) + goto next_ipsa; /* Not transport mode SA */ + + /* + * TODO - If we ever do RFC 3884's dream of transport- + * mode SAs with inner IP address selectors, we need + * to put some code here. + */ + } + /* * XXX should be able to use cached/latched action * to dodge this loop @@ -282,6 +334,8 @@ ipsec_getassocbyconn(isaf_t *bucket, ipsec_out_t *io, uint32_t *src, * * - dest * - source (if source is specified, i.e. non-zeroes) + * - inner dest (if specified) + * - inner source (if specified) * - auth alg (if auth alg is specified, i.e. non-zero) * - encrypt. alg (if encrypt. alg is specified, i.e. non-zero) * and we know that the SA keylengths are appropriate. @@ -412,7 +466,7 @@ next_ipsa: retval->ipsa_unique_id = unique_id; retval->ipsa_unique_mask = SA_UNIQUE_MASK( io->ipsec_out_src_port, io->ipsec_out_dst_port, - protocol); + protocol, 0); } /* |