Home | History | Annotate | Download | only in ip
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #include <sys/types.h>
     27 #include <sys/stream.h>
     28 #include <sys/strsubr.h>
     29 #include <sys/sunddi.h>
     30 #include <sys/ddi.h>
     31 #include <sys/strlog.h>
     32 
     33 #include <inet/common.h>
     34 #include <inet/mib2.h>
     35 #include <inet/ip.h>
     36 #include <inet/ip6.h>
     37 
     38 #include <net/pfkeyv2.h>
     39 #include <inet/sadb.h>
     40 #include <inet/ipsec_impl.h>
     41 #include <inet/ipdrop.h>
     42 #include <inet/ipsecesp.h>
     43 #include <inet/ipsecah.h>
     44 #include <sys/kstat.h>
     45 
     46 /*
     47  * Returns B_TRUE if the identities in the SA match the identities
     48  * in the "latch" structure.
     49  */
     50 
     51 static boolean_t
     52 ipsec_match_outbound_ids(ipsec_latch_t *ipl, ipsa_t *sa)
     53 {
     54 	ASSERT(ipl->ipl_ids_latched == B_TRUE);
     55 	return ipsid_equal(ipl->ipl_local_cid, sa->ipsa_src_cid) &&
     56 	    ipsid_equal(ipl->ipl_remote_cid, sa->ipsa_dst_cid);
     57 }
     58 
     59 /* l1 is packet label; l2 is SA label */
     60 boolean_t
     61 ipsec_label_match(ts_label_t *l1, ts_label_t *l2)
     62 {
     63 	if (!is_system_labeled())
     64 		return (B_TRUE);
     65 
     66 	/*
     67 	 * Check for NULL label.  Unlabeled SA (l2) always matches;
     68 	 * unlabeled user with labeled  SA always fails
     69 	 */
     70 	if (l2 == NULL)
     71 		return (B_TRUE);
     72 
     73 	if (l1 == NULL)
     74 		return (B_FALSE);
     75 
     76 	/* Simple IPsec MLS policy: labels must be equal */
     77 	/* In future will need bit in policy saying whether this is the case */
     78 
     79 	/*
     80 	 * label_equal() checks DOI and label contents.  We should be
     81 	 * good to go with this check.
     82 	 */
     83 	return (label_equal(l1, l2));
     84 }
     85 
     86 
     87 /*
     88  * Look up a security association based on the unique ID generated by IP and
     89  * transport or tunnel information, such as ports and upper-layer protocol,
     90  * and the inner and outer address(es).	 Used for uniqueness testing and
     91  * outbound packets.  The outer source address may be ignored.
     92  *
     93  * I expect an SA hash bucket, and that its per-bucket mutex is held.
     94  * The SA ptr I return will have its reference count incremented by one.
     95  */
     96 ipsa_t *
     97 ipsec_getassocbyconn(isaf_t *bucket, ip_xmit_attr_t *ixa, uint32_t *src,
     98     uint32_t *dst, sa_family_t af, uint8_t protocol, ts_label_t *tsl)
     99 {
    100 	ipsa_t *retval, *candidate;
    101 	ipsec_action_t *candact;
    102 	boolean_t need_unique;
    103 	boolean_t tunnel_mode = (ixa->ixa_flags & IXAF_IPSEC_TUNNEL);
    104 	uint64_t unique_id;
    105 	uint32_t old_flags, excludeflags;
    106 	ipsec_policy_t *pp = ixa->ixa_ipsec_policy;
    107 	ipsec_action_t *actlist = ixa->ixa_ipsec_action;
    108 	ipsec_action_t *act;
    109 	ipsec_latch_t *ipl = ixa->ixa_ipsec_latch;
    110 	ipsa_ref_t *ipr = NULL;
    111 	sa_family_t inaf = ixa->ixa_ipsec_inaf;
    112 	uint32_t *insrc = ixa->ixa_ipsec_insrc;
    113 	uint32_t *indst = ixa->ixa_ipsec_indst;
    114 	uint8_t insrcpfx = ixa->ixa_ipsec_insrcpfx;
    115 	uint8_t indstpfx = ixa->ixa_ipsec_indstpfx;
    116 
    117 	ASSERT(MUTEX_HELD(&bucket->isaf_lock));
    118 
    119 	/*
    120 	 * Caller must set ip_xmit_attr_t structure such that we know
    121 	 * whether this is tunnel mode or transport mode based on
    122 	 * IXAF_IPSEC_TUNNEL.  If this flag is set, we assume that
    123 	 * there are valid inner src and destination addresses to compare.
    124 	 */
    125 
    126 	/*
    127 	 * Fast path: do we have a latch structure, is it for this bucket,
    128 	 * and does the generation number match?  If so, refhold and return.
    129 	 */
    130 
    131 	if (ipl != NULL) {
    132 		ASSERT((protocol == IPPROTO_AH) || (protocol == IPPROTO_ESP));
    133 		ipr = &ixa->ixa_ipsec_ref[protocol - IPPROTO_ESP];
    134 
    135 		retval = ipr->ipsr_sa;
    136 
    137 		/*
    138 		 * NOTE: The isaf_gen check (incremented upon
    139 		 * sadb_unlinkassoc()) protects against retval being a freed
    140 		 * SA.  (We're exploiting short-circuit evaluation.)
    141 		 */
    142 		if ((bucket == ipr->ipsr_bucket) &&
    143 		    (bucket->isaf_gen == ipr->ipsr_gen) &&
    144 		    (retval->ipsa_state != IPSA_STATE_DEAD) &&
    145 		    !(retval->ipsa_flags & IPSA_F_CINVALID)) {
    146 			IPSA_REFHOLD(retval);
    147 			return (retval);
    148 		}
    149 	}
    150 
    151 	ASSERT((pp != NULL) || (actlist != NULL));
    152 	if (actlist == NULL)
    153 		actlist = pp->ipsp_act;
    154 	ASSERT(actlist != NULL);
    155 
    156 	need_unique = actlist->ipa_want_unique;
    157 	unique_id = SA_FORM_UNIQUE_ID(ixa);
    158 
    159 	/*
    160 	 * Precompute mask for SA flags comparison: If we need a
    161 	 * unique SA and an SA has already been used, or if the SA has
    162 	 * a unique value which doesn't match, we aren't interested in
    163 	 * the SA..
    164 	 */
    165 
    166 	excludeflags = IPSA_F_UNIQUE;
    167 	if (need_unique)
    168 		excludeflags |= IPSA_F_USED;
    169 
    170 	/*
    171 	 * Walk the hash bucket, matching on:
    172 	 *
    173 	 * - unique_id
    174 	 * - destination
    175 	 * - source
    176 	 * - algorithms
    177 	 * - inner dst
    178 	 * - inner src
    179 	 * - <MORE TBD>
    180 	 *
    181 	 * Make sure that wildcard sources are inserted at the end of the hash
    182 	 * bucket.
    183 	 *
    184 	 * DEFINITIONS:	A _shared_ SA is one with unique_id == 0 and USED.
    185 	 *		An _unused_ SA is one with unique_id == 0 and not USED.
    186 	 *		A _unique_ SA is one with unique_id != 0 and USED.
    187 	 *		An SA with unique_id != 0 and not USED never happens.
    188 	 */
    189 
    190 	candidate = NULL;
    191 
    192 	for (retval = bucket->isaf_ipsa; retval != NULL;
    193 	    retval = retval->ipsa_next) {
    194 		ASSERT((candidate == NULL) ||
    195 		    MUTEX_HELD(&candidate->ipsa_lock));
    196 
    197 		/*
    198 		 * Q: Should I lock this SA?
    199 		 * A: For now, yes.  I change and use too many fields in here
    200 		 *    (e.g. unique_id) that I may be racing with other threads.
    201 		 *    Also, the refcnt needs to be bumped up.
    202 		 */
    203 
    204 		mutex_enter(&retval->ipsa_lock);
    205 
    206 		/* My apologies for the use of goto instead of continue. */
    207 
    208 		/* Outer destination address */
    209 		if (!IPSA_ARE_ADDR_EQUAL(dst, retval->ipsa_dstaddr, af))
    210 			goto next_ipsa;	/* Destination mismatch. */
    211 
    212 		/* Outer source address */
    213 		if (!IPSA_ARE_ADDR_EQUAL(src, retval->ipsa_srcaddr, af) &&
    214 		    !IPSA_IS_ADDR_UNSPEC(retval->ipsa_srcaddr, af))
    215 			goto next_ipsa;	/* Specific source and not matched. */
    216 
    217 		if (tunnel_mode) {
    218 			/* Check tunnel mode */
    219 			if (!(retval->ipsa_flags & IPSA_F_TUNNEL))
    220 				goto next_ipsa; /* Not tunnel mode SA */
    221 
    222 			/* Inner destination address */
    223 			if (!IPSA_IS_ADDR_UNSPEC(retval->ipsa_innerdst, inaf)) {
    224 				if (!ip_addr_match((uint8_t *)indst,
    225 				    min(indstpfx, retval->ipsa_innerdstpfx),
    226 				    (in6_addr_t *)retval->ipsa_innerdst))
    227 					goto next_ipsa; /* not matched. */
    228 			}
    229 
    230 			/* Inner source address */
    231 			if (!IPSA_IS_ADDR_UNSPEC(retval->ipsa_innersrc, inaf)) {
    232 				if (!ip_addr_match((uint8_t *)insrc,
    233 				    min(insrcpfx, retval->ipsa_innersrcpfx),
    234 				    (in6_addr_t *)retval->ipsa_innersrc))
    235 					goto next_ipsa; /* not matched. */
    236 			}
    237 		} else {
    238 			/* Check transport mode */
    239 			if (retval->ipsa_flags & IPSA_F_TUNNEL)
    240 				goto next_ipsa; /* Not transport mode SA */
    241 
    242 			/*
    243 			 * TODO - If we ever do RFC 3884's dream of transport-
    244 			 * mode SAs with inner IP address selectors, we need
    245 			 * to put some code here.
    246 			 */
    247 		}
    248 
    249 		/*
    250 		 * XXX should be able to use cached/latched action
    251 		 * to dodge this loop
    252 		 */
    253 		for (act = actlist; act != NULL; act = act->ipa_next) {
    254 			ipsec_act_t *ap = &act->ipa_act;
    255 			if (ap->ipa_type != IPSEC_POLICY_APPLY)
    256 				continue;
    257 
    258 			/*
    259 			 * XXX ugly.  should be better way to do this test
    260 			 */
    261 			if (protocol == IPPROTO_AH) {
    262 				if (!(ap->ipa_apply.ipp_use_ah))
    263 					continue;
    264 				if (ap->ipa_apply.ipp_auth_alg !=
    265 				    retval->ipsa_auth_alg)
    266 					continue;
    267 				if (ap->ipa_apply.ipp_ah_minbits >
    268 				    retval->ipsa_authkeybits)
    269 					continue;
    270 			} else {
    271 				if (!(ap->ipa_apply.ipp_use_esp))
    272 					continue;
    273 
    274 				if ((ap->ipa_apply.ipp_encr_alg !=
    275 				    retval->ipsa_encr_alg))
    276 					continue;
    277 
    278 				if (ap->ipa_apply.ipp_espe_minbits >
    279 				    retval->ipsa_encrkeybits)
    280 					continue;
    281 
    282 				if (ap->ipa_apply.ipp_esp_auth_alg != 0) {
    283 					if (ap->ipa_apply.ipp_esp_auth_alg !=
    284 					    retval->ipsa_auth_alg)
    285 						continue;
    286 					if (ap->ipa_apply.ipp_espa_minbits >
    287 					    retval->ipsa_authkeybits)
    288 						continue;
    289 				}
    290 			}
    291 
    292 			/*
    293 			 * Check key mgmt proto, cookie
    294 			 */
    295 			if ((ap->ipa_apply.ipp_km_proto != 0) &&
    296 			    (retval->ipsa_kmp != 0) &&
    297 			    (ap->ipa_apply.ipp_km_proto != retval->ipsa_kmp))
    298 				continue;
    299 
    300 			if ((ap->ipa_apply.ipp_km_cookie != 0) &&
    301 			    (retval->ipsa_kmc != 0) &&
    302 			    (ap->ipa_apply.ipp_km_cookie != retval->ipsa_kmc))
    303 				continue;
    304 
    305 			break;
    306 		}
    307 		if (act == NULL)
    308 			goto next_ipsa;	/* nothing matched */
    309 
    310 		/*
    311 		 * Do identities match?
    312 		 */
    313 		if (ipl && ipl->ipl_ids_latched &&
    314 		    !ipsec_match_outbound_ids(ipl, retval))
    315 			goto next_ipsa;
    316 
    317 		/*
    318 		 * Do labels match?
    319 		 */
    320 		if (!ipsec_label_match(tsl, retval->ipsa_tsl))
    321 			goto next_ipsa;
    322 
    323 		/*
    324 		 * At this point, we know that we have at least a match on:
    325 		 *
    326 		 * - dest
    327 		 * - source (if source is specified, i.e. non-zeroes)
    328 		 * - inner dest (if specified)
    329 		 * - inner source (if specified)
    330 		 * - auth alg (if auth alg is specified, i.e. non-zero)
    331 		 * - encrypt. alg (if encrypt. alg is specified, i.e. non-zero)
    332 		 * and we know that the SA keylengths are appropriate.
    333 		 *
    334 		 * (Keep in mind known-src SAs are hit before zero-src SAs,
    335 		 * thanks to sadb_insertassoc().)
    336 		 * If we need a unique asssociation, optimally we have
    337 		 * ipsa_unique_id == unique_id, otherwise NOT USED
    338 		 * is held in reserve (stored in candidate).
    339 		 *
    340 		 * For those stored in candidate, take best-match (i.e. given
    341 		 * a choice, candidate should have non-zero ipsa_src).
    342 		 */
    343 
    344 		/*
    345 		 * If SA has a unique value which matches, we're all set...
    346 		 * "key management knows best"
    347 		 */
    348 		if ((retval->ipsa_flags & IPSA_F_UNIQUE) &&
    349 		    ((unique_id & retval->ipsa_unique_mask) ==
    350 		    retval->ipsa_unique_id))
    351 			break;
    352 
    353 		/*
    354 		 * If we need a unique SA and this SA has already been used,
    355 		 * or if the SA has a unique value which doesn't match,
    356 		 * this isn't for us.
    357 		 */
    358 
    359 		if (retval->ipsa_flags & excludeflags)
    360 			goto next_ipsa;
    361 
    362 
    363 		/*
    364 		 * I found a candidate..
    365 		 */
    366 		if (candidate == NULL) {
    367 			/*
    368 			 * and didn't already have one..
    369 			 */
    370 			candidate = retval;
    371 			candact = act;
    372 			continue;
    373 		} else {
    374 			/*
    375 			 * If candidate's source address is zero and
    376 			 * the current match (i.e. retval) address is
    377 			 * not zero, we have a better candidate..
    378 			 */
    379 			if (IPSA_IS_ADDR_UNSPEC(candidate->ipsa_srcaddr, af) &&
    380 			    !IPSA_IS_ADDR_UNSPEC(retval->ipsa_srcaddr, af)) {
    381 				mutex_exit(&candidate->ipsa_lock);
    382 				candidate = retval;
    383 				candact = act;
    384 				continue;
    385 			}
    386 		}
    387 next_ipsa:
    388 		mutex_exit(&retval->ipsa_lock);
    389 	}
    390 	ASSERT((retval == NULL) || MUTEX_HELD(&retval->ipsa_lock));
    391 	ASSERT((candidate == NULL) || MUTEX_HELD(&candidate->ipsa_lock));
    392 	ASSERT((retval == NULL) || (act != NULL));
    393 	ASSERT((candidate == NULL) || (candact != NULL));
    394 
    395 	/* Let caller react to a lookup failure when it gets NULL. */
    396 	if (retval == NULL && candidate == NULL)
    397 		return (NULL);
    398 
    399 	if (retval == NULL) {
    400 		ASSERT(MUTEX_HELD(&candidate->ipsa_lock));
    401 		retval = candidate;
    402 		act = candact;
    403 	} else if (candidate != NULL) {
    404 		mutex_exit(&candidate->ipsa_lock);
    405 	}
    406 	ASSERT(MUTEX_HELD(&retval->ipsa_lock));
    407 	ASSERT(act != NULL);
    408 
    409 	/*
    410 	 * Even though I hold the mutex, since the reference counter is an
    411 	 * atomic operation, I really have to use the IPSA_REFHOLD macro.
    412 	 */
    413 	IPSA_REFHOLD(retval);
    414 
    415 	/*
    416 	 * This association is no longer unused.
    417 	 */
    418 	old_flags = retval->ipsa_flags;
    419 	retval->ipsa_flags |= IPSA_F_USED;
    420 
    421 	/*
    422 	 * Cache a reference to this SA for the fast path.
    423 	 */
    424 	if (ipr != NULL) {
    425 		ipr->ipsr_bucket = bucket;
    426 		ipr->ipsr_gen = bucket->isaf_gen;
    427 		ipr->ipsr_sa = retval;
    428 		/* I'm now caching, so the cache-invalid flag goes away! */
    429 		retval->ipsa_flags &= ~IPSA_F_CINVALID;
    430 	}
    431 	/*
    432 	 * Latch various things while we're here..
    433 	 */
    434 	if (ipl != NULL) {
    435 		if (!ipl->ipl_ids_latched) {
    436 			ipsec_latch_ids(ipl,
    437 			    retval->ipsa_src_cid, retval->ipsa_dst_cid);
    438 		}
    439 		if (ixa->ixa_ipsec_action == NULL) {
    440 			IPACT_REFHOLD(act);
    441 			ixa->ixa_ipsec_action = act;
    442 		}
    443 	}
    444 
    445 	/*
    446 	 * Set the uniqueness only first time.
    447 	 */
    448 	if (need_unique && !(old_flags & IPSA_F_USED)) {
    449 		if (retval->ipsa_unique_id == 0) {
    450 			ASSERT((retval->ipsa_flags & IPSA_F_UNIQUE) == 0);
    451 			/*
    452 			 * From now on, only this src, dst[ports, addr],
    453 			 * proto, should use it.
    454 			 */
    455 			retval->ipsa_flags |= IPSA_F_UNIQUE;
    456 			retval->ipsa_unique_id = unique_id;
    457 			retval->ipsa_unique_mask = SA_UNIQUE_MASK(
    458 			    ixa->ixa_ipsec_src_port, ixa->ixa_ipsec_dst_port,
    459 			    protocol, 0);
    460 		}
    461 
    462 		/*
    463 		 * Set the source address and adjust the hash
    464 		 * buckets only if src_addr is zero.
    465 		 */
    466 		if (IPSA_IS_ADDR_UNSPEC(retval->ipsa_srcaddr, af)) {
    467 			/*
    468 			 * sadb_unlinkassoc() will decrement the refcnt.  Bump
    469 			 * up when we have the lock so that we don't have to
    470 			 * acquire locks when we come back from
    471 			 * sadb_insertassoc().
    472 			 *
    473 			 * We don't need to bump the bucket's gen since
    474 			 * we aren't moving to a new bucket.
    475 			 */
    476 			IPSA_REFHOLD(retval);
    477 			IPSA_COPY_ADDR(retval->ipsa_srcaddr, src, af);
    478 			mutex_exit(&retval->ipsa_lock);
    479 			sadb_unlinkassoc(retval);
    480 			/*
    481 			 * Since the bucket lock is held, we know
    482 			 * sadb_insertassoc() will succeed.
    483 			 */
    484 #ifdef DEBUG
    485 			if (sadb_insertassoc(retval, bucket) != 0) {
    486 				cmn_err(CE_PANIC,
    487 				    "sadb_insertassoc() failed in "
    488 				    "ipsec_getassocbyconn().\n");
    489 			}
    490 #else	/* non-DEBUG */
    491 			(void) sadb_insertassoc(retval, bucket);
    492 #endif	/* DEBUG */
    493 			return (retval);
    494 		}
    495 	}
    496 	mutex_exit(&retval->ipsa_lock);
    497 
    498 	return (retval);
    499 }
    500 
    501 /*
    502  * Look up a security association based on the security parameters index (SPI)
    503  * and address(es).  This is used for inbound packets and general SA lookups
    504  * (even in outbound SA tables).  The source address may be ignored.  Return
    505  * NULL if no association is available.	 If an SA is found, return it, with
    506  * its refcnt incremented.  The caller must REFRELE after using the SA.
    507  * The hash bucket must be locked down before calling.
    508  */
    509 ipsa_t *
    510 ipsec_getassocbyspi(isaf_t *bucket, uint32_t spi, uint32_t *src, uint32_t *dst,
    511     sa_family_t af)
    512 {
    513 	ipsa_t *retval;
    514 
    515 	ASSERT(MUTEX_HELD(&bucket->isaf_lock));
    516 
    517 	/*
    518 	 * Walk the hash bucket, matching exactly on SPI, then destination,
    519 	 * then source.
    520 	 *
    521 	 * Per-SA locking doesn't need to happen, because I'm only matching
    522 	 * on addresses.  Addresses are only changed during insertion/deletion
    523 	 * from the hash bucket.  Since the hash bucket lock is held, we don't
    524 	 * need to worry about addresses changing.
    525 	 */
    526 
    527 	for (retval = bucket->isaf_ipsa; retval != NULL;
    528 	    retval = retval->ipsa_next) {
    529 		if (retval->ipsa_spi != spi)
    530 			continue;
    531 		if (!IPSA_ARE_ADDR_EQUAL(dst, retval->ipsa_dstaddr, af))
    532 			continue;
    533 
    534 		/*
    535 		 * Assume that wildcard source addresses are inserted at the
    536 		 * end of the hash bucket.  (See sadb_insertassoc().)
    537 		 * The following check for source addresses is a weak form
    538 		 * of access control/source identity verification.  If an
    539 		 * SA has a source address, I only match an all-zeroes
    540 		 * source address, or that particular one.  If the SA has
    541 		 * an all-zeroes source, then I match regardless.
    542 		 *
    543 		 * There is a weakness here in that a packet with all-zeroes
    544 		 * for an address will match regardless of the source address
    545 		 * stored in the packet.
    546 		 *
    547 		 * Note that port-level packet selectors, if present,
    548 		 * are checked in ipsec_check_ipsecin_unique().
    549 		 */
    550 		if (IPSA_ARE_ADDR_EQUAL(src, retval->ipsa_srcaddr, af) ||
    551 		    IPSA_IS_ADDR_UNSPEC(retval->ipsa_srcaddr, af) ||
    552 		    IPSA_IS_ADDR_UNSPEC(src, af))
    553 			break;
    554 	}
    555 
    556 	if (retval != NULL) {
    557 		/*
    558 		 * Just refhold the return value.  The caller will then
    559 		 * make the appropriate calls to set the USED flag.
    560 		 */
    561 		IPSA_REFHOLD(retval);
    562 	}
    563 
    564 	return (retval);
    565 }
    566 
    567 boolean_t
    568 ipsec_outbound_sa(mblk_t *data_mp, ip_xmit_attr_t *ixa, uint_t proto)
    569 {
    570 	ipaddr_t dst;
    571 	uint32_t *dst_ptr, *src_ptr;
    572 	isaf_t *bucket;
    573 	ipsa_t *assoc;
    574 	ip_pkt_t ipp;
    575 	in6_addr_t dst6;
    576 	ipsa_t **sa;
    577 	sadbp_t *sadbp;
    578 	sadb_t *sp;
    579 	sa_family_t af;
    580 	ip_stack_t	*ipst = ixa->ixa_ipst;
    581 	netstack_t	*ns = ipst->ips_netstack;
    582 
    583 	ASSERT(ixa->ixa_flags & IXAF_IPSEC_SECURE);
    584 
    585 	if (proto == IPPROTO_ESP) {
    586 		ipsecesp_stack_t	*espstack;
    587 
    588 		espstack = ns->netstack_ipsecesp;
    589 		sa = &ixa->ixa_ipsec_esp_sa;
    590 		sadbp = &espstack->esp_sadb;
    591 	} else {
    592 		ipsecah_stack_t	*ahstack;
    593 
    594 		ASSERT(proto == IPPROTO_AH);
    595 		ahstack = ns->netstack_ipsecah;
    596 		sa = &ixa->ixa_ipsec_ah_sa;
    597 		sadbp = &ahstack->ah_sadb;
    598 	}
    599 
    600 	ASSERT(*sa == NULL);
    601 
    602 	if (ixa->ixa_flags & IXAF_IS_IPV4) {
    603 		ipha_t *ipha = (ipha_t *)data_mp->b_rptr;
    604 
    605 		ASSERT(IPH_HDR_VERSION(ipha) == IPV4_VERSION);
    606 		dst = ip_get_dst(ipha);
    607 		sp = &sadbp->s_v4;
    608 		af = AF_INET;
    609 
    610 		/*
    611 		 * NOTE:Getting the outbound association is considerably
    612 		 *	painful.  ipsec_getassocbyconn() will require more
    613 		 *	parameters as policy implementations mature.
    614 		 */
    615 		bucket = OUTBOUND_BUCKET_V4(sp, dst);
    616 		src_ptr = (uint32_t *)&ipha->ipha_src;
    617 		dst_ptr = (uint32_t *)&dst;
    618 	} else {
    619 		ip6_t *ip6h = (ip6_t *)data_mp->b_rptr;
    620 
    621 		ASSERT(IPH_HDR_VERSION(ip6h) == IPV6_VERSION);
    622 		dst6 = ip_get_dst_v6(ip6h, data_mp, NULL);
    623 		af = AF_INET6;
    624 
    625 		bzero(&ipp, sizeof (ipp));
    626 		sp = &sadbp->s_v6;
    627 
    628 		/* Same NOTE: applies here! */
    629 		bucket = OUTBOUND_BUCKET_V6(sp, dst6);
    630 		src_ptr = (uint32_t *)&ip6h->ip6_src;
    631 		dst_ptr = (uint32_t *)&dst6;
    632 	}
    633 
    634 	mutex_enter(&bucket->isaf_lock);
    635 	assoc = ipsec_getassocbyconn(bucket, ixa, src_ptr, dst_ptr, af,
    636 	    proto, ixa->ixa_tsl);
    637 	mutex_exit(&bucket->isaf_lock);
    638 
    639 	if (assoc == NULL)
    640 		return (B_FALSE);
    641 
    642 	if (assoc->ipsa_state == IPSA_STATE_DEAD) {
    643 		IPSA_REFRELE(assoc);
    644 		return (B_FALSE);
    645 	}
    646 
    647 	ASSERT(assoc->ipsa_state != IPSA_STATE_LARVAL);
    648 
    649 	*sa = assoc;
    650 	return (B_TRUE);
    651 }
    652 
    653 /*
    654  * Inbound IPsec SA selection.
    655  * Can return a pulled up mblk.
    656  * When it returns non-NULL ahp is updated
    657  */
    658 mblk_t *
    659 ipsec_inbound_ah_sa(mblk_t *mp, ip_recv_attr_t *ira, ah_t **ahp)
    660 {
    661 	ipha_t *ipha;
    662 	ipsa_t 	*assoc;
    663 	ah_t *ah;
    664 	isaf_t *hptr;
    665 	boolean_t isv6;
    666 	ip6_t *ip6h;
    667 	int ah_offset;
    668 	uint32_t *src_ptr, *dst_ptr;
    669 	int pullup_len;
    670 	sadb_t *sp;
    671 	sa_family_t af;
    672 	netstack_t	*ns = ira->ira_ill->ill_ipst->ips_netstack;
    673 	ipsec_stack_t	*ipss = ns->netstack_ipsec;
    674 	ipsecah_stack_t	*ahstack = ns->netstack_ipsecah;
    675 
    676 	IP_AH_BUMP_STAT(ipss, in_requests);
    677 
    678 	isv6 = !(ira->ira_flags & IRAF_IS_IPV4);
    679 	if (isv6) {
    680 		ip6h = (ip6_t *)mp->b_rptr;
    681 		ah_offset = ipsec_ah_get_hdr_size_v6(mp, B_TRUE);
    682 	} else {
    683 		ipha = (ipha_t *)mp->b_rptr;
    684 		ASSERT(ipha->ipha_protocol == IPPROTO_AH);
    685 		ah_offset = ipha->ipha_version_and_hdr_length -
    686 		    (uint8_t)((IP_VERSION << 4));
    687 		ah_offset <<= 2;
    688 	}
    689 
    690 	/*
    691 	 * We assume that the IP header is pulled up until
    692 	 * the options. We need to see whether we have the
    693 	 * AH header in the same mblk or not.
    694 	 */
    695 	pullup_len = ah_offset + sizeof (ah_t);
    696 	if (mp->b_rptr + pullup_len > mp->b_wptr) {
    697 		if (!pullupmsg(mp, pullup_len)) {
    698 			ipsec_rl_strlog(ns, ip_mod_info.mi_idnum, 0, 0,
    699 			    SL_WARN | SL_ERROR,
    700 			    "ipsec_inbound_ah_sa: Small AH header\n");
    701 			IP_AH_BUMP_STAT(ipss, in_discards);
    702 			ip_drop_packet(mp, B_TRUE, ira->ira_ill,
    703 			    DROPPER(ipss, ipds_ah_bad_length),
    704 			    &ipss->ipsec_dropper);
    705 			return (NULL);
    706 		}
    707 		if (isv6)
    708 			ip6h = (ip6_t *)mp->b_rptr;
    709 		else
    710 			ipha = (ipha_t *)mp->b_rptr;
    711 	}
    712 
    713 	ah = (ah_t *)(mp->b_rptr + ah_offset);
    714 
    715 	if (isv6) {
    716 		src_ptr = (uint32_t *)&ip6h->ip6_src;
    717 		dst_ptr = (uint32_t *)&ip6h->ip6_dst;
    718 		sp = &ahstack->ah_sadb.s_v6;
    719 		af = AF_INET6;
    720 	} else {
    721 		src_ptr = (uint32_t *)&ipha->ipha_src;
    722 		dst_ptr = (uint32_t *)&ipha->ipha_dst;
    723 		sp = &ahstack->ah_sadb.s_v4;
    724 		af = AF_INET;
    725 	}
    726 
    727 	hptr = INBOUND_BUCKET(sp, ah->ah_spi);
    728 	mutex_enter(&hptr->isaf_lock);
    729 	assoc = ipsec_getassocbyspi(hptr, ah->ah_spi, src_ptr, dst_ptr, af);
    730 	mutex_exit(&hptr->isaf_lock);
    731 
    732 	if (assoc == NULL || assoc->ipsa_state == IPSA_STATE_DEAD ||
    733 	    assoc->ipsa_state == IPSA_STATE_ACTIVE_ELSEWHERE) {
    734 		IP_AH_BUMP_STAT(ipss, lookup_failure);
    735 		IP_AH_BUMP_STAT(ipss, in_discards);
    736 		ipsecah_in_assocfailure(mp, 0,
    737 		    SL_ERROR | SL_CONSOLE | SL_WARN,
    738 		    "ipsec_inbound_ah_sa: No association found for "
    739 		    "spi 0x%x, dst addr %s\n",
    740 		    ah->ah_spi, dst_ptr, af, ira);
    741 		if (assoc != NULL) {
    742 			IPSA_REFRELE(assoc);
    743 		}
    744 		return (NULL);
    745 	}
    746 
    747 	if (assoc->ipsa_state == IPSA_STATE_LARVAL &&
    748 	    sadb_set_lpkt(assoc, mp, ira)) {
    749 		/* Not fully baked; swap the packet under a rock until then */
    750 		IPSA_REFRELE(assoc);
    751 		return (NULL);
    752 	}
    753 
    754 	/* Are the IPsec fields initialized at all? */
    755 	if (!(ira->ira_flags & IRAF_IPSEC_SECURE)) {
    756 		ira->ira_ipsec_action = NULL;
    757 		ira->ira_ipsec_ah_sa = NULL;
    758 		ira->ira_ipsec_esp_sa = NULL;
    759 	}
    760 
    761 	/*
    762 	 * Save a reference to the association so that it can
    763 	 * be retrieved after execution. We free any AH SA reference
    764 	 * already there (innermost SA "wins". The reference to
    765 	 * the SA will also be used later when doing the policy checks.
    766 	 */
    767 	if (ira->ira_ipsec_ah_sa != NULL) {
    768 		IPSA_REFRELE(ira->ira_ipsec_ah_sa);
    769 	}
    770 	ira->ira_flags |= IRAF_IPSEC_SECURE;
    771 	ira->ira_ipsec_ah_sa = assoc;
    772 
    773 	*ahp = ah;
    774 	return (mp);
    775 }
    776 
    777 /*
    778  * Can return a pulled up mblk.
    779  * When it returns non-NULL esphp is updated
    780  */
    781 mblk_t *
    782 ipsec_inbound_esp_sa(mblk_t *data_mp, ip_recv_attr_t *ira, esph_t **esphp)
    783 {
    784 	mblk_t *placeholder;
    785 	uint32_t *src_ptr, *dst_ptr;
    786 	ipha_t *ipha;
    787 	ip6_t *ip6h;
    788 	esph_t *esph;
    789 	ipsa_t *ipsa;
    790 	isaf_t *bucket;
    791 	uint_t preamble;
    792 	sa_family_t af;
    793 	boolean_t isv6;
    794 	sadb_t *sp;
    795 	netstack_t	*ns = ira->ira_ill->ill_ipst->ips_netstack;
    796 	ipsec_stack_t	*ipss = ns->netstack_ipsec;
    797 	ipsecesp_stack_t *espstack = ns->netstack_ipsecesp;
    798 
    799 	IP_ESP_BUMP_STAT(ipss, in_requests);
    800 
    801 	isv6 = !(ira->ira_flags & IRAF_IS_IPV4);
    802 	if (isv6) {
    803 		ip6h = (ip6_t *)data_mp->b_rptr;
    804 	} else {
    805 		ipha = (ipha_t *)data_mp->b_rptr;
    806 	}
    807 
    808 	/*
    809 	 * Put all data into one mblk if it's not there already.
    810 	 * XXX This is probably bad long-term.  Figure out better ways of doing
    811 	 * this.  Much of the inbound path depends on all of the data being
    812 	 * in one mblk.
    813 	 *
    814 	 * XXX Jumbogram issues will have to be dealt with here.
    815 	 * If the plen is 0, we'll have to scan for a HBH header with the
    816 	 * actual packet length.
    817 	 */
    818 	if (data_mp->b_datap->db_ref > 1 ||
    819 	    (data_mp->b_wptr - data_mp->b_rptr) < ira->ira_pktlen) {
    820 		placeholder = msgpullup(data_mp, -1);
    821 		if (placeholder == NULL) {
    822 			IP_ESP_BUMP_STAT(ipss, in_discards);
    823 			ip_drop_packet(data_mp, B_TRUE, ira->ira_ill,
    824 			    DROPPER(ipss, ipds_esp_nomem),
    825 			    &ipss->ipsec_dropper);
    826 			return (NULL);
    827 		} else {
    828 			/* Reset packet with new pulled up mblk. */
    829 			freemsg(data_mp);
    830 			data_mp = placeholder;
    831 		}
    832 	}
    833 
    834 	/*
    835 	 * Find the ESP header, point the address pointers at the appropriate
    836 	 * IPv4/IPv6 places.
    837 	 */
    838 	if (isv6) {
    839 		ip6h = (ip6_t *)data_mp->b_rptr;
    840 		src_ptr = (uint32_t *)&ip6h->ip6_src;
    841 		dst_ptr = (uint32_t *)&ip6h->ip6_dst;
    842 		if (ip6h->ip6_nxt != IPPROTO_ESP) {
    843 			/* There are options that need to be processed. */
    844 			preamble = ip_hdr_length_v6(data_mp, ip6h);
    845 		} else {
    846 			preamble = sizeof (ip6_t);
    847 		}
    848 
    849 		sp = &espstack->esp_sadb.s_v6;
    850 		af = AF_INET6;
    851 	} else {
    852 		ipha = (ipha_t *)data_mp->b_rptr;
    853 		src_ptr = (uint32_t *)&ipha->ipha_src;
    854 		dst_ptr = (uint32_t *)&ipha->ipha_dst;
    855 		preamble = IPH_HDR_LENGTH(ipha);
    856 
    857 		sp = &espstack->esp_sadb.s_v4;
    858 		af = AF_INET;
    859 	}
    860 
    861 	esph = (esph_t *)(data_mp->b_rptr + preamble);
    862 
    863 	/* Since hash is common on inbound (SPI value), hash here. */
    864 	bucket = INBOUND_BUCKET(sp, esph->esph_spi);
    865 	mutex_enter(&bucket->isaf_lock);
    866 	ipsa = ipsec_getassocbyspi(bucket, esph->esph_spi, src_ptr, dst_ptr,
    867 	    af);
    868 	mutex_exit(&bucket->isaf_lock);
    869 
    870 	if (ipsa == NULL || ipsa->ipsa_state == IPSA_STATE_DEAD ||
    871 	    ipsa->ipsa_state == IPSA_STATE_ACTIVE_ELSEWHERE) {
    872 		/*  This is a loggable error!  AUDIT ME! */
    873 		IP_ESP_BUMP_STAT(ipss, lookup_failure);
    874 		IP_ESP_BUMP_STAT(ipss, in_discards);
    875 		ipsecesp_in_assocfailure(data_mp, 0,
    876 		    SL_ERROR | SL_CONSOLE | SL_WARN,
    877 		    "ipsec_inbound_esp_sa: No association found for "
    878 		    "spi 0x%x, dst addr %s\n",
    879 		    esph->esph_spi, dst_ptr, af, ira);
    880 		if (ipsa != NULL) {
    881 			IPSA_REFRELE(ipsa);
    882 		}
    883 		return (NULL);
    884 	}
    885 
    886 	if (ipsa->ipsa_state == IPSA_STATE_LARVAL &&
    887 	    sadb_set_lpkt(ipsa, data_mp, ira)) {
    888 		/* Not fully baked; swap the packet under a rock until then */
    889 		IPSA_REFRELE(ipsa);
    890 		return (NULL);
    891 	}
    892 
    893 	/* Are the IPsec fields initialized at all? */
    894 	if (!(ira->ira_flags & IRAF_IPSEC_SECURE)) {
    895 		ira->ira_ipsec_action = NULL;
    896 		ira->ira_ipsec_ah_sa = NULL;
    897 		ira->ira_ipsec_esp_sa = NULL;
    898 	}
    899 
    900 	/*
    901 	 * Save a reference to the association so that it can
    902 	 * be retrieved after execution. We free any AH SA reference
    903 	 * already there (innermost SA "wins". The reference to
    904 	 * the SA will also be used later when doing the policy checks.
    905 	 */
    906 	if (ira->ira_ipsec_esp_sa != NULL) {
    907 		IPSA_REFRELE(ira->ira_ipsec_esp_sa);
    908 	}
    909 	ira->ira_flags |= IRAF_IPSEC_SECURE;
    910 	ira->ira_ipsec_esp_sa = ipsa;
    911 
    912 	*esphp = esph;
    913 	return (data_mp);
    914 }
    915