summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/inet/ip/ip_sadb.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/inet/ip/ip_sadb.c')
-rw-r--r--usr/src/uts/common/inet/ip/ip_sadb.c62
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);
}
/*