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   3055     danmcd  * Common Development and Distribution License (the "License").
      6   3055     danmcd  * 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   8778       Erik  * 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/param.h>
     27      0     stevel #include <sys/types.h>
     28      0     stevel #include <sys/stream.h>
     29      0     stevel #include <sys/strsubr.h>
     30      0     stevel #include <sys/strsun.h>
     31      0     stevel #include <sys/stropts.h>
     32   3448   dh155122 #include <sys/zone.h>
     33      0     stevel #include <sys/vnode.h>
     34      0     stevel #include <sys/sysmacros.h>
     35      0     stevel #define	_SUN_TPI_VERSION 2
     36      0     stevel #include <sys/tihdr.h>
     37      0     stevel #include <sys/ddi.h>
     38      0     stevel #include <sys/sunddi.h>
     39      0     stevel #include <sys/mkdev.h>
     40      0     stevel #include <sys/debug.h>
     41      0     stevel #include <sys/kmem.h>
     42      0     stevel #include <sys/cmn_err.h>
     43      0     stevel #include <sys/suntpi.h>
     44      0     stevel #include <sys/policy.h>
     45  10616  Sebastien #include <sys/dls.h>
     46      0     stevel 
     47      0     stevel #include <sys/socket.h>
     48      0     stevel #include <netinet/in.h>
     49      0     stevel #include <net/pfkeyv2.h>
     50      0     stevel #include <net/pfpolicy.h>
     51      0     stevel 
     52      0     stevel #include <inet/common.h>
     53      0     stevel #include <netinet/ip6.h>
     54      0     stevel #include <inet/ip.h>
     55      0     stevel #include <inet/ip6.h>
     56      0     stevel #include <inet/mi.h>
     57   8348       Eric #include <inet/proto_set.h>
     58      0     stevel #include <inet/nd.h>
     59   3055     danmcd #include <inet/ip_if.h>
     60      0     stevel #include <inet/optcom.h>
     61      0     stevel #include <inet/ipsec_impl.h>
     62      0     stevel #include <inet/spdsock.h>
     63      0     stevel #include <inet/sadb.h>
     64  10616  Sebastien #include <inet/iptun.h>
     65  10616  Sebastien #include <inet/iptun/iptun_impl.h>
     66      0     stevel 
     67      0     stevel #include <sys/isa_defs.h>
     68   4307    pwernau 
     69   4307    pwernau #include <c2/audit.h>
     70      0     stevel 
     71      0     stevel /*
     72      0     stevel  * This is a transport provider for the PF_POLICY IPsec policy
     73      0     stevel  * management socket, which provides a management interface into the
     74      0     stevel  * SPD, allowing policy rules to be added, deleted, and queried.
     75      0     stevel  *
     76      0     stevel  * This effectively replaces the old private SIOC*IPSECONFIG ioctls
     77      0     stevel  * with an extensible interface which will hopefully be public some
     78      0     stevel  * day.
     79      0     stevel  *
     80      0     stevel  * See <net/pfpolicy.h> for more details on the protocol.
     81      0     stevel  *
     82      0     stevel  * We link against drv/ip and call directly into it to manipulate the
     83      0     stevel  * SPD; see ipsec_impl.h for the policy data structures and spd.c for
     84      0     stevel  * the code which maintains them.
     85      0     stevel  *
     86      0     stevel  * The MT model of this is QPAIR with the addition of some explicit
     87      0     stevel  * locking to protect system-wide policy data structures.
     88      0     stevel  */
     89      0     stevel 
     90      0     stevel static vmem_t *spdsock_vmem;		/* for minor numbers. */
     91      0     stevel 
     92      0     stevel #define	ALIGNED64(x) IS_P2ALIGNED((x), sizeof (uint64_t))
     93      0     stevel 
     94      0     stevel /* Default structure copied into T_INFO_ACK messages (from rts.c...) */
     95      0     stevel static struct T_info_ack spdsock_g_t_info_ack = {
     96      0     stevel 	T_INFO_ACK,
     97      0     stevel 	T_INFINITE,	/* TSDU_size. Maximum size messages. */
     98      0     stevel 	T_INVALID,	/* ETSDU_size. No expedited data. */
     99      0     stevel 	T_INVALID,	/* CDATA_size. No connect data. */
    100      0     stevel 	T_INVALID,	/* DDATA_size. No disconnect data. */
    101      0     stevel 	0,		/* ADDR_size. */
    102      0     stevel 	0,		/* OPT_size. No user-settable options */
    103      0     stevel 	64 * 1024,	/* TIDU_size. spdsock allows maximum size messages. */
    104      0     stevel 	T_COTS,		/* SERV_type. spdsock supports connection oriented. */
    105      0     stevel 	TS_UNBND,	/* CURRENT_state. This is set from spdsock_state. */
    106      0     stevel 	(XPG4_1)	/* Provider flags */
    107      0     stevel };
    108      0     stevel 
    109      0     stevel /* Named Dispatch Parameter Management Structure */
    110   3448   dh155122 typedef struct spdsockparam_s {
    111      0     stevel 	uint_t	spdsock_param_min;
    112      0     stevel 	uint_t	spdsock_param_max;
    113      0     stevel 	uint_t	spdsock_param_value;
    114      0     stevel 	char *spdsock_param_name;
    115      0     stevel } spdsockparam_t;
    116      0     stevel 
    117      0     stevel /*
    118      0     stevel  * Table of NDD variables supported by spdsock. These are loaded into
    119      0     stevel  * spdsock_g_nd in spdsock_init_nd.
    120      0     stevel  * All of these are alterable, within the min/max values given, at run time.
    121      0     stevel  */
    122   3448   dh155122 static	spdsockparam_t	lcl_param_arr[] = {
    123      0     stevel 	/* min	max	value	name */
    124      0     stevel 	{ 4096, 65536,	8192,	"spdsock_xmit_hiwat"},
    125      0     stevel 	{ 0,	65536,	1024,	"spdsock_xmit_lowat"},
    126      0     stevel 	{ 4096, 65536,	8192,	"spdsock_recv_hiwat"},
    127      0     stevel 	{ 65536, 1024*1024*1024, 256*1024,	"spdsock_max_buf"},
    128      0     stevel 	{ 0,	3,	0,	"spdsock_debug"},
    129      0     stevel };
    130   3448   dh155122 #define	spds_xmit_hiwat	spds_params[0].spdsock_param_value
    131   3448   dh155122 #define	spds_xmit_lowat	spds_params[1].spdsock_param_value
    132   3448   dh155122 #define	spds_recv_hiwat	spds_params[2].spdsock_param_value
    133   3448   dh155122 #define	spds_max_buf	spds_params[3].spdsock_param_value
    134   3448   dh155122 #define	spds_debug		spds_params[4].spdsock_param_value
    135      0     stevel 
    136      0     stevel #define	ss0dbg(a)	printf a
    137      0     stevel /* NOTE:  != 0 instead of > 0 so lint doesn't complain. */
    138   3448   dh155122 #define	ss1dbg(spds, a)	if (spds->spds_debug != 0) printf a
    139   3448   dh155122 #define	ss2dbg(spds, a)	if (spds->spds_debug > 1) printf a
    140   3448   dh155122 #define	ss3dbg(spds, a)	if (spds->spds_debug > 2) printf a
    141   6430     danmcd 
    142   6430     danmcd #define	RESET_SPDSOCK_DUMP_POLHEAD(ss, iph) { \
    143   6430     danmcd 	ASSERT(RW_READ_HELD(&(iph)->iph_lock)); \
    144   6430     danmcd 	(ss)->spdsock_dump_head = (iph); \
    145   6430     danmcd 	(ss)->spdsock_dump_gen = (iph)->iph_gen; \
    146   6430     danmcd 	(ss)->spdsock_dump_cur_type = 0; \
    147   6430     danmcd 	(ss)->spdsock_dump_cur_af = IPSEC_AF_V4; \
    148   6430     danmcd 	(ss)->spdsock_dump_cur_rule = NULL; \
    149   6430     danmcd 	(ss)->spdsock_dump_count = 0; \
    150   6430     danmcd 	(ss)->spdsock_dump_cur_chain = 0; \
    151   6430     danmcd }
    152      0     stevel 
    153      0     stevel static int spdsock_close(queue_t *);
    154      0     stevel static int spdsock_open(queue_t *, dev_t *, int, int, cred_t *);
    155      0     stevel static void spdsock_wput(queue_t *, mblk_t *);
    156      0     stevel static void spdsock_wsrv(queue_t *);
    157      0     stevel static void spdsock_rsrv(queue_t *);
    158   3448   dh155122 static void *spdsock_stack_init(netstackid_t stackid, netstack_t *ns);
    159   3448   dh155122 static void spdsock_stack_fini(netstackid_t stackid, void *arg);
    160      0     stevel static void spdsock_loadcheck(void *);
    161   3448   dh155122 static void spdsock_merge_algs(spd_stack_t *);
    162   3448   dh155122 static void spdsock_flush_one(ipsec_policy_head_t *, netstack_t *);
    163   3055     danmcd static mblk_t *spdsock_dump_next_record(spdsock_t *);
    164      0     stevel 
    165      0     stevel static struct module_info info = {
    166      0     stevel 	5138, "spdsock", 1, INFPSZ, 512, 128
    167      0     stevel };
    168      0     stevel 
    169      0     stevel static struct qinit rinit = {
    170      0     stevel 	NULL, (pfi_t)spdsock_rsrv, spdsock_open, spdsock_close,
    171      0     stevel 	NULL, &info
    172      0     stevel };
    173      0     stevel 
    174      0     stevel static struct qinit winit = {
    175      0     stevel 	(pfi_t)spdsock_wput, (pfi_t)spdsock_wsrv, NULL, NULL, NULL, &info
    176      0     stevel };
    177      0     stevel 
    178      0     stevel struct streamtab spdsockinfo = {
    179      0     stevel 	&rinit, &winit
    180      0     stevel };
    181      0     stevel 
    182      0     stevel /* mapping from alg type to protocol number, as per RFC 2407 */
    183      0     stevel static const uint_t algproto[] = {
    184      0     stevel 	PROTO_IPSEC_AH,
    185      0     stevel 	PROTO_IPSEC_ESP,
    186      0     stevel };
    187      0     stevel 
    188      0     stevel #define	NALGPROTOS	(sizeof (algproto) / sizeof (algproto[0]))
    189      0     stevel 
    190      0     stevel /* mapping from kernel exec mode to spdsock exec mode */
    191      0     stevel static const uint_t execmodes[] = {
    192      0     stevel 	SPD_ALG_EXEC_MODE_SYNC,
    193      0     stevel 	SPD_ALG_EXEC_MODE_ASYNC
    194      0     stevel };
    195      0     stevel 
    196      0     stevel #define	NEXECMODES	(sizeof (execmodes) / sizeof (execmodes[0]))
    197   3055     danmcd 
    198   3055     danmcd #define	ALL_ACTIVE_POLHEADS ((ipsec_policy_head_t *)-1)
    199   3055     danmcd #define	ALL_INACTIVE_POLHEADS ((ipsec_policy_head_t *)-2)
    200   4307    pwernau 
    201   4307    pwernau #define	ITP_NAME(itp) (itp != NULL ? itp->itp_name : NULL)
    202      0     stevel 
    203      0     stevel /* ARGSUSED */
    204      0     stevel static int
    205      0     stevel spdsock_param_get(q, mp, cp, cr)
    206      0     stevel 	queue_t	*q;
    207      0     stevel 	mblk_t	*mp;
    208      0     stevel 	caddr_t	cp;
    209      0     stevel 	cred_t *cr;
    210      0     stevel {
    211      0     stevel 	spdsockparam_t	*spdsockpa = (spdsockparam_t *)cp;
    212      0     stevel 	uint_t value;
    213   3448   dh155122 	spdsock_t *ss = (spdsock_t *)q->q_ptr;
    214   3448   dh155122 	spd_stack_t	*spds = ss->spdsock_spds;
    215      0     stevel 
    216   3448   dh155122 	mutex_enter(&spds->spds_param_lock);
    217      0     stevel 	value = spdsockpa->spdsock_param_value;
    218   3448   dh155122 	mutex_exit(&spds->spds_param_lock);
    219      0     stevel 
    220      0     stevel 	(void) mi_mpprintf(mp, "%u", value);
    221      0     stevel 	return (0);
    222      0     stevel }
    223      0     stevel 
    224      0     stevel /* This routine sets an NDD variable in a spdsockparam_t structure. */
    225      0     stevel /* ARGSUSED */
    226      0     stevel static int
    227      0     stevel spdsock_param_set(q, mp, value, cp, cr)
    228      0     stevel 	queue_t	*q;
    229      0     stevel 	mblk_t	*mp;
    230      0     stevel 	char *value;
    231      0     stevel 	caddr_t	cp;
    232      0     stevel 	cred_t *cr;
    233      0     stevel {
    234      0     stevel 	ulong_t	new_value;
    235      0     stevel 	spdsockparam_t	*spdsockpa = (spdsockparam_t *)cp;
    236   3448   dh155122 	spdsock_t *ss = (spdsock_t *)q->q_ptr;
    237   3448   dh155122 	spd_stack_t	*spds = ss->spdsock_spds;
    238      0     stevel 
    239      0     stevel 	/* Convert the value from a string into a long integer. */
    240      0     stevel 	if (ddi_strtoul(value, NULL, 10, &new_value) != 0)
    241      0     stevel 		return (EINVAL);
    242      0     stevel 
    243   3448   dh155122 	mutex_enter(&spds->spds_param_lock);
    244      0     stevel 	/*
    245      0     stevel 	 * Fail the request if the new value does not lie within the
    246      0     stevel 	 * required bounds.
    247      0     stevel 	 */
    248      0     stevel 	if (new_value < spdsockpa->spdsock_param_min ||
    249      0     stevel 	    new_value > spdsockpa->spdsock_param_max) {
    250   3448   dh155122 		mutex_exit(&spds->spds_param_lock);
    251      0     stevel 		return (EINVAL);
    252      0     stevel 	}
    253      0     stevel 
    254      0     stevel 	/* Set the new value */
    255      0     stevel 	spdsockpa->spdsock_param_value = new_value;
    256   3448   dh155122 	mutex_exit(&spds->spds_param_lock);
    257      0     stevel 
    258      0     stevel 	return (0);
    259      0     stevel }
    260      0     stevel 
    261   3448   dh155122 /*
    262   3448   dh155122  * Initialize at module load time
    263   3448   dh155122  */
    264      0     stevel boolean_t
    265      0     stevel spdsock_ddi_init(void)
    266      0     stevel {
    267      0     stevel 	spdsock_max_optsize = optcom_max_optsize(
    268      0     stevel 	    spdsock_opt_obj.odb_opt_des_arr, spdsock_opt_obj.odb_opt_arr_cnt);
    269      0     stevel 
    270      0     stevel 	spdsock_vmem = vmem_create("spdsock", (void *)1, MAXMIN, 1,
    271      0     stevel 	    NULL, NULL, NULL, 1, VM_SLEEP | VMC_IDENTIFIER);
    272      0     stevel 
    273   3448   dh155122 	/*
    274   3448   dh155122 	 * We want to be informed each time a stack is created or
    275   3448   dh155122 	 * destroyed in the kernel, so we can maintain the
    276   3448   dh155122 	 * set of spd_stack_t's.
    277   3448   dh155122 	 */
    278   3448   dh155122 	netstack_register(NS_SPDSOCK, spdsock_stack_init, NULL,
    279   3448   dh155122 	    spdsock_stack_fini);
    280      0     stevel 
    281      0     stevel 	return (B_TRUE);
    282   3448   dh155122 }
    283   3448   dh155122 
    284   3448   dh155122 /*
    285   3448   dh155122  * Walk through the param array specified registering each element with the
    286   3448   dh155122  * named dispatch handler.
    287   3448   dh155122  */
    288   3448   dh155122 static boolean_t
    289   3448   dh155122 spdsock_param_register(IDP *ndp, spdsockparam_t *ssp, int cnt)
    290   3448   dh155122 {
    291   3448   dh155122 	for (; cnt-- > 0; ssp++) {
    292   3448   dh155122 		if (ssp->spdsock_param_name != NULL &&
    293   3448   dh155122 		    ssp->spdsock_param_name[0]) {
    294   3448   dh155122 			if (!nd_load(ndp,
    295   3448   dh155122 			    ssp->spdsock_param_name,
    296   3448   dh155122 			    spdsock_param_get, spdsock_param_set,
    297   3448   dh155122 			    (caddr_t)ssp)) {
    298   3448   dh155122 				nd_free(ndp);
    299   3448   dh155122 				return (B_FALSE);
    300   3448   dh155122 			}
    301   3448   dh155122 		}
    302   3448   dh155122 	}
    303   3448   dh155122 	return (B_TRUE);
    304   3448   dh155122 }
    305   3448   dh155122 
    306   3448   dh155122 /*
    307   3448   dh155122  * Initialize for each stack instance
    308   3448   dh155122  */
    309   3448   dh155122 /* ARGSUSED */
    310   3448   dh155122 static void *
    311   3448   dh155122 spdsock_stack_init(netstackid_t stackid, netstack_t *ns)
    312   3448   dh155122 {
    313   3448   dh155122 	spd_stack_t	*spds;
    314   3448   dh155122 	spdsockparam_t	*ssp;
    315   3448   dh155122 
    316   3448   dh155122 	spds = (spd_stack_t *)kmem_zalloc(sizeof (*spds), KM_SLEEP);
    317   3448   dh155122 	spds->spds_netstack = ns;
    318   3448   dh155122 
    319   3448   dh155122 	ASSERT(spds->spds_g_nd == NULL);
    320   3448   dh155122 
    321   3448   dh155122 	ssp = (spdsockparam_t *)kmem_alloc(sizeof (lcl_param_arr), KM_SLEEP);
    322   3448   dh155122 	spds->spds_params = ssp;
    323   3448   dh155122 	bcopy(lcl_param_arr, ssp, sizeof (lcl_param_arr));
    324   3448   dh155122 
    325   3448   dh155122 	(void) spdsock_param_register(&spds->spds_g_nd, ssp,
    326   3448   dh155122 	    A_CNT(lcl_param_arr));
    327   3448   dh155122 
    328   3448   dh155122 	mutex_init(&spds->spds_param_lock, NULL, MUTEX_DEFAULT, NULL);
    329   3448   dh155122 	mutex_init(&spds->spds_alg_lock, NULL, MUTEX_DEFAULT, NULL);
    330   3448   dh155122 
    331   3448   dh155122 	return (spds);
    332      0     stevel }
    333      0     stevel 
    334      0     stevel void
    335      0     stevel spdsock_ddi_destroy(void)
    336      0     stevel {
    337      0     stevel 	vmem_destroy(spdsock_vmem);
    338   3448   dh155122 
    339   3448   dh155122 	netstack_unregister(NS_SPDSOCK);
    340   3448   dh155122 }
    341   3448   dh155122 
    342   3448   dh155122 /* ARGSUSED */
    343   3448   dh155122 static void
    344   3448   dh155122 spdsock_stack_fini(netstackid_t stackid, void *arg)
    345   3448   dh155122 {
    346   3448   dh155122 	spd_stack_t *spds = (spd_stack_t *)arg;
    347   3448   dh155122 
    348   6430     danmcd 	freemsg(spds->spds_mp_algs);
    349   3448   dh155122 	mutex_destroy(&spds->spds_param_lock);
    350   3448   dh155122 	mutex_destroy(&spds->spds_alg_lock);
    351   3448   dh155122 	nd_free(&spds->spds_g_nd);
    352   3448   dh155122 	kmem_free(spds->spds_params, sizeof (lcl_param_arr));
    353   3448   dh155122 	spds->spds_params = NULL;
    354   3448   dh155122 
    355   3448   dh155122 	kmem_free(spds, sizeof (*spds));
    356      0     stevel }
    357      0     stevel 
    358      0     stevel /*
    359      0     stevel  * NOTE: large quantities of this should be shared with keysock.
    360      0     stevel  * Would be nice to combine some of this into a common module, but
    361      0     stevel  * not possible given time pressures.
    362      0     stevel  */
    363      0     stevel 
    364      0     stevel /*
    365      0     stevel  * High-level reality checking of extensions.
    366      0     stevel  */
    367      0     stevel /* ARGSUSED */ /* XXX */
    368      0     stevel static boolean_t
    369      0     stevel ext_check(spd_ext_t *ext)
    370      0     stevel {
    371   3055     danmcd 	spd_if_t *tunname = (spd_if_t *)ext;
    372   3055     danmcd 	int i;
    373   3055     danmcd 	char *idstr;
    374      0     stevel 
    375   3055     danmcd 	if (ext->spd_ext_type == SPD_EXT_TUN_NAME) {
    376   3055     danmcd 		/* (NOTE:  Modified from SADB_EXT_IDENTITY..) */
    377   3055     danmcd 
    378   3055     danmcd 		/*
    379   3055     danmcd 		 * Make sure the strings in these identities are
    380   3055     danmcd 		 * null-terminated.  Let's "proactively" null-terminate the
    381   3055     danmcd 		 * string at the last byte if it's not terminated sooner.
    382   3055     danmcd 		 */
    383   3055     danmcd 		i = SPD_64TO8(tunname->spd_if_len) - sizeof (spd_if_t);
    384   3055     danmcd 		idstr = (char *)(tunname + 1);
    385   3055     danmcd 		while (*idstr != '\0' && i > 0) {
    386   3055     danmcd 			i--;
    387   3055     danmcd 			idstr++;
    388   3055     danmcd 		}
    389   3055     danmcd 		if (i == 0) {
    390   3055     danmcd 			/*
    391   3055     danmcd 			 * I.e., if the bozo user didn't NULL-terminate the
    392   3055     danmcd 			 * string...
    393   3055     danmcd 			 */
    394   3055     danmcd 			idstr--;
    395   3055     danmcd 			*idstr = '\0';
    396   3055     danmcd 		}
    397   3055     danmcd 	}
    398      0     stevel 	return (B_TRUE);	/* For now... */
    399      0     stevel }
    400      0     stevel 
    401      0     stevel 
    402      0     stevel 
    403      0     stevel /* Return values for spdsock_get_ext(). */
    404      0     stevel #define	KGE_OK	0
    405      0     stevel #define	KGE_DUP	1
    406      0     stevel #define	KGE_UNK	2
    407      0     stevel #define	KGE_LEN	3
    408      0     stevel #define	KGE_CHK	4
    409      0     stevel 
    410      0     stevel /*
    411      0     stevel  * Parse basic extension headers and return in the passed-in pointer vector.
    412      0     stevel  * Return values include:
    413      0     stevel  *
    414      0     stevel  *	KGE_OK	Everything's nice and parsed out.
    415      0     stevel  *		If there are no extensions, place NULL in extv[0].
    416      0     stevel  *	KGE_DUP	There is a duplicate extension.
    417      0     stevel  *		First instance in appropriate bin.  First duplicate in
    418      0     stevel  *		extv[0].
    419      0     stevel  *	KGE_UNK	Unknown extension type encountered.  extv[0] contains
    420      0     stevel  *		unknown header.
    421      0     stevel  *	KGE_LEN	Extension length error.
    422      0     stevel  *	KGE_CHK	High-level reality check failed on specific extension.
    423      0     stevel  *
    424      0     stevel  * My apologies for some of the pointer arithmetic in here.  I'm thinking
    425      0     stevel  * like an assembly programmer, yet trying to make the compiler happy.
    426      0     stevel  */
    427      0     stevel static int
    428      0     stevel spdsock_get_ext(spd_ext_t *extv[], spd_msg_t *basehdr, uint_t msgsize)
    429      0     stevel {
    430      0     stevel 	bzero(extv, sizeof (spd_ext_t *) * (SPD_EXT_MAX + 1));
    431      0     stevel 
    432      0     stevel 	/* Use extv[0] as the "current working pointer". */
    433      0     stevel 
    434      0     stevel 	extv[0] = (spd_ext_t *)(basehdr + 1);
    435      0     stevel 
    436      0     stevel 	while (extv[0] < (spd_ext_t *)(((uint8_t *)basehdr) + msgsize)) {
    437      0     stevel 		/* Check for unknown headers. */
    438      0     stevel 		if (extv[0]->spd_ext_type == 0 ||
    439      0     stevel 		    extv[0]->spd_ext_type > SPD_EXT_MAX)
    440      0     stevel 			return (KGE_UNK);
    441      0     stevel 
    442      0     stevel 		/*
    443      0     stevel 		 * Check length.  Use uint64_t because extlen is in units
    444      0     stevel 		 * of 64-bit words.  If length goes beyond the msgsize,
    445      0     stevel 		 * return an error.  (Zero length also qualifies here.)
    446      0     stevel 		 */
    447      0     stevel 		if (extv[0]->spd_ext_len == 0 ||
    448      0     stevel 		    (void *)((uint64_t *)extv[0] + extv[0]->spd_ext_len) >
    449      0     stevel 		    (void *)((uint8_t *)basehdr + msgsize))
    450      0     stevel 			return (KGE_LEN);
    451      0     stevel 
    452      0     stevel 		/* Check for redundant headers. */
    453      0     stevel 		if (extv[extv[0]->spd_ext_type] != NULL)
    454      0     stevel 			return (KGE_DUP);
    455      0     stevel 
    456      0     stevel 		/*
    457      0     stevel 		 * Reality check the extension if possible at the spdsock
    458      0     stevel 		 * level.
    459      0     stevel 		 */
    460      0     stevel 		if (!ext_check(extv[0]))
    461      0     stevel 			return (KGE_CHK);
    462      0     stevel 
    463      0     stevel 		/* If I make it here, assign the appropriate bin. */
    464      0     stevel 		extv[extv[0]->spd_ext_type] = extv[0];
    465      0     stevel 
    466      0     stevel 		/* Advance pointer (See above for uint64_t ptr reasoning.) */
    467      0     stevel 		extv[0] = (spd_ext_t *)
    468      0     stevel 		    ((uint64_t *)extv[0] + extv[0]->spd_ext_len);
    469      0     stevel 	}
    470      0     stevel 
    471      0     stevel 	/* Everything's cool. */
    472      0     stevel 
    473      0     stevel 	/*
    474      0     stevel 	 * If extv[0] == NULL, then there are no extension headers in this
    475      0     stevel 	 * message.  Ensure that this is the case.
    476      0     stevel 	 */
    477      0     stevel 	if (extv[0] == (spd_ext_t *)(basehdr + 1))
    478      0     stevel 		extv[0] = NULL;
    479      0     stevel 
    480      0     stevel 	return (KGE_OK);
    481      0     stevel }
    482      0     stevel 
    483      0     stevel static const int bad_ext_diag[] = {
    484      0     stevel 	SPD_DIAGNOSTIC_MALFORMED_LCLPORT,
    485      0     stevel 	SPD_DIAGNOSTIC_MALFORMED_REMPORT,
    486      0     stevel 	SPD_DIAGNOSTIC_MALFORMED_PROTO,
    487      0     stevel 	SPD_DIAGNOSTIC_MALFORMED_LCLADDR,
    488      0     stevel 	SPD_DIAGNOSTIC_MALFORMED_REMADDR,
    489      0     stevel 	SPD_DIAGNOSTIC_MALFORMED_ACTION,
    490      0     stevel 	SPD_DIAGNOSTIC_MALFORMED_RULE,
    491      0     stevel 	SPD_DIAGNOSTIC_MALFORMED_RULESET,
    492      0     stevel 	SPD_DIAGNOSTIC_MALFORMED_ICMP_TYPECODE
    493      0     stevel };
    494      0     stevel 
    495      0     stevel static const int dup_ext_diag[] = {
    496      0     stevel 	SPD_DIAGNOSTIC_DUPLICATE_LCLPORT,
    497      0     stevel 	SPD_DIAGNOSTIC_DUPLICATE_REMPORT,
    498      0     stevel 	SPD_DIAGNOSTIC_DUPLICATE_PROTO,
    499      0     stevel 	SPD_DIAGNOSTIC_DUPLICATE_LCLADDR,
    500      0     stevel 	SPD_DIAGNOSTIC_DUPLICATE_REMADDR,
    501      0     stevel 	SPD_DIAGNOSTIC_DUPLICATE_ACTION,
    502      0     stevel 	SPD_DIAGNOSTIC_DUPLICATE_RULE,
    503      0     stevel 	SPD_DIAGNOSTIC_DUPLICATE_RULESET,
    504      0     stevel 	SPD_DIAGNOSTIC_DUPLICATE_ICMP_TYPECODE
    505      0     stevel };
    506      0     stevel 
    507      0     stevel /*
    508      0     stevel  * Transmit a PF_POLICY error message to the instance either pointed to
    509      0     stevel  * by ks, the instance with serial number serial, or more, depending.
    510      0     stevel  *
    511      0     stevel  * The faulty message (or a reasonable facsimile thereof) is in mp.
    512      0     stevel  * This function will free mp or recycle it for delivery, thereby causing
    513      0     stevel  * the stream head to free it.
    514      0     stevel  */
    515      0     stevel static void
    516      0     stevel spdsock_error(queue_t *q, mblk_t *mp, int error, int diagnostic)
    517      0     stevel {
    518      0     stevel 	spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr;
    519      0     stevel 
    520      0     stevel 	ASSERT(mp->b_datap->db_type == M_DATA);
    521      0     stevel 
    522      0     stevel 	if (spmsg->spd_msg_type < SPD_MIN ||
    523      0     stevel 	    spmsg->spd_msg_type > SPD_MAX)
    524      0     stevel 		spmsg->spd_msg_type = SPD_RESERVED;
    525      0     stevel 
    526      0     stevel 	/*
    527      0     stevel 	 * Strip out extension headers.
    528      0     stevel 	 */
    529      0     stevel 	ASSERT(mp->b_rptr + sizeof (*spmsg) <= mp->b_datap->db_lim);
    530      0     stevel 	mp->b_wptr = mp->b_rptr + sizeof (*spmsg);
    531      0     stevel 	spmsg->spd_msg_len = SPD_8TO64(sizeof (spd_msg_t));
    532      0     stevel 	spmsg->spd_msg_errno = (uint8_t)error;
    533      0     stevel 	spmsg->spd_msg_diagnostic = (uint16_t)diagnostic;
    534      0     stevel 
    535      0     stevel 	qreply(q, mp);
    536      0     stevel }
    537      0     stevel 
    538      0     stevel static void
    539      0     stevel spdsock_diag(queue_t *q, mblk_t *mp, int diagnostic)
    540      0     stevel {
    541      0     stevel 	spdsock_error(q, mp, EINVAL, diagnostic);
    542      0     stevel }
    543      0     stevel 
    544      0     stevel static void
    545      0     stevel spd_echo(queue_t *q, mblk_t *mp)
    546      0     stevel {
    547      0     stevel 	qreply(q, mp);
    548      0     stevel }
    549      0     stevel 
    550   3055     danmcd /*
    551   3055     danmcd  * Do NOT consume a reference to itp.
    552   3055     danmcd  */
    553   3448   dh155122 /*ARGSUSED*/
    554      0     stevel static void
    555   3448   dh155122 spdsock_flush_node(ipsec_tun_pol_t *itp, void *cookie, netstack_t *ns)
    556   3055     danmcd {
    557   3055     danmcd 	boolean_t active = (boolean_t)cookie;
    558   3055     danmcd 	ipsec_policy_head_t *iph;
    559   3055     danmcd 
    560   3055     danmcd 	iph = active ? itp->itp_policy : itp->itp_inactive;
    561   3055     danmcd 	IPPH_REFHOLD(iph);
    562   3055     danmcd 	mutex_enter(&itp->itp_lock);
    563   3448   dh155122 	spdsock_flush_one(iph, ns);
    564   3055     danmcd 	if (active)
    565   3055     danmcd 		itp->itp_flags &= ~ITPF_PFLAGS;
    566   3055     danmcd 	else
    567   3055     danmcd 		itp->itp_flags &= ~ITPF_IFLAGS;
    568   3055     danmcd 	mutex_exit(&itp->itp_lock);
    569   3055     danmcd }
    570   3055     danmcd 
    571   3055     danmcd /*
    572   3055     danmcd  * Clear out one polhead.
    573   3055     danmcd  */
    574   3055     danmcd static void
    575   3448   dh155122 spdsock_flush_one(ipsec_policy_head_t *iph, netstack_t *ns)
    576      0     stevel {
    577      0     stevel 	rw_enter(&iph->iph_lock, RW_WRITER);
    578   3448   dh155122 	ipsec_polhead_flush(iph, ns);
    579      0     stevel 	rw_exit(&iph->iph_lock);
    580   3448   dh155122 	IPPH_REFRELE(iph, ns);
    581   3055     danmcd }
    582   3055     danmcd 
    583   3055     danmcd static void
    584   4307    pwernau spdsock_flush(queue_t *q, ipsec_policy_head_t *iph, ipsec_tun_pol_t *itp,
    585   4307    pwernau     mblk_t *mp)
    586   3055     danmcd {
    587   3055     danmcd 	boolean_t active;
    588   3448   dh155122 	spdsock_t *ss = (spdsock_t *)q->q_ptr;
    589   6430     danmcd 	netstack_t *ns = ss->spdsock_spds->spds_netstack;
    590   3055     danmcd 
    591   3055     danmcd 	if (iph != ALL_ACTIVE_POLHEADS && iph != ALL_INACTIVE_POLHEADS) {
    592   6430     danmcd 		spdsock_flush_one(iph, ns);
    593   4307    pwernau 		if (audit_active) {
    594   4307    pwernau 			spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr;
    595   8778       Erik 			cred_t *cr;
    596   8778       Erik 			pid_t cpid;
    597   4307    pwernau 
    598   8778       Erik 			cr = msg_getcred(mp, &cpid);
    599   4307    pwernau 			active = (spmsg->spd_msg_spdid == SPD_ACTIVE);
    600   8778       Erik 			audit_pf_policy(SPD_FLUSH, cr, ns,
    601   8778       Erik 			    ITP_NAME(itp), active, 0, cpid);
    602   4307    pwernau 		}
    603   3055     danmcd 	} else {
    604   3055     danmcd 		active = (iph == ALL_ACTIVE_POLHEADS);
    605   3055     danmcd 
    606   3055     danmcd 		/* First flush the global policy. */
    607   3448   dh155122 		spdsock_flush_one(active ? ipsec_system_policy(ns) :
    608   3448   dh155122 		    ipsec_inactive_policy(ns), ns);
    609   4307    pwernau 		if (audit_active) {
    610   8778       Erik 			cred_t *cr;
    611   8778       Erik 			pid_t cpid;
    612   8778       Erik 
    613   8778       Erik 			cr = msg_getcred(mp, &cpid);
    614   8778       Erik 			audit_pf_policy(SPD_FLUSH, cr, ns, NULL,
    615   8778       Erik 			    active, 0, cpid);
    616   4307    pwernau 		}
    617   3055     danmcd 		/* Then flush every tunnel's appropriate one. */
    618   6430     danmcd 		itp_walk(spdsock_flush_node, (void *)active, ns);
    619   8778       Erik 		if (audit_active) {
    620   8778       Erik 			cred_t *cr;
    621   8778       Erik 			pid_t cpid;
    622   8778       Erik 
    623   8778       Erik 			cr = msg_getcred(mp, &cpid);
    624   8778       Erik 			audit_pf_policy(SPD_FLUSH, cr, ns,
    625   8778       Erik 			    "all tunnels", active, 0, cpid);
    626   8778       Erik 		}
    627   3055     danmcd 	}
    628      0     stevel 
    629      0     stevel 	spd_echo(q, mp);
    630      0     stevel }
    631      0     stevel 
    632      0     stevel static boolean_t
    633      0     stevel spdsock_ext_to_sel(spd_ext_t **extv, ipsec_selkey_t *sel, int *diag)
    634      0     stevel {
    635      0     stevel 	bzero(sel, sizeof (*sel));
    636      0     stevel 
    637      0     stevel 	if (extv[SPD_EXT_PROTO] != NULL) {
    638      0     stevel 		struct spd_proto *pr =
    639      0     stevel 		    (struct spd_proto *)extv[SPD_EXT_PROTO];
    640      0     stevel 		sel->ipsl_proto = pr->spd_proto_number;
    641      0     stevel 		sel->ipsl_valid |= IPSL_PROTOCOL;
    642      0     stevel 	}
    643      0     stevel 	if (extv[SPD_EXT_LCLPORT] != NULL) {
    644      0     stevel 		struct spd_portrange *pr =
    645      0     stevel 		    (struct spd_portrange *)extv[SPD_EXT_LCLPORT];
    646      0     stevel 		sel->ipsl_lport = pr->spd_ports_minport;
    647      0     stevel 		sel->ipsl_valid |= IPSL_LOCAL_PORT;
    648      0     stevel 	}
    649      0     stevel 	if (extv[SPD_EXT_REMPORT] != NULL) {
    650      0     stevel 		struct spd_portrange *pr =
    651      0     stevel 		    (struct spd_portrange *)extv[SPD_EXT_REMPORT];
    652      0     stevel 		sel->ipsl_rport = pr->spd_ports_minport;
    653      0     stevel 		sel->ipsl_valid |= IPSL_REMOTE_PORT;
    654      0     stevel 	}
    655      0     stevel 
    656      0     stevel 	if (extv[SPD_EXT_ICMP_TYPECODE] != NULL) {
    657      0     stevel 		struct spd_typecode *tc=
    658      0     stevel 		    (struct spd_typecode *)extv[SPD_EXT_ICMP_TYPECODE];
    659      0     stevel 
    660      0     stevel 		sel->ipsl_valid |= IPSL_ICMP_TYPE;
    661      0     stevel 		sel->ipsl_icmp_type = tc->spd_typecode_type;
    662      0     stevel 		if (tc->spd_typecode_type_end < tc->spd_typecode_type)
    663      0     stevel 			sel->ipsl_icmp_type_end = tc->spd_typecode_type;
    664      0     stevel 		else
    665      0     stevel 			sel->ipsl_icmp_type_end = tc->spd_typecode_type_end;
    666      0     stevel 
    667      0     stevel 		if (tc->spd_typecode_code != 255) {
    668      0     stevel 			sel->ipsl_valid |= IPSL_ICMP_CODE;
    669      0     stevel 			sel->ipsl_icmp_code = tc->spd_typecode_code;
    670      0     stevel 			if (tc->spd_typecode_code_end < tc->spd_typecode_code)
    671      0     stevel 				sel->ipsl_icmp_code_end = tc->spd_typecode_code;
    672      0     stevel 			else
    673      0     stevel 				sel->ipsl_icmp_code_end =
    674      0     stevel 				    tc->spd_typecode_code_end;
    675      0     stevel 		}
    676      0     stevel 	}
    677      0     stevel #define	ADDR2SEL(sel, extv, field, pfield, extn, bit)			      \
    678      0     stevel 	if ((extv)[(extn)] != NULL) {					      \
    679      0     stevel 		uint_t addrlen;						      \
    680      0     stevel 		struct spd_address *ap = 				      \
    681      0     stevel 			(struct spd_address *)((extv)[(extn)]); 	      \
    682      0     stevel 		addrlen = (ap->spd_address_af == AF_INET6) ? 		      \
    683      0     stevel 			IPV6_ADDR_LEN : IP_ADDR_LEN;			      \
    684      0     stevel 		if (SPD_64TO8(ap->spd_address_len) < 			      \
    685      0     stevel 			(addrlen + sizeof (*ap))) {			      \
    686      0     stevel 			*diag = SPD_DIAGNOSTIC_BAD_ADDR_LEN;		      \
    687      0     stevel 			return (B_FALSE);				      \
    688      0     stevel 		}							      \
    689      0     stevel 		bcopy((ap+1), &((sel)->field), addrlen);		      \
    690      0     stevel 		(sel)->pfield = ap->spd_address_prefixlen;		      \
    691      0     stevel 		(sel)->ipsl_valid |= (bit);				      \
    692      0     stevel 		(sel)->ipsl_valid |= (ap->spd_address_af == AF_INET6) ?	      \
    693      0     stevel 			IPSL_IPV6 : IPSL_IPV4;				      \
    694      0     stevel 	}
    695      0     stevel 
    696      0     stevel 	ADDR2SEL(sel, extv, ipsl_local, ipsl_local_pfxlen,
    697      0     stevel 	    SPD_EXT_LCLADDR, IPSL_LOCAL_ADDR);
    698      0     stevel 	ADDR2SEL(sel, extv, ipsl_remote, ipsl_remote_pfxlen,
    699      0     stevel 	    SPD_EXT_REMADDR, IPSL_REMOTE_ADDR);
    700      0     stevel 
    701      0     stevel 	if ((sel->ipsl_valid & (IPSL_IPV6|IPSL_IPV4)) ==
    702      0     stevel 	    (IPSL_IPV6|IPSL_IPV4)) {
    703      0     stevel 		*diag = SPD_DIAGNOSTIC_MIXED_AF;
    704      0     stevel 		return (B_FALSE);
    705      0     stevel 	}
    706      0     stevel 
    707      0     stevel #undef ADDR2SEL
    708      0     stevel 
    709      0     stevel 	return (B_TRUE);
    710      0     stevel }
    711      0     stevel 
    712      0     stevel static boolean_t
    713      0     stevel spd_convert_type(uint32_t type, ipsec_act_t *act)
    714      0     stevel {
    715      0     stevel 	switch (type) {
    716      0     stevel 	case SPD_ACTTYPE_DROP:
    717      0     stevel 		act->ipa_type = IPSEC_ACT_DISCARD;
    718      0     stevel 		return (B_TRUE);
    719      0     stevel 
    720      0     stevel 	case SPD_ACTTYPE_PASS:
    721      0     stevel 		act->ipa_type = IPSEC_ACT_CLEAR;
    722      0     stevel 		return (B_TRUE);
    723      0     stevel 
    724      0     stevel 	case SPD_ACTTYPE_IPSEC:
    725      0     stevel 		act->ipa_type = IPSEC_ACT_APPLY;
    726      0     stevel 		return (B_TRUE);
    727      0     stevel 	}
    728      0     stevel 	return (B_FALSE);
    729      0     stevel }
    730      0     stevel 
    731      0     stevel static boolean_t
    732      0     stevel spd_convert_flags(uint32_t flags, ipsec_act_t *act)
    733      0     stevel {
    734      0     stevel 	/*
    735      0     stevel 	 * Note use of !! for boolean canonicalization.
    736      0     stevel 	 */
    737      0     stevel 	act->ipa_apply.ipp_use_ah = !!(flags & SPD_APPLY_AH);
    738      0     stevel 	act->ipa_apply.ipp_use_esp = !!(flags & SPD_APPLY_ESP);
    739      0     stevel 	act->ipa_apply.ipp_use_espa = !!(flags & SPD_APPLY_ESPA);
    740      0     stevel 	act->ipa_apply.ipp_use_se = !!(flags & SPD_APPLY_SE);
    741      0     stevel 	act->ipa_apply.ipp_use_unique = !!(flags & SPD_APPLY_UNIQUE);
    742      0     stevel 	return (B_TRUE);
    743      0     stevel }
    744      0     stevel 
    745      0     stevel static void
    746      0     stevel spdsock_reset_act(ipsec_act_t *act)
    747      0     stevel {
    748      0     stevel 	bzero(act, sizeof (*act));
    749      0     stevel 	act->ipa_apply.ipp_espe_maxbits = IPSEC_MAX_KEYBITS;
    750      0     stevel 	act->ipa_apply.ipp_espa_maxbits = IPSEC_MAX_KEYBITS;
    751      0     stevel 	act->ipa_apply.ipp_ah_maxbits = IPSEC_MAX_KEYBITS;
    752      0     stevel }
    753      0     stevel 
    754      0     stevel /*
    755      0     stevel  * Sanity check action against reality, and shrink-wrap key sizes..
    756      0     stevel  */
    757      0     stevel static boolean_t
    758   3448   dh155122 spdsock_check_action(ipsec_act_t *act, boolean_t tunnel_polhead, int *diag,
    759   3448   dh155122     spd_stack_t *spds)
    760      0     stevel {
    761   3055     danmcd 	if (tunnel_polhead && act->ipa_apply.ipp_use_unique) {
    762   3055     danmcd 		*diag = SPD_DIAGNOSTIC_ADD_INCON_FLAGS;
    763   3055     danmcd 		return (B_FALSE);
    764   3055     danmcd 	}
    765      0     stevel 	if ((act->ipa_type != IPSEC_ACT_APPLY) &&
    766      0     stevel 	    (act->ipa_apply.ipp_use_ah ||
    767   5240   nordmark 	    act->ipa_apply.ipp_use_esp ||
    768   5240   nordmark 	    act->ipa_apply.ipp_use_espa ||
    769   5240   nordmark 	    act->ipa_apply.ipp_use_se ||
    770   5240   nordmark 	    act->ipa_apply.ipp_use_unique)) {
    771      0     stevel 		*diag = SPD_DIAGNOSTIC_ADD_INCON_FLAGS;
    772      0     stevel 		return (B_FALSE);
    773      0     stevel 	}
    774      0     stevel 	if ((act->ipa_type == IPSEC_ACT_APPLY) &&
    775      0     stevel 	    !act->ipa_apply.ipp_use_ah &&
    776      0     stevel 	    !act->ipa_apply.ipp_use_esp) {
    777      0     stevel 		*diag = SPD_DIAGNOSTIC_ADD_INCON_FLAGS;
    778      0     stevel 		return (B_FALSE);
    779      0     stevel 	}
    780   3448   dh155122 	return (ipsec_check_action(act, diag, spds->spds_netstack));
    781      0     stevel }
    782      0     stevel 
    783      0     stevel /*
    784      0     stevel  * We may be short a few error checks here..
    785      0     stevel  */
    786      0     stevel static boolean_t
    787      0     stevel spdsock_ext_to_actvec(spd_ext_t **extv, ipsec_act_t **actpp, uint_t *nactp,
    788   3448   dh155122     int *diag, spd_stack_t *spds)
    789      0     stevel {
    790      0     stevel 	struct spd_ext_actions *sactp =
    791      0     stevel 	    (struct spd_ext_actions *)extv[SPD_EXT_ACTION];
    792      0     stevel 	ipsec_act_t act, *actp, *endactp;
    793      0     stevel 	struct spd_attribute *attrp, *endattrp;
    794      0     stevel 	uint64_t *endp;
    795      0     stevel 	int nact;
    796   3055     danmcd 	boolean_t tunnel_polhead;
    797   3055     danmcd 
    798   3055     danmcd 	tunnel_polhead = (extv[SPD_EXT_TUN_NAME] != NULL &&
    799   3055     danmcd 	    (((struct spd_rule *)extv[SPD_EXT_RULE])->spd_rule_flags &
    800   5240   nordmark 	    SPD_RULE_FLAG_TUNNEL));
    801      0     stevel 
    802      0     stevel 	*actpp = NULL;
    803      0     stevel 	*nactp = 0;
    804      0     stevel 
    805      0     stevel 	if (sactp == NULL) {
    806      0     stevel 		*diag = SPD_DIAGNOSTIC_NO_ACTION_EXT;
    807      0     stevel 		return (B_FALSE);
    808      0     stevel 	}
    809      0     stevel 
    810      0     stevel 	/*
    811      0     stevel 	 * Parse the "action" extension and convert into an action chain.
    812      0     stevel 	 */
    813      0     stevel 
    814      0     stevel 	nact = sactp->spd_actions_count;
    815      0     stevel 
    816      0     stevel 	endp = (uint64_t *)sactp;
    817      0     stevel 	endp += sactp->spd_actions_len;
    818      0     stevel 	endattrp = (struct spd_attribute *)endp;
    819      0     stevel 
    820      0     stevel 	actp = kmem_alloc(sizeof (*actp) * nact, KM_NOSLEEP);
    821      0     stevel 	if (actp == NULL) {
    822      0     stevel 		*diag = SPD_DIAGNOSTIC_ADD_NO_MEM;
    823      0     stevel 		return (B_FALSE);
    824      0     stevel 	}
    825      0     stevel 	*actpp = actp;
    826      0     stevel 	*nactp = nact;
    827      0     stevel 	endactp = actp + nact;
    828      0     stevel 
    829      0     stevel 	spdsock_reset_act(&act);
    830      0     stevel 	attrp = (struct spd_attribute *)(&sactp[1]);
    831      0     stevel 
    832      0     stevel 	for (; attrp < endattrp; attrp++) {
    833      0     stevel 		switch (attrp->spd_attr_tag) {
    834      0     stevel 		case SPD_ATTR_NOP:
    835      0     stevel 			break;
    836      0     stevel 
    837      0     stevel 		case SPD_ATTR_EMPTY:
    838      0     stevel 			spdsock_reset_act(&act);
    839      0     stevel 			break;
    840      0     stevel 
    841      0     stevel 		case SPD_ATTR_END:
    842      0     stevel 			attrp = endattrp;
    843      0     stevel 			/* FALLTHRU */
    844      0     stevel 		case SPD_ATTR_NEXT:
    845      0     stevel 			if (actp >= endactp) {
    846      0     stevel 				*diag = SPD_DIAGNOSTIC_ADD_WRONG_ACT_COUNT;
    847      0     stevel 				goto fail;
    848      0     stevel 			}
    849   3448   dh155122 			if (!spdsock_check_action(&act, tunnel_polhead,
    850   3448   dh155122 			    diag, spds))
    851      0     stevel 				goto fail;
    852      0     stevel 			*actp++ = act;
    853   3055     danmcd 			spdsock_reset_act(&act);
    854      0     stevel 			break;
    855      0     stevel 
    856      0     stevel 		case SPD_ATTR_TYPE:
    857      0     stevel 			if (!spd_convert_type(attrp->spd_attr_value, &act)) {
    858      0     stevel 				*diag = SPD_DIAGNOSTIC_ADD_BAD_TYPE;
    859      0     stevel 				goto fail;
    860      0     stevel 			}
    861      0     stevel 			break;
    862      0     stevel 
    863      0     stevel 		case SPD_ATTR_FLAGS:
    864   3055     danmcd 			if (!tunnel_polhead && extv[SPD_EXT_TUN_NAME] != NULL) {
    865   3055     danmcd 				/*
    866   3055     danmcd 				 * Set "sa unique" for transport-mode
    867   3055     danmcd 				 * tunnels whether we want to or not.
    868   3055     danmcd 				 */
    869   3055     danmcd 				attrp->spd_attr_value |= SPD_APPLY_UNIQUE;
    870   3055     danmcd 			}
    871      0     stevel 			if (!spd_convert_flags(attrp->spd_attr_value, &act)) {
    872      0     stevel 				*diag = SPD_DIAGNOSTIC_ADD_BAD_FLAGS;
    873      0     stevel 				goto fail;
    874      0     stevel 			}
    875      0     stevel 			break;
    876      0     stevel 
    877      0     stevel 		case SPD_ATTR_AH_AUTH:
    878   3055     danmcd 			if (attrp->spd_attr_value == 0) {
    879   3055     danmcd 				*diag = SPD_DIAGNOSTIC_UNSUPP_AH_ALG;
    880   3055     danmcd 				goto fail;
    881   3055     danmcd 			}
    882      0     stevel 			act.ipa_apply.ipp_auth_alg = attrp->spd_attr_value;
    883      0     stevel 			break;
    884      0     stevel 
    885      0     stevel 		case SPD_ATTR_ESP_ENCR:
    886   3055     danmcd 			if (attrp->spd_attr_value == 0) {
    887   3055     danmcd 				*diag = SPD_DIAGNOSTIC_UNSUPP_ESP_ENCR_ALG;
    888   3055     danmcd 				goto fail;
    889   3055     danmcd 			}
    890      0     stevel 			act.ipa_apply.ipp_encr_alg = attrp->spd_attr_value;
    891      0     stevel 			break;
    892      0     stevel 
    893      0     stevel 		case SPD_ATTR_ESP_AUTH:
    894   3055     danmcd 			if (attrp->spd_attr_value == 0) {
    895   3055     danmcd 				*diag = SPD_DIAGNOSTIC_UNSUPP_ESP_AUTH_ALG;
    896   3055     danmcd 				goto fail;
    897   3055     danmcd 			}
    898      0     stevel 			act.ipa_apply.ipp_esp_auth_alg = attrp->spd_attr_value;
    899      0     stevel 			break;
    900      0     stevel 
    901      0     stevel 		case SPD_ATTR_ENCR_MINBITS:
    902      0     stevel 			act.ipa_apply.ipp_espe_minbits = attrp->spd_attr_value;
    903      0     stevel 			break;
    904      0     stevel 
    905      0     stevel 		case SPD_ATTR_ENCR_MAXBITS:
    906      0     stevel 			act.ipa_apply.ipp_espe_maxbits = attrp->spd_attr_value;
    907      0     stevel 			break;
    908      0     stevel 
    909      0     stevel 		case SPD_ATTR_AH_MINBITS:
    910      0     stevel 			act.ipa_apply.ipp_ah_minbits = attrp->spd_attr_value;
    911      0     stevel 			break;
    912      0     stevel 
    913      0     stevel 		case SPD_ATTR_AH_MAXBITS:
    914      0     stevel 			act.ipa_apply.ipp_ah_maxbits = attrp->spd_attr_value;
    915      0     stevel 			break;
    916      0     stevel 
    917      0     stevel 		case SPD_ATTR_ESPA_MINBITS:
    918      0     stevel 			act.ipa_apply.ipp_espa_minbits = attrp->spd_attr_value;
    919      0     stevel 			break;
    920      0     stevel 
    921      0     stevel 		case SPD_ATTR_ESPA_MAXBITS:
    922      0     stevel 			act.ipa_apply.ipp_espa_maxbits = attrp->spd_attr_value;
    923      0     stevel 			break;
    924      0     stevel 
    925      0     stevel 		case SPD_ATTR_LIFE_SOFT_TIME:
    926      0     stevel 		case SPD_ATTR_LIFE_HARD_TIME:
    927      0     stevel 		case SPD_ATTR_LIFE_SOFT_BYTES:
    928      0     stevel 		case SPD_ATTR_LIFE_HARD_BYTES:
    929      0     stevel 			break;
    930      0     stevel 
    931      0     stevel 		case SPD_ATTR_KM_PROTO:
    932      0     stevel 			act.ipa_apply.ipp_km_proto = attrp->spd_attr_value;
    933      0     stevel 			break;
    934      0     stevel 
    935      0     stevel 		case SPD_ATTR_KM_COOKIE:
    936      0     stevel 			act.ipa_apply.ipp_km_cookie = attrp->spd_attr_value;
    937      0     stevel 			break;
    938      0     stevel 
    939      0     stevel 		case SPD_ATTR_REPLAY_DEPTH:
    940      0     stevel 			act.ipa_apply.ipp_replay_depth = attrp->spd_attr_value;
    941      0     stevel 			break;
    942      0     stevel 		}
    943      0     stevel 	}
    944      0     stevel 	if (actp != endactp) {
    945      0     stevel 		*diag = SPD_DIAGNOSTIC_ADD_WRONG_ACT_COUNT;
    946      0     stevel 		goto fail;
    947      0     stevel 	}
    948      0     stevel 
    949      0     stevel 	return (B_TRUE);
    950      0     stevel fail:
    951      0     stevel 	ipsec_actvec_free(*actpp, nact);
    952      0     stevel 	*actpp = NULL;
    953      0     stevel 	return (B_FALSE);
    954      0     stevel }
    955      0     stevel 
    956      0     stevel typedef struct
    957      0     stevel {
    958      0     stevel 	ipsec_policy_t *pol;
    959      0     stevel 	int dir;
    960      0     stevel } tmprule_t;
    961      0     stevel 
    962      0     stevel static int
    963      0     stevel mkrule(ipsec_policy_head_t *iph, struct spd_rule *rule,
    964      0     stevel     ipsec_selkey_t *sel, ipsec_act_t *actp, int nact, uint_t dir, uint_t af,
    965   3448   dh155122     tmprule_t **rp, uint64_t *index, spd_stack_t *spds)
    966      0     stevel {
    967      0     stevel 	ipsec_policy_t *pol;
    968      0     stevel 
    969      0     stevel 	sel->ipsl_valid &= ~(IPSL_IPV6|IPSL_IPV4);
    970      0     stevel 	sel->ipsl_valid |= af;
    971      0     stevel 
    972   3055     danmcd 	pol = ipsec_policy_create(sel, actp, nact, rule->spd_rule_priority,
    973   3448   dh155122 	    index, spds->spds_netstack);
    974      0     stevel 	if (pol == NULL)
    975      0     stevel 		return (ENOMEM);
    976      0     stevel 
    977      0     stevel 	(*rp)->pol = pol;
    978      0     stevel 	(*rp)->dir = dir;
    979      0     stevel 	(*rp)++;
    980      0     stevel 
    981      0     stevel 	if (!ipsec_check_policy(iph, pol, dir))
    982      0     stevel 		return (EEXIST);
    983      0     stevel 
    984      0     stevel 	rule->spd_rule_index = pol->ipsp_index;
    985      0     stevel 	return (0);
    986      0     stevel }
    987      0     stevel 
    988      0     stevel static int
    989      0     stevel mkrulepair(ipsec_policy_head_t *iph, struct spd_rule *rule,
    990      0     stevel     ipsec_selkey_t *sel, ipsec_act_t *actp, int nact, uint_t dir, uint_t afs,
    991   3448   dh155122     tmprule_t **rp, uint64_t *index, spd_stack_t *spds)
    992      0     stevel {
    993      0     stevel 	int error;
    994      0     stevel 
    995      0     stevel 	if (afs & IPSL_IPV4) {
    996   3055     danmcd 		error = mkrule(iph, rule, sel, actp, nact, dir, IPSL_IPV4, rp,
    997   3448   dh155122 		    index, spds);
    998      0     stevel 		if (error != 0)
    999      0     stevel 			return (error);
   1000      0     stevel 	}
   1001      0     stevel 	if (afs & IPSL_IPV6) {
   1002   3055     danmcd 		error = mkrule(iph, rule, sel, actp, nact, dir, IPSL_IPV6, rp,
   1003   3448   dh155122 		    index, spds);
   1004      0     stevel 		if (error != 0)
   1005      0     stevel 			return (error);
   1006      0     stevel 	}
   1007      0     stevel 	return (0);
   1008      0     stevel }
   1009      0     stevel 
   1010      0     stevel 
   1011      0     stevel static void
   1012   3055     danmcd spdsock_addrule(queue_t *q, ipsec_policy_head_t *iph, mblk_t *mp,
   1013   3055     danmcd     spd_ext_t **extv, ipsec_tun_pol_t *itp)
   1014      0     stevel {
   1015      0     stevel 	ipsec_selkey_t sel;
   1016      0     stevel 	ipsec_act_t *actp;
   1017      0     stevel 	uint_t nact;
   1018   3055     danmcd 	int diag = 0, error, afs;
   1019      0     stevel 	struct spd_rule *rule = (struct spd_rule *)extv[SPD_EXT_RULE];
   1020      0     stevel 	tmprule_t rules[4], *rulep = &rules[0];
   1021   3055     danmcd 	boolean_t tunnel_mode, empty_itp, active;
   1022   3055     danmcd 	uint64_t *index = (itp == NULL) ? NULL : &itp->itp_next_policy_index;
   1023   3448   dh155122 	spdsock_t *ss = (spdsock_t *)q->q_ptr;
   1024   3448   dh155122 	spd_stack_t	*spds = ss->spdsock_spds;
   1025      0     stevel 
   1026      0     stevel 	if (rule == NULL) {
   1027      0     stevel 		spdsock_diag(q, mp, SPD_DIAGNOSTIC_NO_RULE_EXT);
   1028   4307    pwernau 		if (audit_active) {
   1029   4307    pwernau 			spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr;
   1030   8778       Erik 			cred_t *cr;
   1031   8778       Erik 			pid_t cpid;
   1032   4307    pwernau 
   1033   8778       Erik 			cr = msg_getcred(mp, &cpid);
   1034   4307    pwernau 			active = (spmsg->spd_msg_spdid == SPD_ACTIVE);
   1035   8778       Erik 			audit_pf_policy(SPD_ADDRULE, cr,
   1036   4307    pwernau 			    spds->spds_netstack, ITP_NAME(itp), active,
   1037   8778       Erik 			    SPD_DIAGNOSTIC_NO_RULE_EXT, cpid);
   1038   4307    pwernau 		}
   1039      0     stevel 		return;
   1040      0     stevel 	}
   1041      0     stevel 
   1042   3055     danmcd 	tunnel_mode = (rule->spd_rule_flags & SPD_RULE_FLAG_TUNNEL);
   1043   3055     danmcd 
   1044   3055     danmcd 	if (itp != NULL) {
   1045   3055     danmcd 		mutex_enter(&itp->itp_lock);
   1046   3055     danmcd 		ASSERT(itp->itp_policy == iph || itp->itp_inactive == iph);
   1047   3055     danmcd 		active = (itp->itp_policy == iph);
   1048   3055     danmcd 		if (ITP_P_ISACTIVE(itp, iph)) {
   1049   3055     danmcd 			/* Check for mix-and-match of tunnel/transport. */
   1050   3055     danmcd 			if ((tunnel_mode && !ITP_P_ISTUNNEL(itp, iph)) ||
   1051   3055     danmcd 			    (!tunnel_mode && ITP_P_ISTUNNEL(itp, iph))) {
   1052   3055     danmcd 				mutex_exit(&itp->itp_lock);
   1053   3055     danmcd 				spdsock_error(q, mp, EBUSY, 0);
   1054   3055     danmcd 				return;
   1055   3055     danmcd 			}
   1056   3055     danmcd 			empty_itp = B_FALSE;
   1057   3055     danmcd 		} else {
   1058   3055     danmcd 			empty_itp = B_TRUE;
   1059   3055     danmcd 			itp->itp_flags = active ? ITPF_P_ACTIVE : ITPF_I_ACTIVE;
   1060   3055     danmcd 			if (tunnel_mode)
   1061   3055     danmcd 				itp->itp_flags |= active ? ITPF_P_TUNNEL :
   1062   3055     danmcd 				    ITPF_I_TUNNEL;
   1063   3055     danmcd 		}
   1064   3055     danmcd 	} else {
   1065   3055     danmcd 		empty_itp = B_FALSE;
   1066   3055     danmcd 	}
   1067   3055     danmcd 
   1068      0     stevel 	if (rule->spd_rule_index != 0) {
   1069   3055     danmcd 		diag = SPD_DIAGNOSTIC_INVALID_RULE_INDEX;
   1070   3055     danmcd 		error = EINVAL;
   1071   3055     danmcd 		goto fail2;
   1072      0     stevel 	}
   1073      0     stevel 
   1074      0     stevel 	if (!spdsock_ext_to_sel(extv, &sel, &diag)) {
   1075   3055     danmcd 		error = EINVAL;
   1076   3055     danmcd 		goto fail2;
   1077   3055     danmcd 	}
   1078   3055     danmcd 
   1079   3055     danmcd 	if (itp != NULL) {
   1080   3055     danmcd 		if (tunnel_mode) {
   1081   3055     danmcd 			if (sel.ipsl_valid &
   1082   3055     danmcd 			    (IPSL_REMOTE_PORT | IPSL_LOCAL_PORT)) {
   1083   3055     danmcd 				itp->itp_flags |= active ?
   1084   3055     danmcd 				    ITPF_P_PER_PORT_SECURITY :
   1085   3055     danmcd 				    ITPF_I_PER_PORT_SECURITY;
   1086   3055     danmcd 			}
   1087   3055     danmcd 		} else {
   1088   3055     danmcd 			/*
   1089   3055     danmcd 			 * For now, we don't allow transport-mode on a tunnel
   1090   3055     danmcd 			 * with ANY specific selectors.  Bail if we have such
   1091   3055     danmcd 			 * a request.
   1092   3055     danmcd 			 */
   1093   3055     danmcd 			if (sel.ipsl_valid & IPSL_WILDCARD) {
   1094   3055     danmcd 				diag = SPD_DIAGNOSTIC_NO_TUNNEL_SELECTORS;
   1095   3055     danmcd 				error = EINVAL;
   1096   3055     danmcd 				goto fail2;
   1097   3055     danmcd 			}
   1098   3055     danmcd 		}
   1099      0     stevel 	}
   1100      0     stevel 
   1101   3448   dh155122 	if (!spdsock_ext_to_actvec(extv, &actp, &nact, &diag, spds)) {
   1102   3055     danmcd 		error = EINVAL;
   1103   3055     danmcd 		goto fail2;
   1104      0     stevel 	}
   1105      0     stevel 	/*
   1106      0     stevel 	 * If no addresses were specified, add both.
   1107      0     stevel 	 */
   1108      0     stevel 	afs = sel.ipsl_valid & (IPSL_IPV6|IPSL_IPV4);
   1109      0     stevel 	if (afs == 0)
   1110      0     stevel 		afs = (IPSL_IPV6|IPSL_IPV4);
   1111      0     stevel 
   1112      0     stevel 	rw_enter(&iph->iph_lock, RW_WRITER);
   1113      0     stevel 
   1114      0     stevel 	if (rule->spd_rule_flags & SPD_RULE_FLAG_OUTBOUND) {
   1115      0     stevel 		error = mkrulepair(iph, rule, &sel, actp, nact,
   1116   3448   dh155122 		    IPSEC_TYPE_OUTBOUND, afs, &rulep, index, spds);
   1117      0     stevel 		if (error != 0)
   1118      0     stevel 			goto fail;
   1119      0     stevel 	}
   1120      0     stevel 
   1121      0     stevel 	if (rule->spd_rule_flags & SPD_RULE_FLAG_INBOUND) {
   1122      0     stevel 		error = mkrulepair(iph, rule, &sel, actp, nact,
   1123   3448   dh155122 		    IPSEC_TYPE_INBOUND, afs, &rulep, index, spds);
   1124      0     stevel 		if (error != 0)
   1125      0     stevel 			goto fail;
   1126      0     stevel 	}
   1127      0     stevel 
   1128   3448   dh155122 	while ((--rulep) >= &rules[0]) {
   1129   3448   dh155122 		ipsec_enter_policy(iph, rulep->pol, rulep->dir,
   1130   3448   dh155122 		    spds->spds_netstack);
   1131   3448   dh155122 	}
   1132      0     stevel 	rw_exit(&iph->iph_lock);
   1133   3055     danmcd 	if (itp != NULL)
   1134   3055     danmcd 		mutex_exit(&itp->itp_lock);
   1135      0     stevel 
   1136      0     stevel 	ipsec_actvec_free(actp, nact);
   1137      0     stevel 	spd_echo(q, mp);
   1138   4307    pwernau 	if (audit_active) {
   1139   4307    pwernau 		spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr;
   1140   8778       Erik 		cred_t *cr;
   1141   8778       Erik 		pid_t cpid;
   1142   4307    pwernau 
   1143   8778       Erik 		cr = msg_getcred(mp, &cpid);
   1144   4307    pwernau 		active = (spmsg->spd_msg_spdid == SPD_ACTIVE);
   1145   8778       Erik 		audit_pf_policy(SPD_ADDRULE, cr, spds->spds_netstack,
   1146   8778       Erik 		    ITP_NAME(itp), active, 0, cpid);
   1147   4307    pwernau 	}
   1148      0     stevel 	return;
   1149      0     stevel 
   1150      0     stevel fail:
   1151      0     stevel 	rw_exit(&iph->iph_lock);
   1152  11042       Erik 	while ((--rulep) >= &rules[0])
   1153  11042       Erik 		IPPOL_REFRELE(rulep->pol);
   1154      0     stevel 	ipsec_actvec_free(actp, nact);
   1155   3055     danmcd fail2:
   1156   3055     danmcd 	if (itp != NULL) {
   1157   3055     danmcd 		if (empty_itp)
   1158   3055     danmcd 			itp->itp_flags = 0;
   1159   3055     danmcd 		mutex_exit(&itp->itp_lock);
   1160   3055     danmcd 	}
   1161   3055     danmcd 	spdsock_error(q, mp, error, diag);
   1162   4307    pwernau 	if (audit_active) {
   1163   4307    pwernau 		spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr;
   1164   8778       Erik 		cred_t *cr;
   1165   8778       Erik 		pid_t cpid;
   1166   4307    pwernau 
   1167   8778       Erik 		cr = msg_getcred(mp, &cpid);
   1168   4307    pwernau 		active = (spmsg->spd_msg_spdid == SPD_ACTIVE);
   1169   8778       Erik 		audit_pf_policy(SPD_ADDRULE, cr, spds->spds_netstack,
   1170   8778       Erik 		    ITP_NAME(itp), active, error, cpid);
   1171   4307    pwernau 	}
   1172      0     stevel }
   1173      0     stevel 
   1174      0     stevel void
   1175   3055     danmcd spdsock_deleterule(queue_t *q, ipsec_policy_head_t *iph, mblk_t *mp,
   1176   3055     danmcd     spd_ext_t **extv, ipsec_tun_pol_t *itp)
   1177      0     stevel {
   1178      0     stevel 	ipsec_selkey_t sel;
   1179      0     stevel 	struct spd_rule *rule = (struct spd_rule *)extv[SPD_EXT_RULE];
   1180   3055     danmcd 	int err, diag = 0;
   1181   3448   dh155122 	spdsock_t *ss = (spdsock_t *)q->q_ptr;
   1182   6430     danmcd 	netstack_t *ns = ss->spdsock_spds->spds_netstack;
   1183      0     stevel 
   1184      0     stevel 	if (rule == NULL) {
   1185      0     stevel 		spdsock_diag(q, mp, SPD_DIAGNOSTIC_NO_RULE_EXT);
   1186   4307    pwernau 		if (audit_active) {
   1187   4307    pwernau 			boolean_t active;
   1188   4307    pwernau 			spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr;
   1189   8778       Erik 			cred_t *cr;
   1190   8778       Erik 			pid_t cpid;
   1191   4307    pwernau 
   1192   8778       Erik 			cr = msg_getcred(mp, &cpid);
   1193   4307    pwernau 			active = (spmsg->spd_msg_spdid == SPD_ACTIVE);
   1194   8778       Erik 			audit_pf_policy(SPD_DELETERULE, cr, ns,
   1195   6430     danmcd 			    ITP_NAME(itp), active, SPD_DIAGNOSTIC_NO_RULE_EXT,
   1196   8778       Erik 			    cpid);
   1197   4307    pwernau 		}
   1198      0     stevel 		return;
   1199      0     stevel 	}
   1200      0     stevel 
   1201   3055     danmcd 	/*
   1202   3055     danmcd 	 * Must enter itp_lock first to avoid deadlock.  See tun.c's
   1203   3055     danmcd 	 * set_sec_simple() for the other case of itp_lock and iph_lock.
   1204   3055     danmcd 	 */
   1205   3055     danmcd 	if (itp != NULL)
   1206   3055     danmcd 		mutex_enter(&itp->itp_lock);
   1207   3055     danmcd 
   1208      0     stevel 	if (rule->spd_rule_index != 0) {
   1209   6430     danmcd 		if (ipsec_policy_delete_index(iph, rule->spd_rule_index, ns) !=
   1210   6430     danmcd 		    0) {
   1211   3055     danmcd 			err = ESRCH;
   1212   3055     danmcd 			goto fail;
   1213      0     stevel 		}
   1214      0     stevel 	} else {
   1215      0     stevel 		if (!spdsock_ext_to_sel(extv, &sel, &diag)) {
   1216   3055     danmcd 			err = EINVAL;	/* diag already set... */
   1217   3055     danmcd 			goto fail;
   1218      0     stevel 		}
   1219      0     stevel 
   1220   3055     danmcd 		if ((rule->spd_rule_flags & SPD_RULE_FLAG_INBOUND) &&
   1221   6430     danmcd 		    !ipsec_policy_delete(iph, &sel, IPSEC_TYPE_INBOUND, ns)) {
   1222   3055     danmcd 			err = ESRCH;
   1223   3055     danmcd 			goto fail;
   1224      0     stevel 		}
   1225      0     stevel 
   1226   3055     danmcd 		if ((rule->spd_rule_flags & SPD_RULE_FLAG_OUTBOUND) &&
   1227   6430     danmcd 		    !ipsec_policy_delete(iph, &sel, IPSEC_TYPE_OUTBOUND, ns)) {
   1228   3055     danmcd 			err = ESRCH;
   1229   3055     danmcd 			goto fail;
   1230      0     stevel 		}
   1231   3055     danmcd 	}
   1232   3055     danmcd 
   1233   3055     danmcd 	if (itp != NULL) {
   1234   3055     danmcd 		ASSERT(iph == itp->itp_policy || iph == itp->itp_inactive);
   1235   3055     danmcd 		rw_enter(&iph->iph_lock, RW_READER);
   1236   3055     danmcd 		if (avl_numnodes(&iph->iph_rulebyid) == 0) {
   1237   3055     danmcd 			if (iph == itp->itp_policy)
   1238   3055     danmcd 				itp->itp_flags &= ~ITPF_PFLAGS;
   1239   3055     danmcd 			else
   1240   3055     danmcd 				itp->itp_flags &= ~ITPF_IFLAGS;
   1241   3055     danmcd 		}
   1242   3055     danmcd 		/* Can exit locks in any order. */
   1243   3055     danmcd 		rw_exit(&iph->iph_lock);
   1244   3055     danmcd 		mutex_exit(&itp->itp_lock);
   1245      0     stevel 	}
   1246      0     stevel 	spd_echo(q, mp);
   1247   4307    pwernau 	if (audit_active) {
   1248   4307    pwernau 		boolean_t active;
   1249   4307    pwernau 		spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr;
   1250   8778       Erik 		cred_t *cr;
   1251   8778       Erik 		pid_t cpid;
   1252   4307    pwernau 
   1253   8778       Erik 		cr = msg_getcred(mp, &cpid);
   1254   4307    pwernau 		active = (spmsg->spd_msg_spdid == SPD_ACTIVE);
   1255   8778       Erik 		audit_pf_policy(SPD_DELETERULE, cr, ns, ITP_NAME(itp),
   1256   8778       Erik 		    active, 0, cpid);
   1257   4307    pwernau 	}
   1258      0     stevel 	return;
   1259      0     stevel fail:
   1260   3055     danmcd 	if (itp != NULL)
   1261   3055     danmcd 		mutex_exit(&itp->itp_lock);
   1262   3055     danmcd 	spdsock_error(q, mp, err, diag);
   1263   4307    pwernau 	if (audit_active) {
   1264   4307    pwernau 		boolean_t active;
   1265   4307    pwernau 		spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr;
   1266   8778       Erik 		cred_t *cr;
   1267   8778       Erik 		pid_t cpid;
   1268   4307    pwernau 
   1269   8778       Erik 		cr = msg_getcred(mp, &cpid);
   1270   4307    pwernau 		active = (spmsg->spd_msg_spdid == SPD_ACTIVE);
   1271   8778       Erik 		audit_pf_policy(SPD_DELETERULE, cr, ns, ITP_NAME(itp),
   1272   8778       Erik 		    active, err, cpid);
   1273   4307    pwernau 	}
   1274   3055     danmcd }
   1275   3055     danmcd 
   1276   3055     danmcd /* Do NOT consume a reference to itp. */
   1277   3055     danmcd /* ARGSUSED */
   1278   3055     danmcd static void
   1279   3448   dh155122 spdsock_flip_node(ipsec_tun_pol_t *itp, void *ignoreme, netstack_t *ns)
   1280   3055     danmcd {
   1281   3055     danmcd 	mutex_enter(&itp->itp_lock);
   1282   3055     danmcd 	ITPF_SWAP(itp->itp_flags);
   1283   3448   dh155122 	ipsec_swap_policy(itp->itp_policy, itp->itp_inactive, ns);
   1284   3055     danmcd 	mutex_exit(&itp->itp_lock);
   1285      0     stevel }
   1286      0     stevel 
   1287      0     stevel void
   1288   3055     danmcd spdsock_flip(queue_t *q, mblk_t *mp, spd_if_t *tunname)
   1289      0     stevel {
   1290   3055     danmcd 	char *tname;
   1291   3055     danmcd 	ipsec_tun_pol_t *itp;
   1292   3448   dh155122 	spdsock_t *ss = (spdsock_t *)q->q_ptr;
   1293   6430     danmcd 	netstack_t *ns = ss->spdsock_spds->spds_netstack;
   1294   3055     danmcd 
   1295   3055     danmcd 	if (tunname != NULL) {
   1296   3055     danmcd 		tname = (char *)tunname->spd_if_name;
   1297   3055     danmcd 		if (*tname == '\0') {
   1298   3448   dh155122 			/* can't fail */
   1299   6430     danmcd 			ipsec_swap_global_policy(ns);
   1300   4307    pwernau 			if (audit_active) {
   1301   4307    pwernau 				boolean_t active;
   1302   4307    pwernau 				spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr;
   1303   8778       Erik 				cred_t *cr;
   1304   8778       Erik 				pid_t cpid;
   1305   4307    pwernau 
   1306   8778       Erik 				cr = msg_getcred(mp, &cpid);
   1307   4307    pwernau 				active = (spmsg->spd_msg_spdid == SPD_ACTIVE);
   1308   8778       Erik 				audit_pf_policy(SPD_FLIP, cr, ns,
   1309   8778       Erik 				    NULL, active, 0, cpid);
   1310   4307    pwernau 			}
   1311   6430     danmcd 			itp_walk(spdsock_flip_node, NULL, ns);
   1312   4307    pwernau 			if (audit_active) {
   1313   4307    pwernau 				boolean_t active;
   1314   4307    pwernau 				spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr;
   1315   8778       Erik 				cred_t *cr;
   1316   8778       Erik 				pid_t cpid;
   1317   4307    pwernau 
   1318   8778       Erik 				cr = msg_getcred(mp, &cpid);
   1319   4307    pwernau 				active = (spmsg->spd_msg_spdid == SPD_ACTIVE);
   1320   8778       Erik 				audit_pf_policy(SPD_FLIP, cr, ns,
   1321   8778       Erik 				    "all tunnels", active, 0, cpid);
   1322   4307    pwernau 			}
   1323   3055     danmcd 		} else {
   1324   6430     danmcd 			itp = get_tunnel_policy(tname, ns);
   1325   3055     danmcd 			if (itp == NULL) {
   1326   3055     danmcd 				/* Better idea for "tunnel not found"? */
   1327   3055     danmcd 				spdsock_error(q, mp, ESRCH, 0);
   1328   4307    pwernau 				if (audit_active) {
   1329   4307    pwernau 					boolean_t active;
   1330   4307    pwernau 					spd_msg_t *spmsg =
   1331   4307    pwernau 					    (spd_msg_t *)mp->b_rptr;
   1332   8778       Erik 					cred_t *cr;
   1333   8778       Erik 					pid_t cpid;
   1334   4307    pwernau 
   1335   8778       Erik 					cr = msg_getcred(mp, &cpid);
   1336   4307    pwernau 					active = (spmsg->spd_msg_spdid ==
   1337   4307    pwernau 					    SPD_ACTIVE);
   1338   8778       Erik 					audit_pf_policy(SPD_FLIP, cr, ns,
   1339   8778       Erik 					    ITP_NAME(itp), active,
   1340   8778       Erik 					    ESRCH, cpid);
   1341   4307    pwernau 				}
   1342   3055     danmcd 				return;
   1343   3055     danmcd 			}
   1344   3448   dh155122 			spdsock_flip_node(itp, NULL, NULL);
   1345   4307    pwernau 			if (audit_active) {
   1346   4307    pwernau 				boolean_t active;
   1347   4307    pwernau 				spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr;
   1348   8778       Erik 				cred_t *cr;
   1349   8778       Erik 				pid_t cpid;
   1350   4307    pwernau 
   1351   8778       Erik 				cr = msg_getcred(mp, &cpid);
   1352   4307    pwernau 				active = (spmsg->spd_msg_spdid == SPD_ACTIVE);
   1353   8778       Erik 				audit_pf_policy(SPD_FLIP, cr, ns,
   1354   8778       Erik 				    ITP_NAME(itp), active, 0, cpid);
   1355   4307    pwernau 			}
   1356   6430     danmcd 			ITP_REFRELE(itp, ns);
   1357   3055     danmcd 		}
   1358   3055     danmcd 	} else {
   1359   6430     danmcd 		ipsec_swap_global_policy(ns);	/* can't fail */
   1360   4307    pwernau 		if (audit_active) {
   1361   4307    pwernau 			boolean_t active;
   1362   4307    pwernau 			spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr;
   1363   8778       Erik 			cred_t *cr;
   1364   8778       Erik 			pid_t cpid;
   1365   4307    pwernau 
   1366   8778       Erik 			cr = msg_getcred(mp, &cpid);
   1367   4307    pwernau 			active = (spmsg->spd_msg_spdid == SPD_ACTIVE);
   1368   8778       Erik 			audit_pf_policy(SPD_FLIP, cr,
   1369   8778       Erik 			    ns, NULL, active, 0, cpid);
   1370   4307    pwernau 		}
   1371   3055     danmcd 	}
   1372      0     stevel 	spd_echo(q, mp);
   1373      0     stevel }
   1374      0     stevel 
   1375      0     stevel /*
   1376      0     stevel  * Unimplemented feature
   1377      0     stevel  */
   1378      0     stevel /* ARGSUSED */
   1379      0     stevel static void
   1380   3055     danmcd spdsock_lookup(queue_t *q, ipsec_policy_head_t *iph, mblk_t *mp,
   1381   3055     danmcd     spd_ext_t **extv, ipsec_tun_pol_t *itp)
   1382      0     stevel {
   1383      0     stevel 	spdsock_error(q, mp, EINVAL, 0);
   1384      0     stevel }
   1385      0     stevel 
   1386      0     stevel 
   1387      0     stevel static mblk_t *
   1388      0     stevel spdsock_dump_ruleset(mblk_t *req, ipsec_policy_head_t *iph,
   1389      0     stevel     uint32_t count, uint16_t error)
   1390      0     stevel {
   1391      0     stevel 	size_t len = sizeof (spd_ruleset_ext_t) + sizeof (spd_msg_t);
   1392      0     stevel 	spd_msg_t *msg;
   1393      0     stevel 	spd_ruleset_ext_t *ruleset;
   1394      0     stevel 	mblk_t *m = allocb(len, BPRI_HI);
   1395      0     stevel 
   1396      0     stevel 	ASSERT(RW_READ_HELD(&iph->iph_lock));
   1397      0     stevel 
   1398      0     stevel 	if (m == NULL) {
   1399      0     stevel 		return (NULL);
   1400      0     stevel 	}
   1401      0     stevel 	msg = (spd_msg_t *)m->b_rptr;
   1402      0     stevel 	ruleset = (spd_ruleset_ext_t *)(&msg[1]);
   1403      0     stevel 
   1404      0     stevel 	m->b_wptr = (uint8_t *)&ruleset[1];
   1405      0     stevel 
   1406      0     stevel 	*msg = *(spd_msg_t *)(req->b_rptr);
   1407      0     stevel 	msg->spd_msg_len = SPD_8TO64(len);
   1408      0     stevel 	msg->spd_msg_errno = error;
   1409      0     stevel 
   1410      0     stevel 	ruleset->spd_ruleset_len = SPD_8TO64(sizeof (*ruleset));
   1411      0     stevel 	ruleset->spd_ruleset_type = SPD_EXT_RULESET;
   1412      0     stevel 	ruleset->spd_ruleset_count = count;
   1413      0     stevel 	ruleset->spd_ruleset_version = iph->iph_gen;
   1414      0     stevel 	return (m);
   1415      0     stevel }
   1416      0     stevel 
   1417      0     stevel static mblk_t *
   1418      0     stevel spdsock_dump_finish(spdsock_t *ss, int error)
   1419      0     stevel {
   1420      0     stevel 	mblk_t *m;
   1421      0     stevel 	ipsec_policy_head_t *iph = ss->spdsock_dump_head;
   1422      0     stevel 	mblk_t *req = ss->spdsock_dump_req;
   1423  10592     danmcd 	netstack_t *ns = ss->spdsock_spds->spds_netstack;
   1424      0     stevel 
   1425      0     stevel 	rw_enter(&iph->iph_lock, RW_READER);
   1426      0     stevel 	m = spdsock_dump_ruleset(req, iph, ss->spdsock_dump_count, error);
   1427      0     stevel 	rw_exit(&iph->iph_lock);
   1428  10592     danmcd 	IPPH_REFRELE(iph, ns);
   1429  10592     danmcd 	if (ss->spdsock_itp != NULL) {
   1430  10592     danmcd 		ITP_REFRELE(ss->spdsock_itp, ns);
   1431  10592     danmcd 		ss->spdsock_itp = NULL;
   1432  10592     danmcd 	}
   1433      0     stevel 	ss->spdsock_dump_req = NULL;
   1434      0     stevel 	freemsg(req);
   1435      0     stevel 
   1436      0     stevel 	return (m);
   1437      0     stevel }
   1438      0     stevel 
   1439      0     stevel /*
   1440      0     stevel  * Rule encoding functions.
   1441      0     stevel  * We do a two-pass encode.
   1442      0     stevel  * If base != NULL, fill in encoded rule part starting at base+offset.
   1443      0     stevel  * Always return "offset" plus length of to-be-encoded data.
   1444      0     stevel  */
   1445      0     stevel static uint_t
   1446      0     stevel spdsock_encode_typecode(uint8_t *base, uint_t offset, uint8_t type,
   1447      0     stevel     uint8_t type_end, uint8_t code, uint8_t code_end)
   1448      0     stevel {
   1449      0     stevel 	struct spd_typecode *tcp;
   1450      0     stevel 
   1451      0     stevel 	ASSERT(ALIGNED64(offset));
   1452      0     stevel 
   1453      0     stevel 	if (base != NULL) {
   1454      0     stevel 		tcp = (struct spd_typecode *)(base + offset);
   1455      0     stevel 		tcp->spd_typecode_len = SPD_8TO64(sizeof (*tcp));
   1456      0     stevel 		tcp->spd_typecode_exttype = SPD_EXT_ICMP_TYPECODE;
   1457      0     stevel 		tcp->spd_typecode_code = code;
   1458      0     stevel 		tcp->spd_typecode_type = type;
   1459      0     stevel 		tcp->spd_typecode_type_end = type_end;
   1460      0     stevel 		tcp->spd_typecode_code_end = code_end;
   1461      0     stevel 	}
   1462      0     stevel 	offset += sizeof (*tcp);
   1463      0     stevel 
   1464      0     stevel 	ASSERT(ALIGNED64(offset));
   1465      0     stevel 
   1466      0     stevel 	return (offset);
   1467      0     stevel }
   1468      0     stevel 
   1469      0     stevel static uint_t
   1470      0     stevel spdsock_encode_proto(uint8_t *base, uint_t offset, uint8_t proto)
   1471      0     stevel {
   1472      0     stevel 	struct spd_proto *spp;
   1473      0     stevel 
   1474      0     stevel 	ASSERT(ALIGNED64(offset));
   1475      0     stevel 
   1476      0     stevel 	if (base != NULL) {
   1477      0     stevel 		spp = (struct spd_proto *)(base + offset);
   1478      0     stevel 		spp->spd_proto_len = SPD_8TO64(sizeof (*spp));
   1479      0     stevel 		spp->spd_proto_exttype = SPD_EXT_PROTO;
   1480      0     stevel 		spp->spd_proto_number = proto;
   1481      0     stevel 		spp->spd_proto_reserved1 = 0;
   1482      0     stevel 		spp->spd_proto_reserved2 = 0;
   1483      0     stevel 	}
   1484      0     stevel 	offset += sizeof (*spp);
   1485      0     stevel 
   1486      0     stevel 	ASSERT(ALIGNED64(offset));
   1487      0     stevel 
   1488      0     stevel 	return (offset);
   1489      0     stevel }
   1490      0     stevel 
   1491      0     stevel static uint_t
   1492      0     stevel spdsock_encode_port(uint8_t *base, uint_t offset, uint16_t ext, uint16_t port)
   1493      0     stevel {
   1494      0     stevel 	struct spd_portrange *spp;
   1495      0     stevel 
   1496      0     stevel 	ASSERT(ALIGNED64(offset));
   1497      0     stevel 
   1498      0     stevel 	if (base != NULL) {
   1499      0     stevel 		spp = (struct spd_portrange *)(base + offset);
   1500      0     stevel 		spp->spd_ports_len = SPD_8TO64(sizeof (*spp));
   1501      0     stevel 		spp->spd_ports_exttype = ext;
   1502      0     stevel 		spp->spd_ports_minport = port;
   1503      0     stevel 		spp->spd_ports_maxport = port;
   1504      0     stevel 	}
   1505      0     stevel 	offset += sizeof (*spp);
   1506      0     stevel 
   1507      0     stevel 	ASSERT(ALIGNED64(offset));
   1508      0     stevel 
   1509      0     stevel 	return (offset);
   1510      0     stevel }
   1511      0     stevel 
   1512      0     stevel static uint_t
   1513      0     stevel spdsock_encode_addr(uint8_t *base, uint_t offset, uint16_t ext,
   1514      0     stevel     const ipsec_selkey_t *sel, const ipsec_addr_t *addr, uint_t pfxlen)
   1515      0     stevel {
   1516      0     stevel 	struct spd_address *sae;
   1517      0     stevel 	ipsec_addr_t *spdaddr;
   1518      0     stevel 	uint_t start = offset;
   1519      0     stevel 	uint_t addrlen;
   1520      0     stevel 	uint_t af;
   1521      0     stevel 
   1522      0     stevel 	if (sel->ipsl_valid & IPSL_IPV4) {
   1523      0     stevel 		af = AF_INET;
   1524      0     stevel 		addrlen = IP_ADDR_LEN;
   1525      0     stevel 	} else {
   1526      0     stevel 		af = AF_INET6;
   1527      0     stevel 		addrlen = IPV6_ADDR_LEN;
   1528      0     stevel 	}
   1529      0     stevel 
   1530      0     stevel 	ASSERT(ALIGNED64(offset));
   1531      0     stevel 
   1532      0     stevel 	if (base != NULL) {
   1533      0     stevel 		sae = (struct spd_address *)(base + offset);
   1534      0     stevel 		sae->spd_address_exttype = ext;
   1535      0     stevel 		sae->spd_address_af = af;
   1536      0     stevel 		sae->spd_address_prefixlen = pfxlen;
   1537      0     stevel 		sae->spd_address_reserved2 = 0;
   1538      0     stevel 
   1539      0     stevel 		spdaddr = (ipsec_addr_t *)(&sae[1]);
   1540      0     stevel 		bcopy(addr, spdaddr, addrlen);
   1541      0     stevel 	}
   1542      0     stevel 	offset += sizeof (*sae);
   1543      0     stevel 	addrlen = roundup(addrlen, sizeof (uint64_t));
   1544      0     stevel 	offset += addrlen;
   1545      0     stevel 
   1546      0     stevel 	ASSERT(ALIGNED64(offset));
   1547      0     stevel 
   1548      0     stevel 	if (base != NULL)
   1549      0     stevel 		sae->spd_address_len = SPD_8TO64(offset - start);
   1550      0     stevel 	return (offset);
   1551      0     stevel }
   1552      0     stevel 
   1553      0     stevel static uint_t
   1554      0     stevel spdsock_encode_sel(uint8_t *base, uint_t offset, const ipsec_sel_t *sel)
   1555      0     stevel {
   1556      0     stevel 	const ipsec_selkey_t *selkey = &sel->ipsl_key;
   1557      0     stevel 
   1558      0     stevel 	if (selkey->ipsl_valid & IPSL_PROTOCOL)
   1559      0     stevel 		offset = spdsock_encode_proto(base, offset, selkey->ipsl_proto);
   1560      0     stevel 	if (selkey->ipsl_valid & IPSL_LOCAL_PORT)
   1561      0     stevel 		offset = spdsock_encode_port(base, offset, SPD_EXT_LCLPORT,
   1562      0     stevel 		    selkey->ipsl_lport);
   1563      0     stevel 	if (selkey->ipsl_valid & IPSL_REMOTE_PORT)
   1564      0     stevel 		offset = spdsock_encode_port(base, offset, SPD_EXT_REMPORT,
   1565      0     stevel 		    selkey->ipsl_rport);
   1566      0     stevel 	if (selkey->ipsl_valid & IPSL_REMOTE_ADDR)
   1567      0     stevel 		offset = spdsock_encode_addr(base, offset, SPD_EXT_REMADDR,
   1568      0     stevel 		    selkey, &selkey->ipsl_remote, selkey->ipsl_remote_pfxlen);
   1569      0     stevel 	if (selkey->ipsl_valid & IPSL_LOCAL_ADDR)
   1570      0     stevel 		offset = spdsock_encode_addr(base, offset, SPD_EXT_LCLADDR,
   1571      0     stevel 		    selkey, &selkey->ipsl_local, selkey->ipsl_local_pfxlen);
   1572      0     stevel 	if (selkey->ipsl_valid & IPSL_ICMP_TYPE) {
   1573      0     stevel 		offset = spdsock_encode_typecode(base, offset,
   1574      0     stevel 		    selkey->ipsl_icmp_type, selkey->ipsl_icmp_type_end,
   1575      0     stevel 		    (selkey->ipsl_valid & IPSL_ICMP_CODE) ?
   1576   5240   nordmark 		    selkey->ipsl_icmp_code : 255,
   1577      0     stevel 		    (selkey->ipsl_valid & IPSL_ICMP_CODE) ?
   1578   5240   nordmark 		    selkey->ipsl_icmp_code_end : 255);
   1579      0     stevel 	}
   1580      0     stevel 	return (offset);
   1581      0     stevel }
   1582      0     stevel 
   1583      0     stevel static uint_t
   1584      0     stevel spdsock_encode_actattr(uint8_t *base, uint_t offset, uint32_t tag,
   1585      0     stevel     uint32_t value)
   1586      0     stevel {
   1587      0     stevel 	struct spd_attribute *attr;
   1588      0     stevel 
   1589      0     stevel 	ASSERT(ALIGNED64(offset));
   1590      0     stevel 
   1591      0     stevel 	if (base != NULL) {
   1592      0     stevel 		attr = (struct spd_attribute *)(base + offset);
   1593      0     stevel 		attr->spd_attr_tag = tag;
   1594      0     stevel 		attr->spd_attr_value = value;
   1595      0     stevel 	}
   1596      0     stevel 	offset += sizeof (struct spd_attribute);
   1597      0     stevel 
   1598      0     stevel 	ASSERT(ALIGNED64(offset));
   1599      0     stevel 
   1600      0     stevel 	return (offset);
   1601      0     stevel }
   1602      0     stevel 
   1603      0     stevel 
   1604      0     stevel #define	EMIT(t, v) offset = spdsock_encode_actattr(base, offset, (t), (v))
   1605      0     stevel 
   1606      0     stevel static uint_t
   1607      0     stevel spdsock_encode_action(uint8_t *base, uint_t offset, const ipsec_action_t *ap)
   1608      0     stevel {
   1609      0     stevel 	const struct ipsec_act *act = &(ap->ipa_act);
   1610      0     stevel 	uint_t flags;
   1611      0     stevel 
   1612      0     stevel 	EMIT(SPD_ATTR_EMPTY, 0);
   1613      0     stevel 	switch (act->ipa_type) {
   1614      0     stevel 	case IPSEC_ACT_DISCARD:
   1615      0     stevel 	case IPSEC_ACT_REJECT:
   1616      0     stevel 		EMIT(SPD_ATTR_TYPE, SPD_ACTTYPE_DROP);
   1617      0     stevel 		break;
   1618      0     stevel 	case IPSEC_ACT_BYPASS:
   1619      0     stevel 	case IPSEC_ACT_CLEAR:
   1620      0     stevel 		EMIT(SPD_ATTR_TYPE, SPD_ACTTYPE_PASS);
   1621      0     stevel 		break;
   1622      0     stevel 
   1623      0     stevel 	case IPSEC_ACT_APPLY:
   1624      0     stevel 		EMIT(SPD_ATTR_TYPE, SPD_ACTTYPE_IPSEC);
   1625      0     stevel 		flags = 0;
   1626      0     stevel 		if (act->ipa_apply.ipp_use_ah)
   1627      0     stevel 			flags |= SPD_APPLY_AH;
   1628      0     stevel 		if (act->ipa_apply.ipp_use_esp)
   1629      0     stevel 			flags |= SPD_APPLY_ESP;
   1630      0     stevel 		if (act->ipa_apply.ipp_use_espa)
   1631      0     stevel 			flags |= SPD_APPLY_ESPA;
   1632      0     stevel 		if (act->ipa_apply.ipp_use_se)
   1633      0     stevel 			flags |= SPD_APPLY_SE;
   1634      0     stevel 		if (act->ipa_apply.ipp_use_unique)
   1635      0     stevel 			flags |= SPD_APPLY_UNIQUE;
   1636      0     stevel 		EMIT(SPD_ATTR_FLAGS, flags);
   1637      0     stevel 		if (flags & SPD_APPLY_AH) {
   1638      0     stevel 			EMIT(SPD_ATTR_AH_AUTH, act->ipa_apply.ipp_auth_alg);
   1639      0     stevel 			EMIT(SPD_ATTR_AH_MINBITS,
   1640      0     stevel 			    act->ipa_apply.ipp_ah_minbits);
   1641      0     stevel 			EMIT(SPD_ATTR_AH_MAXBITS,
   1642      0     stevel 			    act->ipa_apply.ipp_ah_maxbits);
   1643      0     stevel 		}
   1644      0     stevel 		if (flags & SPD_APPLY_ESP) {
   1645      0     stevel 			EMIT(SPD_ATTR_ESP_ENCR, act->ipa_apply.ipp_encr_alg);
   1646      0     stevel 			EMIT(SPD_ATTR_ENCR_MINBITS,
   1647      0     stevel 			    act->ipa_apply.ipp_espe_minbits);
   1648      0     stevel 			EMIT(SPD_ATTR_ENCR_MAXBITS,
   1649      0     stevel 			    act->ipa_apply.ipp_espe_maxbits);
   1650      0     stevel 			if (flags & SPD_APPLY_ESPA) {
   1651      0     stevel 				EMIT(SPD_ATTR_ESP_AUTH,
   1652      0     stevel 				    act->ipa_apply.ipp_esp_auth_alg);
   1653      0     stevel 				EMIT(SPD_ATTR_ESPA_MINBITS,
   1654      0     stevel 				    act->ipa_apply.ipp_espa_minbits);
   1655      0     stevel 				EMIT(SPD_ATTR_ESPA_MAXBITS,
   1656      0     stevel 				    act->ipa_apply.ipp_espa_maxbits);
   1657      0     stevel 			}
   1658      0     stevel 		}
   1659      0     stevel 		if (act->ipa_apply.ipp_km_proto != 0)
   1660      0     stevel 			EMIT(SPD_ATTR_KM_PROTO, act->ipa_apply.ipp_km_proto);
   1661      0     stevel 		if (act->ipa_apply.ipp_km_cookie != 0)
   1662      0     stevel 			EMIT(SPD_ATTR_KM_PROTO, act->ipa_apply.ipp_km_cookie);
   1663      0     stevel 		if (act->ipa_apply.ipp_replay_depth != 0)
   1664      0     stevel 			EMIT(SPD_ATTR_REPLAY_DEPTH,
   1665      0     stevel 			    act->ipa_apply.ipp_replay_depth);
   1666      0     stevel 		/* Add more here */
   1667      0     stevel 		break;
   1668      0     stevel 	}
   1669      0     stevel 
   1670      0     stevel 	return (offset);
   1671      0     stevel }
   1672      0     stevel 
   1673      0     stevel static uint_t
   1674      0     stevel spdsock_encode_action_list(uint8_t *base, uint_t offset,
   1675      0     stevel     const ipsec_action_t *ap)
   1676      0     stevel {
   1677      0     stevel 	struct spd_ext_actions *act;
   1678      0     stevel 	uint_t nact = 0;
   1679      0     stevel 	uint_t start = offset;
   1680      0     stevel 
   1681      0     stevel 	ASSERT(ALIGNED64(offset));
   1682      0     stevel 
   1683      0     stevel 	if (base != NULL) {
   1684      0     stevel 		act = (struct spd_ext_actions *)(base + offset);
   1685      0     stevel 		act->spd_actions_len = 0;
   1686      0     stevel 		act->spd_actions_exttype = SPD_EXT_ACTION;
   1687      0     stevel 		act->spd_actions_count = 0;
   1688      0     stevel 		act->spd_actions_reserved = 0;
   1689      0     stevel 	}
   1690      0     stevel 
   1691      0     stevel 	offset += sizeof (*act);
   1692      0     stevel 
   1693      0     stevel 	ASSERT(ALIGNED64(offset));
   1694      0     stevel 
   1695      0     stevel 	while (ap != NULL) {
   1696      0     stevel 		offset = spdsock_encode_action(base, offset, ap);
   1697      0     stevel 		ap = ap->ipa_next;
   1698      0     stevel 		nact++;
   1699      0     stevel 		if (ap != NULL) {
   1700      0     stevel 			EMIT(SPD_ATTR_NEXT, 0);
   1701      0     stevel 		}
   1702      0     stevel 	}
   1703      0     stevel 	EMIT(SPD_ATTR_END, 0);
   1704      0     stevel 
   1705      0     stevel 	ASSERT(ALIGNED64(offset));
   1706      0     stevel 
   1707      0     stevel 	if (base != NULL) {
   1708      0     stevel 		act->spd_actions_count = nact;
   1709      0     stevel 		act->spd_actions_len = SPD_8TO64(offset - start);
   1710      0     stevel 	}
   1711      0     stevel 
   1712      0     stevel 	return (offset);
   1713      0     stevel }
   1714      0     stevel 
   1715      0     stevel #undef EMIT
   1716      0     stevel 
   1717      0     stevel /* ARGSUSED */
   1718      0     stevel static uint_t
   1719      0     stevel spdsock_rule_flags(uint_t dir, uint_t af)
   1720      0     stevel {
   1721      0     stevel 	uint_t flags = 0;
   1722      0     stevel 
   1723      0     stevel 	if (dir == IPSEC_TYPE_INBOUND)
   1724      0     stevel 		flags |= SPD_RULE_FLAG_INBOUND;
   1725      0     stevel 	if (dir == IPSEC_TYPE_OUTBOUND)
   1726      0     stevel 		flags |= SPD_RULE_FLAG_OUTBOUND;
   1727      0     stevel 
   1728      0     stevel 	return (flags);
   1729      0     stevel }
   1730      0     stevel 
   1731      0     stevel 
   1732      0     stevel static uint_t
   1733   3055     danmcd spdsock_encode_rule_head(uint8_t *base, uint_t offset, spd_msg_t *req,
   1734   3055     danmcd     const ipsec_policy_t *rule, uint_t dir, uint_t af, char *name,
   1735   3055     danmcd     boolean_t tunnel)
   1736      0     stevel {
   1737      0     stevel 	struct spd_msg *spmsg;
   1738      0     stevel 	struct spd_rule *spr;
   1739   3055     danmcd 	spd_if_t *sid;
   1740      0     stevel 
   1741      0     stevel 	uint_t start = offset;
   1742      0     stevel 
   1743      0     stevel 	ASSERT(ALIGNED64(offset));
   1744      0     stevel 
   1745      0     stevel 	if (base != NULL) {
   1746      0     stevel 		spmsg = (struct spd_msg *)(base + offset);
   1747      0     stevel 		bzero(spmsg, sizeof (*spmsg));
   1748      0     stevel 		spmsg->spd_msg_version = PF_POLICY_V1;
   1749      0     stevel 		spmsg->spd_msg_type = SPD_DUMP;
   1750      0     stevel 		spmsg->spd_msg_seq = req->spd_msg_seq;
   1751      0     stevel 		spmsg->spd_msg_pid = req->spd_msg_pid;
   1752      0     stevel 	}
   1753      0     stevel 	offset += sizeof (struct spd_msg);
   1754      0     stevel 
   1755      0     stevel 	ASSERT(ALIGNED64(offset));
   1756      0     stevel 
   1757      0     stevel 	if (base != NULL) {
   1758      0     stevel 		spr = (struct spd_rule *)(base + offset);
   1759      0     stevel 		spr->spd_rule_type = SPD_EXT_RULE;
   1760      0     stevel 		spr->spd_rule_priority = rule->ipsp_prio;
   1761      0     stevel 		spr->spd_rule_flags = spdsock_rule_flags(dir, af);
   1762   3055     danmcd 		if (tunnel)
   1763   3055     danmcd 			spr->spd_rule_flags |= SPD_RULE_FLAG_TUNNEL;
   1764      0     stevel 		spr->spd_rule_unused = 0;
   1765      0     stevel 		spr->spd_rule_len = SPD_8TO64(sizeof (*spr));
   1766      0     stevel 		spr->spd_rule_index = rule->ipsp_index;
   1767      0     stevel 	}
   1768      0     stevel 	offset += sizeof (struct spd_rule);
   1769   3055     danmcd 
   1770   3055     danmcd 	/*
   1771   3055     danmcd 	 * If we have an interface name (i.e. if this policy head came from
   1772   3055     danmcd 	 * a tunnel), add the SPD_EXT_TUN_NAME extension.
   1773   3055     danmcd 	 */
   1774   6466     danmcd 	if (name != NULL) {
   1775   3055     danmcd 
   1776   3055     danmcd 		ASSERT(ALIGNED64(offset));
   1777   3055     danmcd 
   1778   3055     danmcd 		if (base != NULL) {
   1779   3055     danmcd 			sid = (spd_if_t *)(base + offset);
   1780   3055     danmcd 			sid->spd_if_exttype = SPD_EXT_TUN_NAME;
   1781   3055     danmcd 			sid->spd_if_len = SPD_8TO64(sizeof (spd_if_t) +
   1782   3055     danmcd 			    roundup((strlen(name) - 4), 8));
   1783   3055     danmcd 			(void) strlcpy((char *)sid->spd_if_name, name,
   1784   3055     danmcd 			    LIFNAMSIZ);
   1785   3055     danmcd 		}
   1786   3055     danmcd 
   1787   3055     danmcd 		offset += sizeof (spd_if_t) + roundup((strlen(name) - 4), 8);
   1788   3055     danmcd 	}
   1789   3055     danmcd 
   1790      0     stevel 	offset = spdsock_encode_sel(base, offset, rule->ipsp_sel);
   1791      0     stevel 	offset = spdsock_encode_action_list(base, offset, rule->ipsp_act);
   1792      0     stevel 
   1793      0     stevel 	ASSERT(ALIGNED64(offset));
   1794      0     stevel 
   1795      0     stevel 	if (base != NULL) {
   1796      0     stevel 		spmsg->spd_msg_len = SPD_8TO64(offset - start);
   1797      0     stevel 	}
   1798      0     stevel 	return (offset);
   1799      0     stevel }
   1800      0     stevel 
   1801      0     stevel /* ARGSUSED */
   1802      0     stevel static mblk_t *
   1803      0     stevel spdsock_encode_rule(mblk_t *req, const ipsec_policy_t *rule,
   1804   3055     danmcd     uint_t dir, uint_t af, char *name, boolean_t tunnel)
   1805      0     stevel {
   1806      0     stevel 	mblk_t *m;
   1807      0     stevel 	uint_t len;
   1808      0     stevel 	spd_msg_t *mreq = (spd_msg_t *)req->b_rptr;
   1809      0     stevel 
   1810      0     stevel 	/*
   1811      0     stevel 	 * Figure out how much space we'll need.
   1812      0     stevel 	 */
   1813   3055     danmcd 	len = spdsock_encode_rule_head(NULL, 0, mreq, rule, dir, af, name,
   1814   3055     danmcd 	    tunnel);
   1815      0     stevel 
   1816      0     stevel 	/*
   1817      0     stevel 	 * Allocate mblk.
   1818      0     stevel 	 */
   1819      0     stevel 	m = allocb(len, BPRI_HI);
   1820      0     stevel 	if (m == NULL)
   1821      0     stevel 		return (NULL);
   1822      0     stevel 
   1823      0     stevel 	/*
   1824      0     stevel 	 * Fill it in..
   1825      0     stevel 	 */
   1826      0     stevel 	m->b_wptr = m->b_rptr + len;
   1827      0     stevel 	bzero(m->b_rptr, len);
   1828   3055     danmcd 	(void) spdsock_encode_rule_head(m->b_rptr, 0, mreq, rule, dir, af,
   1829   3055     danmcd 	    name, tunnel);
   1830      0     stevel 	return (m);
   1831      0     stevel }
   1832      0     stevel 
   1833      0     stevel static ipsec_policy_t *
   1834     81   sommerfe spdsock_dump_next_in_chain(spdsock_t *ss, ipsec_policy_head_t *iph,
   1835     81   sommerfe     ipsec_policy_t *cur)
   1836     81   sommerfe {
   1837     81   sommerfe 	ASSERT(RW_READ_HELD(&iph->iph_lock));
   1838     81   sommerfe 
   1839     81   sommerfe 	ss->spdsock_dump_count++;
   1840     81   sommerfe 	ss->spdsock_dump_cur_rule = cur->ipsp_hash.hash_next;
   1841     81   sommerfe 	return (cur);
   1842     81   sommerfe }
   1843     81   sommerfe 
   1844     81   sommerfe static ipsec_policy_t *
   1845      0     stevel spdsock_dump_next_rule(spdsock_t *ss, ipsec_policy_head_t *iph)
   1846      0     stevel {
   1847      0     stevel 	ipsec_policy_t *cur;
   1848     81   sommerfe 	ipsec_policy_root_t *ipr;
   1849     81   sommerfe 	int chain, nchains, type, af;
   1850      0     stevel 
   1851      0     stevel 	ASSERT(RW_READ_HELD(&iph->iph_lock));
   1852      0     stevel 
   1853      0     stevel 	cur = ss->spdsock_dump_cur_rule;
   1854      0     stevel 
   1855     81   sommerfe 	if (cur != NULL)
   1856     81   sommerfe 		return (spdsock_dump_next_in_chain(ss, iph, cur));
   1857     81   sommerfe 
   1858     81   sommerfe 	type = ss->spdsock_dump_cur_type;
   1859     81   sommerfe 
   1860     81   sommerfe next:
   1861     81   sommerfe 	chain = ss->spdsock_dump_cur_chain;
   1862     81   sommerfe 	ipr = &iph->iph_root[type];
   1863     81   sommerfe 	nchains = ipr->ipr_nchains;
   1864     81   sommerfe 
   1865     81   sommerfe 	while (chain < nchains) {
   1866     81   sommerfe 		cur = ipr->ipr_hash[chain].hash_head;
   1867     81   sommerfe 		chain++;
   1868     81   sommerfe 		if (cur != NULL) {
   1869     81   sommerfe 			ss->spdsock_dump_cur_chain = chain;
   1870     81   sommerfe 			return (spdsock_dump_next_in_chain(ss, iph, cur));
   1871     81   sommerfe 		}
   1872      0     stevel 	}
   1873     81   sommerfe 	ss->spdsock_dump_cur_chain = nchains;
   1874     81   sommerfe 
   1875     81   sommerfe 	af = ss->spdsock_dump_cur_af;
   1876     81   sommerfe 	while (af < IPSEC_NAF) {
   1877     81   sommerfe 		cur = ipr->ipr_nonhash[af];
   1878     81   sommerfe 		af++;
   1879     81   sommerfe 		if (cur != NULL) {
   1880     81   sommerfe 			ss->spdsock_dump_cur_af = af;
   1881     81   sommerfe 			return (spdsock_dump_next_in_chain(ss, iph, cur));
   1882     81   sommerfe 		}
   1883     81   sommerfe 	}
   1884     81   sommerfe 
   1885     81   sommerfe 	type++;
   1886     81   sommerfe 	if (type >= IPSEC_NTYPES)
   1887     81   sommerfe 		return (NULL);
   1888     81   sommerfe 
   1889     81   sommerfe 	ss->spdsock_dump_cur_chain = 0;
   1890     81   sommerfe 	ss->spdsock_dump_cur_type = type;
   1891     81   sommerfe 	ss->spdsock_dump_cur_af = IPSEC_AF_V4;
   1892     81   sommerfe 	goto next;
   1893     81   sommerfe 
   1894      0     stevel }
   1895      0     stevel 
   1896   6430     danmcd /*
   1897   6430     danmcd  * If we're done with one policy head, but have more to go, we iterate through
   1898   6430     danmcd  * another IPsec tunnel policy head (itp).  Return NULL if it is an error
   1899   6430     danmcd  * worthy of returning EAGAIN via PF_POLICY.
   1900   6430     danmcd  */
   1901   6430     danmcd static ipsec_tun_pol_t *
   1902   6430     danmcd spdsock_dump_iterate_next_tunnel(spdsock_t *ss, ipsec_stack_t *ipss)
   1903   6430     danmcd {
   1904   6430     danmcd 	ipsec_tun_pol_t *itp;
   1905   6430     danmcd 
   1906   6430     danmcd 	ASSERT(RW_READ_HELD(&ipss->ipsec_tunnel_policy_lock));
   1907   6430     danmcd 	if (ipss->ipsec_tunnel_policy_gen > ss->spdsock_dump_tun_gen) {
   1908   6430     danmcd 		/* Oops, state of the tunnel polheads changed. */
   1909   6430     danmcd 		itp = NULL;
   1910   6430     danmcd 	} else if (ss->spdsock_itp == NULL) {
   1911   6430     danmcd 		/* Just finished global, find first node. */
   1912   6430     danmcd 		itp = avl_first(&ipss->ipsec_tunnel_policies);
   1913   6430     danmcd 	} else {
   1914   6430     danmcd 		/* We just finished current polhead, find the next one. */
   1915   6430     danmcd 		itp = AVL_NEXT(&ipss->ipsec_tunnel_policies, ss->spdsock_itp);
   1916   6430     danmcd 	}
   1917   6430     danmcd 	if (itp != NULL) {
   1918   6430     danmcd 		ITP_REFHOLD(itp);
   1919   6430     danmcd 	}
   1920   6430     danmcd 	if (ss->spdsock_itp != NULL) {
   1921   6430     danmcd 		ITP_REFRELE(ss->spdsock_itp, ipss->ipsec_netstack);
   1922   6430     danmcd 	}
   1923   6430     danmcd 	ss->spdsock_itp = itp;
   1924   6430     danmcd 	return (itp);
   1925   6430     danmcd }
   1926   6430     danmcd 
   1927      0     stevel static mblk_t *
   1928      0     stevel spdsock_dump_next_record(spdsock_t *ss)
   1929      0     stevel {
   1930      0     stevel 	ipsec_policy_head_t *iph;
   1931      0     stevel 	ipsec_policy_t *rule;
   1932      0     stevel 	mblk_t *m;
   1933   6430     danmcd 	ipsec_tun_pol_t *itp;
   1934   6430     danmcd 	netstack_t *ns = ss->spdsock_spds->spds_netstack;
   1935   6430     danmcd 	ipsec_stack_t *ipss = ns->netstack_ipsec;
   1936      0     stevel 
   1937      0     stevel 	iph = ss->spdsock_dump_head;
   1938      0     stevel 
   1939      0     stevel 	ASSERT(iph != NULL);
   1940      0     stevel 
   1941      0     stevel 	rw_enter(&iph->iph_lock, RW_READER);
   1942      0     stevel 
   1943      0     stevel 	if (iph->iph_gen != ss->spdsock_dump_gen) {
   1944      0     stevel 		rw_exit(&iph->iph_lock);
   1945      0     stevel 		return (spdsock_dump_finish(ss, EAGAIN));
   1946      0     stevel 	}
   1947      0     stevel 
   1948   6430     danmcd 	while ((rule = spdsock_dump_next_rule(ss, iph)) == NULL) {
   1949   6430     danmcd 		rw_exit(&iph->iph_lock);
   1950   6430     danmcd 		if (--(ss->spdsock_dump_remaining_polheads) == 0)
   1951   6430     danmcd 			return (spdsock_dump_finish(ss, 0));
   1952      0     stevel 
   1953   6430     danmcd 
   1954   6430     danmcd 		/*
   1955   6430     danmcd 		 * If we reach here, we have more policy heads (tunnel
   1956   6430     danmcd 		 * entries) to dump.  Let's reset to a new policy head
   1957   6430     danmcd 		 * and get some more rules.
   1958   6430     danmcd 		 *
   1959   6430     danmcd 		 * An empty policy head will have spdsock_dump_next_rule()
   1960   6430     danmcd 		 * return NULL, and we loop (while dropping the number of
   1961   6430     danmcd 		 * remaining polheads).  If we loop to 0, we finish.  We
   1962   6430     danmcd 		 * keep looping until we hit 0 or until we have a rule to
   1963   6430     danmcd 		 * encode.
   1964   6430     danmcd 		 *
   1965   6430     danmcd 		 * NOTE:  No need for ITP_REF*() macros here as we're only
   1966   6430     danmcd 		 * going after and refholding the policy head itself.
   1967   6430     danmcd 		 */
   1968   6430     danmcd 		rw_enter(&ipss->ipsec_tunnel_policy_lock, RW_READER);
   1969   6430     danmcd 		itp = spdsock_dump_iterate_next_tunnel(ss, ipss);
   1970   6430     danmcd 		if (itp == NULL) {
   1971   6430     danmcd 			rw_exit(&ipss->ipsec_tunnel_policy_lock);
   1972   6430     danmcd 			return (spdsock_dump_finish(ss, EAGAIN));
   1973   6430     danmcd 		}
   1974   6430     danmcd 
   1975   6430     danmcd 		/* Reset other spdsock_dump thingies. */
   1976   6430     danmcd 		IPPH_REFRELE(ss->spdsock_dump_head, ns);
   1977   6430     danmcd 		if (ss->spdsock_dump_active) {
   1978   6430     danmcd 			ss->spdsock_dump_tunnel =
   1979   6430     danmcd 			    itp->itp_flags & ITPF_P_TUNNEL;
   1980   6430     danmcd 			iph = itp->itp_policy;
   1981   6430     danmcd 		} else {
   1982   6430     danmcd 			ss->spdsock_dump_tunnel =
   1983   6430     danmcd 			    itp->itp_flags & ITPF_I_TUNNEL;
   1984   6430     danmcd 			iph = itp->itp_inactive;
   1985   6430     danmcd 		}
   1986   6430     danmcd 		IPPH_REFHOLD(iph);
   1987   6430     danmcd 		rw_exit(&ipss->ipsec_tunnel_policy_lock);
   1988   6430     danmcd 
   1989   6430     danmcd 		rw_enter(&iph->iph_lock, RW_READER);
   1990   6430     danmcd 		RESET_SPDSOCK_DUMP_POLHEAD(ss, iph);
   1991      0     stevel 	}
   1992      0     stevel 
   1993   6430     danmcd 	m = spdsock_encode_rule(ss->spdsock_dump_req, rule,
   1994   6430     danmcd 	    ss->spdsock_dump_cur_type, ss->spdsock_dump_cur_af,
   1995   6466     danmcd 	    (ss->spdsock_itp == NULL) ? NULL : ss->spdsock_itp->itp_name,
   1996   6466     danmcd 	    ss->spdsock_dump_tunnel);
   1997      0     stevel 	rw_exit(&iph->iph_lock);
   1998      0     stevel 
   1999      0     stevel 	if (m == NULL)
   2000      0     stevel 		return (spdsock_dump_finish(ss, ENOMEM));
   2001      0     stevel 	return (m);
   2002      0     stevel }
   2003      0     stevel 
   2004      0     stevel /*
   2005      0     stevel  * Dump records until we run into flow-control back-pressure.
   2006      0     stevel  */
   2007      0     stevel static void
   2008      0     stevel spdsock_dump_some(queue_t *q, spdsock_t *ss)
   2009      0     stevel {
   2010      0     stevel 	mblk_t *m, *dataind;
   2011      0     stevel 
   2012      0     stevel 	while ((ss->spdsock_dump_req != NULL) && canputnext(q)) {
   2013      0     stevel 		m = spdsock_dump_next_record(ss);
   2014      0     stevel 		if (m == NULL)
   2015      0     stevel 			return;
   2016      0     stevel 		dataind = allocb(sizeof (struct T_data_req), BPRI_HI);
   2017      0     stevel 		if (dataind == NULL) {
   2018      0     stevel 			freemsg(m);
   2019      0     stevel 			return;
   2020      0     stevel 		}
   2021      0     stevel 		dataind->b_cont = m;
   2022      0     stevel 		dataind->b_wptr += sizeof (struct T_data_req);
   2023      0     stevel 		((struct T_data_ind *)dataind->b_rptr)->PRIM_type = T_DATA_IND;
   2024      0     stevel 		((struct T_data_ind *)dataind->b_rptr)->MORE_flag = 0;
   2025      0     stevel 		dataind->b_datap->db_type = M_PROTO;
   2026      0     stevel 		putnext(q, dataind);
   2027      0     stevel 	}
   2028      0     stevel }
   2029      0     stevel 
   2030      0     stevel /*
   2031      0     stevel  * Start dumping.
   2032      0     stevel  * Format a start-of-dump record, and set up the stream and kick the rsrv
   2033      0     stevel  * procedure to continue the job..
   2034      0     stevel  */
   2035      0     stevel /* ARGSUSED */
   2036      0     stevel static void
   2037   3055     danmcd spdsock_dump(queue_t *q, ipsec_policy_head_t *iph, mblk_t *mp)
   2038      0     stevel {
   2039      0     stevel 	spdsock_t *ss = (spdsock_t *)q->q_ptr;
   2040   6430     danmcd 	netstack_t *ns = ss->spdsock_spds->spds_netstack;
   2041   3448   dh155122 	ipsec_stack_t *ipss = ns->netstack_ipsec;
   2042      0     stevel 	mblk_t *mr;
   2043   3055     danmcd 
   2044   6430     danmcd 	/* spdsock_open() already set spdsock_itp to NULL. */
   2045   3055     danmcd 	if (iph == ALL_ACTIVE_POLHEADS || iph == ALL_INACTIVE_POLHEADS) {
   2046   3448   dh155122 		rw_enter(&ipss->ipsec_tunnel_policy_lock, RW_READER);
   2047   3055     danmcd 		ss->spdsock_dump_remaining_polheads = 1 +
   2048   3448   dh155122 		    avl_numnodes(&ipss->ipsec_tunnel_policies);
   2049   3448   dh155122 		ss->spdsock_dump_tun_gen = ipss->ipsec_tunnel_policy_gen;
   2050   3448   dh155122 		rw_exit(&ipss->ipsec_tunnel_policy_lock);
   2051   3055     danmcd 		if (iph == ALL_ACTIVE_POLHEADS) {
   2052   3448   dh155122 			iph = ipsec_system_policy(ns);
   2053   3055     danmcd 			ss->spdsock_dump_active = B_TRUE;
   2054   3055     danmcd 		} else {
   2055   6430     danmcd 			iph = ipsec_inactive_policy(ns);
   2056   3055     danmcd 			ss->spdsock_dump_active = B_FALSE;
   2057   3055     danmcd 		}
   2058   6430     danmcd 		ASSERT(ss->spdsock_itp == NULL);
   2059   3055     danmcd 	} else {
   2060   3055     danmcd 		ss->spdsock_dump_remaining_polheads = 1;
   2061   3055     danmcd 	}
   2062      0     stevel 
   2063      0     stevel 	rw_enter(&iph->iph_lock, RW_READER);
   2064      0     stevel 
   2065      0     stevel 	mr = spdsock_dump_ruleset(mp, iph, 0, 0);
   2066      0     stevel 
   2067      0     stevel 	if (!mr) {
   2068      0     stevel 		rw_exit(&iph->iph_lock);
   2069      0     stevel 		spdsock_error(q, mp, ENOMEM, 0);
   2070      0     stevel 		return;
   2071      0     stevel 	}
   2072      0     stevel 
   2073      0     stevel 	ss->spdsock_dump_req = mp;
   2074   6430     danmcd 	RESET_SPDSOCK_DUMP_POLHEAD(ss, iph);
   2075   6430     danmcd 
   2076      0     stevel 	rw_exit(&iph->iph_lock);
   2077      0     stevel 
   2078      0     stevel 	qreply(q, mr);
   2079      0     stevel 	qenable(OTHERQ(q));
   2080      0     stevel }
   2081      0     stevel 
   2082   3055     danmcd /* Do NOT consume a reference to ITP. */
   2083      0     stevel void
   2084   3448   dh155122 spdsock_clone_node(ipsec_tun_pol_t *itp, void *ep, netstack_t *ns)
   2085      0     stevel {
   2086   3055     danmcd 	int *errptr = (int *)ep;
   2087   3055     danmcd 
   2088   3055     danmcd 	if (*errptr != 0)
   2089   3055     danmcd 		return;	/* We've failed already for some reason. */
   2090   3055     danmcd 	mutex_enter(&itp->itp_lock);
   2091   3055     danmcd 	ITPF_CLONE(itp->itp_flags);
   2092   3448   dh155122 	*errptr = ipsec_copy_polhead(itp->itp_policy, itp->itp_inactive, ns);
   2093   3055     danmcd 	mutex_exit(&itp->itp_lock);
   2094   3055     danmcd }
   2095   3055     danmcd 
   2096   3055     danmcd void
   2097   3055     danmcd spdsock_clone(queue_t *q, mblk_t *mp, spd_if_t *tunname)
   2098   3055     danmcd {
   2099   3055     danmcd 	int error;
   2100   3055     danmcd 	char *tname;
   2101   3055     danmcd 	ipsec_tun_pol_t *itp;
   2102   3448   dh155122 	spdsock_t *ss = (spdsock_t *)q->q_ptr;
   2103   6430     danmcd 	netstack_t *ns = ss->spdsock_spds->spds_netstack;
   2104   3055     danmcd 
   2105   3055     danmcd 	if (tunname != NULL) {
   2106   3055     danmcd 		tname = (char *)tunname->spd_if_name;
   2107   3055     danmcd 		if (*tname == '\0') {
   2108   6430     danmcd 			error = ipsec_clone_system_policy(ns);
   2109   4307    pwernau 			if (audit_active) {
   2110   4307    pwernau 				boolean_t active;
   2111   4307    pwernau 				spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr;
   2112   8778       Erik 				cred_t *cr;
   2113   8778       Erik 				pid_t cpid;
   2114   4307    pwernau 
   2115   8778       Erik 				cr = msg_getcred(mp, &cpid);
   2116   4307    pwernau 				active = (spmsg->spd_msg_spdid == SPD_ACTIVE);
   2117   8778       Erik 				audit_pf_policy(SPD_CLONE, cr, ns,
   2118   8778       Erik 				    NULL, active, error, cpid);
   2119   4307    pwernau 			}
   2120   4307    pwernau 			if (error == 0) {
   2121   6430     danmcd 				itp_walk(spdsock_clone_node, &error, ns);
   2122   4307    pwernau 				if (audit_active) {
   2123   4307    pwernau 					boolean_t active;
   2124   4307    pwernau 					spd_msg_t *spmsg =
   2125   4307    pwernau 					    (spd_msg_t *)mp->b_rptr;
   2126   8778       Erik 					cred_t *cr;
   2127   8778       Erik 					pid_t cpid;
   2128   4307    pwernau 
   2129   8778       Erik 					cr = msg_getcred(mp, &cpid);
   2130   4307    pwernau 					active = (spmsg->spd_msg_spdid ==
   2131   4307    pwernau 					    SPD_ACTIVE);
   2132   8778       Erik 					audit_pf_policy(SPD_CLONE, cr,
   2133   6430     danmcd 					    ns, "all tunnels", active, 0,
   2134   8778       Erik 					    cpid);
   2135   4307    pwernau 				}
   2136   4307    pwernau 			}
   2137   3055     danmcd 		} else {
   2138   6430     danmcd 			itp = get_tunnel_policy(tname, ns);
   2139   3055     danmcd 			if (itp == NULL) {
   2140   3055     danmcd 				spdsock_error(q, mp, ENOENT, 0);
   2141   4307    pwernau 				if (audit_active) {
   2142   4307    pwernau 					boolean_t active;
   2143   4307    pwernau 					spd_msg_t *spmsg =
   2144   4307    pwernau 					    (spd_msg_t *)mp->b_rptr;
   2145   8778       Erik 					cred_t *cr;
   2146   8778       Erik 					pid_t cpid;
   2147   4307    pwernau 
   2148   8778       Erik 					cr = msg_getcred(mp, &cpid);
   2149   4307    pwernau 					active = (spmsg->spd_msg_spdid ==
   2150   4307    pwernau 					    SPD_ACTIVE);
   2151   8778       Erik 					audit_pf_policy(SPD_CLONE, cr,
   2152  10764     danmcd 					    ns, NULL, active, ENOENT, cpid);
   2153   4307    pwernau 				}
   2154   3055     danmcd 				return;
   2155   3055     danmcd 			}
   2156   3448   dh155122 			spdsock_clone_node(itp, &error, NULL);
   2157   4307    pwernau 			if (audit_active) {
   2158   4307    pwernau 				boolean_t active;
   2159   4307    pwernau 				spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr;
   2160   8778       Erik 				cred_t *cr;
   2161   8778       Erik 				pid_t cpid;
   2162   4307    pwernau 
   2163   8778       Erik 				cr = msg_getcred(mp, &cpid);
   2164   4307    pwernau 				active = (spmsg->spd_msg_spdid == SPD_ACTIVE);
   2165   8778       Erik 				audit_pf_policy(SPD_CLONE, cr, ns,
   2166   8778       Erik 				    ITP_NAME(itp), active, error, cpid);
   2167   4307    pwernau 			}
   2168  10764     danmcd 			ITP_REFRELE(itp, ns);
   2169   3055     danmcd 		}
   2170   3055     danmcd 	} else {
   2171   6430     danmcd 		error = ipsec_clone_system_policy(ns);
   2172   4307    pwernau 		if (audit_active) {
   2173   4307    pwernau 			boolean_t active;
   2174   4307    pwernau 			spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr;
   2175   8778       Erik 			cred_t *cr;
   2176   8778       Erik 			pid_t cpid;
   2177   4307    pwernau 
   2178   8778       Erik 			cr = msg_getcred(mp, &cpid);
   2179   4307    pwernau 			active = (spmsg->spd_msg_spdid == SPD_ACTIVE);
   2180   8778       Erik 			audit_pf_policy(SPD_CLONE, cr, ns, NULL,
   2181   8778       Erik 			    active, error, cpid);
   2182   4307    pwernau 		}
   2183   3055     danmcd 	}
   2184   3055     danmcd 
   2185      0     stevel 	if (error != 0)
   2186      0     stevel 		spdsock_error(q, mp, error, 0);
   2187      0     stevel 	else
   2188      0     stevel 		spd_echo(q, mp);
   2189      0     stevel }
   2190      0     stevel 
   2191      0     stevel /*
   2192      0     stevel  * Process a SPD_ALGLIST request. The caller expects separate alg entries
   2193      0     stevel  * for AH authentication, ESP authentication, and ESP encryption.
   2194      0     stevel  * The same distinction is then used when setting the min and max key
   2195      0     stevel  * sizes when defining policies.
   2196      0     stevel  */
   2197      0     stevel 
   2198      0     stevel #define	SPDSOCK_AH_AUTH		0
   2199      0     stevel #define	SPDSOCK_ESP_AUTH	1
   2200      0     stevel #define	SPDSOCK_ESP_ENCR	2
   2201      0     stevel #define	SPDSOCK_NTYPES		3
   2202      0     stevel 
   2203      0     stevel static const uint_t algattr[SPDSOCK_NTYPES] = {
   2204      0     stevel 	SPD_ATTR_AH_AUTH,
   2205      0     stevel 	SPD_ATTR_ESP_AUTH,
   2206      0     stevel 	SPD_ATTR_ESP_ENCR
   2207      0     stevel };
   2208      0     stevel static const uint_t minbitsattr[SPDSOCK_NTYPES] = {
   2209      0     stevel 	SPD_ATTR_AH_MINBITS,
   2210      0     stevel 	SPD_ATTR_ESPA_MINBITS,
   2211      0     stevel 	SPD_ATTR_ENCR_MINBITS
   2212      0     stevel };
   2213      0     stevel static const uint_t maxbitsattr[SPDSOCK_NTYPES] = {
   2214      0     stevel 	SPD_ATTR_AH_MAXBITS,
   2215      0     stevel 	SPD_ATTR_ESPA_MAXBITS,
   2216      0     stevel 	SPD_ATTR_ENCR_MAXBITS
   2217      0     stevel };
   2218      0     stevel static const uint_t defbitsattr[SPDSOCK_NTYPES] = {
   2219      0     stevel 	SPD_ATTR_AH_DEFBITS,
   2220      0     stevel 	SPD_ATTR_ESPA_DEFBITS,
   2221      0     stevel 	SPD_ATTR_ENCR_DEFBITS
   2222      0     stevel };
   2223      0     stevel static const uint_t incrbitsattr[SPDSOCK_NTYPES] = {
   2224      0     stevel 	SPD_ATTR_AH_INCRBITS,
   2225      0     stevel 	SPD_ATTR_ESPA_INCRBITS,
   2226      0     stevel 	SPD_ATTR_ENCR_INCRBITS
   2227      0     stevel };
   2228      0     stevel 
   2229      0     stevel #define	ATTRPERALG	6	/* fixed attributes per algs */
   2230      0     stevel 
   2231      0     stevel void
   2232      0     stevel spdsock_alglist(queue_t *q, mblk_t *mp)
   2233      0     stevel {
   2234      0     stevel 	uint_t algtype;
   2235      0     stevel 	uint_t algidx;
   2236      0     stevel 	uint_t algcount;
   2237      0     stevel 	uint_t size;
   2238      0     stevel 	mblk_t *m;
   2239      0     stevel 	uint8_t *cur;
   2240      0     stevel 	spd_msg_t *msg;
   2241      0     stevel 	struct spd_ext_actions *act;
   2242      0     stevel 	struct spd_attribute *attr;
   2243   3448   dh155122 	spdsock_t *ss = (spdsock_t *)q->q_ptr;
   2244   6430     danmcd 	ipsec_stack_t *ipss = ss->spdsock_spds->spds_netstack->netstack_ipsec;
   2245      0     stevel 
   2246   3448   dh155122 	mutex_enter(&ipss->ipsec_alg_lock);
   2247      0     stevel 	/*
   2248      0     stevel 	 * The SPD client expects to receive separate entries for
   2249      0     stevel 	 * AH authentication and ESP authentication supported algorithms.
   2250      0     stevel 	 *
   2251      0     stevel 	 * Don't return the "any" algorithms, if defined, as no
   2252      0     stevel 	 * kernel policies can be set for these algorithms.
   2253      0     stevel 	 */
   2254   3448   dh155122 	algcount = 2 * ipss->ipsec_nalgs[IPSEC_ALG_AUTH] +
   2255   3448   dh155122 	    ipss->ipsec_nalgs[IPSEC_ALG_ENCR];
   2256      0     stevel 
   2257   3448   dh155122 	if (ipss->ipsec_alglists[IPSEC_ALG_AUTH][SADB_AALG_NONE] != NULL)
   2258      0     stevel 		algcount--;
   2259   3448   dh155122 	if (ipss->ipsec_alglists[IPSEC_ALG_ENCR][SADB_EALG_NONE] != NULL)
   2260      0     stevel 		algcount--;
   2261      0     stevel 
   2262      0     stevel 	/*
   2263      0     stevel 	 * For each algorithm, we encode:
   2264      0     stevel 	 * ALG / MINBITS / MAXBITS / DEFBITS / INCRBITS / {END, NEXT}
   2265      0     stevel 	 */
   2266      0     stevel 
   2267      0     stevel 	size = sizeof (spd_msg_t) + sizeof (struct spd_ext_actions) +
   2268      0     stevel 	    ATTRPERALG * sizeof (struct spd_attribute) * algcount;
   2269      0     stevel 
   2270      0     stevel 	ASSERT(ALIGNED64(size));
   2271      0     stevel 
   2272      0     stevel 	m = allocb(size, BPRI_HI);
   2273      0     stevel 	if (m == NULL) {
   2274   3448   dh155122 		mutex_exit(&ipss->ipsec_alg_lock);
   2275      0     stevel 		spdsock_error(q, mp, ENOMEM, 0);
   2276      0     stevel 		return;
   2277      0     stevel 	}
   2278      0     stevel 
   2279      0     stevel 	m->b_wptr = m->b_rptr + size;
   2280      0     stevel 	cur = m->b_rptr;
   2281      0     stevel 
   2282      0     stevel 	msg = (spd_msg_t *)cur;
   2283      0     stevel 	bcopy(mp->b_rptr, cur, sizeof (*msg));
   2284      0     stevel 
   2285      0     stevel 	msg->spd_msg_len = SPD_8TO64(size);
   2286      0     stevel 	msg->spd_msg_errno = 0;
   2287      0     stevel 	msg->spd_msg_diagnostic = 0;
   2288      0     stevel 
   2289      0     stevel 	cur += sizeof (*msg);
   2290      0     stevel 
   2291      0     stevel 	act = (struct spd_ext_actions *)cur;
   2292      0     stevel 	cur += sizeof (*act);
   2293      0     stevel 
   2294      0     stevel 	act->spd_actions_len = SPD_8TO64(size - sizeof (spd_msg_t));
   2295      0     stevel 	act->spd_actions_exttype = SPD_EXT_ACTION;
   2296      0     stevel 	act->spd_actions_count = algcount;
   2297      0     stevel 	act->spd_actions_reserved = 0;
   2298      0     stevel 
   2299      0     stevel 	attr = (struct spd_attribute *)cur;
   2300      0     stevel 
   2301      0     stevel #define	EMIT(tag, value) {					\
   2302      0     stevel 		attr->spd_attr_tag = (tag); 			\
   2303      0     stevel 		attr->spd_attr_value = (value); 		\
   2304      0     stevel 		attr++;			  			\
   2305      0     stevel 	}
   2306      0     stevel 
   2307      0     stevel 	/*
   2308      0     stevel 	 * If you change the number of EMIT's here, change
   2309      0     stevel 	 * ATTRPERALG above to match
   2310      0     stevel 	 */
   2311      0     stevel #define	EMITALGATTRS(_type) {					\
   2312      0     stevel 		EMIT(algattr[_type], algid); 		/* 1 */	\
   2313      0     stevel 		EMIT(minbitsattr[_type], minbits);	/* 2 */	\
   2314      0     stevel 		EMIT(maxbitsattr[_type], maxbits);	/* 3 */	\
   2315      0     stevel 		EMIT(defbitsattr[_type], defbits);	/* 4 */	\
   2316      0     stevel 		EMIT(incrbitsattr[_type], incr);	/* 5 */	\
   2317      0     stevel 		EMIT(SPD_ATTR_NEXT, 0);			/* 6 */	\
   2318      0     stevel 	}
   2319      0     stevel 
   2320      0     stevel 	for (algtype = 0; algtype < IPSEC_NALGTYPES; algtype++) {
   2321   3448   dh155122 		for (algidx = 0; algidx < ipss->ipsec_nalgs[algtype];
   2322   3448   dh155122 		    algidx++) {
   2323   3448   dh155122 			int algid = ipss->ipsec_sortlist[algtype][algidx];
   2324   3448   dh155122 			ipsec_alginfo_t *alg =
   2325   3448   dh155122 			    ipss->ipsec_alglists[algtype][algid];
   2326      0     stevel 			uint_t minbits = alg->alg_minbits;
   2327      0     stevel 			uint_t maxbits = alg->alg_maxbits;
   2328      0     stevel 			uint_t defbits = alg->alg_default_bits;
   2329      0     stevel 			uint_t incr = alg->alg_increment;
   2330      0     stevel 
   2331      0     stevel 			if (algtype == IPSEC_ALG_AUTH) {
   2332      0     stevel 				if (algid == SADB_AALG_NONE)
   2333      0     stevel 					continue;
   2334      0     stevel 				EMITALGATTRS(SPDSOCK_AH_AUTH);
   2335      0     stevel 				EMITALGATTRS(SPDSOCK_ESP_AUTH);
   2336      0     stevel 			} else {
   2337      0     stevel 				if (algid == SADB_EALG_NONE)
   2338      0     stevel 					continue;
   2339      0     stevel 				ASSERT(algtype == IPSEC_ALG_ENCR);
   2340      0     stevel 				EMITALGATTRS(SPDSOCK_ESP_ENCR);
   2341      0     stevel 			}
   2342      0     stevel 		}
   2343      0     stevel 	}
   2344      0     stevel 
   2345   3448   dh155122 	mutex_exit(&ipss->ipsec_alg_lock);
   2346      0     stevel 
   2347      0     stevel #undef EMITALGATTRS
   2348      0     stevel #undef EMIT
   2349      0     stevel #undef ATTRPERALG
   2350      0     stevel 
   2351      0     stevel 	attr--;
   2352      0     stevel 	attr->spd_attr_tag = SPD_ATTR_END;
   2353      0     stevel 
   2354      0     stevel 	freemsg(mp);
   2355      0     stevel 	qreply(q, m);
   2356      0     stevel }
   2357      0     stevel 
   2358      0     stevel /*
   2359      0     stevel  * Process a SPD_DUMPALGS request.
   2360      0     stevel  */
   2361      0     stevel 
   2362  10824       Mark #define	ATTRPERALG	9	/* fixed attributes per algs */
   2363      0     stevel 
   2364      0     stevel void
   2365      0     stevel spdsock_dumpalgs(queue_t *q, mblk_t *mp)
   2366      0     stevel {
   2367      0     stevel 	uint_t algtype;
   2368      0     stevel 	uint_t algidx;
   2369      0     stevel 	uint_t size;
   2370      0     stevel 	mblk_t *m;
   2371      0     stevel 	uint8_t *cur;
   2372      0     stevel 	spd_msg_t *msg;
   2373      0     stevel 	struct spd_ext_actions *act;
   2374      0     stevel 	struct spd_attribute *attr;
   2375      0     stevel 	ipsec_alginfo_t *alg;
   2376      0     stevel 	uint_t algid;
   2377      0     stevel 	uint_t i;
   2378      0     stevel 	uint_t alg_size;
   2379   3448   dh155122 	spdsock_t *ss = (spdsock_t *)q->q_ptr;
   2380   6430     danmcd 	ipsec_stack_t *ipss = ss->spdsock_spds->spds_netstack->netstack_ipsec;
   2381      0     stevel 
   2382   3448   dh155122 	mutex_enter(&ipss->ipsec_alg_lock);
   2383      0     stevel 
   2384      0     stevel 	/*
   2385      0     stevel 	 * For each algorithm, we encode:
   2386      0     stevel 	 * ALG / MINBITS / MAXBITS / DEFBITS / INCRBITS / {END, NEXT}
   2387      0     stevel 	 *
   2388      0     stevel 	 * ALG_ID / ALG_PROTO / ALG_INCRBITS / ALG_NKEYSIZES / ALG_KEYSIZE*
   2389  10824       Mark 	 * ALG_NBLOCKSIZES / ALG_BLOCKSIZE* / ALG_NPARAMS / ALG_PARAMS* /
   2390  10824       Mark 	 * ALG_MECHNAME / ALG_FLAGS / {END, NEXT}
   2391      0     stevel 	 */
   2392      0     stevel 
   2393      0     stevel 	/*
   2394      0     stevel 	 * Compute the size of the SPD message.
   2395      0     stevel 	 */
   2396      0     stevel 	size = sizeof (spd_msg_t) + sizeof (struct spd_ext_actions);
   2397      0     stevel 
   2398      0     stevel 	for (algtype = 0; algtype < IPSEC_NALGTYPES; algtype++) {
   2399   3448   dh155122 		for (algidx = 0; algidx < ipss->ipsec_nalgs[algtype];
   2400   3448   dh155122 		    algidx++) {
   2401   3448   dh155122 			algid = ipss->ipsec_sortlist[algtype][algidx];
   2402   3448   dh155122 			alg = ipss->ipsec_alglists[algtype][algid];
   2403      0     stevel 			alg_size = sizeof (struct spd_attribute) *
   2404      0     stevel 			    (ATTRPERALG + alg->alg_nkey_sizes +
   2405  10824       Mark 			    alg->alg_nblock_sizes + alg->alg_nparams) +
   2406  10824       Mark 			    CRYPTO_MAX_MECH_NAME;
   2407      0     stevel 			size += alg_size;
   2408      0     stevel 		}
   2409      0     stevel 	}
   2410      0     stevel 
   2411      0     stevel 	ASSERT(ALIGNED64(size));
   2412      0     stevel 
   2413      0     stevel 	m = allocb(size, BPRI_HI);
   2414      0     stevel 	if (m == NULL) {
   2415   3448   dh155122 		mutex_exit(&ipss->ipsec_alg_lock);
   2416      0     stevel 		spdsock_error(q, mp, ENOMEM, 0);
   2417      0     stevel 		return;
   2418      0     stevel 	}
   2419      0     stevel 
   2420      0     stevel 	m->b_wptr = m->b_rptr + size;
   2421      0     stevel 	cur = m->b_rptr;
   2422      0     stevel 
   2423      0     stevel 	msg = (spd_msg_t *)cur;
   2424      0     stevel 	bcopy(mp->b_rptr, cur, sizeof (*msg));
   2425      0     stevel 
   2426      0     stevel 	msg->spd_msg_len = SPD_8TO64(size);
   2427      0     stevel 	msg->spd_msg_errno = 0;
   2428  10019       Mark 	msg->spd_msg_type = SPD_ALGLIST;
   2429  10019       Mark 
   2430      0     stevel 	msg->spd_msg_diagnostic = 0;
   2431      0     stevel 
   2432      0     stevel 	cur += sizeof (*msg);
   2433      0     stevel 
   2434      0     stevel 	act = (struct spd_ext_actions *)cur;
   2435      0     stevel 	cur += sizeof (*act);
   2436      0     stevel 
   2437      0     stevel 	act->spd_actions_len = SPD_8TO64(size - sizeof (spd_msg_t));
   2438      0     stevel 	act->spd_actions_exttype = SPD_EXT_ACTION;
   2439   3448   dh155122 	act->spd_actions_count = ipss->ipsec_nalgs[IPSEC_ALG_AUTH] +
   2440   3448   dh155122 	    ipss->ipsec_nalgs[IPSEC_ALG_ENCR];
   2441      0     stevel 	act->spd_actions_reserved = 0;
   2442  10019       Mark 
   2443  10019       Mark 	/*
   2444  10019       Mark 	 * If there aren't any algorithms registered, return an empty message.
   2445  10019       Mark 	 * spdsock_get_ext() knows how to deal with this.
   2446  10019       Mark 	 */
   2447  10019       Mark 	if (act->spd_actions_count == 0) {
   2448  10019       Mark 		act->spd_actions_len = 0;
   2449  10019       Mark 		mutex_exit(&ipss->ipsec_alg_lock);
   2450  10019       Mark 		goto error;
   2451  10019       Mark 	}
   2452      0     stevel 
   2453      0     stevel 	attr = (struct spd_attribute *)cur;
   2454      0     stevel 
   2455      0     stevel #define	EMIT(tag, value) {					\
   2456      0     stevel 		attr->spd_attr_tag = (tag); 			\
   2457      0     stevel 		attr->spd_attr_value = (value); 		\
   2458      0     stevel 		attr++;			  			\
   2459      0     stevel 	}
   2460      0     stevel 
   2461      0     stevel 	for (algtype = 0; algtype < IPSEC_NALGTYPES; algtype++) {
   2462   3448   dh155122 		for (algidx = 0; algidx < ipss->ipsec_nalgs[algtype];
   2463   3448   dh155122 		    algidx++) {
   2464      0     stevel 
   2465   3448   dh155122 			algid = ipss->ipsec_sortlist[algtype][algidx];
   2466   3448   dh155122 			alg = ipss->ipsec_alglists[algtype][algid];
   2467      0     stevel 
   2468      0     stevel 			/*
   2469      0     stevel 			 * If you change the number of EMIT's here, change
   2470      0     stevel 			 * ATTRPERALG above to match
   2471      0     stevel 			 */
   2472      0     stevel 			EMIT(SPD_ATTR_ALG_ID, algid);
   2473      0     stevel 			EMIT(SPD_ATTR_ALG_PROTO, algproto[algtype]);
   2474      0     stevel 			EMIT(SPD_ATTR_ALG_INCRBITS, alg->alg_increment);
   2475      0     stevel 			EMIT(SPD_ATTR_ALG_NKEYSIZES, alg->alg_nkey_sizes);
   2476      0     stevel 			for (i = 0; i < alg->alg_nkey_sizes; i++)
   2477      0     stevel 				EMIT(SPD_ATTR_ALG_KEYSIZE,
   2478      0     stevel 				    alg->alg_key_sizes[i]);
   2479      0     stevel 
   2480      0     stevel 			EMIT(SPD_ATTR_ALG_NBLOCKSIZES, alg->alg_nblock_sizes);
   2481      0     stevel 			for (i = 0; i < alg->alg_nblock_sizes; i++)
   2482      0     stevel 				EMIT(SPD_ATTR_ALG_BLOCKSIZE,
   2483      0     stevel 				    alg->alg_block_sizes[i]);
   2484  10824       Mark 
   2485  10824       Mark 			EMIT(SPD_ATTR_ALG_NPARAMS, alg->alg_nparams);
   2486  10824       Mark 			for (i = 0; i < alg->alg_nparams; i++)
   2487  10824       Mark 				EMIT(SPD_ATTR_ALG_PARAMS,
   2488  10824       Mark 				    alg->alg_params[i]);
   2489  10824       Mark 
   2490  10824       Mark 			EMIT(SPD_ATTR_ALG_FLAGS, alg->alg_flags);
   2491      0     stevel 
   2492      0     stevel 			EMIT(SPD_ATTR_ALG_MECHNAME, CRYPTO_MAX_MECH_NAME);
   2493      0     stevel 			bcopy(alg->alg_mech_name, attr, CRYPTO_MAX_MECH_NAME);
   2494      0     stevel 			attr = (struct spd_attribute *)((char *)attr +
   2495      0     stevel 			    CRYPTO_MAX_MECH_NAME);
   2496      0     stevel 
   2497      0     stevel 			EMIT(SPD_ATTR_NEXT, 0);
   2498      0     stevel 		}
   2499      0     stevel 	}
   2500      0     stevel 
   2501   3448   dh155122 	mutex_exit(&ipss->ipsec_alg_lock);
   2502      0     stevel 
   2503      0     stevel #undef EMITALGATTRS
   2504      0     stevel #undef EMIT
   2505      0     stevel #undef ATTRPERALG
   2506      0     stevel 
   2507      0     stevel 	attr--;
   2508      0     stevel 	attr->spd_attr_tag = SPD_ATTR_END;
   2509      0     stevel 
   2510  10019       Mark error:
   2511      0     stevel 	freemsg(mp);
   2512      0     stevel 	qreply(q, m);
   2513      0     stevel }
   2514      0     stevel 
   2515      0     stevel /*
   2516      0     stevel  * Do the actual work of processing an SPD_UPDATEALGS request. Can
   2517      0     stevel  * be invoked either once IPsec is loaded on a cached request, or
   2518      0     stevel  * when a request is received while IPsec is loaded.
   2519      0     stevel  */
   2520  11042       Erik static int
   2521  11042       Erik spdsock_do_updatealg(spd_ext_t *extv[], spd_stack_t *spds)
   2522      0     stevel {
   2523      0     stevel 	struct spd_ext_actions *actp;
   2524      0     stevel 	struct spd_attribute *attr, *endattr;
   2525      0     stevel 	uint64_t *start, *end;
   2526      0     stevel 	ipsec_alginfo_t *alg = NULL;
   2527      0     stevel 	ipsec_algtype_t alg_type = 0;
   2528      0     stevel 	boolean_t skip_alg = B_TRUE, doing_proto = B_FALSE;
   2529      0     stevel 	uint_t i, cur_key, cur_block, algid;
   2530  11042       Erik 	int diag = -1;
   2531      0     stevel 
   2532   3448   dh155122 	ASSERT(MUTEX_HELD(&spds->spds_alg_lock));
   2533      0     stevel 
   2534      0     stevel 	/* parse the message, building the list of algorithms */
   2535      0     stevel 
   2536      0     stevel 	actp = (struct spd_ext_actions *)extv[SPD_EXT_ACTION];
   2537  11042       Erik 	if (actp == NULL)
   2538  11042       Erik 		return (SPD_DIAGNOSTIC_NO_ACTION_EXT);
   2539      0     stevel 
   2540      0     stevel 	start = (uint64_t *)actp;
   2541      0     stevel 	end = (start + actp->spd_actions_len);
   2542      0     stevel 	endattr = (struct spd_attribute *)end;
   2543      0     stevel 	attr = (struct spd_attribute *)&actp[1];
   2544      0     stevel 
   2545   3448   dh155122 	bzero(spds->spds_algs, IPSEC_NALGTYPES * IPSEC_MAX_ALGS *
   2546      0     stevel 	    sizeof (ipsec_alginfo_t *));
   2547      0     stevel 
   2548      0     stevel 	alg = kmem_zalloc(sizeof (*alg), KM_SLEEP);
   2549      0     stevel 
   2550      0     stevel #define	ALG_KEY_SIZES(a)   (((a)->alg_nkey_sizes + 1) * sizeof (uint16_t))
   2551      0     stevel #define	ALG_BLOCK_SIZES(a) (((a)->alg_nblock_sizes + 1) * sizeof (uint16_t))
   2552  11136       Mark #define	ALG_PARAM_SIZES(a) (((a)->alg_nparams + 1) * sizeof (uint16_t))
   2553      0     stevel 
   2554      0     stevel 	while (attr < endattr) {
   2555      0     stevel 		switch (attr->spd_attr_tag) {
   2556      0     stevel 		case SPD_ATTR_NOP:
   2557      0     stevel 		case SPD_ATTR_EMPTY:
   2558      0     stevel 			break;
   2559      0     stevel 		case SPD_ATTR_END:
   2560      0     stevel 			attr = endattr;
   2561      0     stevel 			/* FALLTHRU */
   2562      0     stevel 		case SPD_ATTR_NEXT:
   2563      0     stevel 			if (doing_proto) {
   2564      0     stevel 				doing_proto = B_FALSE;
   2565      0     stevel 				break;
   2566      0     stevel 			}
   2567      0     stevel 			if (skip_alg) {
   2568      0     stevel 				ipsec_alg_free(alg);
   2569      0     stevel 			} else {
   2570      0     stevel 				ipsec_alg_free(
   2571   3448   dh155122 				    spds->spds_algs[alg_type][alg->alg_id]);
   2572   3448   dh155122 				spds->spds_algs[alg_type][alg->alg_id] =
   2573   3448   dh155122 				    alg;
   2574      0     stevel 			}
   2575      0     stevel 			alg = kmem_zalloc(sizeof (*alg), KM_SLEEP);
   2576      0     stevel 			break;
   2577      0     stevel 
   2578      0     stevel 		case SPD_ATTR_ALG_ID:
   2579      0     stevel 			if (attr->spd_attr_value >= IPSEC_MAX_ALGS) {
   2580   3448   dh155122 				ss1dbg(spds, ("spdsock_do_updatealg: "
   2581      0     stevel 				    "invalid alg id %d\n",
   2582      0     stevel 				    attr->spd_attr_value));
   2583  11042       Erik 				diag = SPD_DIAGNOSTIC_ALG_ID_RANGE;
   2584      0     stevel 				goto bail;
   2585      0     stevel 			}
   2586      0     stevel 			alg->alg_id = attr->spd_attr_value;
   2587      0     stevel 			break;
   2588      0     stevel 
   2589      0     stevel 		case SPD_ATTR_ALG_PROTO:
   2590      0     stevel 			/* find the alg type */
   2591      0     stevel 			for (i = 0; i < NALGPROTOS; i++)
   2592      0     stevel 				if (algproto[i] == attr->spd_attr_value)
   2593      0     stevel 					break;
   2594      0     stevel 			skip_alg = (i == NALGPROTOS);
   2595      0     stevel 			if (!skip_alg)
   2596      0     stevel 				alg_type = i;
   2597      0     stevel 			break;
   2598      0     stevel 
   2599      0     stevel 		case SPD_ATTR_ALG_INCRBITS:
   2600      0     stevel 			alg->alg_increment = attr->spd_attr_value;
   2601      0     stevel 			break;
   2602      0     stevel 
   2603      0     stevel 		case SPD_ATTR_ALG_NKEYSIZES:
   2604      0     stevel 			if (alg->alg_key_sizes != NULL) {
   2605      0     stevel 				kmem_free(alg->alg_key_sizes,
   2606      0     stevel 				    ALG_KEY_SIZES(alg));
   2607      0     stevel 			}
   2608      0     stevel 			alg->alg_nkey_sizes = attr->spd_attr_value;
   2609      0     stevel 			/*
   2610      0     stevel 			 * Allocate room for the trailing zero key size
   2611      0     stevel 			 * value as well.
   2612      0     stevel 			 */
   2613      0     stevel 			alg->alg_key_sizes = kmem_zalloc(ALG_KEY_SIZES(alg),
   2614      0     stevel 			    KM_SLEEP);
   2615      0     stevel 			cur_key = 0;
   2616      0     stevel 			break;
   2617      0     stevel 
   2618      0     stevel 		case SPD_ATTR_ALG_KEYSIZE:
   2619      0     stevel 			if (alg->alg_key_sizes == NULL ||
   2620      0     stevel 			    cur_key >= alg->alg_nkey_sizes) {
   2621   3448   dh155122 				ss1dbg(spds, ("spdsock_do_updatealg: "
   2622   5240   nordmark 				    "too many key sizes\n"));
   2623  11042       Erik 				diag = SPD_DIAGNOSTIC_ALG_NUM_KEY_SIZES;
   2624      0     stevel 				goto bail;
   2625      0     stevel 			}
   2626      0     stevel 			alg->alg_key_sizes[cur_key++] = attr->spd_attr_value;
   2627      0     stevel 			break;
   2628      0     stevel 
   2629  10824       Mark 		case SPD_ATTR_ALG_FLAGS:
   2630  10824       Mark 			/*
   2631  10824       Mark 			 * Flags (bit mask). The alg_flags element of
   2632  10824       Mark 			 * ipsecalg_flags_t is only 8 bits wide. The
   2633  10824       Mark 			 * user can set the VALID bit, but we will ignore it
   2634  10824       Mark 			 * and make the decision is the algorithm is valid.
   2635  10824       Mark 			 */
   2636  10824       Mark 			alg->alg_flags |= (uint8_t)attr->spd_attr_value;
   2637  10824       Mark 			break;
   2638  10824       Mark 
   2639      0     stevel 		case SPD_ATTR_ALG_NBLOCKSIZES:
   2640      0     stevel 			if (alg->alg_block_sizes != NULL) {
   2641      0     stevel 				kmem_free(alg->alg_block_sizes,
   2642      0     stevel 				    ALG_BLOCK_SIZES(alg));
   2643      0     stevel 			}
   2644      0     stevel 			alg->alg_nblock_sizes = attr->spd_attr_value;
   2645      0     stevel 			/*
   2646      0     stevel 			 * Allocate room for the trailing zero block size
   2647      0     stevel 			 * value as well.
   2648      0     stevel 			 */
   2649      0     stevel 			alg->alg_block_sizes = kmem_zalloc(ALG_BLOCK_SIZES(alg),
   2650      0     stevel 			    KM_SLEEP);
   2651      0     stevel 			cur_block = 0;
   2652      0     stevel 			break;
   2653      0     stevel 
   2654      0     stevel 		case SPD_ATTR_ALG_BLOCKSIZE:
   2655      0     stevel 			if (alg->alg_block_sizes == NULL ||
   2656      0     stevel 			    cur_block >= alg->alg_nblock_sizes) {
   2657   3448   dh155122 				ss1dbg(spds, ("spdsock_do_updatealg: "
   2658   5240   nordmark 				    "too many block sizes\n"));
   2659  11042       Erik 				diag = SPD_DIAGNOSTIC_ALG_NUM_BLOCK_SIZES;
   2660      0     stevel 				goto bail;
   2661      0     stevel 			}
   2662      0     stevel 			alg->alg_block_sizes[cur_block++] =
   2663  10824       Mark 			    attr->spd_attr_value;
   2664  10824       Mark 			break;
   2665  10824       Mark 
   2666  10824       Mark 		case SPD_ATTR_ALG_NPARAMS:
   2667  10824       Mark 			if (alg->alg_params != NULL) {
   2668  10824       Mark 				kmem_free(alg->alg_params,
   2669  11136       Mark 				    ALG_PARAM_SIZES(alg));
   2670  10824       Mark 			}
   2671  10824       Mark 			alg->alg_nparams = attr->spd_attr_value;
   2672  10824       Mark 			/*
   2673  10824       Mark 			 * Allocate room for the trailing zero block size
   2674  10824       Mark 			 * value as well.
   2675  10824       Mark 			 */
   2676  11136       Mark 			alg->alg_params = kmem_zalloc(ALG_PARAM_SIZES(alg),
   2677  10824       Mark 			    KM_SLEEP);
   2678  10824       Mark 			cur_block = 0;
   2679  10824       Mark 			break;
   2680  10824       Mark 
   2681  10824       Mark 		case SPD_ATTR_ALG_PARAMS:
   2682  10824       Mark 			if (alg->alg_params == NULL ||
   2683  10824       Mark 			    cur_block >= alg->alg_nparams) {
   2684  10824       Mark 				ss1dbg(spds, ("spdsock_do_updatealg: "
   2685  10824       Mark 				    "too many params\n"));
   2686  11042       Erik 				diag = SPD_DIAGNOSTIC_ALG_NUM_BLOCK_SIZES;
   2687  10824       Mark 				goto bail;
   2688  10824       Mark 			}
   2689  10824       Mark 			/*
   2690  10824       Mark 			 * Array contains: iv_len, icv_len, salt_len
   2691  10824       Mark 			 * Any additional parameters are currently ignored.
   2692  10824       Mark 			 */
   2693  10824       Mark 			alg->alg_params[cur_block++] =
   2694      0     stevel 			    attr->spd_attr_value;
   2695      0     stevel 			break;
   2696      0     stevel 
   2697      0     stevel 		case SPD_ATTR_ALG_MECHNAME: {
   2698      0     stevel 			char *mech_name;
   2699      0     stevel 
   2700      0     stevel 			if (attr->spd_attr_value > CRYPTO_MAX_MECH_NAME) {
   2701   3448   dh155122 				ss1dbg(spds, ("spdsock_do_updatealg: "
   2702   5240   nordmark 				    "mech name too long\n"));
   2703  11042       Erik 				diag = SPD_DIAGNOSTIC_ALG_MECH_NAME_LEN;
   2704      0     stevel 				goto bail;
   2705      0     stevel 			}
   2706      0     stevel 			mech_name = (char *)(attr + 1);
   2707      0     stevel 			bcopy(mech_name, alg->alg_mech_name,
   2708      0     stevel 			    attr->spd_attr_value);
   2709      0     stevel 			alg->alg_mech_name[CRYPTO_MAX_MECH_NAME-1] = '\0';
   2710      0     stevel 			attr = (struct spd_attribute *)((char *)attr +
   2711      0     stevel 			    attr->spd_attr_value);
   2712      0     stevel 			break;
   2713      0     stevel 		}
   2714      0     stevel 
   2715      0     stevel 		case SPD_ATTR_PROTO_ID:
   2716      0     stevel 			doing_proto = B_TRUE;
   2717      0     stevel 			for (i = 0; i < NALGPROTOS; i++) {
   2718      0     stevel 				if (algproto[i] == attr->spd_attr_value) {
   2719      0     stevel 					alg_type = i;
   2720      0     stevel 					break;
   2721      0     stevel 				}
   2722      0     stevel 			}
   2723      0     stevel 			break;
   2724      0     stevel 
   2725      0     stevel 		case SPD_ATTR_PROTO_EXEC_MODE:
   2726      0     stevel 			if (!doing_proto)
   2727      0     stevel 				break;
   2728      0     stevel 			for (i = 0; i < NEXECMODES; i++) {
   2729      0     stevel 				if (execmodes[i] == attr->spd_attr_value) {
   2730   3448   dh155122 					spds->spds_algs_exec_mode[alg_type] = i;
   2731      0     stevel 					break;
   2732      0     stevel 				}
   2733      0     stevel 			}
   2734      0     stevel 			break;
   2735      0     stevel 		}
   2736      0     stevel 		attr++;
   2737      0     stevel 	}
   2738      0     stevel 
   2739      0     stevel #undef	ALG_KEY_SIZES
   2740      0     stevel #undef	ALG_BLOCK_SIZES
   2741  11136       Mark #undef	ALG_PARAM_SIZES
   2742      0     stevel 
   2743      0     stevel 	/* update the algorithm tables */
   2744   3448   dh155122 	spdsock_merge_algs(spds);
   2745      0     stevel bail:
   2746      0     stevel 	/* cleanup */
   2747      0     stevel 	ipsec_alg_free(alg);
   2748      0     stevel 	for (alg_type = 0; alg_type < IPSEC_NALGTYPES; alg_type++)
   2749   5240   nordmark 		for (algid = 0; algid < IPSEC_MAX_ALGS; algid++)
   2750   3448   dh155122 		if (spds->spds_algs[alg_type][algid] != NULL)
   2751   5240   nordmark 			ipsec_alg_free(spds->spds_algs[alg_type][algid]);
   2752  11042       Erik 	return (diag);
   2753      0     stevel }
   2754      0     stevel 
   2755      0     stevel /*
   2756      0     stevel  * Process an SPD_UPDATEALGS request. If IPsec is not loaded, queue
   2757      0     stevel  * the request until IPsec loads. If IPsec is loaded, act on it
   2758      0     stevel  * immediately.
   2759      0     stevel  */
   2760      0     stevel 
   2761      0     stevel static void
   2762      0     stevel spdsock_updatealg(queue_t *q, mblk_t *mp, spd_ext_t *extv[])
   2763      0     stevel {
   2764   3448   dh155122 	spdsock_t *ss = (spdsock_t *)q->q_ptr;
   2765   3448   dh155122 	spd_stack_t	*spds = ss->spdsock_spds;
   2766   3448   dh155122 	ipsec_stack_t	*ipss = spds->spds_netstack->netstack_ipsec;
   2767   3448   dh155122 
   2768   3448   dh155122 	if (!ipsec_loaded(ipss)) {
   2769      0     stevel 		/*
   2770      0     stevel 		 * IPsec is not loaded, save request and return nicely,
   2771      0     stevel 		 * the message will be processed once IPsec loads.
   2772      0     stevel 		 */
   2773      0     stevel 		mblk_t *new_mp;
   2774      0     stevel 
   2775      0     stevel 		/* last update message wins */
   2776      0     stevel 		if ((new_mp = copymsg(mp)) == NULL) {
   2777      0     stevel 			spdsock_error(q, mp, ENOMEM, 0);
   2778      0     stevel 			return;
   2779      0     stevel 		}
   2780   3448   dh155122 		mutex_enter(&spds->spds_alg_lock);
   2781   3448   dh155122 		bcopy(extv, spds->spds_extv_algs,
   2782      0     stevel 		    sizeof (spd_ext_t *) * (SPD_EXT_MAX + 1));
   2783   3448   dh155122 		if (spds->spds_mp_algs != NULL)
   2784   3448   dh155122 			freemsg(spds->spds_mp_algs);
   2785   3448   dh155122 		spds->spds_mp_algs = mp;
   2786   3448   dh155122 		spds->spds_algs_pending = B_TRUE;
   2787   3448   dh155122 		mutex_exit(&spds->spds_alg_lock);
   2788   8778       Erik 		if (audit_active) {
   2789   8778       Erik 			cred_t *cr;
   2790   8778       Erik 			pid_t cpid;
   2791   8778       Erik 
   2792   8778       Erik 			cr = msg_getcred(mp, &cpid);
   2793   8778       Erik 			audit_pf_policy(SPD_UPDATEALGS, cr,
   2794   4307    pwernau 			    spds->spds_netstack, NULL, B_TRUE, EAGAIN,
   2795   8778       Erik 			    cpid);
   2796   8778       Erik 		}
   2797      0     stevel 		spd_echo(q, new_mp);
   2798      0     stevel 	} else {
   2799      0     stevel 		/*
   2800      0     stevel 		 * IPsec is loaded, act on the message immediately.
   2801      0     stevel 		 */
   2802      0     stevel 		int diag;
   2803      0     stevel 
   2804   3448   dh155122 		mutex_enter(&spds->spds_alg_lock);
   2805  11042       Erik 		diag = spdsock_do_updatealg(extv, spds);
   2806   4307    pwernau 		if (diag == -1) {
   2807  11042       Erik 			/* Keep the lock held while we walk the SA tables. */
   2808  11042       Erik 			sadb_alg_update(IPSEC_ALG_ALL, 0, 0,
   2809  11042       Erik 			    spds->spds_netstack);
   2810  11042       Erik 			mutex_exit(&spds->spds_alg_lock);
   2811      0     stevel 			spd_echo(q, mp);
   2812   8778       Erik 			if (audit_active) {
   2813   8778       Erik 				cred_t *cr;
   2814   8778       Erik 				pid_t cpid;
   2815   8778       Erik 
   2816   8778       Erik 				cr = msg_getcred(mp, &cpid);
   2817   8778       Erik 				audit_pf_policy(SPD_UPDATEALGS, cr,
   2818   8778       Erik 				    spds->spds_netstack, NULL, B_TRUE, 0,
   2819   8778       Erik 				    cpid);
   2820   8778       Erik 			}
   2821   4307    pwernau 		} else {
   2822  11042       Erik 			mutex_exit(&spds->spds_alg_lock);
   2823      0     stevel 			spdsock_diag(q, mp, diag);
   2824   8778       Erik 			if (audit_active) {
   2825   8778       Erik 				cred_t *cr;
   2826   8778       Erik 				pid_t cpid;
   2827   8778       Erik 
   2828   8778       Erik 				cr = msg_getcred(mp, &cpid);
   2829   8778       Erik 				audit_pf_policy(SPD_UPDATEALGS, cr,
   2830   8778       Erik 				    spds->spds_netstack, NULL, B_TRUE, diag,
   2831   8778       Erik 				    cpid);
   2832   8778       Erik 			}
   2833   4307    pwernau 		}
   2834      0     stevel 	}
   2835      0     stevel }
   2836      0     stevel 
   2837   3055     danmcd /*
   2838   3055     danmcd  * Sort through the mess of polhead options to retrieve an appropriate one.
   2839   3055     danmcd  * Returns NULL if we send an spdsock error.  Returns a valid pointer if we
   2840   3055     danmcd  * found a valid polhead.  Returns ALL_ACTIVE_POLHEADS (aka. -1) or
   2841   3055     danmcd  * ALL_INACTIVE_POLHEADS (aka. -2) if the operation calls for the operation to
   2842   3055     danmcd  * act on ALL policy heads.
   2843   3055     danmcd  */
   2844   3055     danmcd static ipsec_policy_head_t *
   2845   3055     danmcd get_appropriate_polhead(queue_t *q, mblk_t *mp, spd_if_t *tunname, int spdid,
   2846   3055     danmcd     int msgtype, ipsec_tun_pol_t **itpp)
   2847   3055     danmcd {
   2848   3055     danmcd 	ipsec_tun_pol_t *itp;
   2849   3055     danmcd 	ipsec_policy_head_t *iph;
   2850   3055     danmcd 	int errno;
   2851   3055     danmcd 	char *tname;
   2852   3055     danmcd 	boolean_t active;
   2853   3055     danmcd 	spdsock_t *ss = (spdsock_t *)q->q_ptr;
   2854   6430     danmcd 	netstack_t *ns = ss->spdsock_spds->spds_netstack;
   2855   3055     danmcd 	uint64_t gen;	/* Placeholder */
   2856  10616  Sebastien 	datalink_id_t linkid;
   2857   3055     danmcd 
   2858   3055     danmcd 	active = (spdid == SPD_ACTIVE);
   2859   3055     danmcd 	*itpp = NULL;
   2860   3055     danmcd 	if (!active && spdid != SPD_STANDBY) {
   2861   3055     danmcd 		spdsock_diag(q, mp, SPD_DIAGNOSTIC_BAD_SPDID);
   2862   3055     danmcd 		return (NULL);
   2863   3055     danmcd 	}
   2864   3055     danmcd 
   2865   3055     danmcd 	if (tunname != NULL) {
   2866   3055     danmcd 		/* Acting on a tunnel's SPD. */
   2867   3055     danmcd 		tname = (char *)tunname->spd_if_name;
   2868   3055     danmcd 		if (*tname == '\0') {
   2869   3055     danmcd 			/* Handle all-polhead cases here. */
   2870   3055     danmcd 			if (msgtype != SPD_FLUSH && msgtype != SPD_DUMP) {
   2871   3055     danmcd 				spdsock_diag(q, mp,
   2872   3055     danmcd 				    SPD_DIAGNOSTIC_NOT_GLOBAL_OP);
   2873   3055     danmcd 				return (NULL);
   2874   3055     danmcd 			}
   2875   3055     danmcd 			return (active ? ALL_ACTIVE_POLHEADS :
   2876   3055     danmcd 			    ALL_INACTIVE_POLHEADS);
   2877   3055     danmcd 		}
   2878   3055     danmcd 
   2879   6430     danmcd 		itp = get_tunnel_policy(tname, ns);
   2880   3055     danmcd 		if (itp == NULL) {
   2881   3055     danmcd 			if (msgtype != SPD_ADDRULE) {
   2882   3055     danmcd 				/* "Tunnel not found" */
   2883   3055     danmcd 				spdsock_error(q, mp, ENOENT, 0);
   2884   3055     danmcd 				return (NULL);
   2885   3055     danmcd 			}
   2886   3055     danmcd 
   2887   3055     danmcd 			errno = 0;
   2888   6430     danmcd 			itp = create_tunnel_policy(tname, &errno, &gen, ns);
   2889   3055     danmcd 			if (itp == NULL) {
   2890   3055     danmcd 				/*
   2891   3055     danmcd 				 * Something very bad happened, most likely
   2892   3055     danmcd 				 * ENOMEM.  Return an indicator.
   2893   3055     danmcd 				 */
   2894   3055     danmcd 				spdsock_error(q, mp, errno, 0);
   2895   3055     danmcd 				return (NULL);
   2896   3055     danmcd 			}
   2897   3055     danmcd 		}
   2898   3055     danmcd 		/*
   2899  10616  Sebastien 		 * Troll the plumbed tunnels and see if we have a match.  We
   2900  10616  Sebastien 		 * need to do this always in case we add policy AFTER plumbing
   2901  10616  Sebastien 		 * a tunnel.
   2902   3055     danmcd 		 */
   2903  10616  Sebastien 		if (dls_mgmt_get_linkid(tname, &linkid) == 0)
   2904  10616  Sebastien 			iptun_set_policy(linkid, itp);
   2905  10616  Sebastien 
   2906   3055     danmcd 		*itpp = itp;
   2907   3055     danmcd 		/* For spdsock dump state, set the polhead's name. */
   2908   3055     danmcd 		if (msgtype == SPD_DUMP) {
   2909   6430     danmcd 			ITP_REFHOLD(itp);
   2910   6430     danmcd 			ss->spdsock_itp = itp;
   2911   3055     danmcd 			ss->spdsock_dump_tunnel = itp->itp_flags &
   2912   3055     danmcd 			    (active ? ITPF_P_TUNNEL : ITPF_I_TUNNEL);
   2913   3055     danmcd 		}
   2914   3055     danmcd 	} else {
   2915   3055     danmcd 		itp = NULL;
   2916   3055     danmcd 		/* For spdsock dump state, indicate it's global policy. */
   2917   3055     danmcd 		if (msgtype == SPD_DUMP)
   2918   6430     danmcd 			ss->spdsock_itp = NULL;
   2919   3055     danmcd 	}
   2920   3055     danmcd 
   2921   3055     danmcd 	if (active)
   2922   3448   dh155122 		iph = (itp == NULL) ? ipsec_system_policy(ns) : itp->itp_policy;
   2923   3055     danmcd 	else
   2924   3448   dh155122 		iph = (itp == NULL) ? ipsec_inactive_policy(ns) :
   2925   3055     danmcd 		    itp->itp_inactive;
   2926   3055     danmcd 
   2927   3055     danmcd 	ASSERT(iph != NULL);
   2928   3055     danmcd 	if (itp != NULL) {
   2929   3055     danmcd 		IPPH_REFHOLD(iph);
   2930   3055     danmcd 	}
   2931   3055     danmcd 
   2932   3055     danmcd 	return (iph);
   2933   3055     danmcd }
   2934   3055     danmcd 
   2935      0     stevel static void
   2936      0     stevel spdsock_parse(queue_t *q, mblk_t *mp)
   2937      0     stevel {
   2938      0     stevel 	spd_msg_t *spmsg;
   2939      0     stevel 	spd_ext_t *extv[SPD_EXT_MAX + 1];
   2940      0     stevel 	uint_t msgsize;
   2941      0     stevel 	ipsec_policy_head_t *iph;
   2942   3055     danmcd 	ipsec_tun_pol_t *itp;
   2943   3055     danmcd 	spd_if_t *tunname;
   2944   3448   dh155122 	spdsock_t *ss = (spdsock_t *)q->q_ptr;
   2945   3448   dh155122 	spd_stack_t *spds = ss->spdsock_spds;
   2946   3448