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 2010 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
51static boolean_t
52ipsec_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 */
60boolean_t
61ipsec_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 */
96ipsa_t *
97ipsec_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		}
387next_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 */
509ipsa_t *
510ipsec_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
567boolean_t
568ipsec_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 */
658mblk_t *
659ipsec_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		/* Not fully baked; swap the packet under a rock until then */
749
750		mp = sadb_set_lpkt(assoc, mp, ira);
751		if (mp == NULL) {
752			IPSA_REFRELE(assoc);
753			return (NULL);
754		}
755		/* Looks like the SA is no longer LARVAL. */
756	}
757
758	/* Are the IPsec fields initialized at all? */
759	if (!(ira->ira_flags & IRAF_IPSEC_SECURE)) {
760		ira->ira_ipsec_action = NULL;
761		ira->ira_ipsec_ah_sa = NULL;
762		ira->ira_ipsec_esp_sa = NULL;
763	}
764
765	/*
766	 * Save a reference to the association so that it can
767	 * be retrieved after execution. We free any AH SA reference
768	 * already there (innermost SA "wins". The reference to
769	 * the SA will also be used later when doing the policy checks.
770	 */
771	if (ira->ira_ipsec_ah_sa != NULL) {
772		IPSA_REFRELE(ira->ira_ipsec_ah_sa);
773	}
774	ira->ira_flags |= IRAF_IPSEC_SECURE;
775	ira->ira_ipsec_ah_sa = assoc;
776
777	*ahp = ah;
778	return (mp);
779}
780
781/*
782 * Can return a pulled up mblk.
783 * When it returns non-NULL esphp is updated
784 */
785mblk_t *
786ipsec_inbound_esp_sa(mblk_t *data_mp, ip_recv_attr_t *ira, esph_t **esphp)
787{
788	mblk_t *placeholder;
789	uint32_t *src_ptr, *dst_ptr;
790	ipha_t *ipha;
791	ip6_t *ip6h;
792	esph_t *esph;
793	ipsa_t *ipsa;
794	isaf_t *bucket;
795	uint_t preamble;
796	sa_family_t af;
797	boolean_t isv6;
798	sadb_t *sp;
799	netstack_t	*ns = ira->ira_ill->ill_ipst->ips_netstack;
800	ipsec_stack_t	*ipss = ns->netstack_ipsec;
801	ipsecesp_stack_t *espstack = ns->netstack_ipsecesp;
802
803	IP_ESP_BUMP_STAT(ipss, in_requests);
804
805	isv6 = !(ira->ira_flags & IRAF_IS_IPV4);
806	if (isv6) {
807		ip6h = (ip6_t *)data_mp->b_rptr;
808	} else {
809		ipha = (ipha_t *)data_mp->b_rptr;
810	}
811
812	/*
813	 * Put all data into one mblk if it's not there already.
814	 * XXX This is probably bad long-term.  Figure out better ways of doing
815	 * this.  Much of the inbound path depends on all of the data being
816	 * in one mblk.
817	 *
818	 * XXX Jumbogram issues will have to be dealt with here.
819	 * If the plen is 0, we'll have to scan for a HBH header with the
820	 * actual packet length.
821	 */
822	if (data_mp->b_datap->db_ref > 1 ||
823	    (data_mp->b_wptr - data_mp->b_rptr) < ira->ira_pktlen) {
824		placeholder = msgpullup(data_mp, -1);
825		if (placeholder == NULL) {
826			IP_ESP_BUMP_STAT(ipss, in_discards);
827			ip_drop_packet(data_mp, B_TRUE, ira->ira_ill,
828			    DROPPER(ipss, ipds_esp_nomem),
829			    &ipss->ipsec_dropper);
830			return (NULL);
831		} else {
832			/* Reset packet with new pulled up mblk. */
833			freemsg(data_mp);
834			data_mp = placeholder;
835		}
836	}
837
838	/*
839	 * Find the ESP header, point the address pointers at the appropriate
840	 * IPv4/IPv6 places.
841	 */
842	if (isv6) {
843		ip6h = (ip6_t *)data_mp->b_rptr;
844		src_ptr = (uint32_t *)&ip6h->ip6_src;
845		dst_ptr = (uint32_t *)&ip6h->ip6_dst;
846		if (ip6h->ip6_nxt != IPPROTO_ESP) {
847			/* There are options that need to be processed. */
848			preamble = ip_hdr_length_v6(data_mp, ip6h);
849		} else {
850			preamble = sizeof (ip6_t);
851		}
852
853		sp = &espstack->esp_sadb.s_v6;
854		af = AF_INET6;
855	} else {
856		ipha = (ipha_t *)data_mp->b_rptr;
857		src_ptr = (uint32_t *)&ipha->ipha_src;
858		dst_ptr = (uint32_t *)&ipha->ipha_dst;
859		preamble = IPH_HDR_LENGTH(ipha);
860
861		sp = &espstack->esp_sadb.s_v4;
862		af = AF_INET;
863	}
864
865	esph = (esph_t *)(data_mp->b_rptr + preamble);
866
867	/* Since hash is common on inbound (SPI value), hash here. */
868	bucket = INBOUND_BUCKET(sp, esph->esph_spi);
869	mutex_enter(&bucket->isaf_lock);
870	ipsa = ipsec_getassocbyspi(bucket, esph->esph_spi, src_ptr, dst_ptr,
871	    af);
872	mutex_exit(&bucket->isaf_lock);
873
874	if (ipsa == NULL || ipsa->ipsa_state == IPSA_STATE_DEAD ||
875	    ipsa->ipsa_state == IPSA_STATE_ACTIVE_ELSEWHERE) {
876		/*  This is a loggable error!  AUDIT ME! */
877		IP_ESP_BUMP_STAT(ipss, lookup_failure);
878		IP_ESP_BUMP_STAT(ipss, in_discards);
879		ipsecesp_in_assocfailure(data_mp, 0,
880		    SL_ERROR | SL_CONSOLE | SL_WARN,
881		    "ipsec_inbound_esp_sa: No association found for "
882		    "spi 0x%x, dst addr %s\n",
883		    esph->esph_spi, dst_ptr, af, ira);
884		if (ipsa != NULL) {
885			IPSA_REFRELE(ipsa);
886		}
887		return (NULL);
888	}
889
890	if (ipsa->ipsa_state == IPSA_STATE_LARVAL) {
891		/* Not fully baked; swap the packet under a rock until then */
892
893		data_mp = sadb_set_lpkt(ipsa, data_mp, ira);
894		if (data_mp == NULL) {
895			IPSA_REFRELE(ipsa);
896			return (NULL);
897		}
898		/* Looks like the SA is no longer LARVAL. */
899	}
900
901	/* Are the IPsec fields initialized at all? */
902	if (!(ira->ira_flags & IRAF_IPSEC_SECURE)) {
903		ira->ira_ipsec_action = NULL;
904		ira->ira_ipsec_ah_sa = NULL;
905		ira->ira_ipsec_esp_sa = NULL;
906	}
907
908	/*
909	 * Save a reference to the association so that it can
910	 * be retrieved after execution. We free any AH SA reference
911	 * already there (innermost SA "wins". The reference to
912	 * the SA will also be used later when doing the policy checks.
913	 */
914	if (ira->ira_ipsec_esp_sa != NULL) {
915		IPSA_REFRELE(ira->ira_ipsec_esp_sa);
916	}
917	ira->ira_flags |= IRAF_IPSEC_SECURE;
918	ira->ira_ipsec_esp_sa = ipsa;
919
920	*esphp = esph;
921	return (data_mp);
922}
923