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   8704      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      0      stevel #include <sys/stropts.h>
     29   8778        Erik #include <sys/strsubr.h>
     30   6668     markfen #include <sys/errno.h>
     31      0      stevel #include <sys/ddi.h>
     32      0      stevel #include <sys/debug.h>
     33      0      stevel #include <sys/cmn_err.h>
     34      0      stevel #include <sys/stream.h>
     35      0      stevel #include <sys/strlog.h>
     36      0      stevel #include <sys/kmem.h>
     37      0      stevel #include <sys/sunddi.h>
     38      0      stevel #include <sys/tihdr.h>
     39      0      stevel #include <sys/atomic.h>
     40      0      stevel #include <sys/socket.h>
     41      0      stevel #include <sys/sysmacros.h>
     42      0      stevel #include <sys/crypto/common.h>
     43      0      stevel #include <sys/crypto/api.h>
     44      0      stevel #include <sys/zone.h>
     45      0      stevel #include <netinet/in.h>
     46      0      stevel #include <net/if.h>
     47      0      stevel #include <net/pfkeyv2.h>
     48  10824        Mark #include <net/pfpolicy.h>
     49      0      stevel #include <inet/common.h>
     50      0      stevel #include <netinet/ip6.h>
     51      0      stevel #include <inet/ip.h>
     52   3055      danmcd #include <inet/ip_ire.h>
     53      0      stevel #include <inet/ip6.h>
     54      0      stevel #include <inet/ipsec_info.h>
     55      0      stevel #include <inet/tcp.h>
     56      0      stevel #include <inet/sadb.h>
     57   3448    dh155122 #include <inet/ipsec_impl.h>
     58      0      stevel #include <inet/ipsecah.h>
     59      0      stevel #include <inet/ipsecesp.h>
     60      0      stevel #include <sys/random.h>
     61      0      stevel #include <sys/dlpi.h>
     62  10934  sommerfeld #include <sys/strsun.h>
     63  10934  sommerfeld #include <sys/strsubr.h>
     64      0      stevel #include <inet/ip_if.h>
     65      0      stevel #include <inet/ipdrop.h>
     66      0      stevel #include <inet/ipclassifier.h>
     67      0      stevel #include <inet/sctp_ip.h>
     68  10934  sommerfeld #include <sys/tsol/tnet.h>
     69      0      stevel 
     70      0      stevel /*
     71      0      stevel  * This source file contains Security Association Database (SADB) common
     72      0      stevel  * routines.  They are linked in with the AH module.  Since AH has no chance
     73      0      stevel  * of falling under export control, it was safe to link it in there.
     74      0      stevel  */
     75      0      stevel 
     76      0      stevel static mblk_t *sadb_extended_acquire(ipsec_selector_t *, ipsec_policy_t *,
     77  10934  sommerfeld     ipsec_action_t *, boolean_t, uint32_t, uint32_t, sadb_sens_t *,
     78  10934  sommerfeld     netstack_t *);
     79  11042        Erik static ipsa_t *sadb_torch_assoc(isaf_t *, ipsa_t *);
     80   3448    dh155122 static void sadb_destroy_acqlist(iacqf_t **, uint_t, boolean_t,
     81   3448    dh155122 			    netstack_t *);
     82   3448    dh155122 static void sadb_destroy(sadb_t *, netstack_t *);
     83   3055      danmcd static mblk_t *sadb_sa2msg(ipsa_t *, sadb_msg_t *);
     84  11042        Erik static ts_label_t *sadb_label_from_sens(sadb_sens_t *, uint64_t *);
     85  11042        Erik static sadb_sens_t *sadb_make_sens_ext(ts_label_t *tsl, int *len);
     86   3055      danmcd 
     87   3055      danmcd static time_t sadb_add_time(time_t, uint64_t);
     88   6668     markfen static void lifetime_fuzz(ipsa_t *);
     89   6668     markfen static void age_pair_peer_list(templist_t *, sadb_t *, boolean_t);
     90  10934  sommerfeld static int get_ipsa_pair(ipsa_query_t *, ipsap_t *, int *);
     91  10934  sommerfeld static void init_ipsa_pair(ipsap_t *);
     92  10934  sommerfeld static void destroy_ipsa_pair(ipsap_t *);
     93  10934  sommerfeld static int update_pairing(ipsap_t *, ipsa_query_t *, keysock_in_t *, int *);
     94   7749  Thejaswini static void ipsa_set_replay(ipsa_t *ipsa, uint32_t offset);
     95   7749  Thejaswini 
     96   1659     markfen /*
     97   1659     markfen  * ipsacq_maxpackets is defined here to make it tunable
     98   1659     markfen  * from /etc/system.
     99   1659     markfen  */
    100   1659     markfen extern uint64_t ipsacq_maxpackets;
    101   1659     markfen 
    102      0      stevel #define	SET_EXPIRE(sa, delta, exp) {				\
    103      0      stevel 	if (((sa)->ipsa_ ## delta) != 0) {				\
    104      0      stevel 		(sa)->ipsa_ ## exp = sadb_add_time((sa)->ipsa_addtime,	\
    105      0      stevel 			(sa)->ipsa_ ## delta);				\
    106      0      stevel 	}								\
    107      0      stevel }
    108      0      stevel 
    109      0      stevel #define	UPDATE_EXPIRE(sa, delta, exp) {					\
    110      0      stevel 	if (((sa)->ipsa_ ## delta) != 0) {				\
    111      0      stevel 		time_t tmp = sadb_add_time((sa)->ipsa_usetime,		\
    112      0      stevel 			(sa)->ipsa_ ## delta);				\
    113      0      stevel 		if (((sa)->ipsa_ ## exp) == 0)				\
    114      0      stevel 			(sa)->ipsa_ ## exp = tmp;			\
    115      0      stevel 		else							\
    116      0      stevel 			(sa)->ipsa_ ## exp = 				\
    117      0      stevel 			    MIN((sa)->ipsa_ ## exp, tmp); 		\
    118      0      stevel 	}								\
    119      0      stevel }
    120      0      stevel 
    121      0      stevel 
    122      0      stevel /* wrap the macro so we can pass it as a function pointer */
    123      0      stevel void
    124      0      stevel sadb_sa_refrele(void *target)
    125      0      stevel {
    126      0      stevel 	IPSA_REFRELE(((ipsa_t *)target));
    127      0      stevel }
    128      0      stevel 
    129      0      stevel /*
    130      0      stevel  * We presume that sizeof (long) == sizeof (time_t) and that time_t is
    131      0      stevel  * a signed type.
    132      0      stevel  */
    133      0      stevel #define	TIME_MAX LONG_MAX
    134      0      stevel 
    135      0      stevel /*
    136      0      stevel  * PF_KEY gives us lifetimes in uint64_t seconds.  We presume that
    137      0      stevel  * time_t is defined to be a signed type with the same range as
    138      0      stevel  * "long".  On ILP32 systems, we thus run the risk of wrapping around
    139      0      stevel  * at end of time, as well as "overwrapping" the clock back around
    140      0      stevel  * into a seemingly valid but incorrect future date earlier than the
    141      0      stevel  * desired expiration.
    142      0      stevel  *
    143      0      stevel  * In order to avoid odd behavior (either negative lifetimes or loss
    144      0      stevel  * of high order bits) when someone asks for bizarrely long SA
    145      0      stevel  * lifetimes, we do a saturating add for expire times.
    146      0      stevel  *
    147      0      stevel  * We presume that ILP32 systems will be past end of support life when
    148      0      stevel  * the 32-bit time_t overflows (a dangerous assumption, mind you..).
    149      0      stevel  *
    150      0      stevel  * On LP64, 2^64 seconds are about 5.8e11 years, at which point we
    151      0      stevel  * will hopefully have figured out clever ways to avoid the use of
    152      0      stevel  * fixed-sized integers in computation.
    153      0      stevel  */
    154      0      stevel static time_t
    155      0      stevel sadb_add_time(time_t base, uint64_t delta)
    156      0      stevel {
    157      0      stevel 	time_t sum;
    158      0      stevel 
    159      0      stevel 	/*
    160      0      stevel 	 * Clip delta to the maximum possible time_t value to
    161      0      stevel 	 * prevent "overwrapping" back into a shorter-than-desired
    162      0      stevel 	 * future time.
    163      0      stevel 	 */
    164      0      stevel 	if (delta > TIME_MAX)
    165      0      stevel 		delta = TIME_MAX;
    166      0      stevel 	/*
    167      0      stevel 	 * This sum may still overflow.
    168      0      stevel 	 */
    169      0      stevel 	sum = base + delta;
    170      0      stevel 
    171      0      stevel 	/*
    172      0      stevel 	 * .. so if the result is less than the base, we overflowed.
    173      0      stevel 	 */
    174      0      stevel 	if (sum < base)
    175      0      stevel 		sum = TIME_MAX;
    176      0      stevel 
    177      0      stevel 	return (sum);
    178      0      stevel }
    179      0      stevel 
    180      0      stevel /*
    181      0      stevel  * Callers of this function have already created a working security
    182      0      stevel  * association, and have found the appropriate table & hash chain.  All this
    183      0      stevel  * function does is check duplicates, and insert the SA.  The caller needs to
    184      0      stevel  * hold the hash bucket lock and increment the refcnt before insertion.
    185      0      stevel  *
    186      0      stevel  * Return 0 if success, EEXIST if collision.
    187      0      stevel  */
    188   4987      danmcd #define	SA_UNIQUE_MATCH(sa1, sa2) \
    189   4987      danmcd 	(((sa1)->ipsa_unique_id & (sa1)->ipsa_unique_mask) == \
    190   4987      danmcd 	((sa2)->ipsa_unique_id & (sa2)->ipsa_unique_mask))
    191   4987      danmcd 
    192      0      stevel int
    193      0      stevel sadb_insertassoc(ipsa_t *ipsa, isaf_t *bucket)
    194      0      stevel {
    195      0      stevel 	ipsa_t **ptpn = NULL;
    196      0      stevel 	ipsa_t *walker;
    197      0      stevel 	boolean_t unspecsrc;
    198      0      stevel 
    199      0      stevel 	ASSERT(MUTEX_HELD(&bucket->isaf_lock));
    200      0      stevel 
    201      0      stevel 	unspecsrc = IPSA_IS_ADDR_UNSPEC(ipsa->ipsa_srcaddr, ipsa->ipsa_addrfam);
    202      0      stevel 
    203      0      stevel 	walker = bucket->isaf_ipsa;
    204      0      stevel 	ASSERT(walker == NULL || ipsa->ipsa_addrfam == walker->ipsa_addrfam);
    205      0      stevel 
    206      0      stevel 	/*
    207      0      stevel 	 * Find insertion point (pointed to with **ptpn).  Insert at the head
    208      0      stevel 	 * of the list unless there's an unspecified source address, then
    209      0      stevel 	 * insert it after the last SA with a specified source address.
    210      0      stevel 	 *
    211      0      stevel 	 * BTW, you'll have to walk the whole chain, matching on {DST, SPI}
    212      0      stevel 	 * checking for collisions.
    213      0      stevel 	 */
    214      0      stevel 
    215      0      stevel 	while (walker != NULL) {
    216      0      stevel 		if (IPSA_ARE_ADDR_EQUAL(walker->ipsa_dstaddr,
    217      0      stevel 		    ipsa->ipsa_dstaddr, ipsa->ipsa_addrfam)) {
    218      0      stevel 			if (walker->ipsa_spi == ipsa->ipsa_spi)
    219      0      stevel 				return (EEXIST);
    220      0      stevel 
    221      0      stevel 			mutex_enter(&walker->ipsa_lock);
    222      0      stevel 			if (ipsa->ipsa_state == IPSA_STATE_MATURE &&
    223      0      stevel 			    (walker->ipsa_flags & IPSA_F_USED) &&
    224   4987      danmcd 			    SA_UNIQUE_MATCH(walker, ipsa)) {
    225      0      stevel 				walker->ipsa_flags |= IPSA_F_CINVALID;
    226      0      stevel 			}
    227      0      stevel 			mutex_exit(&walker->ipsa_lock);
    228      0      stevel 		}
    229      0      stevel 
    230      0      stevel 		if (ptpn == NULL && unspecsrc) {
    231      0      stevel 			if (IPSA_IS_ADDR_UNSPEC(walker->ipsa_srcaddr,
    232      0      stevel 			    walker->ipsa_addrfam))
    233      0      stevel 				ptpn = walker->ipsa_ptpn;
    234      0      stevel 			else if (walker->ipsa_next == NULL)
    235      0      stevel 				ptpn = &walker->ipsa_next;
    236      0      stevel 		}
    237      0      stevel 
    238      0      stevel 		walker = walker->ipsa_next;
    239      0      stevel 	}
    240      0      stevel 
    241      0      stevel 	if (ptpn == NULL)
    242      0      stevel 		ptpn = &bucket->isaf_ipsa;
    243      0      stevel 	ipsa->ipsa_next = *ptpn;
    244      0      stevel 	ipsa->ipsa_ptpn = ptpn;
    245      0      stevel 	if (ipsa->ipsa_next != NULL)
    246      0      stevel 		ipsa->ipsa_next->ipsa_ptpn = &ipsa->ipsa_next;
    247      0      stevel 	*ptpn = ipsa;
    248      0      stevel 	ipsa->ipsa_linklock = &bucket->isaf_lock;
    249      0      stevel 
    250      0      stevel 	return (0);
    251      0      stevel }
    252   4987      danmcd #undef SA_UNIQUE_MATCH
    253      0      stevel 
    254      0      stevel /*
    255      0      stevel  * Free a security association.  Its reference count is 0, which means
    256      0      stevel  * I must free it.  The SA must be unlocked and must not be linked into
    257      0      stevel  * any fanout list.
    258      0      stevel  */
    259      0      stevel static void
    260      0      stevel sadb_freeassoc(ipsa_t *ipsa)
    261      0      stevel {
    262   3448    dh155122 	ipsec_stack_t	*ipss = ipsa->ipsa_netstack->netstack_ipsec;
    263  11042        Erik 	mblk_t		*asyncmp, *mp;
    264   3448    dh155122 
    265   3448    dh155122 	ASSERT(ipss != NULL);
    266   7373  sommerfeld 	ASSERT(MUTEX_NOT_HELD(&ipsa->ipsa_lock));
    267      0      stevel 	ASSERT(ipsa->ipsa_refcnt == 0);
    268      0      stevel 	ASSERT(ipsa->ipsa_next == NULL);
    269      0      stevel 	ASSERT(ipsa->ipsa_ptpn == NULL);
    270      0      stevel 
    271  11042        Erik 
    272  11042        Erik 	asyncmp = sadb_clear_lpkt(ipsa);
    273  11042        Erik 	if (asyncmp != NULL) {
    274  11042        Erik 		mp = ip_recv_attr_free_mblk(asyncmp);
    275  11042        Erik 		ip_drop_packet(mp, B_TRUE, NULL,
    276  11042        Erik 		    DROPPER(ipss, ipds_sadb_inlarval_timeout),
    277  11042        Erik 		    &ipss->ipsec_sadb_dropper);
    278  11042        Erik 	}
    279   8185      danmcd 	mutex_enter(&ipsa->ipsa_lock);
    280  11042        Erik 
    281  11042        Erik 	if (ipsa->ipsa_tsl != NULL) {
    282  11042        Erik 		label_rele(ipsa->ipsa_tsl);
    283  11042        Erik 		ipsa->ipsa_tsl = NULL;
    284  11042        Erik 	}
    285  11042        Erik 
    286  11042        Erik 	if (ipsa->ipsa_otsl != NULL) {
    287  11042        Erik 		label_rele(ipsa->ipsa_otsl);
    288  11042        Erik 		ipsa->ipsa_otsl = NULL;
    289  10934  sommerfeld 	}
    290  10934  sommerfeld 
    291      0      stevel 	ipsec_destroy_ctx_tmpl(ipsa, IPSEC_ALG_AUTH);
    292      0      stevel 	ipsec_destroy_ctx_tmpl(ipsa, IPSEC_ALG_ENCR);
    293      0      stevel 	mutex_exit(&ipsa->ipsa_lock);
    294      0      stevel 
    295      0      stevel 	/* bzero() these fields for paranoia's sake. */
    296      0      stevel 	if (ipsa->ipsa_authkey != NULL) {
    297      0      stevel 		bzero(ipsa->ipsa_authkey, ipsa->ipsa_authkeylen);
    298      0      stevel 		kmem_free(ipsa->ipsa_authkey, ipsa->ipsa_authkeylen);
    299      0      stevel 	}
    300      0      stevel 	if (ipsa->ipsa_encrkey != NULL) {
    301      0      stevel 		bzero(ipsa->ipsa_encrkey, ipsa->ipsa_encrkeylen);
    302      0      stevel 		kmem_free(ipsa->ipsa_encrkey, ipsa->ipsa_encrkeylen);
    303      0      stevel 	}
    304  10824        Mark 	if (ipsa->ipsa_nonce_buf != NULL) {
    305  10824        Mark 		bzero(ipsa->ipsa_nonce_buf, sizeof (ipsec_nonce_t));
    306  10824        Mark 		kmem_free(ipsa->ipsa_nonce_buf, sizeof (ipsec_nonce_t));
    307  10824        Mark 	}
    308      0      stevel 	if (ipsa->ipsa_src_cid != NULL) {
    309      0      stevel 		IPSID_REFRELE(ipsa->ipsa_src_cid);
    310      0      stevel 	}
    311      0      stevel 	if (ipsa->ipsa_dst_cid != NULL) {
    312      0      stevel 		IPSID_REFRELE(ipsa->ipsa_dst_cid);
    313      0      stevel 	}
    314  10824        Mark 	if (ipsa->ipsa_emech.cm_param != NULL)
    315  10824        Mark 		kmem_free(ipsa->ipsa_emech.cm_param,
    316  10824        Mark 		    ipsa->ipsa_emech.cm_param_len);
    317      0      stevel 
    318      0      stevel 	mutex_destroy(&ipsa->ipsa_lock);
    319      0      stevel 	kmem_free(ipsa, sizeof (*ipsa));
    320      0      stevel }
    321      0      stevel 
    322      0      stevel /*
    323      0      stevel  * Unlink a security association from a hash bucket.  Assume the hash bucket
    324      0      stevel  * lock is held, but the association's lock is not.
    325      0      stevel  *
    326      0      stevel  * Note that we do not bump the bucket's generation number here because
    327      0      stevel  * we might not be making a visible change to the set of visible SA's.
    328      0      stevel  * All callers MUST bump the bucket's generation number before they unlock
    329      0      stevel  * the bucket if they use sadb_unlinkassoc to permanetly remove an SA which
    330      0      stevel  * was present in the bucket at the time it was locked.
    331      0      stevel  */
    332      0      stevel void
    333      0      stevel sadb_unlinkassoc(ipsa_t *ipsa)
    334      0      stevel {
    335      0      stevel 	ASSERT(ipsa->ipsa_linklock != NULL);
    336      0      stevel 	ASSERT(MUTEX_HELD(ipsa->ipsa_linklock));
    337      0      stevel 
    338      0      stevel 	/* These fields are protected by the link lock. */
    339      0      stevel 	*(ipsa->ipsa_ptpn) = ipsa->ipsa_next;
    340      0      stevel 	if (ipsa->ipsa_next != NULL) {
    341      0      stevel 		ipsa->ipsa_next->ipsa_ptpn = ipsa->ipsa_ptpn;
    342      0      stevel 		ipsa->ipsa_next = NULL;
    343      0      stevel 	}
    344      0      stevel 
    345      0      stevel 	ipsa->ipsa_ptpn = NULL;
    346      0      stevel 
    347      0      stevel 	/* This may destroy the SA. */
    348      0      stevel 	IPSA_REFRELE(ipsa);
    349      0      stevel }
    350      0      stevel 
    351   7749  Thejaswini void
    352   7749  Thejaswini sadb_delete_cluster(ipsa_t *assoc)
    353   7749  Thejaswini {
    354   7749  Thejaswini 	uint8_t protocol;
    355   7749  Thejaswini 
    356   7749  Thejaswini 	if (cl_inet_deletespi &&
    357   7749  Thejaswini 	    ((assoc->ipsa_state == IPSA_STATE_LARVAL) ||
    358   7749  Thejaswini 	    (assoc->ipsa_state == IPSA_STATE_MATURE))) {
    359   7749  Thejaswini 		protocol = (assoc->ipsa_type == SADB_SATYPE_AH) ?
    360   7749  Thejaswini 		    IPPROTO_AH : IPPROTO_ESP;
    361   8392     Huafeng 		cl_inet_deletespi(assoc->ipsa_netstack->netstack_stackid,
    362   8392     Huafeng 		    protocol, assoc->ipsa_spi, NULL);
    363   7749  Thejaswini 	}
    364   7749  Thejaswini }
    365   7749  Thejaswini 
    366      0      stevel /*
    367      0      stevel  * Create a larval security association with the specified SPI.	 All other
    368      0      stevel  * fields are zeroed.
    369      0      stevel  */
    370      0      stevel static ipsa_t *
    371   3448    dh155122 sadb_makelarvalassoc(uint32_t spi, uint32_t *src, uint32_t *dst, int addrfam,
    372   3448    dh155122     netstack_t *ns)
    373      0      stevel {
    374      0      stevel 	ipsa_t *newbie;
    375      0      stevel 
    376      0      stevel 	/*
    377      0      stevel 	 * Allocate...
    378      0      stevel 	 */
    379      0      stevel 
    380      0      stevel 	newbie = (ipsa_t *)kmem_zalloc(sizeof (ipsa_t), KM_NOSLEEP);
    381      0      stevel 	if (newbie == NULL) {
    382      0      stevel 		/* Can't make new larval SA. */
    383      0      stevel 		return (NULL);
    384      0      stevel 	}
    385      0      stevel 
    386      0      stevel 	/* Assigned requested SPI, assume caller does SPI allocation magic. */
    387      0      stevel 	newbie->ipsa_spi = spi;
    388   3448    dh155122 	newbie->ipsa_netstack = ns;	/* No netstack_hold */
    389      0      stevel 
    390      0      stevel 	/*
    391      0      stevel 	 * Copy addresses...
    392      0      stevel 	 */
    393      0      stevel 
    394      0      stevel 	IPSA_COPY_ADDR(newbie->ipsa_srcaddr, src, addrfam);
    395      0      stevel 	IPSA_COPY_ADDR(newbie->ipsa_dstaddr, dst, addrfam);
    396      0      stevel 
    397      0      stevel 	newbie->ipsa_addrfam = addrfam;
    398      0      stevel 
    399      0      stevel 	/*
    400      0      stevel 	 * Set common initialization values, including refcnt.
    401      0      stevel 	 */
    402      0      stevel 	mutex_init(&newbie->ipsa_lock, NULL, MUTEX_DEFAULT, NULL);
    403      0      stevel 	newbie->ipsa_state = IPSA_STATE_LARVAL;
    404      0      stevel 	newbie->ipsa_refcnt = 1;
    405      0      stevel 	newbie->ipsa_freefunc = sadb_freeassoc;
    406      0      stevel 
    407      0      stevel 	/*
    408      0      stevel 	 * There aren't a lot of other common initialization values, as
    409      0      stevel 	 * they are copied in from the PF_KEY message.
    410      0      stevel 	 */
    411      0      stevel 
    412      0      stevel 	return (newbie);
    413      0      stevel }
    414      0      stevel 
    415      0      stevel /*
    416      0      stevel  * Call me to initialize a security association fanout.
    417      0      stevel  */
    418    564    sommerfe static int
    419    564    sommerfe sadb_init_fanout(isaf_t **tablep, uint_t size, int kmflag)
    420      0      stevel {
    421      0      stevel 	isaf_t *table;
    422      0      stevel 	int i;
    423      0      stevel 
    424    564    sommerfe 	table = (isaf_t *)kmem_alloc(size * sizeof (*table), kmflag);
    425      0      stevel 	*tablep = table;
    426      0      stevel 
    427    564    sommerfe 	if (table == NULL)
    428    564    sommerfe 		return (ENOMEM);
    429    564    sommerfe 
    430    564    sommerfe 	for (i = 0; i < size; i++) {
    431      0      stevel 		mutex_init(&(table[i].isaf_lock), NULL, MUTEX_DEFAULT, NULL);
    432      0      stevel 		table[i].isaf_ipsa = NULL;
    433      0      stevel 		table[i].isaf_gen = 0;
    434      0      stevel 	}
    435    564    sommerfe 
    436    564    sommerfe 	return (0);
    437    564    sommerfe }
    438    564    sommerfe 
    439    564    sommerfe /*
    440    564    sommerfe  * Call me to initialize an acquire fanout
    441    564    sommerfe  */
    442    564    sommerfe static int
    443    564    sommerfe sadb_init_acfanout(iacqf_t **tablep, uint_t size, int kmflag)
    444      0      stevel {
    445      0      stevel 	iacqf_t *table;
    446      0      stevel 	int i;
    447      0      stevel 
    448    564    sommerfe 	table = (iacqf_t *)kmem_alloc(size * sizeof (*table), kmflag);
    449      0      stevel 	*tablep = table;
    450      0      stevel 
    451    564    sommerfe 	if (table == NULL)
    452    564    sommerfe 		return (ENOMEM);
    453    564    sommerfe 
    454    564    sommerfe 	for (i = 0; i < size; i++) {
    455      0      stevel 		mutex_init(&(table[i].iacqf_lock), NULL, MUTEX_DEFAULT, NULL);
    456      0      stevel 		table[i].iacqf_ipsacq = NULL;
    457      0      stevel 	}
    458    564    sommerfe 
    459    564    sommerfe 	return (0);
    460    564    sommerfe }
    461    564    sommerfe 
    462    564    sommerfe /*
    463    564    sommerfe  * Attempt to initialize an SADB instance.  On failure, return ENOMEM;
    464    564    sommerfe  * caller must clean up partial allocations.
    465    564    sommerfe  */
    466    564    sommerfe static int
    467    564    sommerfe sadb_init_trial(sadb_t *sp, uint_t size, int kmflag)
    468    564    sommerfe {
    469    564    sommerfe 	ASSERT(sp->sdb_of == NULL);
    470    564    sommerfe 	ASSERT(sp->sdb_if == NULL);
    471    564    sommerfe 	ASSERT(sp->sdb_acq == NULL);
    472    564    sommerfe 
    473    564    sommerfe 	sp->sdb_hashsize = size;
    474    564    sommerfe 	if (sadb_init_fanout(&sp->sdb_of, size, kmflag) != 0)
    475    564    sommerfe 		return (ENOMEM);
    476    564    sommerfe 	if (sadb_init_fanout(&sp->sdb_if, size, kmflag) != 0)
    477    564    sommerfe 		return (ENOMEM);
    478    564    sommerfe 	if (sadb_init_acfanout(&sp->sdb_acq, size, kmflag) != 0)
    479    564    sommerfe 		return (ENOMEM);
    480    564    sommerfe 
    481    564    sommerfe 	return (0);
    482    564    sommerfe }
    483    564    sommerfe 
    484    564    sommerfe /*
    485    564    sommerfe  * Call me to initialize an SADB instance; fall back to default size on failure.
    486    564    sommerfe  */
    487    564    sommerfe static void
    488   3448    dh155122 sadb_init(const char *name, sadb_t *sp, uint_t size, uint_t ver,
    489   3448    dh155122     netstack_t *ns)
    490    564    sommerfe {
    491    564    sommerfe 	ASSERT(sp->sdb_of == NULL);
    492    564    sommerfe 	ASSERT(sp->sdb_if == NULL);
    493    564    sommerfe 	ASSERT(sp->sdb_acq == NULL);
    494    564    sommerfe 
    495    564    sommerfe 	if (size < IPSEC_DEFAULT_HASH_SIZE)
    496    564    sommerfe 		size = IPSEC_DEFAULT_HASH_SIZE;
    497    564    sommerfe 
    498    564    sommerfe 	if (sadb_init_trial(sp, size, KM_NOSLEEP) != 0) {
    499    564    sommerfe 
    500    564    sommerfe 		cmn_err(CE_WARN,
    501    564    sommerfe 		    "Unable to allocate %u entry IPv%u %s SADB hash table",
    502    564    sommerfe 		    size, ver, name);
    503    564    sommerfe 
    504   3448    dh155122 		sadb_destroy(sp, ns);
    505    564    sommerfe 		size = IPSEC_DEFAULT_HASH_SIZE;
    506    564    sommerfe 		cmn_err(CE_WARN, "Falling back to %d entries", size);
    507    564    sommerfe 		(void) sadb_init_trial(sp, size, KM_SLEEP);
    508    564    sommerfe 	}
    509    564    sommerfe }
    510    564    sommerfe 
    511      0      stevel 
    512      0      stevel /*
    513      0      stevel  * Initialize an SADB-pair.
    514      0      stevel  */
    515      0      stevel void
    516   3448    dh155122 sadbp_init(const char *name, sadbp_t *sp, int type, int size, netstack_t *ns)
    517   3448    dh155122 {
    518   3448    dh155122 	sadb_init(name, &sp->s_v4, size, 4, ns);
    519   3448    dh155122 	sadb_init(name, &sp->s_v6, size, 6, ns);
    520      0      stevel 
    521      0      stevel 	sp->s_satype = type;
    522      0      stevel 
    523      0      stevel 	ASSERT((type == SADB_SATYPE_AH) || (type == SADB_SATYPE_ESP));
    524   3448    dh155122 	if (type == SADB_SATYPE_AH) {
    525   3448    dh155122 		ipsec_stack_t	*ipss = ns->netstack_ipsec;
    526   3448    dh155122 
    527   3448    dh155122 		ip_drop_register(&ipss->ipsec_sadb_dropper, "IPsec SADB");
    528   7110      danmcd 		sp->s_addflags = AH_ADD_SETTABLE_FLAGS;
    529   7110      danmcd 		sp->s_updateflags = AH_UPDATE_SETTABLE_FLAGS;
    530   7110      danmcd 	} else {
    531   7110      danmcd 		sp->s_addflags = ESP_ADD_SETTABLE_FLAGS;
    532   7110      danmcd 		sp->s_updateflags = ESP_UPDATE_SETTABLE_FLAGS;
    533   3448    dh155122 	}
    534      0      stevel }
    535      0      stevel 
    536      0      stevel /*
    537      0      stevel  * Deliver a single SADB_DUMP message representing a single SA.  This is
    538      0      stevel  * called many times by sadb_dump().
    539      0      stevel  *
    540      0      stevel  * If the return value of this is ENOBUFS (not the same as ENOMEM), then
    541      0      stevel  * the caller should take that as a hint that dupb() on the "original answer"
    542      0      stevel  * failed, and that perhaps the caller should try again with a copyb()ed
    543      0      stevel  * "original answer".
    544      0      stevel  */
    545      0      stevel static int
    546      0      stevel sadb_dump_deliver(queue_t *pfkey_q, mblk_t *original_answer, ipsa_t *ipsa,
    547      0      stevel     sadb_msg_t *samsg)
    548      0      stevel {
    549      0      stevel 	mblk_t *answer;
    550      0      stevel 
    551      0      stevel 	answer = dupb(original_answer);
    552      0      stevel 	if (answer == NULL)
    553      0      stevel 		return (ENOBUFS);
    554      0      stevel 	answer->b_cont = sadb_sa2msg(ipsa, samsg);
    555      0      stevel 	if (answer->b_cont == NULL) {
    556      0      stevel 		freeb(answer);
    557      0      stevel 		return (ENOMEM);
    558      0      stevel 	}
    559      0      stevel 
    560      0      stevel 	/* Just do a putnext, and let keysock deal with flow control. */
    561      0      stevel 	putnext(pfkey_q, answer);
    562      0      stevel 	return (0);
    563      0      stevel }
    564      0      stevel 
    565      0      stevel /*
    566      0      stevel  * Common function to allocate and prepare a keysock_out_t M_CTL message.
    567      0      stevel  */
    568      0      stevel mblk_t *
    569      0      stevel sadb_keysock_out(minor_t serial)
    570      0      stevel {
    571      0      stevel 	mblk_t *mp;
    572      0      stevel 	keysock_out_t *kso;
    573      0      stevel 
    574      0      stevel 	mp = allocb(sizeof (ipsec_info_t), BPRI_HI);
    575      0      stevel 	if (mp != NULL) {
    576      0      stevel 		mp->b_datap->db_type = M_CTL;
    577      0      stevel 		mp->b_wptr += sizeof (ipsec_info_t);
    578      0      stevel 		kso = (keysock_out_t *)mp->b_rptr;
    579      0      stevel 		kso->ks_out_type = KEYSOCK_OUT;
    580      0      stevel 		kso->ks_out_len = sizeof (*kso);
    581      0      stevel 		kso->ks_out_serial = serial;
    582      0      stevel 	}
    583      0      stevel 
    584      0      stevel 	return (mp);
    585      0      stevel }
    586      0      stevel 
    587      0      stevel /*
    588      0      stevel  * Perform an SADB_DUMP, spewing out every SA in an array of SA fanouts
    589      0      stevel  * to keysock.
    590      0      stevel  */
    591      0      stevel static int
    592      0      stevel sadb_dump_fanout(queue_t *pfkey_q, mblk_t *mp, minor_t serial, isaf_t *fanout,
    593   7749  Thejaswini     int num_entries, boolean_t do_peers, time_t active_time)
    594      0      stevel {
    595      0      stevel 	int i, error = 0;
    596      0      stevel 	mblk_t *original_answer;
    597      0      stevel 	ipsa_t *walker;
    598      0      stevel 	sadb_msg_t *samsg;
    599   7749  Thejaswini 	time_t	current;
    600      0      stevel 
    601      0      stevel 	/*
    602      0      stevel 	 * For each IPSA hash bucket do:
    603      0      stevel 	 *	- Hold the mutex
    604      0      stevel 	 *	- Walk each entry, doing an sadb_dump_deliver() on it.
    605      0      stevel 	 */
    606      0      stevel 	ASSERT(mp->b_cont != NULL);
    607      0      stevel 	samsg = (sadb_msg_t *)mp->b_cont->b_rptr;
    608      0      stevel 
    609      0      stevel 	original_answer = sadb_keysock_out(serial);
    610      0      stevel 	if (original_answer == NULL)
    611      0      stevel 		return (ENOMEM);
    612      0      stevel 
    613   7749  Thejaswini 	current = gethrestime_sec();
    614      0      stevel 	for (i = 0; i < num_entries; i++) {
    615      0      stevel 		mutex_enter(&fanout[i].isaf_lock);
    616      0      stevel 		for (walker = fanout[i].isaf_ipsa; walker != NULL;
    617      0      stevel 		    walker = walker->ipsa_next) {
    618      0      stevel 			if (!do_peers && walker->ipsa_haspeer)
    619   7749  Thejaswini 				continue;
    620   7749  Thejaswini 			if ((active_time != 0) &&
    621   7749  Thejaswini 			    ((current - walker->ipsa_lastuse) > active_time))
    622      0      stevel 				continue;
    623      0      stevel 			error = sadb_dump_deliver(pfkey_q, original_answer,
    624      0      stevel 			    walker, samsg);
    625      0      stevel 			if (error == ENOBUFS) {
    626      0      stevel 				mblk_t *new_original_answer;
    627      0      stevel 
    628      0      stevel 				/* Ran out of dupb's.  Try a copyb. */
    629      0      stevel 				new_original_answer = copyb(original_answer);
    630      0      stevel 				if (new_original_answer == NULL) {
    631      0      stevel 					error = ENOMEM;
    632      0      stevel 				} else {
    633      0      stevel 					freeb(original_answer);
    634      0      stevel 					original_answer = new_original_answer;
    635      0      stevel 					error = sadb_dump_deliver(pfkey_q,
    636      0      stevel 					    original_answer, walker, samsg);
    637      0      stevel 				}
    638      0      stevel 			}
    639      0      stevel 			if (error != 0)
    640      0      stevel 				break;	/* out of for loop. */
    641      0      stevel 		}
    642      0      stevel 		mutex_exit(&fanout[i].isaf_lock);
    643      0      stevel 		if (error != 0)
    644      0      stevel 			break;	/* out of for loop. */
    645      0      stevel 	}
    646      0      stevel 
    647      0      stevel 	freeb(original_answer);
    648      0      stevel 	return (error);
    649      0      stevel }
    650      0      stevel 
    651      0      stevel /*
    652      0      stevel  * Dump an entire SADB; outbound first, then inbound.
    653      0      stevel  */
    654      0      stevel 
    655      0      stevel int
    656   7749  Thejaswini sadb_dump(queue_t *pfkey_q, mblk_t *mp, keysock_in_t *ksi, sadb_t *sp)
    657      0      stevel {
    658      0      stevel 	int error;
    659   7749  Thejaswini 	time_t	active_time = 0;
    660   7749  Thejaswini 	sadb_x_edump_t	*edump =
    661   7749  Thejaswini 	    (sadb_x_edump_t *)ksi->ks_in_extv[SADB_X_EXT_EDUMP];
    662   7749  Thejaswini 
    663   7749  Thejaswini 	if (edump != NULL) {
    664   7749  Thejaswini 		active_time = edump->sadb_x_edump_timeout;
    665   7749  Thejaswini 	}
    666      0      stevel 
    667      0      stevel 	/* Dump outbound */
    668   7749  Thejaswini 	error = sadb_dump_fanout(pfkey_q, mp, ksi->ks_in_serial, sp->sdb_of,
    669   7749  Thejaswini 	    sp->sdb_hashsize, B_TRUE, active_time);
    670      0      stevel 	if (error)
    671      0      stevel 		return (error);
    672      0      stevel 
    673      0      stevel 	/* Dump inbound */
    674   7749  Thejaswini 	return sadb_dump_fanout(pfkey_q, mp, ksi->ks_in_serial, sp->sdb_if,
    675   7749  Thejaswini 	    sp->sdb_hashsize, B_FALSE, active_time);
    676      0      stevel }
    677      0      stevel 
    678      0      stevel /*
    679      0      stevel  * Generic sadb table walker.
    680      0      stevel  *
    681      0      stevel  * Call "walkfn" for each SA in each bucket in "table"; pass the
    682      0      stevel  * bucket, the entry and "cookie" to the callback function.
    683      0      stevel  * Take care to ensure that walkfn can delete the SA without screwing
    684      0      stevel  * up our traverse.
    685      0      stevel  *
    686      0      stevel  * The bucket is locked for the duration of the callback, both so that the
    687      0      stevel  * callback can just call sadb_unlinkassoc() when it wants to delete something,
    688      0      stevel  * and so that no new entries are added while we're walking the list.
    689      0      stevel  */
    690      0      stevel static void
    691      0      stevel sadb_walker(isaf_t *table, uint_t numentries,
    692      0      stevel     void (*walkfn)(isaf_t *head, ipsa_t *entry, void *cookie),
    693      0      stevel     void *cookie)
    694      0      stevel {
    695      0      stevel 	int i;
    696      0      stevel 	for (i = 0; i < numentries; i++) {
    697      0      stevel 		ipsa_t *entry, *next;
    698      0      stevel 
    699      0      stevel 		mutex_enter(&table[i].isaf_lock);
    700      0      stevel 
    701      0      stevel 		for (entry = table[i].isaf_ipsa; entry != NULL;
    702      0      stevel 		    entry = next) {
    703      0      stevel 			next = entry->ipsa_next;
    704      0      stevel 			(*walkfn)(&table[i], entry, cookie);
    705      0      stevel 		}
    706      0      stevel 		mutex_exit(&table[i].isaf_lock);
    707      0      stevel 	}
    708      0      stevel }
    709      0      stevel 
    710      0      stevel /*
    711      0      stevel  * Call me to free up a security association fanout.  Use the forever
    712      0      stevel  * variable to indicate freeing up the SAs (forever == B_FALSE, e.g.
    713      0      stevel  * an SADB_FLUSH message), or destroying everything (forever == B_TRUE,
    714      0      stevel  * when a module is unloaded).
    715      0      stevel  */
    716      0      stevel static void
    717   7749  Thejaswini sadb_destroyer(isaf_t **tablep, uint_t numentries, boolean_t forever,
    718   7749  Thejaswini     boolean_t inbound)
    719    564    sommerfe {
    720    564    sommerfe 	int i;
    721    564    sommerfe 	isaf_t *table = *tablep;
    722   7749  Thejaswini 	uint8_t protocol;
    723   8392     Huafeng 	ipsa_t *sa;
    724   8392     Huafeng 	netstackid_t sid;
    725    564    sommerfe 
    726    564    sommerfe 	if (table == NULL)
    727    564    sommerfe 		return;
    728      0      stevel 
    729      0      stevel 	for (i = 0; i < numentries; i++) {
    730      0      stevel 		mutex_enter(&table[i].isaf_lock);
    731   8392     Huafeng 		while ((sa = table[i].isaf_ipsa) != NULL) {
    732   7749  Thejaswini 			if (inbound && cl_inet_deletespi &&
    733   8392     Huafeng 			    (sa->ipsa_state != IPSA_STATE_ACTIVE_ELSEWHERE) &&
    734   8392     Huafeng 			    (sa->ipsa_state != IPSA_STATE_IDLE)) {
    735   8392     Huafeng 				protocol = (sa->ipsa_type == SADB_SATYPE_AH) ?
    736   8392     Huafeng 				    IPPROTO_AH : IPPROTO_ESP;
    737   8392     Huafeng 				sid = sa->ipsa_netstack->netstack_stackid;
    738   8392     Huafeng 				cl_inet_deletespi(sid, protocol, sa->ipsa_spi,
    739   8392     Huafeng 				    NULL);
    740   8392     Huafeng 			}
    741   8392     Huafeng 			sadb_unlinkassoc(sa);
    742   7749  Thejaswini 		}
    743      0      stevel 		table[i].isaf_gen++;
    744      0      stevel 		mutex_exit(&table[i].isaf_lock);
    745      0      stevel 		if (forever)
    746      0      stevel 			mutex_destroy(&(table[i].isaf_lock));
    747      0      stevel 	}
    748      0      stevel 
    749    564    sommerfe 	if (forever) {
    750    564    sommerfe 		*tablep = NULL;
    751      0      stevel 		kmem_free(table, numentries * sizeof (*table));
    752    564    sommerfe 	}
    753      0      stevel }
    754      0      stevel 
    755      0      stevel /*
    756      0      stevel  * Entry points to sadb_destroyer().
    757      0      stevel  */
    758      0      stevel static void
    759   3448    dh155122 sadb_flush(sadb_t *sp, netstack_t *ns)
    760      0      stevel {
    761      0      stevel 	/*
    762      0      stevel 	 * Flush out each bucket, one at a time.  Were it not for keysock's
    763      0      stevel 	 * enforcement, there would be a subtlety where I could add on the
    764      0      stevel 	 * heels of a flush.  With keysock's enforcement, however, this
    765      0      stevel 	 * makes ESP's job easy.
    766      0      stevel 	 */
    767   7749  Thejaswini 	sadb_destroyer(&sp->sdb_of, sp->sdb_hashsize, B_FALSE, B_FALSE);
    768   7749  Thejaswini 	sadb_destroyer(&sp->sdb_if, sp->sdb_hashsize, B_FALSE, B_TRUE);
    769      0      stevel 
    770      0      stevel 	/* For each acquire, destroy it; leave the bucket mutex alone. */
    771   3448    dh155122 	sadb_destroy_acqlist(&sp->sdb_acq, sp->sdb_hashsize, B_FALSE, ns);
    772   3448    dh155122 }
    773   3448    dh155122 
    774   3448    dh155122 static void
    775   3448    dh155122 sadb_destroy(sadb_t *sp, netstack_t *ns)
    776      0      stevel {
    777   7749  Thejaswini 	sadb_destroyer(&sp->sdb_of, sp->sdb_hashsize, B_TRUE, B_FALSE);
    778   7749  Thejaswini 	sadb_destroyer(&sp->sdb_if, sp->sdb_hashsize, B_TRUE, B_TRUE);
    779      0      stevel 
    780      0      stevel 	/* For each acquire, destroy it, including the bucket mutex. */
    781   3448    dh155122 	sadb_destroy_acqlist(&sp->sdb_acq, sp->sdb_hashsize, B_TRUE, ns);
    782    564    sommerfe 
    783    564    sommerfe 	ASSERT(sp->sdb_of == NULL);
    784    564    sommerfe 	ASSERT(sp->sdb_if == NULL);
    785    564    sommerfe 	ASSERT(sp->sdb_acq == NULL);
    786      0      stevel }
    787      0      stevel 
    788      0      stevel void
    789   3448    dh155122 sadbp_flush(sadbp_t *spp, netstack_t *ns)
    790   3448    dh155122 {
    791   3448    dh155122 	sadb_flush(&spp->s_v4, ns);
    792   3448    dh155122 	sadb_flush(&spp->s_v6, ns);
    793      0      stevel }
    794      0      stevel 
    795      0      stevel void
    796   3448    dh155122 sadbp_destroy(sadbp_t *spp, netstack_t *ns)
    797   3448    dh155122 {
    798   3448    dh155122 	sadb_destroy(&spp->s_v4, ns);
    799   3448    dh155122 	sadb_destroy(&spp->s_v6, ns);
    800      0      stevel 
    801   3448    dh155122 	if (spp->s_satype == SADB_SATYPE_AH) {
    802   3448    dh155122 		ipsec_stack_t	*ipss = ns->netstack_ipsec;
    803   3448    dh155122 
    804   3448    dh155122 		ip_drop_unregister(&ipss->ipsec_sadb_dropper);
    805   3448    dh155122 	}
    806      0      stevel }
    807      0      stevel 
    808      0      stevel 
    809      0      stevel /*
    810      0      stevel  * Check hard vs. soft lifetimes.  If there's a reality mismatch (e.g.
    811      0      stevel  * soft lifetimes > hard lifetimes) return an appropriate diagnostic for
    812      0      stevel  * EINVAL.
    813      0      stevel  */
    814      0      stevel int
    815   7749  Thejaswini sadb_hardsoftchk(sadb_lifetime_t *hard, sadb_lifetime_t *soft,
    816   7749  Thejaswini     sadb_lifetime_t *idle)
    817      0      stevel {
    818      0      stevel 	if (hard == NULL || soft == NULL)
    819      0      stevel 		return (0);
    820      0      stevel 
    821      0      stevel 	if (hard->sadb_lifetime_allocations != 0 &&
    822      0      stevel 	    soft->sadb_lifetime_allocations != 0 &&
    823      0      stevel 	    hard->sadb_lifetime_allocations < soft->sadb_lifetime_allocations)
    824      0      stevel 		return (SADB_X_DIAGNOSTIC_ALLOC_HSERR);
    825      0      stevel 
    826      0      stevel 	if (hard->sadb_lifetime_bytes != 0 &&
    827      0      stevel 	    soft->sadb_lifetime_bytes != 0 &&
    828      0      stevel 	    hard->sadb_lifetime_bytes < soft->sadb_lifetime_bytes)
    829      0      stevel 		return (SADB_X_DIAGNOSTIC_BYTES_HSERR);
    830      0      stevel 
    831      0      stevel 	if (hard->sadb_lifetime_addtime != 0 &&
    832      0      stevel 	    soft->sadb_lifetime_addtime != 0 &&
    833      0      stevel 	    hard->sadb_lifetime_addtime < soft->sadb_lifetime_addtime)
    834      0      stevel 		return (SADB_X_DIAGNOSTIC_ADDTIME_HSERR);
    835      0      stevel 
    836      0      stevel 	if (hard->sadb_lifetime_usetime != 0 &&
    837      0      stevel 	    soft->sadb_lifetime_usetime != 0 &&
    838      0      stevel 	    hard->sadb_lifetime_usetime < soft->sadb_lifetime_usetime)
    839      0      stevel 		return (SADB_X_DIAGNOSTIC_USETIME_HSERR);
    840   7749  Thejaswini 
    841   7749  Thejaswini 	if (idle != NULL) {
    842   7749  Thejaswini 		if (hard->sadb_lifetime_addtime != 0 &&
    843   7749  Thejaswini 		    idle->sadb_lifetime_addtime != 0 &&
    844   7749  Thejaswini 		    hard->sadb_lifetime_addtime < idle->sadb_lifetime_addtime)
    845   7749  Thejaswini 			return (SADB_X_DIAGNOSTIC_ADDTIME_HSERR);
    846   7749  Thejaswini 
    847   7749  Thejaswini 		if (soft->sadb_lifetime_addtime != 0 &&
    848   7749  Thejaswini 		    idle->sadb_lifetime_addtime != 0 &&
    849   7749  Thejaswini 		    soft->sadb_lifetime_addtime < idle->sadb_lifetime_addtime)
    850   7749  Thejaswini 			return (SADB_X_DIAGNOSTIC_ADDTIME_HSERR);
    851   7749  Thejaswini 
    852   7749  Thejaswini 		if (hard->sadb_lifetime_usetime != 0 &&
    853   7749  Thejaswini 		    idle->sadb_lifetime_usetime != 0 &&
    854   7749  Thejaswini 		    hard->sadb_lifetime_usetime < idle->sadb_lifetime_usetime)
    855   7749  Thejaswini 			return (SADB_X_DIAGNOSTIC_USETIME_HSERR);
    856   7749  Thejaswini 
    857   7749  Thejaswini 		if (soft->sadb_lifetime_usetime != 0 &&
    858   7749  Thejaswini 		    idle->sadb_lifetime_usetime != 0 &&
    859   7749  Thejaswini 		    soft->sadb_lifetime_usetime < idle->sadb_lifetime_usetime)
    860   7749  Thejaswini 			return (SADB_X_DIAGNOSTIC_USETIME_HSERR);
    861   7749  Thejaswini 	}
    862      0      stevel 
    863      0      stevel 	return (0);
    864      0      stevel }
    865      0      stevel 
    866      0      stevel /*
    867  10934  sommerfeld  * Sanity check sensitivity labels.
    868  10934  sommerfeld  *
    869  10934  sommerfeld  * For now, just reject labels on unlabeled systems.
    870  10934  sommerfeld  */
    871  10934  sommerfeld int
    872  10934  sommerfeld sadb_labelchk(keysock_in_t *ksi)
    873  10934  sommerfeld {
    874  10934  sommerfeld 	if (!is_system_labeled()) {
    875  10934  sommerfeld 		if (ksi->ks_in_extv[SADB_EXT_SENSITIVITY] != NULL)
    876  10934  sommerfeld 			return (SADB_X_DIAGNOSTIC_BAD_LABEL);
    877  10934  sommerfeld 
    878  10934  sommerfeld 		if (ksi->ks_in_extv[SADB_X_EXT_OUTER_SENS] != NULL)
    879  10934  sommerfeld 			return (SADB_X_DIAGNOSTIC_BAD_LABEL);
    880  10934  sommerfeld 	}
    881  10934  sommerfeld 
    882  10934  sommerfeld 	return (0);
    883  10934  sommerfeld }
    884  10934  sommerfeld 
    885  10934  sommerfeld /*
    886      0      stevel  * Clone a security association for the purposes of inserting a single SA
    887   6668     markfen  * into inbound and outbound tables respectively. This function should only
    888   6668     markfen  * be called from sadb_common_add().
    889      0      stevel  */
    890      0      stevel static ipsa_t *
    891      0      stevel sadb_cloneassoc(ipsa_t *ipsa)
    892      0      stevel {
    893      0      stevel 	ipsa_t *newbie;
    894      0      stevel 	boolean_t error = B_FALSE;
    895      0      stevel 
    896   7373  sommerfeld 	ASSERT(MUTEX_NOT_HELD(&(ipsa->ipsa_lock)));
    897      0      stevel 
    898      0      stevel 	newbie = kmem_alloc(sizeof (ipsa_t), KM_NOSLEEP);
    899      0      stevel 	if (newbie == NULL)
    900      0      stevel 		return (NULL);
    901      0      stevel 
    902      0      stevel 	/* Copy over what we can. */
    903      0      stevel 	*newbie = *ipsa;
    904      0      stevel 
    905      0      stevel 	/* bzero and initialize locks, in case *_init() allocates... */
    906      0      stevel 	mutex_init(&newbie->ipsa_lock, NULL, MUTEX_DEFAULT, NULL);
    907  10934  sommerfeld 
    908  11042        Erik 	if (newbie->ipsa_tsl != NULL)
    909  11042        Erik 		label_hold(newbie->ipsa_tsl);
    910  11042        Erik 
    911  11042        Erik 	if (newbie->ipsa_otsl != NULL)
    912  11042        Erik 		label_hold(newbie->ipsa_otsl);
    913      0      stevel 
    914      0      stevel 	/*
    915      0      stevel 	 * While somewhat dain-bramaged, the most graceful way to
    916      0      stevel 	 * recover from errors is to keep plowing through the
    917      0      stevel 	 * allocations, and getting what I can.  It's easier to call
    918      0      stevel 	 * sadb_freeassoc() on the stillborn clone when all the
    919      0      stevel 	 * pointers aren't pointing to the parent's data.
    920      0      stevel 	 */
    921      0      stevel 
    922      0      stevel 	if (ipsa->ipsa_authkey != NULL) {
    923      0      stevel 		newbie->ipsa_authkey = kmem_alloc(newbie->ipsa_authkeylen,
    924      0      stevel 		    KM_NOSLEEP);
    925      0      stevel 		if (newbie->ipsa_authkey == NULL) {
    926      0      stevel 			error = B_TRUE;
    927      0      stevel 		} else {
    928      0      stevel 			bcopy(ipsa->ipsa_authkey, newbie->ipsa_authkey,
    929      0      stevel 			    newbie->ipsa_authkeylen);
    930      0      stevel 
    931      0      stevel 			newbie->ipsa_kcfauthkey.ck_data =
    932      0      stevel 			    newbie->ipsa_authkey;
    933      0      stevel 		}
    934      0      stevel 
    935      0      stevel 		if (newbie->ipsa_amech.cm_param != NULL) {
    936      0      stevel 			newbie->ipsa_amech.cm_param =
    937      0      stevel 			    (char *)&newbie->ipsa_mac_len;
    938      0      stevel 		}
    939      0      stevel 	}
    940      0      stevel 
    941      0      stevel 	if (ipsa->ipsa_encrkey != NULL) {
    942      0      stevel 		newbie->ipsa_encrkey = kmem_alloc(newbie->ipsa_encrkeylen,
    943      0      stevel 		    KM_NOSLEEP);
    944      0      stevel 		if (newbie->ipsa_encrkey == NULL) {
    945      0      stevel 			error = B_TRUE;
    946      0      stevel 		} else {
    947      0      stevel 			bcopy(ipsa->ipsa_encrkey, newbie->ipsa_encrkey,
    948      0      stevel 			    newbie->ipsa_encrkeylen);
    949      0      stevel 
    950      0      stevel 			newbie->ipsa_kcfencrkey.ck_data =
    951      0      stevel 			    newbie->ipsa_encrkey;
    952      0      stevel 		}
    953      0      stevel 	}
    954      0      stevel 
    955      0      stevel 	newbie->ipsa_authtmpl = NULL;
    956      0      stevel 	newbie->ipsa_encrtmpl = NULL;
    957   6668     markfen 	newbie->ipsa_haspeer = B_TRUE;
    958      0      stevel 
    959      0      stevel 	if (ipsa->ipsa_src_cid != NULL) {
    960      0      stevel 		newbie->ipsa_src_cid = ipsa->ipsa_src_cid;
    961      0      stevel 		IPSID_REFHOLD(ipsa->ipsa_src_cid);
    962      0      stevel 	}
    963      0      stevel 
    964      0      stevel 	if (ipsa->ipsa_dst_cid != NULL) {
    965      0      stevel 		newbie->ipsa_dst_cid = ipsa->ipsa_dst_cid;
    966      0      stevel 		IPSID_REFHOLD(ipsa->ipsa_dst_cid);
    967      0      stevel 	}
    968      0      stevel 
    969      0      stevel 	if (error) {
    970      0      stevel 		sadb_freeassoc(newbie);
    971      0      stevel 		return (NULL);
    972      0      stevel 	}
    973      0      stevel 
    974      0      stevel 	return (newbie);
    975      0      stevel }
    976      0      stevel 
    977      0      stevel /*
    978      0      stevel  * Initialize a SADB address extension at the address specified by addrext.
    979      0      stevel  * Return a pointer to the end of the new address extension.
    980      0      stevel  */
    981      0      stevel static uint8_t *
    982      0      stevel sadb_make_addr_ext(uint8_t *start, uint8_t *end, uint16_t exttype,
    983   3055      danmcd     sa_family_t af, uint32_t *addr, uint16_t port, uint8_t proto, int prefix)
    984      0      stevel {
    985      0      stevel 	struct sockaddr_in *sin;
    986      0      stevel 	struct sockaddr_in6 *sin6;
    987      0      stevel 	uint8_t *cur = start;
    988      0      stevel 	int addrext_len;
    989      0      stevel 	int sin_len;
    990      0      stevel 	sadb_address_t *addrext	= (sadb_address_t *)cur;
    991      0      stevel 
    992      0      stevel 	if (cur == NULL)
    993      0      stevel 		return (NULL);
    994      0      stevel 
    995      0      stevel 	cur += sizeof (*addrext);
    996      0      stevel 	if (cur > end)
    997      0      stevel 		return (NULL);
    998      0      stevel 
    999      0      stevel 	addrext->sadb_address_proto = proto;
   1000   3055      danmcd 	addrext->sadb_address_prefixlen = prefix;
   1001      0      stevel 	addrext->sadb_address_reserved = 0;
   1002      0      stevel 	addrext->sadb_address_exttype = exttype;
   1003      0      stevel 
   1004      0      stevel 	switch (af) {
   1005      0      stevel 	case AF_INET:
   1006      0      stevel 		sin = (struct sockaddr_in *)cur;
   1007      0      stevel 		sin_len = sizeof (*sin);
   1008      0      stevel 		cur += sin_len;
   1009      0      stevel 		if (cur > end)
   1010      0      stevel 			return (NULL);
   1011      0      stevel 
   1012      0      stevel 		sin->sin_family = af;
   1013      0      stevel 		bzero(sin->sin_zero, sizeof (sin->sin_zero));
   1014      0      stevel 		sin->sin_port = port;
   1015      0      stevel 		IPSA_COPY_ADDR(&sin->sin_addr, addr, af);
   1016      0      stevel 		break;
   1017      0      stevel 	case AF_INET6:
   1018      0      stevel 		sin6 = (struct sockaddr_in6 *)cur;
   1019      0      stevel 		sin_len = sizeof (*sin6);
   1020      0      stevel 		cur += sin_len;
   1021      0      stevel 		if (cur > end)
   1022      0      stevel 			return (NULL);
   1023      0      stevel 
   1024      0      stevel 		bzero(sin6, sizeof (*sin6));
   1025      0      stevel 		sin6->sin6_family = af;
   1026      0      stevel 		sin6->sin6_port = port;
   1027      0      stevel 		IPSA_COPY_ADDR(&sin6->sin6_addr, addr, af);
   1028      0      stevel 		break;
   1029      0      stevel 	}
   1030      0      stevel 
   1031      0      stevel 	addrext_len = roundup(cur - start, sizeof (uint64_t));
   1032      0      stevel 	addrext->sadb_address_len = SADB_8TO64(addrext_len);
   1033      0      stevel 
   1034      0      stevel 	cur = start + addrext_len;
   1035      0      stevel 	if (cur > end)
   1036      0      stevel 		cur = NULL;
   1037      0      stevel 
   1038      0      stevel 	return (cur);
   1039      0      stevel }
   1040      0      stevel 
   1041      0      stevel /*
   1042      0      stevel  * Construct a key management cookie extension.
   1043      0      stevel  */
   1044      0      stevel 
   1045      0      stevel static uint8_t *
   1046      0      stevel sadb_make_kmc_ext(uint8_t *cur, uint8_t *end, uint32_t kmp, uint32_t kmc)
   1047      0      stevel {
   1048      0      stevel 	sadb_x_kmc_t *kmcext = (sadb_x_kmc_t *)cur;
   1049      0      stevel 
   1050      0      stevel 	if (cur == NULL)
   1051      0      stevel 		return (NULL);
   1052      0      stevel 
   1053      0      stevel 	cur += sizeof (*kmcext);
   1054      0      stevel 
   1055      0      stevel 	if (cur > end)
   1056      0      stevel 		return (NULL);
   1057      0      stevel 
   1058      0      stevel 	kmcext->sadb_x_kmc_len = SADB_8TO64(sizeof (*kmcext));
   1059      0      stevel 	kmcext->sadb_x_kmc_exttype = SADB_X_EXT_KM_COOKIE;
   1060      0      stevel 	kmcext->sadb_x_kmc_proto = kmp;
   1061      0      stevel 	kmcext->sadb_x_kmc_cookie = kmc;
   1062      0      stevel 	kmcext->sadb_x_kmc_reserved = 0;
   1063      0      stevel 
   1064      0      stevel 	return (cur);
   1065      0      stevel }
   1066      0      stevel 
   1067      0      stevel /*
   1068      0      stevel  * Given an original message header with sufficient space following it, and an
   1069      0      stevel  * SA, construct a full PF_KEY message with all of the relevant extensions.
   1070      0      stevel  * This is mostly used for SADB_GET, and SADB_DUMP.
   1071      0      stevel  */
   1072   3055      danmcd static mblk_t *
   1073      0      stevel sadb_sa2msg(ipsa_t *ipsa, sadb_msg_t *samsg)
   1074      0      stevel {
   1075      0      stevel 	int alloclen, addrsize, paddrsize, authsize, encrsize;
   1076  10934  sommerfeld 	int srcidsize, dstidsize, senslen, osenslen;
   1077      0      stevel 	sa_family_t fam, pfam;	/* Address family for SADB_EXT_ADDRESS */
   1078      0      stevel 				/* src/dst and proxy sockaddrs. */
   1079      0      stevel 	/*
   1080      0      stevel 	 * The following are pointers into the PF_KEY message this PF_KEY
   1081      0      stevel 	 * message creates.
   1082      0      stevel 	 */
   1083      0      stevel 	sadb_msg_t *newsamsg;
   1084      0      stevel 	sadb_sa_t *assoc;
   1085      0      stevel 	sadb_lifetime_t *lt;
   1086      0      stevel 	sadb_key_t *key;
   1087      0      stevel 	sadb_ident_t *ident;
   1088      0      stevel 	sadb_sens_t *sens;
   1089      0      stevel 	sadb_ext_t *walker;	/* For when we need a generic ext. pointer. */
   1090   7749  Thejaswini 	sadb_x_replay_ctr_t *repl_ctr;
   1091   6668     markfen 	sadb_x_pair_t *pair_ext;
   1092   6668     markfen 
   1093      0      stevel 	mblk_t *mp;
   1094      0      stevel 	uint8_t *cur, *end;
   1095      0      stevel 	/* These indicate the presence of the above extension fields. */
   1096  10934  sommerfeld 	boolean_t soft = B_FALSE, hard = B_FALSE;
   1097  10934  sommerfeld 	boolean_t isrc = B_FALSE, idst = B_FALSE;
   1098  10934  sommerfeld 	boolean_t auth = B_FALSE, encr = B_FALSE;
   1099  10934  sommerfeld 	boolean_t sensinteg = B_FALSE, osensinteg = B_FALSE;
   1100  10934  sommerfeld 	boolean_t srcid = B_FALSE, dstid = B_FALSE;
   1101   7749  Thejaswini 	boolean_t idle;
   1102   6668     markfen 	boolean_t paired;
   1103   6668     markfen 	uint32_t otherspi;
   1104      0      stevel 
   1105      0      stevel 	/* First off, figure out the allocation length for this message. */
   1106      0      stevel 	/*
   1107      0      stevel 	 * Constant stuff.  This includes base, SA, address (src, dst),
   1108      0      stevel 	 * and lifetime (current).
   1109      0      stevel 	 */
   1110      0      stevel 	alloclen = sizeof (sadb_msg_t) + sizeof (sadb_sa_t) +
   1111      0      stevel 	    sizeof (sadb_lifetime_t);
   1112      0      stevel 
   1113      0      stevel 	fam = ipsa->ipsa_addrfam;
   1114      0      stevel 	switch (fam) {
   1115      0      stevel 	case AF_INET:
   1116      0      stevel 		addrsize = roundup(sizeof (struct sockaddr_in) +
   1117      0      stevel 		    sizeof (sadb_address_t), sizeof (uint64_t));
   1118      0      stevel 		break;
   1119      0      stevel 	case AF_INET6:
   1120      0      stevel 		addrsize = roundup(sizeof (struct sockaddr_in6) +
   1121      0      stevel 		    sizeof (sadb_address_t), sizeof (uint64_t));
   1122      0      stevel 		break;
   1123      0      stevel 	default:
   1124      0      stevel 		return (NULL);
   1125      0      stevel 	}
   1126      0      stevel 	/*
   1127      0      stevel 	 * Allocate TWO address extensions, for source and destination.
   1128      0      stevel 	 * (Thus, the * 2.)
   1129      0      stevel 	 */
   1130      0      stevel 	alloclen += addrsize * 2;
   1131      0      stevel 	if (ipsa->ipsa_flags & IPSA_F_NATT_REM)
   1132   4987      danmcd 		alloclen += addrsize;
   1133      0      stevel 	if (ipsa->ipsa_flags & IPSA_F_NATT_LOC)
   1134   4987      danmcd 		alloclen += addrsize;
   1135      0      stevel 
   1136   6668     markfen 	if (ipsa->ipsa_flags & IPSA_F_PAIRED) {
   1137   6668     markfen 		paired = B_TRUE;
   1138   6668     markfen 		alloclen += sizeof (sadb_x_pair_t);
   1139   6668     markfen 		otherspi = ipsa->ipsa_otherspi;
   1140   6668     markfen 	} else {
   1141   6668     markfen 		paired = B_FALSE;
   1142   6668     markfen 	}
   1143      0      stevel 
   1144      0      stevel 	/* How 'bout other lifetimes? */
   1145      0      stevel 	if (ipsa->ipsa_softaddlt != 0 || ipsa->ipsa_softuselt != 0 ||
   1146      0      stevel 	    ipsa->ipsa_softbyteslt != 0 || ipsa->ipsa_softalloc != 0) {
   1147      0      stevel 		alloclen += sizeof (sadb_lifetime_t);
   1148      0      stevel 		soft = B_TRUE;
   1149      0      stevel 	}
   1150      0      stevel 
   1151      0      stevel 	if (ipsa->ipsa_hardaddlt != 0 || ipsa->ipsa_harduselt != 0 ||
   1152      0      stevel 	    ipsa->ipsa_hardbyteslt != 0 || ipsa->ipsa_hardalloc != 0) {
   1153      0      stevel 		alloclen += sizeof (sadb_lifetime_t);
   1154      0      stevel 		hard = B_TRUE;
   1155   7749  Thejaswini 	}
   1156   7749  Thejaswini 
   1157   7749  Thejaswini 	if (ipsa->ipsa_idleaddlt != 0 || ipsa->ipsa_idleuselt != 0) {
   1158   7749  Thejaswini 		alloclen += sizeof (sadb_lifetime_t);
   1159   7749  Thejaswini 		idle = B_TRUE;
   1160   7749  Thejaswini 	} else {
   1161   7749  Thejaswini 		idle = B_FALSE;
   1162      0      stevel 	}
   1163      0      stevel 
   1164   3055      danmcd 	/* Inner addresses. */
   1165  10934  sommerfeld 	if (ipsa->ipsa_innerfam != 0) {
   1166   3055      danmcd 		pfam = ipsa->ipsa_innerfam;
   1167      0      stevel 		switch (pfam) {
   1168      0      stevel 		case AF_INET6:
   1169      0      stevel 			paddrsize = roundup(sizeof (struct sockaddr_in6) +
   1170      0      stevel 			    sizeof (sadb_address_t), sizeof (uint64_t));
   1171      0      stevel 			break;
   1172      0      stevel 		case AF_INET:
   1173      0      stevel 			paddrsize = roundup(sizeof (struct sockaddr_in) +
   1174      0      stevel 			    sizeof (sadb_address_t), sizeof (uint64_t));
   1175      0      stevel 			break;
   1176      0      stevel 		default:
   1177      0      stevel 			cmn_err(CE_PANIC,
   1178      0      stevel 			    "IPsec SADB: Proxy length failure.\n");
   1179      0      stevel 			break;
   1180      0      stevel 		}
   1181   3055      danmcd 		isrc = B_TRUE;
   1182   3055      danmcd 		idst = B_TRUE;
   1183   3055      danmcd 		alloclen += 2 * paddrsize;
   1184      0      stevel 	}
   1185      0      stevel 
   1186      0      stevel 	/* For the following fields, assume that length != 0 ==> stuff */
   1187      0      stevel 	if (ipsa->ipsa_authkeylen != 0) {
   1188      0      stevel 		authsize = roundup(sizeof (sadb_key_t) + ipsa->ipsa_authkeylen,
   1189      0      stevel 		    sizeof (uint64_t));
   1190      0      stevel 		alloclen += authsize;
   1191      0      stevel 		auth = B_TRUE;
   1192      0      stevel 	}
   1193      0      stevel 
   1194      0      stevel 	if (ipsa->ipsa_encrkeylen != 0) {
   1195  10824        Mark 		encrsize = roundup(sizeof (sadb_key_t) + ipsa->ipsa_encrkeylen +
   1196  10824        Mark 		    ipsa->ipsa_nonce_len, sizeof (uint64_t));
   1197      0      stevel 		alloclen += encrsize;
   1198      0      stevel 		encr = B_TRUE;
   1199      0      stevel 	} else {
   1200      0      stevel 		encr = B_FALSE;
   1201      0      stevel 	}
   1202      0      stevel 
   1203  11042        Erik 	if (ipsa->ipsa_tsl != NULL) {
   1204  11042        Erik 		senslen = sadb_sens_len_from_label(ipsa->ipsa_tsl);
   1205  10934  sommerfeld 		alloclen += senslen;
   1206      0      stevel 		sensinteg = B_TRUE;
   1207  10934  sommerfeld 	}
   1208  10934  sommerfeld 
   1209  11042        Erik 	if (ipsa->ipsa_otsl != NULL) {
   1210  11042        Erik 		osenslen = sadb_sens_len_from_label(ipsa->ipsa_otsl);
   1211  10934  sommerfeld 		alloclen += osenslen;
   1212  10934  sommerfeld 		osensinteg = B_TRUE;
   1213      0      stevel 	}
   1214      0      stevel 
   1215      0      stevel 	/*
   1216      0      stevel 	 * Must use strlen() here for lengths.	Identities use NULL
   1217      0      stevel 	 * pointers to indicate their nonexistence.
   1218      0      stevel 	 */
   1219      0      stevel 	if (ipsa->ipsa_src_cid != NULL) {
   1220      0      stevel 		srcidsize = roundup(sizeof (sadb_ident_t) +
   1221      0      stevel 		    strlen(ipsa->ipsa_src_cid->ipsid_cid) + 1,
   1222      0      stevel 		    sizeof (uint64_t));
   1223      0      stevel 		alloclen += srcidsize;
   1224      0      stevel 		srcid = B_TRUE;
   1225      0      stevel 	}
   1226      0      stevel 
   1227      0      stevel 	if (ipsa->ipsa_dst_cid != NULL) {
   1228      0      stevel 		dstidsize = roundup(sizeof (sadb_ident_t) +
   1229      0      stevel 		    strlen(ipsa->ipsa_dst_cid->ipsid_cid) + 1,
   1230      0      stevel 		    sizeof (uint64_t));
   1231      0      stevel 		alloclen += dstidsize;
   1232      0      stevel 		dstid = B_TRUE;
   1233      0      stevel 	}
   1234      0      stevel 
   1235      0      stevel 	if ((ipsa->ipsa_kmp != 0) || (ipsa->ipsa_kmc != 0))
   1236      0      stevel 		alloclen += sizeof (sadb_x_kmc_t);
   1237   7749  Thejaswini 
   1238   7749  Thejaswini 	if (ipsa->ipsa_replay != 0) {
   1239   7749  Thejaswini 		alloclen += sizeof (sadb_x_replay_ctr_t);
   1240   7749  Thejaswini 	}
   1241      0      stevel 
   1242      0      stevel 	/* Make sure the allocation length is a multiple of 8 bytes. */
   1243      0      stevel 	ASSERT((alloclen & 0x7) == 0);
   1244      0      stevel 
   1245      0      stevel 	/* XXX Possibly make it esballoc, with a bzero-ing free_ftn. */
   1246      0      stevel 	mp = allocb(alloclen, BPRI_HI);
   1247      0      stevel 	if (mp == NULL)
   1248      0      stevel 		return (NULL);
   1249  10934  sommerfeld 	bzero(mp->b_rptr, alloclen);
   1250      0      stevel 
   1251      0      stevel 	mp->b_wptr += alloclen;
   1252      0      stevel 	end = mp->b_wptr;
   1253      0      stevel 	newsamsg = (sadb_msg_t *)mp->b_rptr;
   1254      0      stevel 	*newsamsg = *samsg;
   1255      0      stevel 	newsamsg->sadb_msg_len = (uint16_t)SADB_8TO64(alloclen);
   1256      0      stevel 
   1257      0      stevel 	mutex_enter(&ipsa->ipsa_lock);	/* Since I'm grabbing SA fields... */
   1258      0      stevel 
   1259      0      stevel 	newsamsg->sadb_msg_satype = ipsa->ipsa_type;
   1260      0      stevel 
   1261      0      stevel 	assoc = (sadb_sa_t *)(newsamsg + 1);
   1262      0      stevel 	assoc->sadb_sa_len = SADB_8TO64(sizeof (*assoc));
   1263      0      stevel 	assoc->sadb_sa_exttype = SADB_EXT_SA;
   1264      0      stevel 	assoc->sadb_sa_spi = ipsa->ipsa_spi;
   1265      0      stevel 	assoc->sadb_sa_replay = ipsa->ipsa_replay_wsize;
   1266      0      stevel 	assoc->sadb_sa_state = ipsa->ipsa_state;
   1267      0      stevel 	assoc->sadb_sa_auth = ipsa->ipsa_auth_alg;
   1268      0      stevel 	assoc->sadb_sa_encrypt = ipsa->ipsa_encr_alg;
   1269      0      stevel 	assoc->sadb_sa_flags = ipsa->ipsa_flags;
   1270      0      stevel 
   1271      0      stevel 	lt = (sadb_lifetime_t *)(assoc + 1);
   1272      0      stevel 	lt->sadb_lifetime_len = SADB_8TO64(sizeof (*lt));
   1273      0      stevel 	lt->sadb_lifetime_exttype = SADB_EXT_LIFETIME_CURRENT;
   1274   4987      danmcd 	/* We do not support the concept. */
   1275   4987      danmcd 	lt->sadb_lifetime_allocations = 0;
   1276      0      stevel 	lt->sadb_lifetime_bytes = ipsa->ipsa_bytes;
   1277      0      stevel 	lt->sadb_lifetime_addtime = ipsa->ipsa_addtime;
   1278      0      stevel 	lt->sadb_lifetime_usetime = ipsa->ipsa_usetime;
   1279      0      stevel 
   1280      0      stevel 	if (hard) {
   1281      0      stevel 		lt++;
   1282      0      stevel 		lt->sadb_lifetime_len = SADB_8TO64(sizeof (*lt));
   1283      0      stevel 		lt->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
   1284      0      stevel 		lt->sadb_lifetime_allocations = ipsa->ipsa_hardalloc;
   1285      0      stevel 		lt->sadb_lifetime_bytes = ipsa->ipsa_hardbyteslt;
   1286      0      stevel 		lt->sadb_lifetime_addtime = ipsa->ipsa_hardaddlt;
   1287      0      stevel 		lt->sadb_lifetime_usetime = ipsa->ipsa_harduselt;
   1288      0      stevel 	}
   1289      0      stevel 
   1290      0      stevel 	if (soft) {
   1291      0      stevel 		lt++;
   1292      0      stevel 		lt->sadb_lifetime_len = SADB_8TO64(sizeof (*lt));
   1293      0      stevel 		lt->sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
   1294      0      stevel 		lt->sadb_lifetime_allocations = ipsa->ipsa_softalloc;
   1295      0      stevel 		lt->sadb_lifetime_bytes = ipsa->ipsa_softbyteslt;
   1296      0      stevel 		lt->sadb_lifetime_addtime = ipsa->ipsa_softaddlt;
   1297      0      stevel 		lt->sadb_lifetime_usetime = ipsa->ipsa_softuselt;
   1298   7749  Thejaswini 	}
   1299   7749  Thejaswini 
   1300   7749  Thejaswini 	if (idle) {
   1301   7749  Thejaswini 		lt++;
   1302   7749  Thejaswini 		lt->sadb_lifetime_len = SADB_8TO64(sizeof (*lt));
   1303   7749  Thejaswini 		lt->sadb_lifetime_exttype = SADB_X_EXT_LIFETIME_IDLE;
   1304   7749  Thejaswini 		lt->sadb_lifetime_addtime = ipsa->ipsa_idleaddlt;
   1305   7749  Thejaswini 		lt->sadb_lifetime_usetime = ipsa->ipsa_idleuselt;
   1306      0      stevel 	}
   1307      0      stevel 
   1308      0      stevel 	cur = (uint8_t *)(lt + 1);
   1309      0      stevel 
   1310   3055      danmcd 	/* NOTE:  Don't fill in ports here if we are a tunnel-mode SA. */
   1311      0      stevel 	cur = sadb_make_addr_ext(cur, end, SADB_EXT_ADDRESS_SRC, fam,
   1312   3055      danmcd 	    ipsa->ipsa_srcaddr, (!isrc && !idst) ? SA_SRCPORT(ipsa) : 0,
   1313   3055      danmcd 	    SA_PROTO(ipsa), 0);
   1314      0      stevel 	if (cur == NULL) {
   1315      0      stevel 		freemsg(mp);
   1316      0      stevel 		mp = NULL;
   1317      0      stevel 		goto bail;
   1318      0      stevel 	}
   1319      0      stevel 
   1320      0      stevel 	cur = sadb_make_addr_ext(cur, end, SADB_EXT_ADDRESS_DST, fam,
   1321   3055      danmcd 	    ipsa->ipsa_dstaddr, (!isrc && !idst) ? SA_DSTPORT(ipsa) : 0,
   1322   3055      danmcd 	    SA_PROTO(ipsa), 0);
   1323      0      stevel 	if (cur == NULL) {
   1324      0      stevel 		freemsg(mp);
   1325      0      stevel 		mp = NULL;
   1326      0      stevel 		goto bail;
   1327      0      stevel 	}
   1328      0      stevel 
   1329      0      stevel 	if (ipsa->ipsa_flags & IPSA_F_NATT_LOC) {
   1330      0      stevel 		cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_NATT_LOC,
   1331   4987      danmcd 		    fam, &ipsa->ipsa_natt_addr_loc, ipsa->ipsa_local_nat_port,
   1332   4987      danmcd 		    IPPROTO_UDP, 0);
   1333      0      stevel 		if (cur == NULL) {
   1334      0      stevel 			freemsg(mp);
   1335      0      stevel 			mp = NULL;
   1336      0      stevel 			goto bail;
   1337      0      stevel 		}
   1338      0      stevel 	}
   1339      0      stevel 
   1340      0      stevel 	if (ipsa->ipsa_flags & IPSA_F_NATT_REM) {
   1341      0      stevel 		cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_NATT_REM,
   1342   4987      danmcd 		    fam, &ipsa->ipsa_natt_addr_rem, ipsa->ipsa_remote_nat_port,
   1343   3055      danmcd 		    IPPROTO_UDP, 0);
   1344      0      stevel 		if (cur == NULL) {
   1345      0      stevel 			freemsg(mp);
   1346      0      stevel 			mp = NULL;
   1347      0      stevel 			goto bail;
   1348      0      stevel 		}
   1349      0      stevel 	}
   1350      0      stevel 
   1351   3055      danmcd 	/* If we are a tunnel-mode SA, fill in the inner-selectors. */
   1352   3055      danmcd 	if (isrc) {
   1353   3055      danmcd 		cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_SRC,
   1354   3055      danmcd 		    pfam, ipsa->ipsa_innersrc, SA_SRCPORT(ipsa),
   1355   3055      danmcd 		    SA_IPROTO(ipsa), ipsa->ipsa_innersrcpfx);
   1356   3055      danmcd 		if (cur == NULL) {
   1357   3055      danmcd 			freemsg(mp);
   1358   3055      danmcd 			mp = NULL;
   1359   3055      danmcd 			goto bail;
   1360   3055      danmcd 		}
   1361   3055      danmcd 	}
   1362   3055      danmcd 
   1363   3055      danmcd 	if (idst) {
   1364   3055      danmcd 		cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_DST,
   1365   3055      danmcd 		    pfam, ipsa->ipsa_innerdst, SA_DSTPORT(ipsa),
   1366   3055      danmcd 		    SA_IPROTO(ipsa), ipsa->ipsa_innerdstpfx);
   1367      0      stevel 		if (cur == NULL) {
   1368      0      stevel 			freemsg(mp);
   1369      0      stevel 			mp = NULL;
   1370      0      stevel 			goto bail;
   1371      0      stevel 		}
   1372      0      stevel 	}
   1373      0      stevel 
   1374      0      stevel 	if ((ipsa->ipsa_kmp != 0) || (ipsa->ipsa_kmc != 0)) {
   1375      0      stevel 		cur = sadb_make_kmc_ext(cur, end,
   1376      0      stevel 		    ipsa->ipsa_kmp, ipsa->ipsa_kmc);
   1377      0      stevel 		if (cur == NULL) {
   1378      0      stevel 			freemsg(mp);
   1379      0      stevel 			mp = NULL;
   1380      0      stevel 			goto bail;
   1381      0      stevel 		}
   1382      0      stevel 	}
   1383      0      stevel 
   1384      0      stevel 	walker = (sadb_ext_t *)cur;
   1385      0      stevel 	if (auth) {
   1386      0      stevel 		key = (sadb_key_t *)walker;
   1387      0      stevel 		key->sadb_key_len = SADB_8TO64(authsize);
   1388      0      stevel 		key->sadb_key_exttype = SADB_EXT_KEY_AUTH;
   1389      0      stevel 		key->sadb_key_bits = ipsa->ipsa_authkeybits;
   1390      0      stevel 		key->sadb_key_reserved = 0;
   1391      0      stevel 		bcopy(ipsa->ipsa_authkey, key + 1, ipsa->ipsa_authkeylen);
   1392      0      stevel 		walker = (sadb_ext_t *)((uint64_t *)walker +
   1393      0      stevel 		    walker->sadb_ext_len);
   1394      0      stevel 	}
   1395      0      stevel 
   1396      0      stevel 	if (encr) {
   1397  10824        Mark 		uint8_t *buf_ptr;
   1398      0      stevel 		key = (sadb_key_t *)walker;
   1399      0      stevel 		key->sadb_key_len = SADB_8TO64(encrsize);
   1400      0      stevel 		key->sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
   1401      0      stevel 		key->sadb_key_bits = ipsa->ipsa_encrkeybits;
   1402  10824        Mark 		key->sadb_key_reserved = ipsa->ipsa_saltbits;
   1403  10824        Mark 		buf_ptr = (uint8_t *)(key + 1);
   1404  10824        Mark 		bcopy(ipsa->ipsa_encrkey, buf_ptr, ipsa->ipsa_encrkeylen);
   1405  10824        Mark 		if (ipsa->ipsa_salt != NULL) {
   1406  10824        Mark 			buf_ptr += ipsa->ipsa_encrkeylen;
   1407  10824        Mark 			bcopy(ipsa->ipsa_salt, buf_ptr, ipsa->ipsa_saltlen);
   1408  10824        Mark 		}
   1409      0      stevel 		walker = (sadb_ext_t *)((uint64_t *)walker +
   1410      0      stevel 		    walker->sadb_ext_len);
   1411      0      stevel 	}
   1412      0      stevel 
   1413      0      stevel 	if (srcid) {
   1414      0      stevel 		ident = (sadb_ident_t *)walker;
   1415      0      stevel 		ident->sadb_ident_len = SADB_8TO64(srcidsize);
   1416      0      stevel 		ident->sadb_ident_exttype = SADB_EXT_IDENTITY_SRC;
   1417      0      stevel 		ident->sadb_ident_type = ipsa->ipsa_src_cid->ipsid_type;
   1418      0      stevel 		ident->sadb_ident_id = 0;
   1419      0      stevel 		ident->sadb_ident_reserved = 0;
   1420      0      stevel 		(void) strcpy((char *)(ident + 1),
   1421      0      stevel 		    ipsa->ipsa_src_cid->ipsid_cid);
   1422      0      stevel 		walker = (sadb_ext_t *)((uint64_t *)walker +
   1423      0      stevel 		    walker->sadb_ext_len);
   1424      0      stevel 	}
   1425      0      stevel 
   1426      0      stevel 	if (dstid) {
   1427      0      stevel 		ident = (sadb_ident_t *)walker;
   1428      0      stevel 		ident->sadb_ident_len = SADB_8TO64(dstidsize);
   1429      0      stevel 		ident->sadb_ident_exttype = SADB_EXT_IDENTITY_DST;
   1430      0      stevel 		ident->sadb_ident_type = ipsa->ipsa_dst_cid->ipsid_type;
   1431      0      stevel 		ident->sadb_ident_id = 0;
   1432      0      stevel 		ident->sadb_ident_reserved = 0;
   1433      0      stevel 		(void) strcpy((char *)(ident + 1),
   1434      0      stevel 		    ipsa->ipsa_dst_cid->ipsid_cid);
   1435      0      stevel 		walker = (sadb_ext_t *)((uint64_t *)walker +
   1436      0      stevel 		    walker->sadb_ext_len);
   1437      0      stevel 	}
   1438      0      stevel 
   1439      0      stevel 	if (sensinteg) {
   1440      0      stevel 		sens = (sadb_sens_t *)walker;
   1441  11042        Erik 		sadb_sens_from_label(sens, SADB_EXT_SENSITIVITY,
   1442  11042        Erik 		    ipsa->ipsa_tsl, senslen);
   1443  10934  sommerfeld 
   1444  10934  sommerfeld 		walker = (sadb_ext_t *)((uint64_t *)walker +
   1445  10934  sommerfeld 		    walker->sadb_ext_len);
   1446  10934  sommerfeld 	}
   1447  10934  sommerfeld 
   1448  10934  sommerfeld 	if (osensinteg) {
   1449  10934  sommerfeld 		sens = (sadb_sens_t *)walker;
   1450  10934  sommerfeld 
   1451  11042        Erik 		sadb_sens_from_label(sens, SADB_X_EXT_OUTER_SENS,
   1452  11042        Erik 		    ipsa->ipsa_otsl, osenslen);
   1453  10934  sommerfeld 		if (ipsa->ipsa_mac_exempt)
   1454  10934  sommerfeld 			sens->sadb_x_sens_flags = SADB_X_SENS_IMPLICIT;
   1455  10934  sommerfeld 
   1456   6668     markfen 		walker = (sadb_ext_t *)((uint64_t *)walker +
   1457   6668     markfen 		    walker->sadb_ext_len);
   1458   6668     markfen 	}
   1459   6668     markfen 
   1460   6668     markfen 	if (paired) {
   1461   6668     markfen 		pair_ext = (sadb_x_pair_t *)walker;
   1462   6668     markfen 
   1463   6668     markfen 		pair_ext->sadb_x_pair_len = SADB_8TO64(sizeof (sadb_x_pair_t));
   1464   6668     markfen 		pair_ext->sadb_x_pair_exttype = SADB_X_EXT_PAIR;
   1465   6668     markfen 		pair_ext->sadb_x_pair_spi = otherspi;
   1466   6668     markfen 
   1467      0      stevel 		walker = (sadb_ext_t *)((uint64_t *)walker +
   1468      0      stevel 		    walker->sadb_ext_len);
   1469      0      stevel 	}
   1470      0      stevel 
   1471   7749  Thejaswini 	if (ipsa->ipsa_replay != 0) {
   1472   7749  Thejaswini 		repl_ctr = (sadb_x_replay_ctr_t *)walker;
   1473   7749  Thejaswini 		repl_ctr->sadb_x_rc_len = SADB_8TO64(sizeof (*repl_ctr));
   1474   7749  Thejaswini 		repl_ctr->sadb_x_rc_exttype = SADB_X_EXT_REPLAY_VALUE;
   1475   7749  Thejaswini 		repl_ctr->sadb_x_rc_replay32 = ipsa->ipsa_replay;
   1476   7749  Thejaswini 		repl_ctr->sadb_x_rc_replay64 = 0;
   1477   7749  Thejaswini 		walker = (sadb_ext_t *)(repl_ctr + 1);
   1478   7749  Thejaswini 	}
   1479   7749  Thejaswini 
   1480      0      stevel bail:
   1481      0      stevel 	/* Pardon any delays... */
   1482      0      stevel 	mutex_exit(&ipsa->ipsa_lock);
   1483      0      stevel 
   1484      0      stevel 	return (mp);
   1485      0      stevel }
   1486      0      stevel 
   1487      0      stevel /*
   1488      0      stevel  * Strip out key headers or unmarked headers (SADB_EXT_KEY_*, SADB_EXT_UNKNOWN)
   1489      0      stevel  * and adjust base message accordingly.
   1490      0      stevel  *
   1491      0      stevel  * Assume message is pulled up in one piece of contiguous memory.
   1492      0      stevel  *
   1493      0      stevel  * Say if we start off with:
   1494      0      stevel  *
   1495      0      stevel  * +------+----+-------------+-----------+---------------+---------------+
   1496      0      stevel  * | base | SA | source addr | dest addr | rsrvd. or key | soft lifetime |
   1497      0      stevel  * +------+----+-------------+-----------+---------------+---------------+
   1498      0      stevel  *
   1499      0      stevel  * we will end up with
   1500      0      stevel  *
   1501      0      stevel  * +------+----+-------------+-----------+---------------+
   1502      0      stevel  * | base | SA | source addr | dest addr | soft lifetime |
   1503      0      stevel  * +------+----+-------------+-----------+---------------+
   1504      0      stevel  */
   1505      0      stevel static void
   1506      0      stevel sadb_strip(sadb_msg_t *samsg)
   1507      0      stevel {
   1508      0      stevel 	sadb_ext_t *ext;
   1509      0      stevel 	uint8_t *target = NULL;
   1510      0      stevel 	uint8_t *msgend;
   1511      0      stevel 	int sofar = SADB_8TO64(sizeof (*samsg));
   1512      0      stevel 	int copylen;
   1513      0      stevel 
   1514      0      stevel 	ext = (sadb_ext_t *)(samsg + 1);
   1515      0      stevel 	msgend = (uint8_t *)samsg;
   1516      0      stevel 	msgend += SADB_64TO8(samsg->sadb_msg_len);
   1517      0      stevel 	while ((uint8_t *)ext < msgend) {
   1518      0      stevel 		if (ext->sadb_ext_type == SADB_EXT_RESERVED ||
   1519      0      stevel 		    ext->sadb_ext_type == SADB_EXT_KEY_AUTH ||
   1520   7749  Thejaswini 		    ext->sadb_ext_type == SADB_X_EXT_EDUMP ||
   1521      0      stevel 		    ext->sadb_ext_type == SADB_EXT_KEY_ENCRYPT) {
   1522      0      stevel 			/*
   1523      0      stevel 			 * Aha!	 I found a header to be erased.
   1524      0      stevel 			 */
   1525      0      stevel 
   1526      0      stevel 			if (target != NULL) {
   1527      0      stevel 				/*
   1528      0      stevel 				 * If I had a previous header to be erased,
   1529      0      stevel 				 * copy over it.  I can get away with just
   1530      0      stevel 				 * copying backwards because the target will
   1531      0      stevel 				 * always be 8 bytes behind the source.
   1532      0      stevel 				 */
   1533      0      stevel 				copylen = ((uint8_t *)ext) - (target +
   1534      0      stevel 				    SADB_64TO8(
   1535   4987      danmcd 				    ((sadb_ext_t *)target)->sadb_ext_len));
   1536      0      stevel 				ovbcopy(((uint8_t *)ext - copylen), target,
   1537      0      stevel 				    copylen);
   1538      0      stevel 				target += copylen;
   1539      0      stevel 				((sadb_ext_t *)target)->sadb_ext_len =
   1540      0      stevel 				    SADB_8TO64(((uint8_t *)ext) - target +
   1541   4987      danmcd 				    SADB_64TO8(ext->sadb_ext_len));
   1542      0      stevel 			} else {
   1543      0      stevel 				target = (uint8_t *)ext;
   1544      0      stevel 			}
   1545      0      stevel 		} else {
   1546      0      stevel 			sofar += ext->sadb_ext_len;
   1547      0      stevel 		}
   1548      0      stevel 
   1549      0      stevel 		ext = (sadb_ext_t *)(((uint64_t *)ext) + ext->sadb_ext_len);
   1550      0      stevel 	}
   1551      0      stevel 
   1552      0      stevel 	ASSERT((uint8_t *)ext == msgend);
   1553      0      stevel 
   1554      0      stevel 	if (target != NULL) {
   1555      0      stevel 		copylen = ((uint8_t *)ext) - (target +
   1556      0      stevel 		    SADB_64TO8(((sadb_ext_t *)target)->sadb_ext_len));
   1557      0      stevel 		if (copylen != 0)
   1558      0      stevel 			ovbcopy(((uint8_t *)ext - copylen), target, copylen);
   1559      0      stevel 	}
   1560      0      stevel 
   1561      0      stevel 	/* Adjust samsg. */
   1562      0      stevel 	samsg->sadb_msg_len = (uint16_t)sofar;
   1563      0      stevel 
   1564      0      stevel 	/* Assume all of the rest is cleared by caller in sadb_pfkey_echo(). */
   1565      0      stevel }
   1566      0      stevel 
   1567      0      stevel /*
   1568      0      stevel  * AH needs to send an error to PF_KEY.	 Assume mp points to an M_CTL
   1569      0      stevel  * followed by an M_DATA with a PF_KEY message in it.  The serial of
   1570      0      stevel  * the sending keysock instance is included.
   1571      0      stevel  */
   1572      0      stevel void
   1573      0      stevel sadb_pfkey_error(queue_t *pfkey_q, mblk_t *mp, int error, int diagnostic,
   1574      0      stevel     uint_t serial)
   1575      0      stevel {
   1576      0      stevel 	mblk_t *msg = mp->b_cont;
   1577      0      stevel 	sadb_msg_t *samsg;
   1578      0      stevel 	keysock_out_t *kso;
   1579      0      stevel 
   1580      0      stevel 	/*
   1581      0      stevel 	 * Enough functions call this to merit a NULL queue check.
   1582      0      stevel 	 */
   1583      0      stevel 	if (pfkey_q == NULL) {
   1584      0      stevel 		freemsg(mp);
   1585      0      stevel 		return;
   1586      0      stevel 	}
   1587      0      stevel 
   1588      0      stevel 	ASSERT(msg != NULL);
   1589      0      stevel 	ASSERT((mp->b_wptr - mp->b_rptr) == sizeof (ipsec_info_t));
   1590      0      stevel 	ASSERT((msg->b_wptr - msg->b_rptr) >= sizeof (sadb_msg_t));
   1591      0      stevel 	samsg = (sadb_msg_t *)msg->b_rptr;
   1592      0      stevel 	kso = (keysock_out_t *)mp->b_rptr;
   1593      0      stevel 
   1594      0      stevel 	kso->ks_out_type = KEYSOCK_OUT;
   1595      0      stevel 	kso->ks_out_len = sizeof (*kso);
   1596      0      stevel 	kso->ks_out_serial = serial;
   1597      0      stevel 
   1598      0      stevel 	/*
   1599      0      stevel 	 * Only send the base message up in the event of an error.
   1600      0      stevel 	 * Don't worry about bzero()-ing, because it was probably bogus
   1601      0      stevel 	 * anyway.
   1602      0      stevel 	 */
   1603      0      stevel 	msg->b_wptr = msg->b_rptr + sizeof (*samsg);
   1604      0      stevel 	samsg = (sadb_msg_t *)msg->b_rptr;
   1605      0      stevel 	samsg->sadb_msg_len = SADB_8TO64(sizeof (*samsg));
   1606      0      stevel 	samsg->sadb_msg_errno = (uint8_t)error;
   1607      0      stevel 	if (diagnostic != SADB_X_DIAGNOSTIC_PRESET)
   1608      0      stevel 		samsg->sadb_x_msg_diagnostic = (uint16_t)diagnostic;
   1609      0      stevel 
   1610      0      stevel 	putnext(pfkey_q, mp);
   1611      0      stevel }
   1612      0      stevel 
   1613      0      stevel /*
   1614      0      stevel  * Send a successful return packet back to keysock via the queue in pfkey_q.
   1615      0      stevel  *
   1616      0      stevel  * Often, an SA is associated with the reply message, it's passed in if needed,
   1617      0      stevel  * and NULL if not.  BTW, that ipsa will have its refcnt appropriately held,
   1618      0      stevel  * and the caller will release said refcnt.
   1619      0      stevel  */
   1620      0      stevel void
   1621      0      stevel sadb_pfkey_echo(queue_t *pfkey_q, mblk_t *mp, sadb_msg_t *samsg,
   1622      0      stevel     keysock_in_t *ksi, ipsa_t *ipsa)
   1623      0      stevel {
   1624      0      stevel 	keysock_out_t *kso;
   1625      0      stevel 	mblk_t *mp1;
   1626      0      stevel 	sadb_msg_t *newsamsg;
   1627      0      stevel 	uint8_t *oldend;
   1628      0      stevel 
   1629      0      stevel 	ASSERT((mp->b_cont != NULL) &&
   1630      0      stevel 	    ((void *)samsg == (void *)mp->b_cont->b_rptr) &&
   1631      0      stevel 	    ((void *)mp->b_rptr == (void *)ksi));
   1632      0      stevel 
   1633      0      stevel 	switch (samsg->sadb_msg_type) {
   1634      0      stevel 	case SADB_ADD:
   1635      0      stevel 	case SADB_UPDATE:
   1636   6668     markfen 	case SADB_X_UPDATEPAIR:
   1637   7749  Thejaswini 	case SADB_X_DELPAIR_STATE:
   1638      0      stevel 	case SADB_FLUSH:
   1639      0      stevel 	case SADB_DUMP:
   1640      0      stevel 		/*
   1641      0      stevel 		 * I have all of the message already.  I just need to strip
   1642      0      stevel 		 * out the keying material and echo the message back.
   1643      0      stevel 		 *
   1644      0      stevel 		 * NOTE: for SADB_DUMP, the function sadb_dump() did the
   1645      0      stevel 		 * work.  When DUMP reaches here, it should only be a base
   1646      0      stevel 		 * message.
   1647      0      stevel 		 */
   1648      0      stevel 	justecho:
   1649      0      stevel 		if (ksi->ks_in_extv[SADB_EXT_KEY_AUTH] != NULL ||
   1650   7749  Thejaswini 		    ksi->ks_in_extv[SADB_EXT_KEY_ENCRYPT] != NULL ||
   1651   7749  Thejaswini 		    ksi->ks_in_extv[SADB_X_EXT_EDUMP] != NULL) {
   1652      0      stevel 			sadb_strip(samsg);
   1653      0      stevel 			/* Assume PF_KEY message is contiguous. */
   1654      0      stevel 			ASSERT(mp->b_cont->b_cont == NULL);
   1655      0      stevel 			oldend = mp->b_cont->b_wptr;
   1656      0      stevel 			mp->b_cont->b_wptr = mp->b_cont->b_rptr +
   1657      0      stevel 			    SADB_64TO8(samsg->sadb_msg_len);
   1658      0      stevel 			bzero(mp->b_cont->b_wptr, oldend - mp->b_cont->b_wptr);
   1659      0      stevel 		}
   1660      0      stevel 		break;
   1661      0      stevel 	case SADB_GET:
   1662      0      stevel 		/*
   1663      0      stevel 		 * Do a lot of work here, because of the ipsa I just found.
   1664   3055      danmcd 		 * First construct the new PF_KEY message, then abandon
   1665   3055      danmcd 		 * the old one.
   1666      0      stevel 		 */
   1667      0      stevel 		mp1 = sadb_sa2msg(ipsa, samsg);
   1668      0      stevel 		if (mp1 == NULL) {
   1669      0      stevel 			sadb_pfkey_error(pfkey_q, mp, ENOMEM,
   1670      0      stevel 			    SADB_X_DIAGNOSTIC_NONE, ksi->ks_in_serial);
   1671      0      stevel 			return;
   1672      0      stevel 		}
   1673      0      stevel 		freemsg(mp->b_cont);
   1674      0      stevel 		mp->b_cont = mp1;
   1675      0      stevel 		break;
   1676      0      stevel 	case SADB_DELETE:
   1677   6668     markfen 	case SADB_X_DELPAIR:
   1678      0      stevel 		if (ipsa == NULL)
   1679      0      stevel 			goto justecho;
   1680      0      stevel 		/*
   1681      0      stevel 		 * Because listening KMds may require more info, treat
   1682      0      stevel 		 * DELETE like a special case of GET.
   1683      0      stevel 		 */
   1684      0      stevel 		mp1 = sadb_sa2msg(ipsa, samsg);
   1685      0      stevel 		if (mp1 == NULL) {
   1686      0      stevel 			sadb_pfkey_error(pfkey_q, mp, ENOMEM,
   1687      0      stevel 			    SADB_X_DIAGNOSTIC_NONE, ksi->ks_in_serial);
   1688      0      stevel 			return;
   1689      0      stevel 		}
   1690      0      stevel 		newsamsg = (sadb_msg_t *)mp1->b_rptr;
   1691      0      stevel 		sadb_strip(newsamsg);
   1692      0      stevel 		oldend = mp1->b_wptr;
   1693      0      stevel 		mp1->b_wptr = mp1->b_rptr + SADB_64TO8(newsamsg->sadb_msg_len);
   1694      0      stevel 		bzero(mp1->b_wptr, oldend - mp1->b_wptr);
   1695      0      stevel 		freemsg(mp->b_cont);
   1696      0      stevel 		mp->b_cont = mp1;
   1697      0      stevel 		break;
   1698      0      stevel 	default:
   1699      0      stevel 		if (mp != NULL)
   1700      0      stevel 			freemsg(mp);
   1701      0      stevel 		return;
   1702      0      stevel 	}
   1703      0      stevel 
   1704      0      stevel 	/* ksi is now null and void. */
   1705      0      stevel 	kso = (keysock_out_t *)ksi;
   1706      0      stevel 	kso->ks_out_type = KEYSOCK_OUT;
   1707      0      stevel 	kso->ks_out_len = sizeof (*kso);
   1708      0      stevel 	kso->ks_out_serial = ksi->ks_in_serial;
   1709      0      stevel 	/* We're ready to send... */
   1710      0      stevel 	putnext(pfkey_q, mp);
   1711      0      stevel }
   1712      0      stevel 
   1713      0      stevel /*
   1714      0      stevel  * Set up a global pfkey_q instance for AH, ESP, or some other consumer.
   1715      0      stevel  */
   1716      0      stevel void
   1717      0      stevel sadb_keysock_hello(queue_t **pfkey_qp, queue_t *q, mblk_t *mp,
   1718   3448    dh155122     void (*ager)(void *), void *agerarg, timeout_id_t *top, int satype)
   1719      0      stevel {
   1720      0      stevel 	keysock_hello_ack_t *kha;
   1721      0      stevel 	queue_t *oldq;
   1722      0      stevel 
   1723      0      stevel 	ASSERT(OTHERQ(q) != NULL);
   1724      0      stevel 
   1725      0      stevel 	/*
   1726      0      stevel 	 * First, check atomically that I'm the first and only keysock
   1727      0      stevel 	 * instance.
   1728      0      stevel 	 *
   1729      0      stevel 	 * Use OTHERQ(q), because qreply(q, mp) == putnext(OTHERQ(q), mp),
   1730      0      stevel 	 * and I want this module to say putnext(*_pfkey_q, mp) for PF_KEY
   1731      0      stevel 	 * messages.
   1732      0      stevel 	 */
   1733      0      stevel 
   1734      0      stevel 	oldq = casptr((void **)pfkey_qp, NULL, OTHERQ(q));
   1735      0      stevel 	if (oldq != NULL) {
   1736      0      stevel 		ASSERT(oldq != q);
   1737      0      stevel 		cmn_err(CE_WARN, "Danger!  Multiple keysocks on top of %s.\n",
   1738      0      stevel 		    (satype == SADB_SATYPE_ESP)? "ESP" : "AH or other");
   1739      0      stevel 		freemsg(mp);
   1740      0      stevel 		return;
   1741      0      stevel 	}
   1742      0      stevel 
   1743      0      stevel 	kha = (keysock_hello_ack_t *)mp->b_rptr;
   1744      0      stevel 	kha->ks_hello_len = sizeof (keysock_hello_ack_t);
   1745      0      stevel 	kha->ks_hello_type = KEYSOCK_HELLO_ACK;
   1746      0      stevel 	kha->ks_hello_satype = (uint8_t)satype;
   1747      0      stevel 
   1748      0      stevel 	/*
   1749      0      stevel 	 * If we made it past the casptr, then we have "exclusive" access
   1750   9670      danmcd 	 * to the timeout handle.  Fire it off after the default ager
   1751   9670      danmcd 	 * interval.
   1752   9670      danmcd 	 */
   1753   9670      danmcd 	*top = qtimeout(*pfkey_qp, ager, agerarg,
   1754   9670      danmcd 	    drv_usectohz(SADB_AGE_INTERVAL_DEFAULT * 1000));
   1755      0      stevel 
   1756      0      stevel 	putnext(*pfkey_qp, mp);
   1757      0      stevel }
   1758      0      stevel 
   1759      0      stevel /*
   1760   3055      danmcd  * Normalize IPv4-mapped IPv6 addresses (and prefixes) as appropriate.
   1761   3055      danmcd  *
   1762   3055      danmcd  * Check addresses themselves for wildcard or multicast.
   1763   3055      danmcd  * Check ire table for local/non-local/broadcast.
   1764   3055      danmcd  */
   1765   3055      danmcd int
   1766   3448    dh155122 sadb_addrcheck(queue_t *pfkey_q, mblk_t *mp, sadb_ext_t *ext, uint_t serial,
   1767   3448    dh155122     netstack_t *ns)
   1768      0      stevel {
   1769      0      stevel 	sadb_address_t *addr = (sadb_address_t *)ext;
   1770      0      stevel 	struct sockaddr_in *sin;
   1771      0      stevel 	struct sockaddr_in6 *sin6;
   1772   3055      danmcd 	int diagnostic, type;
   1773   3055      danmcd 	boolean_t normalized = B_FALSE;
   1774      0      stevel 
   1775      0      stevel 	ASSERT(ext != NULL);
   1776      0      stevel 	ASSERT((ext->sadb_ext_type == SADB_EXT_ADDRESS_SRC) ||
   1777      0      stevel 	    (ext->sadb_ext_type == SADB_EXT_ADDRESS_DST) ||
   1778   3055      danmcd 	    (ext->sadb_ext_type == SADB_X_EXT_ADDRESS_INNER_SRC) ||
   1779   3055      danmcd 	    (ext->sadb_ext_type == SADB_X_EXT_ADDRESS_INNER_DST) ||
   1780   3055      danmcd 	    (ext->sadb_ext_type == SADB_X_EXT_ADDRESS_NATT_LOC) ||
   1781   3055      danmcd 	    (ext->sadb_ext_type == SADB_X_EXT_ADDRESS_NATT_REM));
   1782      0      stevel 
   1783      0      stevel 	/* Assign both sockaddrs, the compiler will do the right thing. */
   1784      0      stevel 	sin = (struct sockaddr_in *)(addr + 1);
   1785      0      stevel 	sin6 = (struct sockaddr_in6 *)(addr + 1);
   1786      0      stevel 
   1787   3055      danmcd 	if (sin6->sin6_family == AF_INET6) {
   1788   3055      danmcd 		if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
   1789   3055      danmcd 			/*
   1790   3055      danmcd 			 * Convert to an AF_INET sockaddr.  This means the
   1791   3055      danmcd 			 * return messages will have the extra space, but have
   1792   3055      danmcd 			 * AF_INET sockaddrs instead of AF_INET6.
   1793   3055      danmcd 			 *
   1794   3055      danmcd 			 * Yes, RFC 2367 isn't clear on what to do here w.r.t.
   1795   3055      danmcd 			 * mapped addresses, but since AF_INET6 ::ffff:<v4> is
   1796   3055      danmcd 			 * equal to AF_INET <v4>, it shouldnt be a huge
   1797   3055      danmcd 			 * problem.
   1798   3055      danmcd 			 */
   1799   3055      danmcd 			sin->sin_family = AF_INET;
   1800   3055      danmcd 			IN6_V4MAPPED_TO_INADDR(&sin6->sin6_addr,
   1801   3055      danmcd 			    &sin->sin_addr);
   1802   3055      danmcd 			bzero(&sin->sin_zero, sizeof (sin->sin_zero));
   1803   3055      danmcd 			normalized = B_TRUE;
   1804   3055      danmcd 		}
   1805   3055      danmcd 	} else if (sin->sin_family != AF_INET) {
   1806      0      stevel 		switch (ext->sadb_ext_type) {
   1807      0      stevel 		case SADB_EXT_ADDRESS_SRC:
   1808      0      stevel 			diagnostic = SADB_X_DIAGNOSTIC_BAD_SRC_AF;
   1809      0      stevel 			break;
   1810      0      stevel 		case SADB_EXT_ADDRESS_DST:
   1811      0      stevel 			diagnostic = SADB_X_DIAGNOSTIC_BAD_DST_AF;
   1812      0      stevel 			break;
   1813   3055      danmcd 		case SADB_X_EXT_ADDRESS_INNER_SRC:
   1814      0      stevel 			diagnostic = SADB_X_DIAGNOSTIC_BAD_PROXY_AF;
   1815      0      stevel 			break;
   1816   3055      danmcd 		case SADB_X_EXT_ADDRESS_INNER_DST:
   1817   3055      danmcd 			diagnostic = SADB_X_DIAGNOSTIC_BAD_INNER_DST_AF;
   1818   3055      danmcd 			break;
   1819   3055      danmcd 		case SADB_X_EXT_ADDRESS_NATT_LOC:
   1820   3055      danmcd 			diagnostic = SADB_X_DIAGNOSTIC_BAD_NATT_LOC_AF;
   1821   3055      danmcd 			break;
   1822   3055      danmcd 		case SADB_X_EXT_ADDRESS_NATT_REM:
   1823   3055      danmcd 			diagnostic = SADB_X_DIAGNOSTIC_BAD_NATT_REM_AF;
   1824   3055      danmcd 			break;
   1825      0      stevel 			/* There is no default, see above ASSERT. */
   1826      0      stevel 		}
   1827   3055      danmcd bail:
   1828   3055      danmcd 		if (pfkey_q != NULL) {
   1829   3055      danmcd 			sadb_pfkey_error(pfkey_q, mp, EINVAL, diagnostic,
   1830   3055      danmcd 			    serial);
   1831   3055      danmcd 		} else {
   1832   3055      danmcd 			/*
   1833   3055      danmcd 			 * Scribble in sadb_msg that we got passed in.
   1834   3055      danmcd 			 * Overload "mp" to be an sadb_msg pointer.
   1835   3055      danmcd 			 */
   1836   3055      danmcd 			sadb_msg_t *samsg = (sadb_msg_t *)mp;
   1837   3055      danmcd 
   1838   3055      danmcd 			samsg->sadb_msg_errno = EINVAL;
   1839   3055      danmcd 			samsg->sadb_x_msg_diagnostic = diagnostic;
   1840   3055      danmcd 		}
   1841      0      stevel 		return (KS_IN_ADDR_UNKNOWN);
   1842      0      stevel 	}
   1843   3055      danmcd 
   1844   3055      danmcd 	if (ext->sadb_ext_type == SADB_X_EXT_ADDRESS_INNER_SRC ||
   1845   3055      danmcd 	    ext->sadb_ext_type == SADB_X_EXT_ADDRESS_INNER_DST) {
   1846   3055      danmcd 		/*
   1847   3055      danmcd 		 * We need only check for prefix issues.
   1848   3055      danmcd 		 */
   1849   3055      danmcd 
   1850   3055      danmcd 		/* Set diagnostic now, in case we need it later. */
   1851   3055      danmcd 		diagnostic =
   1852   3055      danmcd 		    (ext->sadb_ext_type == SADB_X_EXT_ADDRESS_INNER_SRC) ?
   1853   3055      danmcd 		    SADB_X_DIAGNOSTIC_PREFIX_INNER_SRC :
   1854   3055      danmcd 		    SADB_X_DIAGNOSTIC_PREFIX_INNER_DST;
   1855   3055      danmcd 
   1856   3055      danmcd 		if (normalized)
   1857   3055      danmcd 			addr->sadb_address_prefixlen -= 96;
   1858   3055      danmcd 
   1859   3055      danmcd 		/*
   1860   3055      danmcd 		 * Verify and mask out inner-addresses based on prefix length.
   1861   3055      danmcd 		 */
   1862   3055      danmcd 		if (sin->sin_family == AF_INET) {
   1863   3055      danmcd 			if (addr->sadb_address_prefixlen > 32)
   1864   3055      danmcd 				goto bail;
   1865   3055      danmcd 			sin->sin_addr.s_addr &=
   1866   3055      danmcd 			    ip_plen_to_mask(addr->sadb_address_prefixlen);
   1867   3055      danmcd 		} else {
   1868   3055      danmcd 			in6_addr_t mask;
   1869   3055      danmcd 
   1870   3055      danmcd 			ASSERT(sin->sin_family == AF_INET6);
   1871   3055      danmcd 			/*
   1872   3055      danmcd 			 * ip_plen_to_mask_v6() returns NULL if the value in
   1873   3055      danmcd 			 * question is out of range.
   1874   3055      danmcd 			 */
   1875   3055      danmcd 			if (ip_plen_to_mask_v6(addr->sadb_address_prefixlen,
   1876   4987      danmcd 			    &mask) == NULL)
   1877   3055      danmcd 				goto bail;
   1878   3055      danmcd 			sin6->sin6_addr.s6_addr32[0] &= mask.s6_addr32[0];
   1879   3055      danmcd 			sin6->sin6_addr.s6_addr32[1] &= mask.s6_addr32[1];
   1880   3055      danmcd 			sin6->sin6_addr.s6_addr32[2] &= mask.s6_addr32[2];
   1881   3055      danmcd 			sin6->sin6_addr.s6_addr32[3] &= mask.s6_addr32[3];
   1882   3055      danmcd 		}
   1883   3055      danmcd 
   1884   3055      danmcd 		/* We don't care in these cases. */
   1885   3055      danmcd 		return (KS_IN_ADDR_DONTCARE);
   1886   3055      danmcd 	}
   1887   3055      danmcd 
   1888   3055      danmcd 	if (sin->sin_family == AF_INET6) {
   1889   3055      danmcd 		/* Check the easy ones now. */
   1890   3055      danmcd 		if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
   1891   3055      danmcd 			return (KS_IN_ADDR_MBCAST);
   1892   3055      danmcd 		if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
   1893   3055      danmcd 			return (KS_IN_ADDR_UNSPEC);
   1894   3055      danmcd 		/*
   1895   3055      danmcd 		 * At this point, we're a unicast IPv6 address.
   1896   3055      danmcd 		 *
   1897   3055      danmcd 		 * XXX Zones alert -> me/notme decision needs to be tempered
   1898   3055      danmcd 		 * by what zone we're in when we go to zone-aware IPsec.
   1899   3055      danmcd 		 */
   1900  11042        Erik 		if (ip_type_v6(&sin6->sin6_addr, ns->netstack_ip) ==
   1901  11042        Erik 		    IRE_LOCAL) {
   1902   3055      danmcd 			/* Hey hey, it's local. */
   1903   3055      danmcd 			return (KS_IN_ADDR_ME);
   1904   3055      danmcd 		}
   1905   3055      danmcd 	} else {
   1906   3055      danmcd 		ASSERT(sin->sin_family == AF_INET);
   1907   3055      danmcd 		if (sin->sin_addr.s_addr == INADDR_ANY)
   1908   3055      danmcd 			return (KS_IN_ADDR_UNSPEC);
   1909   3055      danmcd 		if (CLASSD(sin->sin_addr.s_addr))
   1910   3055      danmcd 			return (KS_IN_ADDR_MBCAST);
   1911   3055      danmcd 		/*
   1912   3055      danmcd 		 * At this point we're a unicast or broadcast IPv4 address.
   1913   3055      danmcd 		 *
   1914  11042        Erik 		 * Check if the address is IRE_BROADCAST or IRE_LOCAL.
   1915   3055      danmcd 		 *
   1916   3055      danmcd 		 * XXX Zones alert -> me/notme decision needs to be tempered
   1917   3055      danmcd 		 * by what zone we're in when we go to zone-aware IPsec.
   1918   3055      danmcd 		 */
   1919  11042        Erik 		type = ip_type_v4(sin->sin_addr.s_addr, ns->netstack_ip);
   1920  11042        Erik 		switch (type) {
   1921  11042        Erik 		case IRE_LOCAL:
   1922  11042        Erik 			return (KS_IN_ADDR_ME);
   1923  11042        Erik 		case IRE_BROADCAST:
   1924  11042        Erik 			return (KS_IN_ADDR_MBCAST);
   1925   3055      danmcd 		}
   1926   3055      danmcd 	}
   1927   3055      danmcd 
   1928   3055      danmcd 	return (KS_IN_ADDR_NOTME);
   1929   3055      danmcd }
   1930   3055      danmcd 
   1931   3055      danmcd /*
   1932   3055      danmcd  * Address normalizations and reality checks for inbound PF_KEY messages.
   1933   3055      danmcd  *
   1934      0      stevel  * For the case of src == unspecified AF_INET6, and dst == AF_INET, convert
   1935   3055      danmcd  * the source to AF_INET.  Do the same for the inner sources.
   1936   3055      danmcd  */
   1937   3055      danmcd boolean_t
   1938   3448    dh155122 sadb_addrfix(keysock_in_t *ksi, queue_t *pfkey_q, mblk_t *mp, netstack_t *ns)
   1939   3055      danmcd {
   1940   3055      danmcd 	struct sockaddr_in *src, *isrc;
   1941   3055      danmcd 	struct sockaddr_in6 *dst, *idst;
   1942      0      stevel 	sadb_address_t *srcext, *dstext;
   1943    691    sommerfe 	uint16_t sport;
   1944   3055      danmcd 	sadb_ext_t **extv = ksi->ks_in_extv;
   1945   3055      danmcd 	int rc;
   1946   3055      danmcd 
   1947   3055      danmcd 	if (extv[SADB_EXT_ADDRESS_SRC] != NULL) {
   1948   3055      danmcd 		rc = sadb_addrcheck(pfkey_q, mp, extv[SADB_EXT_ADDRESS_SRC],
   1949   3448    dh155122 		    ksi->ks_in_serial, ns);
   1950   3055      danmcd 		if (rc == KS_IN_ADDR_UNKNOWN)
   1951   3055      danmcd 			return (B_FALSE);
   1952   3055      danmcd 		if (rc == KS_IN_ADDR_MBCAST) {
   1953   3055      danmcd 			sadb_pfkey_error(pfkey_q, mp, EINVAL,
   1954   3055      danmcd 			    SADB_X_DIAGNOSTIC_BAD_SRC, ksi->ks_in_serial);
   1955   3055      danmcd 			return (B_FALSE);
   1956   3055      danmcd 		}
   1957   3055      danmcd 		ksi->ks_in_srctype = rc;
   1958   3055      danmcd 	}
   1959   3055      danmcd 
   1960   3055      danmcd 	if (extv[SADB_EXT_ADDRESS_DST] != NULL) {
   1961   3055      danmcd 		rc = sadb_addrcheck(pfkey_q, mp, extv[SADB_EXT_ADDRESS_DST],
   1962   3448    dh155122 		    ksi->ks_in_serial, ns);
   1963   3055      danmcd 		if (rc == KS_IN_ADDR_UNKNOWN)
   1964   3055      danmcd 			return (B_FALSE);
   1965   3055      danmcd 		if (rc == KS_IN_ADDR_UNSPEC) {
   1966   3055      danmcd 			sadb_pfkey_error(pfkey_q, mp, EINVAL,
   1967   3055      danmcd 			    SADB_X_DIAGNOSTIC_BAD_DST, ksi->ks_in_serial);
   1968   3055      danmcd 			return (B_FALSE);
   1969   3055      danmcd 		}
   1970   3055      danmcd 		ksi->ks_in_dsttype = rc;
   1971   3055      danmcd 	}
   1972   3055      danmcd 
   1973   3055      danmcd 	/*
   1974   3055      danmcd 	 * NAT-Traversal addrs are simple enough to not require all of
   1975   3055      danmcd 	 * the checks in sadb_addrcheck().  Just normalize or reject if not
   1976   3055      danmcd 	 * AF_INET.
   1977   3055      danmcd 	 */
   1978   3055      danmcd 	if (extv[SADB_X_EXT_ADDRESS_NATT_LOC] != NULL) {
   1979   3055      danmcd 		rc = sadb_addrcheck(pfkey_q, mp,
   1980   3448    dh155122 		    extv[SADB_X_EXT_ADDRESS_NATT_LOC], ksi->ks_in_serial, ns);
   1981   3055      danmcd 
   1982   3055      danmcd 		/*
   1983   4987      danmcd 		 * Local NAT-T addresses never use an IRE_LOCAL, so it should
   1984   4987      danmcd 		 * always be NOTME, or UNSPEC (to handle both tunnel mode
   1985   4987      danmcd 		 * AND local-port flexibility).
   1986   4987      danmcd 		 */
   1987   4987      danmcd 		if (rc != KS_IN_ADDR_NOTME && rc != KS_IN_ADDR_UNSPEC) {
   1988   4987      danmcd 			sadb_pfkey_error(pfkey_q, mp, EINVAL,
   1989   4987      danmcd 			    SADB_X_DIAGNOSTIC_MALFORMED_NATT_LOC,
   1990   4987      danmcd 			    ksi->ks_in_serial);
   1991   3055      danmcd 			return (B_FALSE);
   1992   3055      danmcd 		}
   1993   3055      danmcd 		src = (struct sockaddr_in *)
   1994   3055      danmcd 		    (((sadb_address_t *)extv[SADB_X_EXT_ADDRESS_NATT_LOC]) + 1);
   1995   3055      danmcd 		if (src->sin_family != AF_INET) {
   1996   3055      danmcd 			sadb_pfkey_error(pfkey_q, mp, EINVAL,
   1997   3055      danmcd 			    SADB_X_DIAGNOSTIC_BAD_NATT_LOC_AF,
   1998   3055      danmcd 			    ksi->ks_in_serial);
   1999   3055      danmcd 			return (B_FALSE);
   2000   3055      danmcd 		}
   2001   3055      danmcd 	}
   2002   3055      danmcd 
   2003   3055      danmcd 	if (extv[SADB_X_EXT_ADDRESS_NATT_REM] != NULL) {
   2004   3055      danmcd 		rc = sadb_addrcheck(pfkey_q, mp,
   2005   3448    dh155122 		    extv[SADB_X_EXT_ADDRESS_NATT_REM], ksi->ks_in_serial, ns);
   2006   3055      danmcd 
   2007   3055      danmcd 		/*
   2008   4987      danmcd 		 * Remote NAT-T addresses never use an IRE_LOCAL, so it should
   2009   3055      danmcd 		 * always be NOTME, or UNSPEC if it's a tunnel-mode SA.
   2010   3055      danmcd 		 */
   2011   3055      danmcd 		if (rc != KS_IN_ADDR_NOTME &&
   2012   3055      danmcd 		    !(extv[SADB_X_EXT_ADDRESS_INNER_SRC] != NULL &&
   2013   4987      danmcd 		    rc == KS_IN_ADDR_UNSPEC)) {
   2014   4987      danmcd 			sadb_pfkey_error(pfkey_q, mp, EINVAL,
   2015   4987      danmcd 			    SADB_X_DIAGNOSTIC_MALFORMED_NATT_REM,
   2016   4987      danmcd 			    ksi->ks_in_serial);
   2017   3055      danmcd 			return (B_FALSE);
   2018   3055      danmcd 		}
   2019   3055      danmcd 		src = (struct sockaddr_in *)
   2020   3055      danmcd 		    (((sadb_address_t *)extv[SADB_X_EXT_ADDRESS_NATT_REM]) + 1);
   2021   3055      danmcd 		if (src->sin_family != AF_INET) {
   2022   3055      danmcd 			sadb_pfkey_error(pfkey_q, mp, EINVAL,
   2023   3055      danmcd 			    SADB_X_DIAGNOSTIC_BAD_NATT_REM_AF,
   2024   3055      danmcd 			    ksi->ks_in_serial);
   2025   3055      danmcd 			return (B_FALSE);
   2026   3055      danmcd 		}
   2027   3055      danmcd 	}
   2028   3055      danmcd 
   2029   3055      danmcd 	if (extv[SADB_X_EXT_ADDRESS_INNER_SRC] != NULL) {
   2030   3055      danmcd 		if (extv[SADB_X_EXT_ADDRESS_INNER_DST] == NULL) {
   2031   3055      danmcd 			sadb_pfkey_error(pfkey_q, mp, EINVAL,
   2032   3055      danmcd 			    SADB_X_DIAGNOSTIC_MISSING_INNER_DST,
   2033   3055      danmcd 			    ksi->ks_in_serial);
   2034   3055      danmcd 			return (B_FALSE);
   2035   3055      danmcd 		}
   2036   3055      danmcd 
   2037   3055      danmcd 		if (sadb_addrcheck(pfkey_q, mp,
   2038   3448    dh155122 		    extv[SADB_X_EXT_ADDRESS_INNER_DST], ksi->ks_in_serial, ns)
   2039   3055      danmcd 		    == KS_IN_ADDR_UNKNOWN ||
   2040   3055      danmcd 		    sadb_addrcheck(pfkey_q, mp,
   2041   3448    dh155122 		    extv[SADB_X_EXT_ADDRESS_INNER_SRC], ksi->ks_in_serial, ns)
   2042   3055      danmcd 		    == KS_IN_ADDR_UNKNOWN)
   2043   3055      danmcd 			return (B_FALSE);
   2044   3055      danmcd 
   2045   3055      danmcd 		isrc = (struct sockaddr_in *)
   2046   3055      danmcd 		    (((sadb_address_t *)extv[SADB_X_EXT_ADDRESS_INNER_SRC]) +
   2047   4987      danmcd 		    1);
   2048   3055      danmcd 		idst = (struct sockaddr_in6 *)
   2049   3055      danmcd 		    (((sadb_address_t *)extv[SADB_X_EXT_ADDRESS_INNER_DST]) +
   2050   4987      danmcd 		    1);
   2051   3055      danmcd 		if (isrc->sin_family != idst->sin6_family) {
   2052   3055      danmcd 			sadb_pfkey_error(pfkey_q, mp, EINVAL,
   2053   3055      danmcd 			    SADB_X_DIAGNOSTIC_INNER_AF_MISMATCH,
   2054   3055      danmcd 			    ksi->ks_in_serial);
   2055   3055      danmcd 			return (B_FALSE);
   2056   3055      danmcd 		}
   2057   3055      danmcd 	} else if (extv[SADB_X_EXT_ADDRESS_INNER_DST] != NULL) {
   2058   3055      danmcd 			sadb_pfkey_error(pfkey_q, mp, EINVAL,
   2059   3055      danmcd 			    SADB_X_DIAGNOSTIC_MISSING_INNER_SRC,
   2060   3055      danmcd 			    ksi->ks_in_serial);
   2061   3055      danmcd 			return (B_FALSE);
   2062   3055      danmcd 	} else {
   2063   3055      danmcd 		isrc = NULL;	/* For inner/outer port check below. */
   2064   3055      danmcd 	}
   2065   3055      danmcd 
   2066   3055      danmcd 	dstext = (sadb_address_t *)extv[SADB_EXT_ADDRESS_DST];
   2067   3055      danmcd 	srcext = (sadb_address_t *)extv[SADB_EXT_ADDRESS_SRC];
   2068   3055      danmcd 
   2069   3055      danmcd 	if (dstext == NULL || srcext == NULL)
   2070   3055      danmcd 		return (B_TRUE);
   2071   3055      danmcd 
   2072      0      stevel 	dst = (struct sockaddr_in6 *)(dstext + 1);
   2073      0      stevel 	src = (struct sockaddr_in *)(srcext + 1);
   2074      0      stevel 
   2075   3055      danmcd 	if (isrc != NULL &&
   2076   3055      danmcd 	    (isrc->sin_port != 0 || idst->sin6_port != 0) &&
   2077   3055      danmcd 	    (src->sin_port != 0 || dst->sin6_port != 0)) {
   2078   3055      danmcd 		/* Can't set inner and outer ports in one SA. */
   2079   3055      danmcd 		sadb_pfkey_error(pfkey_q, mp, EINVAL,
   2080   3055      danmcd 		    SADB_X_DIAGNOSTIC_DUAL_PORT_SETS,
   2081   3055      danmcd 		    ksi->ks_in_serial);
   2082   3055      danmcd 		return (B_FALSE);
   2083   3055      danmcd 	}
   2084   3055      danmcd 
   2085   3055      danmcd 	if (dst->sin6_family == src->sin_family)
   2086   3055      danmcd 		return (B_TRUE);
   2087   3055      danmcd 
   2088   3055      danmcd 	if (srcext->sadb_address_proto != dstext->sadb_address_proto) {
   2089   3055      danmcd 		if (srcext->sadb_address_proto == 0) {
   2090   3055      danmcd 			srcext->sadb_address_proto = dstext->sadb_address_proto;
   2091   3055      danmcd 		} else if (dstext->sadb_address_proto == 0) {
   2092   3055      danmcd 			dstext->sadb_address_proto = srcext->sadb_address_proto;
   2093   3055      danmcd 		} else {
   2094   3055      danmcd 			/* Inequal protocols, neither were 0.  Report error. */
   2095   3055      danmcd 			sadb_pfkey_error(pfkey_q, mp, EINVAL,
   2096   3055      danmcd 			    SADB_X_DIAGNOSTIC_PROTO_MISMATCH,
   2097   3055      danmcd 			    ksi->ks_in_serial);
   2098   3055      danmcd 			return (B_FALSE);
   2099   3055      danmcd 		}
   2100   3055      danmcd 	}
   2101   3055      danmcd 
   2102   3055      danmcd 	/*
   2103   3055      danmcd 	 * With the exception of an unspec IPv6 source and an IPv4
   2104   3055      danmcd 	 * destination, address families MUST me matched.
   2105   3055      danmcd 	 */
   2106   3055      danmcd 	if (src->sin_family == AF_INET ||
   2107   3055      danmcd 	    ksi->ks_in_srctype != KS_IN_ADDR_UNSPEC) {
   2108   3055      danmcd 		sadb_pfkey_error(pfkey_q, mp, EINVAL,
   2109   3055      danmcd 		    SADB_X_DIAGNOSTIC_AF_MISMATCH, ksi->ks_in_serial);
   2110   3055      danmcd 		return (B_FALSE);
   2111   3055      danmcd 	}
   2112      0      stevel 
   2113    691    sommerfe 	/*
   2114    691    sommerfe 	 * Convert "src" to AF_INET INADDR_ANY.  We rely on sin_port being
   2115    691    sommerfe 	 * in the same place for sockaddr_in and sockaddr_in6.
   2116    691    sommerfe 	 */
   2117    691    sommerfe 	sport = src->sin_port;
   2118      0      stevel 	bzero(src, sizeof (*src));
   2119      0      stevel 	src->sin_family = AF_INET;
   2120    691    sommerfe 	src->sin_port = sport;
   2121   3055      danmcd 
   2122   3055      danmcd 	return (B_TRUE);
   2123      0      stevel }
   2124      0      stevel 
   2125      0      stevel /*
   2126      0      stevel  * Set the results in "addrtype", given an IRE as requested by
   2127      0      stevel  * sadb_addrcheck().
   2128      0      stevel  */
   2129      0      stevel int
   2130      0      stevel sadb_addrset(ire_t *ire)
   2131      0      stevel {
   2132      0      stevel 	if ((ire->ire_type & IRE_BROADCAST) ||
   2133      0      stevel 	    (ire->ire_ipversion == IPV4_VERSION && CLASSD(ire->ire_addr)) ||
   2134      0      stevel 	    (ire->ire_ipversion == IPV6_VERSION &&
   2135   4987      danmcd 	    IN6_IS_ADDR_MULTICAST(&(ire->ire_addr_v6))))
   2136      0      stevel 		return (KS_IN_ADDR_MBCAST);
   2137      0      stevel 	if (ire->ire_type & (IRE_LOCAL | IRE_LOOPBACK))
   2138      0      stevel 		return (KS_IN_ADDR_ME);
   2139      0      stevel 	return (KS_IN_ADDR_NOTME);
   2140      0      stevel }
   2141      0      stevel 
   2142  10934  sommerfeld /*
   2143  10934  sommerfeld  * Match primitives..
   2144  10934  sommerfeld  * !!! TODO: short term: inner selectors
   2145  10934  sommerfeld  *		ipv6 scope id (ifindex)
   2146  10934  sommerfeld  * longer term:  zone id.  sensitivity label. uid.
   2147  10934  sommerfeld  */
   2148  10934  sommerfeld boolean_t
   2149  10934  sommerfeld sadb_match_spi(ipsa_query_t *sq, ipsa_t *sa)
   2150  10934  sommerfeld {
   2151  10934  sommerfeld 	return (sq->spi == sa->ipsa_spi);
   2152  10934  sommerfeld }
   2153  10934  sommerfeld 
   2154  10934  sommerfeld boolean_t
   2155  10934  sommerfeld sadb_match_dst_v6(ipsa_query_t *sq, ipsa_t *sa)
   2156  10934  sommerfeld {
   2157  10934  sommerfeld 	return (IPSA_ARE_ADDR_EQUAL(sa->ipsa_dstaddr, sq->dstaddr, AF_INET6));
   2158  10934  sommerfeld }
   2159  10934  sommerfeld 
   2160  10934  sommerfeld boolean_t
   2161  10934  sommerfeld sadb_match_src_v6(ipsa_query_t *sq, ipsa_t *sa)
   2162  10934  sommerfeld {
   2163  10934  sommerfeld 	return (IPSA_ARE_ADDR_EQUAL(sa->ipsa_srcaddr, sq->srcaddr, AF_INET6));
   2164  10934  sommerfeld }
   2165  10934  sommerfeld 
   2166  10934  sommerfeld boolean_t
   2167  10934  sommerfeld sadb_match_dst_v4(ipsa_query_t *sq, ipsa_t *sa)
   2168  10934  sommerfeld {
   2169  10934  sommerfeld 	return (sq->dstaddr[0] == sa->ipsa_dstaddr[0]);
   2170  10934  sommerfeld }
   2171  10934  sommerfeld 
   2172  10934  sommerfeld boolean_t
   2173  10934  sommerfeld sadb_match_src_v4(ipsa_query_t *sq, ipsa_t *sa)
   2174  10934  sommerfeld {
   2175  10934  sommerfeld 	return (sq->srcaddr[0] == sa->ipsa_srcaddr[0]);
   2176  10934  sommerfeld }
   2177  10934  sommerfeld 
   2178  10934  sommerfeld boolean_t
   2179  10934  sommerfeld sadb_match_dstid(ipsa_query_t *sq, ipsa_t *sa)
   2180  10934  sommerfeld {
   2181  10934  sommerfeld 	return ((sa->ipsa_dst_cid != NULL) &&
   2182  10934  sommerfeld 	    (sq->didtype == sa->ipsa_dst_cid->ipsid_type) &&
   2183  10934  sommerfeld 	    (strcmp(sq->didstr, sa->ipsa_dst_cid->ipsid_cid) == 0));
   2184  10934  sommerfeld 
   2185  10934  sommerfeld }
   2186  10934  sommerfeld boolean_t
   2187  10934  sommerfeld sadb_match_srcid(ipsa_query_t *sq, ipsa_t *sa)
   2188  10934  sommerfeld {
   2189  10934  sommerfeld 	return ((sa->ipsa_src_cid != NULL) &&
   2190  10934  sommerfeld 	    (sq->sidtype == sa->ipsa_src_cid->ipsid_type) &&
   2191  10934  sommerfeld 	    (strcmp(sq->sidstr, sa->ipsa_src_cid->ipsid_cid) == 0));
   2192  10934  sommerfeld }
   2193  10934  sommerfeld 
   2194  10934  sommerfeld boolean_t
   2195  10934  sommerfeld sadb_match_kmc(ipsa_query_t *sq, ipsa_t *sa)
   2196  10934  sommerfeld {
   2197  10934  sommerfeld #define	M(a, b) (((a) == 0) || ((b) == 0) || ((a) == (b)))
   2198  10934  sommerfeld 
   2199  10934  sommerfeld 	return (M(sq->kmc, sa->ipsa_kmc) && M(sq->kmp, sa->ipsa_kmp));
   2200  10934  sommerfeld 
   2201  10934  sommerfeld #undef M
   2202  10934  sommerfeld }
   2203  10934  sommerfeld 
   2204  10934  sommerfeld /*
   2205  10934  sommerfeld  * Common function which extracts several PF_KEY extensions for ease of
   2206  10934  sommerfeld  * SADB matching.
   2207  10934  sommerfeld  *
   2208  10934  sommerfeld  * XXX TODO: weed out ipsa_query_t fields not used during matching
   2209  10934  sommerfeld  * or afterwards?
   2210  10934  sommerfeld  */
   2211  10934  sommerfeld int
   2212  10934  sommerfeld sadb_form_query(keysock_in_t *ksi, uint32_t req, uint32_t match,
   2213  10934  sommerfeld     ipsa_query_t *sq, int *diagnostic)
   2214  10934  sommerfeld {
   2215  10934  sommerfeld 	int i;
   2216  10934  sommerfeld 	ipsa_match_fn_t *mfpp = &(sq->matchers[0]);
   2217  10934  sommerfeld 
   2218  10934  sommerfeld 	for (i = 0; i < IPSA_NMATCH; i++)
   2219  10934  sommerfeld 		sq->matchers[i] = NULL;
   2220  10934  sommerfeld 
   2221  10934  sommerfeld 	ASSERT((req & ~match) == 0);
   2222  10934  sommerfeld 
   2223  10934  sommerfeld 	sq->req = req;
   2224  10934  sommerfeld 	sq->dstext = (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_DST];
   2225  10934  sommerfeld 	sq->srcext = (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_SRC];
   2226  10934  sommerfeld 	sq->assoc = (sadb_sa_t *)ksi->ks_in_extv[SADB_EXT_SA];
   2227  10934  sommerfeld 
   2228  10934  sommerfeld 	if ((req & IPSA_Q_DST) && (sq->dstext == NULL)) {
   2229  10934  sommerfeld 		*diagnostic = SADB_X_DIAGNOSTIC_MISSING_DST;
   2230  10934  sommerfeld 		return (EINVAL);
   2231  10934  sommerfeld 	}
   2232  10934  sommerfeld 	if ((req & IPSA_Q_SRC) && (sq->srcext == NULL)) {
   2233  10934  sommerfeld 		*diagnostic = SADB_X_DIAGNOSTIC_MISSING_SRC;
   2234  10934  sommerfeld 		return (EINVAL);
   2235  10934  sommerfeld 	}
   2236  10934  sommerfeld 	if ((req & IPSA_Q_SA) && (sq->assoc == NULL)) {
   2237  10934  sommerfeld 		*diagnostic = SADB_X_DIAGNOSTIC_MISSING_SA;
   2238  10934  sommerfeld 		return (EINVAL);
   2239  10934  sommerfeld 	}
   2240  10934  sommerfeld 
   2241  10934  sommerfeld 	if (match & IPSA_Q_SA) {
   2242  10934  sommerfeld 		*mfpp++ = sadb_match_spi;
   2243  10934  sommerfeld 		sq->spi = sq->assoc->sadb_sa_spi;
   2244  10934  sommerfeld 	}
   2245  10934  sommerfeld 
   2246  10934  sommerfeld 	if (sq->dstext != NULL)
   2247  10934  sommerfeld 		sq->dst = (struct sockaddr_in *)(sq->dstext + 1);
   2248  10934  sommerfeld 	else {
   2249  10934  sommerfeld 		sq->dst = NULL;
   2250  10934  sommerfeld 		sq->dst6 = NULL;
   2251  10934  sommerfeld 		sq->dstaddr = NULL;
   2252  10934  sommerfeld 	}
   2253  10934  sommerfeld 
   2254  10934  sommerfeld 	if (sq->srcext != NULL)
   2255  10934  sommerfeld 		sq->src = (struct sockaddr_in *)(sq->srcext + 1);
   2256  10934  sommerfeld 	else {
   2257  10934  sommerfeld 		sq->src = NULL;
   2258  10934  sommerfeld 		sq->src6 = NULL;
   2259  10934  sommerfeld 		sq->srcaddr = NULL;
   2260  10934  sommerfeld 	}
   2261  10934  sommerfeld 
   2262  10934  sommerfeld 	if (sq->dst != NULL)
   2263  10934  sommerfeld 		sq->af = sq->dst->sin_family;
   2264  10934  sommerfeld 	else if (sq->src != NULL)
   2265  10934  sommerfeld 		sq->af = sq->src->sin_family;
   2266  10934  sommerfeld 	else
   2267  10934  sommerfeld 		sq->af = AF_INET;
   2268  10934  sommerfeld 
   2269  10934  sommerfeld 	if (sq->af == AF_INET6) {
   2270  10934  sommerfeld 		if ((match & IPSA_Q_DST) && (sq->dstext != NULL)) {
   2271  10934  sommerfeld 			*mfpp++ = sadb_match_dst_v6;
   2272  10934  sommerfeld 			sq->dst6 = (struct sockaddr_in6 *)sq->dst;
   2273  10934  sommerfeld 			sq->dstaddr = (uint32_t *)&(sq->dst6->sin6_addr);
   2274  10934  sommerfeld 		} else {
   2275  10934  sommerfeld 			match &= ~IPSA_Q_DST;
   2276  10934  sommerfeld 			sq->dstaddr = ALL_ZEROES_PTR;
   2277  10934  sommerfeld 		}
   2278  10934  sommerfeld 
   2279  10934  sommerfeld 		if ((match & IPSA_Q_SRC) && (sq->srcext != NULL)) {
   2280  10934  sommerfeld 			sq->src6 = (struct sockaddr_in6 *)(sq->srcext + 1);
   2281  10934  sommerfeld 			sq->srcaddr = (uint32_t *)&sq->src6->sin6_addr;
   2282  10934  sommerfeld 			if (sq->src6->sin6_family != AF_INET6) {
   2283  10934  sommerfeld 				*diagnostic = SADB_X_DIAGNOSTIC_AF_MISMATCH;
   2284  10934  sommerfeld 				return (EINVAL);
   2285  10934  sommerfeld 			}
   2286  10934  sommerfeld 			*mfpp++ = sadb_match_src_v6;
   2287  10934  sommerfeld 		} else {
   2288  10934  sommerfeld 			match &= ~IPSA_Q_SRC;
   2289  10934  sommerfeld 			sq->srcaddr = ALL_ZEROES_PTR;
   2290  10934  sommerfeld 		}
   2291  10934  sommerfeld 	} else {
   2292  10934  sommerfeld 		sq->src6 = sq->dst6 = NULL;
   2293  10934  sommerfeld 		if ((match & IPSA_Q_DST) && (sq->dstext != NULL)) {
   2294  10934  sommerfeld 			*mfpp++ = sadb_match_dst_v4;
   2295  10934  sommerfeld 			sq->dstaddr = (uint32_t *)&sq->dst->sin_addr;
   2296  10934  sommerfeld 		} else {
   2297  10934  sommerfeld 			match &= ~IPSA_Q_DST;
   2298  10934  sommerfeld 			sq->dstaddr = ALL_ZEROES_PTR;
   2299  10934  sommerfeld 		}
   2300  10934  sommerfeld 		if ((match & IPSA_Q_SRC) && (sq->srcext != NULL)) {
   2301  10934  sommerfeld 			sq->srcaddr = (uint32_t *)&sq->src->sin_addr;
   2302  10934  sommerfeld 			if (sq->src->sin_family != AF_INET) {
   2303  10934  sommerfeld 				*diagnostic = SADB_X_DIAGNOSTIC_AF_MISMATCH;
   2304  10934  sommerfeld 				return (EINVAL);
   2305  10934  sommerfeld 			}
   2306  10934  sommerfeld 			*mfpp++ = sadb_match_src_v4;
   2307  10934  sommerfeld 		} else {
   2308  10934  sommerfeld 			match &= ~IPSA_Q_SRC;
   2309  10934  sommerfeld 			sq->srcaddr = ALL_ZEROES_PTR;
   2310  10934  sommerfeld 		}
   2311  10934  sommerfeld 	}
   2312  10934  sommerfeld 
   2313  10934  sommerfeld 	sq->dstid = (sadb_ident_t *)ksi->ks_in_extv[SADB_EXT_IDENTITY_DST];
   2314  10934  sommerfeld 	if ((match & IPSA_Q_DSTID) && (sq->dstid != NULL)) {
   2315  10934  sommerfeld 		sq->didstr = (char *)(sq->dstid + 1);
   2316  10934  sommerfeld 		sq->didtype = sq->dstid->sadb_ident_type;
   2317  10934  sommerfeld 		*mfpp++ = sadb_match_dstid;
   2318  10934  sommerfeld 	}
   2319  10934  sommerfeld 
   2320  10934  sommerfeld 	sq->srcid = (sadb_ident_t *)ksi->ks_in_extv[SADB_EXT_IDENTITY_SRC];
   2321  10934  sommerfeld 
   2322  10934  sommerfeld 	if ((match & IPSA_Q_SRCID) && (sq->srcid != NULL)) {
   2323  10934  sommerfeld 		sq->sidstr = (char *)(sq->srcid + 1);
   2324  10934  sommerfeld 		sq->sidtype = sq->srcid->sadb_ident_type;
   2325  10934  sommerfeld 		*mfpp++ = sadb_match_srcid;
   2326  10934  sommerfeld 	}
   2327  10934  sommerfeld 
   2328  10934  sommerfeld 	sq->kmcext = (sadb_x_kmc_t *)ksi->ks_in_extv[SADB_X_EXT_KM_COOKIE];
   2329  10934  sommerfeld 	sq->kmc = 0;
   2330  10934  sommerfeld 	sq->kmp = 0;
   2331  10934  sommerfeld 
   2332  10934  sommerfeld 	if ((match & IPSA_Q_KMC) && (sq->kmcext)) {
   2333  10934  sommerfeld 		sq->kmc = sq->kmcext->sadb_x_kmc_cookie;
   2334  10934  sommerfeld 		sq->kmp = sq->kmcext->sadb_x_kmc_proto;
   2335  10934  sommerfeld 		*mfpp++ = sadb_match_kmc;
   2336  10934  sommerfeld 	}
   2337  10934  sommerfeld 
   2338  10934  sommerfeld 	if (match & (IPSA_Q_INBOUND|IPSA_Q_OUTBOUND)) {
   2339  10934  sommerfeld 		if (sq->af == AF_INET6)
   2340  10934  sommerfeld 			sq->sp = &sq->spp->s_v6;
   2341  10934  sommerfeld 		else
   2342  10934  sommerfeld 			sq->sp = &sq->spp->s_v4;
   2343  10934  sommerfeld 	} else {
   2344  10934  sommerfeld 		sq->sp = NULL;
   2345  10934  sommerfeld 	}
   2346  10934  sommerfeld 
   2347  10934  sommerfeld 	if (match & IPSA_Q_INBOUND) {
   2348  10934  sommerfeld 		sq->inhash = INBOUND_HASH(sq->sp, sq->assoc->sadb_sa_spi);
   2349  10934  sommerfeld 		sq->inbound = &sq->sp->sdb_if[sq->inhash];
   2350  10934  sommerfeld 	} else {
   2351  10934  sommerfeld 		sq->inhash = 0;
   2352  10934  sommerfeld 		sq->inbound = NULL;
   2353  10934  sommerfeld 	}
   2354  10934  sommerfeld 
   2355  10934  sommerfeld 	if (match & IPSA_Q_OUTBOUND) {
   2356  10934  sommerfeld 		if (sq->af == AF_INET6) {
   2357  10934  sommerfeld 			sq->outhash = OUTBOUND_HASH_V6(sq->sp, *(sq->dstaddr));
   2358  10934  sommerfeld 		} else {
   2359  10934  sommerfeld 			sq->outhash = OUTBOUND_HASH_V4(sq->sp, *(sq->dstaddr));
   2360  10934  sommerfeld 		}
   2361  10934  sommerfeld 		sq->outbound = &sq->sp->sdb_of[sq->outhash];
   2362  10934  sommerfeld 	} else {
   2363  10934  sommerfeld 		sq->outhash = 0;
   2364  10934  sommerfeld 		sq->outbound = NULL;
   2365  10934  sommerfeld 	}
   2366  10934  sommerfeld 	sq->match = match;
   2367  10934  sommerfeld 	return (0);
   2368  10934  sommerfeld }
   2369  10934  sommerfeld 
   2370  10934  sommerfeld /*
   2371  10934  sommerfeld  * Match an initialized query structure with a security association;
   2372  10934  sommerfeld  * return B_TRUE on a match, B_FALSE on a miss.
   2373  10934  sommerfeld  * Applies match functions set up by sadb_form_query() until one returns false.
   2374  10934  sommerfeld  */
   2375  10934  sommerfeld boolean_t
   2376  10934  sommerfeld sadb_match_query(ipsa_query_t *sq, ipsa_t *sa)
   2377  10934  sommerfeld {
   2378  10934  sommerfeld 	ipsa_match_fn_t *mfpp = &(sq->matchers[0]);
   2379  10934  sommerfeld 	ipsa_match_fn_t mfp;
   2380  10934  sommerfeld 
   2381  10934  sommerfeld 	for (mfp = *mfpp++; mfp != NULL; mfp = *mfpp++) {
   2382  10934  sommerfeld 		if (!mfp(sq, sa))
   2383  10934  sommerfeld 			return (B_FALSE);
   2384  10934  sommerfeld 	}
   2385  10934  sommerfeld 	return (B_TRUE);
   2386  10934  sommerfeld }
   2387      0      stevel 
   2388      0      stevel /*
   2389      0      stevel  * Walker callback function to delete sa's based on src/dst address.
   2390      0      stevel  * Assumes that we're called with *head locked, no other locks held;
   2391      0      stevel  * Conveniently, and not coincidentally, this is both what sadb_walker
   2392      0      stevel  * gives us and also what sadb_unlinkassoc expects.
   2393      0      stevel  */
   2394      0      stevel struct sadb_purge_state
   2395      0      stevel {
   2396  10934  sommerfeld 	ipsa_query_t sq;
   2397      0      stevel 	boolean_t inbnd;
   2398   7749  Thejaswini 	uint8_t sadb_sa_state;
   2399      0      stevel };
   2400      0      stevel 
   2401      0      stevel static void
   2402      0      stevel sadb_purge_cb(isaf_t *head, ipsa_t *entry, void *cookie)
   2403      0      stevel {
   2404      0      stevel 	struct sadb_purge_state *ps = (struct sadb_purge_state *)cookie;
   2405      0      stevel 
   2406      0      stevel 	ASSERT(MUTEX_HELD(&head->isaf_lock));
   2407      0      stevel 
   2408      0      stevel 	mutex_enter(&entry->ipsa_lock);
   2409      0      stevel 
   2410  10934  sommerfeld 	if (entry->ipsa_state == IPSA_STATE_LARVAL ||
   2411  10934  sommerfeld 	    !sadb_match_query(&ps->sq, entry)) {
   2412      0      stevel 		mutex_exit(&entry->ipsa_lock);
   2413      0      stevel 		return;
   2414      0      stevel 	}
   2415      0      stevel 
   2416   7749  Thejaswini 	if (ps->inbnd) {
   2417   7749  Thejaswini 		sadb_delete_cluster(entry);
   2418   7749  Thejaswini 	}
   2419      0      stevel 	entry->ipsa_state = IPSA_STATE_DEAD;
   2420  11042        Erik 	(void) sadb_torch_assoc(head, entry);
   2421      0      stevel }
   2422      0      stevel 
   2423      0      stevel /*
   2424      0      stevel  * Common code to purge an SA with a matching src or dst address.
   2425      0      stevel  * Don't kill larval SA's in such a purge.
   2426      0      stevel  */
   2427      0      stevel int
   2428  10934  sommerfeld sadb_purge_sa(mblk_t *mp, keysock_in_t *ksi, sadb_t *sp,
   2429  11042        Erik 	int *diagnostic, queue_t *pfkey_q)
   2430  10934  sommerfeld {
   2431      0      stevel 	struct sadb_purge_state ps;
   2432  10934  sommerfeld 	int error = sadb_form_query(ksi, 0,
   2433  10934  sommerfeld 	    IPSA_Q_SRC|IPSA_Q_DST|IPSA_Q_SRCID|IPSA_Q_DSTID|IPSA_Q_KMC,
   2434  10934  sommerfeld 	    &ps.sq, diagnostic);
   2435  10934  sommerfeld 
   2436  10934  sommerfeld 	if (error != 0)
   2437  10934  sommerfeld 		return (error);
   2438      0      stevel 
   2439      0      stevel 	/*
   2440      0      stevel 	 * This is simple, crude, and effective.
   2441      0      stevel 	 * Unimplemented optimizations (TBD):
   2442      0      stevel 	 * - we can limit how many places we search based on where we
   2443      0      stevel 	 * think the SA is filed.
   2444      0      stevel 	 * - if we get a dst address, we can hash based on dst addr to find
   2445      0      stevel 	 * the correct bucket in the outbound table.
   2446      0      stevel 	 */
   2447      0      stevel 	ps.inbnd = B_TRUE;
   2448    564    sommerfe 	sadb_walker(sp->sdb_if, sp->sdb_hashsize, sadb_purge_cb, &ps);
   2449      0      stevel 	ps.inbnd = B_FALSE;
   2450    564    sommerfe 	sadb_walker(sp->sdb_of, sp->sdb_hashsize, sadb_purge_cb, &ps);
   2451      0      stevel 
   2452      0      stevel 	ASSERT(mp->b_cont != NULL);
   2453      0      stevel 	sadb_pfkey_echo(pfkey_q, mp, (sadb_msg_t *)mp->b_cont->b_rptr, ksi,
   2454      0      stevel 	    NULL);
   2455      0      stevel 	return (0);
   2456      0      stevel }
   2457      0      stevel 
   2458   7749  Thejaswini static void
   2459  10934  sommerfeld sadb_delpair_state_one(isaf_t *head, ipsa_t *entry, void *cookie)
   2460   7749  Thejaswini {
   2461   7749  Thejaswini 	struct sadb_purge_state *ps = (struct sadb_purge_state *)cookie;
   2462   7749  Thejaswini 	isaf_t  *inbound_bucket;
   2463   7749  Thejaswini 	ipsa_t *peer_assoc;
   2464  10934  sommerfeld 	ipsa_query_t *sq = &ps->sq;
   2465   7749  Thejaswini 
   2466   7749  Thejaswini 	ASSERT(MUTEX_HELD(&head->isaf_lock));
   2467   7749  Thejaswini 
   2468   7749  Thejaswini 	mutex_enter(&entry->ipsa_lock);
   2469   7749  Thejaswini 
   2470   7749  Thejaswini 	if ((entry->ipsa_state != ps->sadb_sa_state) ||
   2471  10934  sommerfeld 	    ((sq->srcaddr != NULL) &&
   2472  10934  sommerfeld 	    !IPSA_ARE_ADDR_EQUAL(entry->ipsa_srcaddr, sq->srcaddr, sq->af))) {
   2473   7749  Thejaswini 		mutex_exit(&entry->ipsa_lock);
   2474   7749  Thejaswini 		return;
   2475   7749  Thejaswini 	}
   2476   7749  Thejaswini 
   2477   7749  Thejaswini 	/*
   2478   7749  Thejaswini 	 * The isaf_t *, which is passed in , is always an outbound bucket,
   2479   7749  Thejaswini 	 * and we are preserving the outbound-then-inbound hash-bucket lock
   2480   7749  Thejaswini 	 * ordering. The sadb_walker() which triggers this function is called
   2481   7749  Thejaswini 	 * only on the outbound fanout, and the corresponding inbound bucket
   2482   7749  Thejaswini 	 * lock is safe to acquire here.
   2483   7749  Thejaswini 	 */
   2484   7749  Thejaswini 
   2485   7749  Thejaswini 	if (entry->ipsa_haspeer) {
   2486  10934  sommerfeld 		inbound_bucket = INBOUND_BUCKET(sq->sp, entry->ipsa_spi);
   2487   7749  Thejaswini 		mutex_enter(&inbound_bucket->isaf_lock);
   2488   7749  Thejaswini 		peer_assoc = ipsec_getassocbyspi(inbound_bucket,
   2489   7749  Thejaswini 		    entry->ipsa_spi, entry->ipsa_srcaddr,
   2490   7749  Thejaswini 		    entry->ipsa_dstaddr, entry->ipsa_addrfam);
   2491   7749  Thejaswini 	} else {
   2492  10934  sommerfeld 		inbound_bucket = INBOUND_BUCKET(sq->sp, entry->ipsa_otherspi);
   2493   7749  Thejaswini 		mutex_enter(&inbound_bucket->isaf_lock);
   2494   7749  Thejaswini 		peer_assoc = ipsec_getassocbyspi(inbound_bucket,
   2495   7749  Thejaswini 		    entry->ipsa_otherspi, entry->ipsa_dstaddr,
   2496   7749  Thejaswini 		    entry->ipsa_srcaddr, entry->ipsa_addrfam);
   2497   7749  Thejaswini 	}
   2498   7749  Thejaswini 
   2499   7749  Thejaswini 	entry->ipsa_state = IPSA_STATE_DEAD;
   2500  11042        Erik 	(void) sadb_torch_assoc(head, entry);
   2501   7749  Thejaswini 	if (peer_assoc != NULL) {
   2502   7749  Thejaswini 		mutex_enter(&peer_assoc->ipsa_lock);
   2503   7749  Thejaswini 		peer_assoc->ipsa_state = IPSA_STATE_DEAD;
   2504  11042        Erik 		(void) sadb_torch_assoc(inbound_bucket, peer_assoc);
   2505   7749  Thejaswini 	}
   2506   7749  Thejaswini 	mutex_exit(&inbound_bucket->isaf_lock);
   2507   7749  Thejaswini }
   2508   7749  Thejaswini 
   2509  10934  sommerfeld static int
   2510  10934  sommerfeld sadb_delpair_state(mblk_t *mp, keysock_in_t *ksi, sadbp_t *spp,
   2511  10934  sommerfeld     int *diagnostic, queue_t *pfkey_q)
   2512  10934  sommerfeld {
   2513  10934  sommerfeld 	sadb_sa_t *assoc = (sadb_sa_t *)ksi->ks_in_extv[SADB_EXT_SA];
   2514  10934  sommerfeld 	struct sadb_purge_state ps;
   2515  10934  sommerfeld 	int error;
   2516  10934  sommerfeld 
   2517  10934  sommerfeld 	ps.sq.spp = spp;		/* XXX param */
   2518  10934  sommerfeld 
   2519  10934  sommerfeld 	error = sadb_form_query(ksi, IPSA_Q_DST|IPSA_Q_SRC,
   2520  10934  sommerfeld 	    IPSA_Q_SRC|IPSA_Q_DST|IPSA_Q_SRCID|IPSA_Q_DSTID|IPSA_Q_KMC,
   2521  10934  sommerfeld 	    &ps.sq, diagnostic);
   2522  10934  sommerfeld 	if (error != 0)
   2523  10934  sommerfeld 		return (error);
   2524  10934  sommerfeld 
   2525  10934  sommerfeld 	ps.inbnd = B_FALSE;
   2526  10934  sommerfeld 	ps.sadb_sa_state = assoc->sadb_sa_state;
   2527  10934  sommerfeld 	sadb_walker(ps.sq.sp->sdb_of, ps.sq.sp->sdb_hashsize,
   2528  10934  sommerfeld 	    sadb_delpair_state_one, &ps);
   2529  10934  sommerfeld 
   2530  10934  sommerfeld 	ASSERT(mp->b_cont != NULL);
   2531  10934  sommerfeld 	sadb_pfkey_echo(pfkey_q, mp, (sadb_msg_t *)mp->b_cont->b_rptr,
   2532  10934  sommerfeld 	    ksi, NULL);
   2533  10934  sommerfeld 	return (0);
   2534  10934  sommerfeld }
   2535  10934  sommerfeld 
   2536      0      stevel /*
   2537      0      stevel  * Common code to delete/get an SA.
   2538      0      stevel  */
   2539      0      stevel int
   2540      0      stevel sadb_delget_sa(mblk_t *mp, keysock_in_t *ksi, sadbp_t *spp,
   2541   6668     markfen     int *diagnostic, queue_t *pfkey_q, uint8_t sadb_msg_type)
   2542      0      stevel {
   2543  10934  sommerfeld 	ipsa_query_t sq;
   2544   6668     markfen 	ipsa_t *echo_target = NULL;
   2545  10934  sommerfeld 	ipsap_t ipsapp;
   2546   6668     markfen 	uint_t	error = 0;
   2547   6668     markfen 
   2548  10934  sommerfeld 	if (sadb_msg_type == SADB_X_DELPAIR_STATE)
   2549  10934  sommerfeld 		return (sadb_delpair_state(mp, ksi, spp, diagnostic, pfkey_q));
   2550  10934  sommerfeld 
   2551  10934  sommerfeld 	sq.spp = spp;		/* XXX param */
   2552  10934  sommerfeld 	error = sadb_form_query(ksi, IPSA_Q_DST|IPSA_Q_SA,
   2553  10934  sommerfeld 	    IPSA_Q_SRC|IPSA_Q_DST|IPSA_Q_SA|IPSA_Q_INBOUND|IPSA_Q_OUTBOUND,
   2554  10934  sommerfeld 	    &sq, diagnostic);
   2555  10934  sommerfeld 	if (error != 0)
   2556  10934  sommerfeld 		return (error);
   2557  10934  sommerfeld 
   2558  10934  sommerfeld 	error = get_ipsa_pair(&sq, &ipsapp, diagnostic);
   2559  10934  sommerfeld 	if (error != 0) {
   2560  10934  sommerfeld 		return (error);
   2561  10934  sommerfeld 	}
   2562  10934  sommerfeld 
   2563  10934  sommerfeld 	echo_target = ipsapp.ipsap_sa_ptr;
   2564   6668     markfen 	if (echo_target == NULL)
   2565  10934  sommerfeld 		echo_target = ipsapp.ipsap_psa_ptr;
   2566   6668     markfen 
   2567   6668     markfen 	if (sadb_msg_type == SADB_DELETE || sadb_msg_type == SADB_X_DELPAIR) {
   2568   6668     markfen 		/*
   2569   6668     markfen 		 * Bucket locks will be required if SA is actually unlinked.
   2570   6668     markfen 		 * get_ipsa_pair() returns valid hash bucket pointers even
   2571  10019        Mark 		 * if it can't find a pair SA pointer. To prevent a potential
   2572  10019        Mark 		 * deadlock, always lock the outbound bucket before the inbound.
   2573  10019        Mark 		 */
   2574  10934  sommerfeld 		if (ipsapp.in_inbound_table) {
   2575  10934  sommerfeld 			mutex_enter(&ipsapp.ipsap_pbucket->isaf_lock);
   2576  10934  sommerfeld 			mutex_enter(&ipsapp.ipsap_bucket->isaf_lock);
   2577  10934  sommerfeld 		} else {
   2578  10934  sommerfeld 			mutex_enter(&ipsapp.ipsap_bucket->isaf_lock);
   2579  10934  sommerfeld 			mutex_enter(&ipsapp.ipsap_pbucket->isaf_lock);
   2580  10934  sommerfeld 		}
   2581  10934  sommerfeld 
   2582  10934  sommerfeld 		if (ipsapp.ipsap_sa_ptr != NULL) {
   2583  10934  sommerfeld 			mutex_enter(&ipsapp.ipsap_sa_ptr->ipsa_lock);
   2584  10934  sommerfeld 			if (ipsapp.ipsap_sa_ptr->ipsa_flags & IPSA_F_INBOUND) {
   2585  10934  sommerfeld 				sadb_delete_cluster(ipsapp.ipsap_sa_ptr);
   2586  10934  sommerfeld 			}
   2587  10934  sommerfeld 			ipsapp.ipsap_sa_ptr->ipsa_state = IPSA_STATE_DEAD;
   2588  10934  sommerfeld 			(void) sadb_torch_assoc(ipsapp.ipsap_bucket,
   2589  11042        Erik 			    ipsapp.ipsap_sa_ptr);
   2590   6668     markfen 			/*
   2591   6668     markfen 			 * sadb_torch_assoc() releases the ipsa_lock
   2592   6668     markfen 			 * and calls sadb_unlinkassoc() which does a
   2593   6668     markfen 			 * IPSA_REFRELE.
   2594   6668     markfen 			 */
   2595   6668     markfen 		}
   2596  10934  sommerfeld 		if (ipsapp.ipsap_psa_ptr != NULL) {
   2597  10934  sommerfeld 			mutex_enter(&ipsapp.ipsap_psa_ptr->ipsa_lock);
   2598   9322        Paul 			if (sadb_msg_type == SADB_X_DELPAIR ||
   2599  10934  sommerfeld 			    ipsapp.ipsap_psa_ptr->ipsa_haspeer) {
   2600  10934  sommerfeld 				if (ipsapp.ipsap_psa_ptr->ipsa_flags &
   2601   7749  Thejaswini 				    IPSA_F_INBOUND) {
   2602  10934  sommerfeld 					sadb_delete_cluster
   2603  10934  sommerfeld 					    (ipsapp.ipsap_psa_ptr);
   2604  10934  sommerfeld 				}
   2605  10934  sommerfeld 				ipsapp.ipsap_psa_ptr->ipsa_state =
   2606   6668     markfen 				    IPSA_STATE_DEAD;
   2607  10934  sommerfeld 				(void) sadb_torch_assoc(ipsapp.ipsap_pbucket,
   2608  11042        Erik 				    ipsapp.ipsap_psa_ptr);
   2609   6668     markfen 			} else {
   2610   6668     markfen 				/*
   2611   6668     markfen 				 * Only half of the "pair" has been deleted.
   2612   6668     markfen 				 * Update the remaining SA and remove references
   2613   6668     markfen 				 * to its pair SA, which is now gone.
   2614   6668     markfen 				 */
   2615  10934  sommerfeld 				ipsapp.ipsap_psa_ptr->ipsa_otherspi = 0;
   2616  10934  sommerfeld 				ipsapp.ipsap_psa_ptr->ipsa_flags &=
   2617   6668     markfen 				    ~IPSA_F_PAIRED;
   2618  10934  sommerfeld 				mutex_exit(&ipsapp.ipsap_psa_ptr->ipsa_lock);
   2619   6668     markfen 			}
   2620   6668     markfen 		} else if (sadb_msg_type == SADB_X_DELPAIR) {
   2621   6668     markfen 			*diagnostic = SADB_X_DIAGNOSTIC_PAIR_SA_NOTFOUND;
   2622   6668     markfen 			error = ESRCH;
   2623   6668     markfen 		}
   2624  10934  sommerfeld 		mutex_exit(&ipsapp.ipsap_bucket->isaf_lock);
   2625  10934  sommerfeld 		mutex_exit(&ipsapp.ipsap_pbucket->isaf_lock);
   2626   6668     markfen 	}
   2627   6668     markfen 
   2628   6668     markfen 	ASSERT(mp->b_cont != NULL);
   2629   6668     markfen 
   2630   6668     markfen 	if (error == 0)
   2631   6668     markfen 		sadb_pfkey_echo(pfkey_q, mp, (sadb_msg_t *)
   2632   6668     markfen 		    mp->b_cont->b_rptr, ksi, echo_target);
   2633   6668     markfen 
   2634  10934  sommerfeld 	destroy_ipsa_pair(&ipsapp);
   2635   6668     markfen 
   2636   6668     markfen 	return (error);
   2637   6668     markfen }
   2638   6668     markfen 
   2639   6668     markfen /*
   2640   6668     markfen  * This function takes a sadb_sa_t and finds the ipsa_t structure
   2641   6668     markfen  * and the isaf_t (hash bucket) that its stored under. If the security
   2642   6668     markfen  * association has a peer, the ipsa_t structure and bucket for that security
   2643   6668     markfen  * association are also searched for. The "pair" of ipsa_t's and isaf_t's
   2644   6668     markfen  * are returned as a ipsap_t.
   2645   6668     markfen  *
   2646  10019        Mark  * The hash buckets are returned for convenience, if the calling function
   2647  10019        Mark  * needs to use the hash bucket locks, say to remove the SA's, it should
   2648  10019        Mark  * take care to observe the convention of locking outbound bucket then
   2649  10019        Mark  * inbound bucket. The flag in_inbound_table provides direction.
   2650  10019        Mark  *
   2651   6668     markfen  * Note that a "pair" is defined as one (but not both) of the following:
   2652   6668     markfen  *
   2653   6668     markfen  * A security association which has a soft reference to another security
   2654   6668     markfen  * association via its SPI.
   2655   6668     markfen  *
   2656   6668     markfen  * A security association that is not obviously "inbound" or "outbound" so
   2657   6668     markfen  * it appears in both hash tables, the "peer" being the same security
   2658   6668     markfen  * association in the other hash table.
   2659   6668     markfen  *
   2660   6668     markfen  * This function will return NULL if the ipsa_t can't be found in the
   2661   6668     markfen  * inbound or outbound  hash tables (not found). If only one ipsa_t is
   2662   6668     markfen  * found, the pair ipsa_t will be NULL. Both isaf_t values are valid
   2663   6668     markfen  * provided at least one ipsa_t is found.
   2664   6668     markfen  */
   2665  10934  sommerfeld static int
   2666  10934  sommerfeld get_ipsa_pair(ipsa_query_t *sq, ipsap_t *ipsapp, int *diagnostic)
   2667  10934  sommerfeld {
   2668   6668     markfen 	uint32_t pair_srcaddr[IPSA_MAX_ADDRLEN];
   2669   6668     markfen 	uint32_t pair_dstaddr[IPSA_MAX_ADDRLEN];
   2670   6668     markfen 	uint32_t pair_spi;
   2671   6668     markfen 
   2672  10934  sommerfeld 	init_ipsa_pair(ipsapp);
   2673  10019        Mark 
   2674  10019        Mark 	ipsapp->in_inbound_table = B_FALSE;
   2675      0      stevel 
   2676      0      stevel 	/* Lock down both buckets. */
   2677  10934  sommerfeld 	mutex_enter(&sq->outbound->isaf_lock);
   2678  10934  sommerfeld 	mutex_enter(&sq->inbound->isaf_lock);
   2679  10934  sommerfeld 
   2680  10934  sommerfeld 	if (sq->assoc->sadb_sa_flags & IPSA_F_INBOUND) {
   2681  10934  sommerfeld 		ipsapp->ipsap_sa_ptr = ipsec_getassocbyspi(sq->inbound,
   2682  10934  sommerfeld 		    sq->assoc->sadb_sa_spi, sq->srcaddr, sq->dstaddr, sq->af);
   2683   6668     markfen 		if (ipsapp->ipsap_sa_ptr != NULL) {
   2684  10934  sommerfeld 			ipsapp->ipsap_bucket = sq->inbound;
   2685  10934  sommerfeld 			ipsapp->ipsap_pbucket = sq->outbound;
   2686  10019        Mark 			ipsapp->in_inbound_table = B_TRUE;
   2687   6668     markfen 		} else {
   2688  10934  sommerfeld 			ipsapp->ipsap_sa_ptr = ipsec_getassocbyspi(sq->outbound,
   2689  10934  sommerfeld 			    sq->assoc->sadb_sa_spi, sq->srcaddr, sq->dstaddr,
   2690  10934  sommerfeld 			    sq->af);
   2691  10934  sommerfeld 			ipsapp->ipsap_bucket = sq->outbound;
   2692  10934  sommerfeld 			ipsapp->ipsap_pbucket = sq->inbound;
   2693   6668     markfen 		}
   2694   6668     markfen 	} else {
   2695   6668     markfen 		/* IPSA_F_OUTBOUND is set *or* no directions flags set. */
   2696   6668     markfen 		ipsapp->ipsap_sa_ptr =
   2697  10934  sommerfeld 		    ipsec_getassocbyspi(sq->outbound,
   2698  10934  sommerfeld 		    sq->assoc->sadb_sa_spi, sq->srcaddr, sq->dstaddr, sq->af);
   2699   6668     markfen 		if (ipsapp->ipsap_sa_ptr != NULL) {
   2700  10934  sommerfeld 			ipsapp->ipsap_bucket = sq->outbound;
   2701  10934  sommerfeld 			ipsapp->ipsap_pbucket = sq->inbound;
   2702  10934  sommerfeld 		} else {
   2703  10934  sommerfeld 			ipsapp->ipsap_sa_ptr = ipsec_getassocbyspi(sq->inbound,
   2704  10934  sommerfeld 			    sq->assoc->sadb_sa_spi, sq->srcaddr, sq->dstaddr,
   2705  10934  sommerfeld 			    sq->af);
   2706  10934  sommerfeld 			ipsapp->ipsap_bucket = sq->inbound;
   2707  10934  sommerfeld 			ipsapp->ipsap_pbucket = sq->outbound;
   2708   6668     markfen 			if (ipsapp->ipsap_sa_ptr != NULL)
   2709  10019        Mark 				ipsapp->in_inbound_table = B_TRUE;
   2710   6668     markfen 		}
   2711   6668     markfen 	}
   2712   6668     markfen 
   2713   6668     markfen 	if (ipsapp->ipsap_sa_ptr == NULL) {
   2714  10934  sommerfeld 		mutex_exit(&sq->outbound->isaf_lock);
   2715  10934  sommerfeld 		mutex_exit(&sq->inbound->isaf_lock);
   2716  10934  sommerfeld 		*diagnostic = SADB_X_DIAGNOSTIC_SA_NOTFOUND;
   2717  10934  sommerfeld 		return (ESRCH);
   2718   6668     markfen 	}
   2719   6668     markfen 
   2720   6668     markfen 	if ((ipsapp->ipsap_sa_ptr->ipsa_state == IPSA_STATE_LARVAL) &&
   2721  10019        Mark 	    ipsapp->in_inbound_table) {
   2722  10934  sommerfeld 		mutex_exit(&sq->outbound->isaf_lock);
   2723  10934  sommerfeld 		mutex_exit(&sq->inbound->isaf_lock);
   2724  10934  sommerfeld 		return (0);
   2725   6668     markfen 	}
   2726   6668     markfen 
   2727   6668     markfen 	mutex_enter(&ipsapp->ipsap_sa_ptr->ipsa_lock);
   2728   6668     markfen 	if (ipsapp->ipsap_sa_ptr->ipsa_haspeer) {
   2729   6668     markfen 		/*
   2730   6668     markfen 		 * haspeer implies no sa_pairing, look for same spi
   2731   6668     markfen 		 * in other hashtable.
   2732   6668     markfen 		 */
   2733   6668     markfen 		ipsapp->ipsap_psa_ptr =
   2734   6668     markfen 		    ipsec_getassocbyspi(ipsapp->ipsap_pbucket,
   2735  10934  sommerfeld 		    sq->assoc->sadb_sa_spi, sq->srcaddr, sq->dstaddr, sq->af);
   2736   6668     markfen 		mutex_exit(&ipsapp->ipsap_sa_ptr->ipsa_lock);
   2737  10934  sommerfeld 		mutex_exit(&sq->outbound->isaf_lock);
   2738  10934  sommerfeld 		mutex_exit(&sq->inbound->isaf_lock);
   2739  10934  sommerfeld 		return (0);
   2740   6668     markfen 	}
   2741   6668     markfen 	pair_spi = ipsapp->ipsap_sa_ptr->ipsa_otherspi;
   2742   6668     markfen 	IPSA_COPY_ADDR(&pair_srcaddr,
   2743  10934  sommerfeld 	    ipsapp->ipsap_sa_ptr->ipsa_srcaddr, sq->af);
   2744   6668     markfen 	IPSA_COPY_ADDR(&pair_dstaddr,
   2745  10934  sommerfeld 	    ipsapp->ipsap_sa_ptr->ipsa_dstaddr, sq->af);
   2746   6668     markfen 	mutex_exit(&ipsapp->ipsap_sa_ptr->ipsa_lock);
   2747  10934  sommerfeld 	mutex_exit(&sq->inbound->isaf_lock);
   2748  10934  sommerfeld 	mutex_exit(&sq->outbound->isaf_lock);
   2749   6668     markfen 
   2750   6668     markfen 	if (pair_spi == 0) {
   2751   6668     markfen 		ASSERT(ipsapp->ipsap_bucket != NULL);
   2752   6668     markfen 		ASSERT(ipsapp->ipsap_pbucket != NULL);
   2753  10934  sommerfeld 		return (0);
   2754   6668     markfen 	}
   2755   6668     markfen 
   2756   6668     markfen 	/* found sa in outbound sadb, peer should be inbound */
   2757   6668     markfen 
   2758  10019        Mark 	if (ipsapp->in_inbound_table) {
   2759   6668     markfen 		/* Found SA in inbound table, pair will be in outbound. */
   2760  10934  sommerfeld 		if (sq->af == AF_INET6) {
   2761  10934  sommerfeld 			ipsapp->ipsap_pbucket = OUTBOUND_BUCKET_V6(sq->sp,
   2762   6668     markfen 			    *(uint32_t *)pair_srcaddr);
   2763   6668     markfen 		} else {
   2764  10934  sommerfeld 			ipsapp->ipsap_pbucket = OUTBOUND_BUCKET_V4(sq->sp,
   2765   6668     markfen 			    *(uint32_t *)pair_srcaddr);
   2766   6668     markfen 		}
   2767   6668     markfen 	} else {
   2768  10934  sommerfeld 		ipsapp->ipsap_pbucket = INBOUND_BUCKET(sq->sp, pair_spi);
   2769   6668     markfen 	}
   2770   6668     markfen 	mutex_enter(&ipsapp->ipsap_pbucket->isaf_lock);
   2771   6668     markfen 	ipsapp->ipsap_psa_ptr = ipsec_getassocbyspi(ipsapp->ipsap_pbucket,
   2772  10934  sommerfeld 	    pair_spi, pair_dstaddr, pair_srcaddr, sq->af);
   2773   6668     markfen 	mutex_exit(&ipsapp->ipsap_pbucket->isaf_lock);
   2774   6668     markfen 	ASSERT(ipsapp->ipsap_bucket != NULL);
   2775   6668     markfen 	ASSERT(ipsapp->ipsap_pbucket != NULL);
   2776  10934  sommerfeld 	return (0);
   2777      0      stevel }
   2778      0      stevel 
   2779   3055      danmcd /*
   2780   3055      danmcd  * Perform NAT-traversal cached checksum offset calculations here.
   2781   3055      danmcd  */
   2782   3055      danmcd static void
   2783   3055      danmcd sadb_nat_calculations(ipsa_t *newbie, sadb_address_t *natt_loc_ext,
   2784   3055      danmcd     sadb_address_t *natt_rem_ext, uint32_t *src_addr_ptr,
   2785   3055      danmcd     uint32_t *dst_addr_ptr)
   2786   3055      danmcd {
   2787   3055      danmcd 	struct sockaddr_in *natt_loc, *natt_rem;
   2788   3055      danmcd 	uint32_t *natt_loc_ptr = NULL, *natt_rem_ptr = NULL;
   2789   3055      danmcd 	uint32_t running_sum = 0;
   2790   3055      danmcd 
   2791   3055      danmcd #define	DOWN_SUM(x) (x) = ((x) & 0xFFFF) +	 ((x) >> 16)
   2792   3055      danmcd 
   2793   3055      danmcd 	if (natt_rem_ext != NULL) {
   2794   3055      danmcd 		uint32_t l_src;
   2795   3055      danmcd 		uint32_t l_rem;
   2796   3055      danmcd 
   2797   3055      danmcd 		natt_rem = (struct sockaddr_in *)(natt_rem_ext + 1);
   2798   3055      danmcd 
   2799   3055      danmcd 		/* Ensured by sadb_addrfix(). */
   2800   3055      danmcd 		ASSERT(natt_rem->sin_family == AF_INET);
   2801   3055      danmcd 
   2802   3055      danmcd 		natt_rem_ptr = (uint32_t *)(&natt_rem->sin_addr);
   2803   4987      danmcd 		newbie->ipsa_remote_nat_port = natt_rem->sin_port;
   2804   3055      danmcd 		l_src = *src_addr_ptr;
   2805   3055      danmcd 		l_rem = *natt_rem_ptr;
   2806   3055      danmcd 
   2807   3055      danmcd 		/* Instead of IPSA_COPY_ADDR(), just copy first 32 bits. */
   2808   4987      danmcd 		newbie->ipsa_natt_addr_rem = *natt_rem_ptr;
   2809   3055      danmcd 
   2810   3055      danmcd 		l_src = ntohl(l_src);
   2811   3055      danmcd 		DOWN_SUM(l_src);
   2812   3055      danmcd 		DOWN_SUM(l_src);
   2813   3055      danmcd 		l_rem = ntohl(l_rem);
   2814   3055      danmcd 		DOWN_SUM(l_rem);
   2815   3055      danmcd 		DOWN_SUM(l_rem);
   2816   3055      danmcd 
   2817   3055      danmcd 		/*
   2818   3055      danmcd 		 * We're 1's complement for checksums, so check for wraparound
   2819   3055      danmcd 		 * here.
   2820   3055      danmcd 		 */
   2821   3055      danmcd 		if (l_rem > l_src)
   2822   3055      danmcd 			l_src--;
   2823   3055      danmcd 
   2824   3055      danmcd 		running_sum += l_src - l_rem;
   2825   3055      danmcd 
   2826   3055      danmcd 		DOWN_SUM(running_sum);
   2827   3055      danmcd 		DOWN_SUM(running_sum);
   2828   3055      danmcd 	}
   2829   3055      danmcd 
   2830   3055      danmcd 	if (natt_loc_ext != NULL) {
   2831   3055      danmcd 		natt_loc = (struct sockaddr_in *)(natt_loc_ext + 1);
   2832   3055      danmcd 
   2833   3055      danmcd 		/* Ensured by sadb_addrfix(). */
   2834   3055      danmcd 		ASSERT(natt_loc->sin_family == AF_INET);
   2835   3055      danmcd 
   2836   4987      danmcd 		natt_loc_ptr = (uint32_t *)(&natt_loc->sin_addr);
   2837   4987      danmcd 		newbie->ipsa_local_nat_port = natt_loc->sin_port;
   2838   3055      danmcd 
   2839   3055      danmcd 		/* Instead of IPSA_COPY_ADDR(), just copy first 32 bits. */
   2840   4987      danmcd 		newbie->ipsa_natt_addr_loc = *natt_loc_ptr;
   2841   4987      danmcd 
   2842   4987      danmcd 		/*
   2843   4987      danmcd 		 * NAT-T port agility means we may have natt_loc_ext, but
   2844   4987      danmcd 		 * only for a local-port change.
   2845   4987      danmcd 		 */
   2846   4987      danmcd 		if (natt_loc->sin_addr.s_addr != INADDR_ANY) {
   2847   4987      danmcd 			uint32_t l_dst = ntohl(*dst_addr_ptr);
   2848   4987      danmcd 			uint32_t l_loc = ntohl(*natt_loc_ptr);
   2849   4987      danmcd 
   2850   4987      danmcd 			DOWN_SUM(l_loc);
   2851   4987      danmcd 			DOWN_SUM(l_loc);
   2852   4987      danmcd 			DOWN_SUM(l_dst);
   2853   4987      danmcd 			DOWN_SUM(l_dst);
   2854   4987      danmcd 
   2855   4987      danmcd 			/*
   2856   4987      danmcd 			 * We're 1's complement for checksums, so check for
   2857   4987      danmcd 			 * wraparound here.
   2858   4987      danmcd 			 */
   2859   4987      danmcd 			if (l_loc > l_dst)
   2860   4987      danmcd 				l_dst--;
   2861   4987      danmcd 
   2862   4987      danmcd 			running_sum += l_dst - l_loc;
   2863   4987      danmcd 			DOWN_SUM(running_sum);
   2864   4987      danmcd 			DOWN_SUM(running_sum);
   2865   4987      danmcd 		}
   2866   3055      danmcd 	}
   2867   3055      danmcd 
   2868   3055      danmcd 	newbie->ipsa_inbound_cksum = running_sum;
   2869   3055      danmcd #undef DOWN_SUM
   2870   3055      danmcd }
   2871      0      stevel 
   2872      0      stevel /*
   2873      0      stevel  * This function is called from consumers that need to insert a fully-grown
   2874      0      stevel  * security association into its tables.  This function takes into account that
   2875      0      stevel  * SAs can be "inbound", "outbound", or "both".	 The "primary" and "secondary"
   2876      0      stevel  * hash bucket parameters are set in order of what the SA will be most of the
   2877      0      stevel  * time.  (For example, an SA with an unspecified source, and a multicast
   2878      0      stevel  * destination will primarily be an outbound SA.  OTOH, if that destination
   2879      0      stevel  * is unicast for this node, then the SA will primarily be inbound.)
   2880      0      stevel  *
   2881      0      stevel  * It takes a lot of parameters because even if clone is B_FALSE, this needs
   2882      0      stevel  * to check both buckets for purposes of collision.
   2883      0      stevel  *
   2884      0      stevel  * Return 0 upon success.  Return various errnos (ENOMEM, EEXIST) for
   2885   3055      danmcd  * various error conditions.  We may need to set samsg->sadb_x_msg_diagnostic
   2886   3055      danmcd  * with additional diagnostic information because there is at least one EINVAL
   2887   3055      danmcd  * case here.
   2888      0      stevel  */
   2889      0      stevel int
   2890  11042        Erik sadb_common_add(queue_t *pfkey_q, mblk_t *mp, sadb_msg_t *samsg,
   2891      0      stevel     keysock_in_t *ksi, isaf_t *primary, isaf_t *secondary,
   2892   3448    dh155122     ipsa_t *newbie, boolean_t clone, boolean_t is_inbound, int *diagnostic,
   2893   6668     markfen     netstack_t *ns, sadbp_t *spp)
   2894      0      stevel {
   2895      0      stevel 	ipsa_t *newbie_clone = NULL, *scratch;
   2896  10934  sommerfeld 	ipsap_t ipsapp;
   2897      0      stevel 	sadb_sa_t *assoc = (sadb_sa_t *)ksi->ks_in_extv[SADB_EXT_SA];
   2898      0      stevel 	sadb_address_t *srcext =
   2899      0      stevel 	    (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_SRC];
   2900      0      stevel 	sadb_address_t *dstext =
   2901      0      stevel 	    (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_DST];
   2902   3055      danmcd 	sadb_address_t *isrcext =
   2903   3055      danmcd 	    (sadb_address_t *)ksi->ks_in_extv[SADB_X_EXT_ADDRESS_INNER_SRC];
   2904   3055      danmcd 	sadb_address_t *idstext =
   2905   3055      danmcd 	    (sadb_address_t *)ksi->ks_in_extv[SADB_X_EXT_ADDRESS_INNER_DST];
   2906      0      stevel 	sadb_x_kmc_t *kmcext =
   2907      0      stevel 	    (sadb_x_kmc_t *)ksi->ks_in_extv[SADB_X_EXT_KM_COOKIE];
   2908      0      stevel 	sadb_key_t *akey = (sadb_key_t *)ksi->ks_in_extv[SADB_EXT_KEY_AUTH];
   2909      0      stevel 	sadb_key_t *ekey = (sadb_key_t *)ksi->ks_in_extv[SADB_EXT_KEY_ENCRYPT];
   2910  10934  sommerfeld 	sadb_sens_t *sens =
   2911  10934  sommerfeld 	    (sadb_sens_t *)ksi->ks_in_extv[SADB_EXT_SENSITIVITY];
   2912  10934  sommerfeld 	sadb_sens_t *osens =
   2913  10934  sommerfeld 	    (sadb_sens_t *)ksi->ks_in_extv[SADB_X_EXT_OUTER_SENS];
   2914   6668     markfen 	sadb_x_pair_t *pair_ext =
   2915   6668     markfen 	    (sadb_x_pair_t *)ksi->ks_in_extv[SADB_X_EXT_PAIR];
   2916   7749  Thejaswini 	sadb_x_replay_ctr_t *replayext =
   2917   7749  Thejaswini 	    (sadb_x_replay_ctr_t *)ksi->ks_in_extv[SADB_X_EXT_REPLAY_VALUE];
   2918   7749  Thejaswini 	uint8_t protocol =
   2919   7749  Thejaswini 	    (samsg->sadb_msg_satype == SADB_SATYPE_AH) ? IPPROTO_AH:IPPROTO_ESP;
   2920  10824        Mark 	int salt_offset;
   2921  10824        Mark 	uint8_t *buf_ptr;
   2922   3055      danmcd 	struct sockaddr_in *src, *dst, *isrc, *idst;
   2923   3055      danmcd 	struct sockaddr_in6 *src6, *dst6, *isrc6, *idst6;
   2924      0      stevel 	sadb_lifetime_t *soft =
   2925      0      stevel 	    (sadb_lifetime_t *)