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