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   2465      danmcd  * Common Development and Distribution License (the "License").
      6   2465      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   8730      danmcd  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23      0      stevel  * Use is subject to license terms.
     24      0      stevel  */
     25      0      stevel 
     26      0      stevel #include <sys/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      0      stevel #include <sys/vnode.h>
     33   3448    dh155122 #include <sys/zone.h>
     34      0      stevel #include <sys/strlog.h>
     35      0      stevel #include <sys/sysmacros.h>
     36      0      stevel #define	_SUN_TPI_VERSION 2
     37      0      stevel #include <sys/tihdr.h>
     38      0      stevel #include <sys/timod.h>
     39      0      stevel #include <sys/tiuser.h>
     40      0      stevel #include <sys/ddi.h>
     41      0      stevel #include <sys/sunddi.h>
     42      0      stevel #include <sys/sunldi.h>
     43      0      stevel #include <sys/file.h>
     44      0      stevel #include <sys/modctl.h>
     45      0      stevel #include <sys/debug.h>
     46      0      stevel #include <sys/kmem.h>
     47      0      stevel #include <sys/cmn_err.h>
     48      0      stevel #include <sys/proc.h>
     49      0      stevel #include <sys/suntpi.h>
     50      0      stevel #include <sys/atomic.h>
     51      0      stevel #include <sys/mkdev.h>
     52      0      stevel #include <sys/policy.h>
     53   3448    dh155122 #include <sys/disp.h>
     54      0      stevel 
     55      0      stevel #include <sys/socket.h>
     56      0      stevel #include <netinet/in.h>
     57      0      stevel #include <net/pfkeyv2.h>
     58      0      stevel 
     59      0      stevel #include <inet/common.h>
     60      0      stevel #include <netinet/ip6.h>
     61      0      stevel #include <inet/ip.h>
     62   8348        Eric #include <inet/proto_set.h>
     63      0      stevel #include <inet/nd.h>
     64      0      stevel #include <inet/optcom.h>
     65      0      stevel #include <inet/ipsec_info.h>
     66      0      stevel #include <inet/ipsec_impl.h>
     67      0      stevel #include <inet/keysock.h>
     68      0      stevel 
     69      0      stevel #include <sys/isa_defs.h>
     70      0      stevel 
     71      0      stevel /*
     72      0      stevel  * This is a transport provider for the PF_KEY key mangement socket.
     73      0      stevel  * (See RFC 2367 for details.)
     74      0      stevel  * Downstream messages are wrapped in a keysock consumer interface KEYSOCK_IN
     75      0      stevel  * messages (see ipsec_info.h), and passed to the appropriate consumer.
     76      0      stevel  * Upstream messages are generated for all open PF_KEY sockets, when
     77      0      stevel  * appropriate, as well as the sender (as long as SO_USELOOPBACK is enabled)
     78      0      stevel  * in reply to downstream messages.
     79      0      stevel  *
     80      0      stevel  * Upstream messages must be created asynchronously for the following
     81      0      stevel  * situations:
     82      0      stevel  *
     83      0      stevel  *	1.) A keysock consumer requires an SA, and there is currently none.
     84      0      stevel  *	2.) An SA expires, either hard or soft lifetime.
     85      0      stevel  *	3.) Other events a consumer deems fit.
     86      0      stevel  *
     87      0      stevel  * The MT model of this is PERMOD, with shared put procedures.  Two types of
     88      0      stevel  * messages, SADB_FLUSH and SADB_DUMP, need to lock down the perimeter to send
     89      0      stevel  * down the *multiple* messages they create.
     90      0      stevel  */
     91      0      stevel 
     92      0      stevel static vmem_t *keysock_vmem;		/* for minor numbers. */
     93      0      stevel 
     94      0      stevel #define	KEYSOCK_MAX_CONSUMERS 256
     95      0      stevel 
     96      0      stevel /* Default structure copied into T_INFO_ACK messages (from rts.c...) */
     97      0      stevel static struct T_info_ack keysock_g_t_info_ack = {
     98      0      stevel 	T_INFO_ACK,
     99      0      stevel 	T_INFINITE,	/* TSDU_size. Maximum size messages. */
    100      0      stevel 	T_INVALID,	/* ETSDU_size. No expedited data. */
    101      0      stevel 	T_INVALID,	/* CDATA_size. No connect data. */
    102      0      stevel 	T_INVALID,	/* DDATA_size. No disconnect data. */
    103      0      stevel 	0,		/* ADDR_size. */
    104      0      stevel 	0,		/* OPT_size. No user-settable options */
    105      0      stevel 	64 * 1024,	/* TIDU_size. keysock allows maximum size messages. */
    106      0      stevel 	T_COTS,		/* SERV_type. keysock supports connection oriented. */
    107      0      stevel 	TS_UNBND,	/* CURRENT_state. This is set from keysock_state. */
    108      0      stevel 	(XPG4_1)	/* Provider flags */
    109      0      stevel };
    110      0      stevel 
    111      0      stevel /* Named Dispatch Parameter Management Structure */
    112   3448    dh155122 typedef struct keysockparam_s {
    113      0      stevel 	uint_t	keysock_param_min;
    114      0      stevel 	uint_t	keysock_param_max;
    115      0      stevel 	uint_t	keysock_param_value;
    116      0      stevel 	char	*keysock_param_name;
    117      0      stevel } keysockparam_t;
    118      0      stevel 
    119      0      stevel /*
    120      0      stevel  * Table of NDD variables supported by keysock. These are loaded into
    121      0      stevel  * keysock_g_nd in keysock_init_nd.
    122      0      stevel  * All of these are alterable, within the min/max values given, at run time.
    123      0      stevel  */
    124   3448    dh155122 static	keysockparam_t	lcl_param_arr[] = {
    125      0      stevel 	/* min	max	value	name */
    126      0      stevel 	{ 4096, 65536,	8192,	"keysock_xmit_hiwat"},
    127      0      stevel 	{ 0,	65536,	1024,	"keysock_xmit_lowat"},
    128      0      stevel 	{ 4096, 65536,	8192,	"keysock_recv_hiwat"},
    129      0      stevel 	{ 65536, 1024*1024*1024, 256*1024,	"keysock_max_buf"},
    130      0      stevel 	{ 0,	3,	0,	"keysock_debug"},
    131      0      stevel };
    132   3448    dh155122 #define	keystack_xmit_hiwat	keystack_params[0].keysock_param_value
    133   3448    dh155122 #define	keystack_xmit_lowat	keystack_params[1].keysock_param_value
    134   3448    dh155122 #define	keystack_recv_hiwat	keystack_params[2].keysock_param_value
    135   3448    dh155122 #define	keystack_max_buf	keystack_params[3].keysock_param_value
    136   3448    dh155122 #define	keystack_debug	keystack_params[4].keysock_param_value
    137      0      stevel 
    138      0      stevel #define	ks0dbg(a)	printf a
    139      0      stevel /* NOTE:  != 0 instead of > 0 so lint doesn't complain. */
    140   3448    dh155122 #define	ks1dbg(keystack, a)	if (keystack->keystack_debug != 0) printf a
    141   3448    dh155122 #define	ks2dbg(keystack, a)	if (keystack->keystack_debug > 1) printf a
    142   3448    dh155122 #define	ks3dbg(keystack, a)	if (keystack->keystack_debug > 2) printf a
    143      0      stevel 
    144      0      stevel static int keysock_close(queue_t *);
    145      0      stevel static int keysock_open(queue_t *, dev_t *, int, int, cred_t *);
    146      0      stevel static void keysock_wput(queue_t *, mblk_t *);
    147      0      stevel static void keysock_rput(queue_t *, mblk_t *);
    148      0      stevel static void keysock_rsrv(queue_t *);
    149      0      stevel static void keysock_passup(mblk_t *, sadb_msg_t *, minor_t,
    150   3448    dh155122     keysock_consumer_t *, boolean_t, keysock_stack_t *);
    151   3448    dh155122 static void *keysock_stack_init(netstackid_t stackid, netstack_t *ns);
    152   3448    dh155122 static void keysock_stack_fini(netstackid_t stackid, void *arg);
    153      0      stevel 
    154      0      stevel static struct module_info info = {
    155      0      stevel 	5138, "keysock", 1, INFPSZ, 512, 128
    156      0      stevel };
    157      0      stevel 
    158      0      stevel static struct qinit rinit = {
    159      0      stevel 	(pfi_t)keysock_rput, (pfi_t)keysock_rsrv, keysock_open, keysock_close,
    160      0      stevel 	NULL, &info
    161      0      stevel };
    162      0      stevel 
    163      0      stevel static struct qinit winit = {
    164      0      stevel 	(pfi_t)keysock_wput, NULL, NULL, NULL, NULL, &info
    165      0      stevel };
    166      0      stevel 
    167      0      stevel struct streamtab keysockinfo = {
    168      0      stevel 	&rinit, &winit
    169      0      stevel };
    170      0      stevel 
    171      0      stevel extern struct modlinkage *keysock_modlp;
    172      0      stevel 
    173      0      stevel /*
    174      0      stevel  * Plumb IPsec.
    175      0      stevel  *
    176      0      stevel  * NOTE:  New "default" modules will need to be loaded here if needed before
    177      0      stevel  *	  boot time.
    178      0      stevel  */
    179      0      stevel 
    180      0      stevel /* Keep these in global space to keep the lint from complaining. */
    181      0      stevel static char *IPSECESP = "ipsecesp";
    182      0      stevel static char *IPSECESPDEV = "/devices/pseudo/ipsecesp@0:ipsecesp";
    183      0      stevel static char *IPSECAH = "ipsecah";
    184      0      stevel static char *IPSECAHDEV = "/devices/pseudo/ipsecah@0:ipsecah";
    185      0      stevel static char *IP6DEV = "/devices/pseudo/ip6@0:ip6";
    186      0      stevel static char *KEYSOCK = "keysock";
    187      0      stevel static char *STRMOD = "strmod";
    188      0      stevel 
    189      0      stevel /*
    190      0      stevel  * Load the other ipsec modules and plumb them together.
    191      0      stevel  */
    192      0      stevel int
    193   3448    dh155122 keysock_plumb_ipsec(netstack_t *ns)
    194      0      stevel {
    195      0      stevel 	ldi_handle_t	lh, ip6_lh = NULL;
    196      0      stevel 	ldi_ident_t	li = NULL;
    197      0      stevel 	int		err = 0;
    198      0      stevel 	int		muxid, rval;
    199      0      stevel 	boolean_t	esp_present = B_TRUE;
    200   3448    dh155122 	cred_t		*cr;
    201   3448    dh155122 	keysock_stack_t *keystack = ns->netstack_keysock;
    202      0      stevel 
    203   3448    dh155122 #ifdef NS_DEBUG
    204   3448    dh155122 	(void) printf("keysock_plumb_ipsec(%d)\n",
    205   3448    dh155122 	    ns->netstack_stackid);
    206   3448    dh155122 #endif
    207      0      stevel 
    208   3448    dh155122 	keystack->keystack_plumbed = 0;	/* we're trying again.. */
    209      0      stevel 
    210   3448    dh155122 	cr = zone_get_kcred(netstackid_to_zoneid(
    211   5240    nordmark 	    keystack->keystack_netstack->netstack_stackid));
    212   3448    dh155122 	ASSERT(cr != NULL);
    213      0      stevel 	/*
    214      0      stevel 	 * Load up the drivers (AH/ESP).
    215      0      stevel 	 *
    216      0      stevel 	 * I do this separately from the actual plumbing in case this function
    217      0      stevel 	 * ever gets called from a diskless boot before the root filesystem is
    218      0      stevel 	 * up.  I don't have to worry about "keysock" because, well, if I'm
    219      0      stevel 	 * here, keysock must've loaded successfully.
    220      0      stevel 	 */
    221      0      stevel 	if (i_ddi_attach_pseudo_node(IPSECAH) == NULL) {
    222      0      stevel 		ks0dbg(("IPsec:  AH failed to attach.\n"));
    223      0      stevel 		goto bail;
    224      0      stevel 	}
    225      0      stevel 	if (i_ddi_attach_pseudo_node(IPSECESP) == NULL) {
    226      0      stevel 		ks0dbg(("IPsec:  ESP failed to attach.\n"));
    227      0      stevel 		esp_present = B_FALSE;
    228      0      stevel 	}
    229      0      stevel 
    230      0      stevel 	/*
    231      0      stevel 	 * Set up the IP streams for AH and ESP, as well as tacking keysock
    232      0      stevel 	 * on top of them.  Assume keysock has set the autopushes up already.
    233      0      stevel 	 */
    234      0      stevel 
    235      0      stevel 	/* Open IP. */
    236      0      stevel 	err = ldi_ident_from_mod(keysock_modlp, &li);
    237      0      stevel 	if (err) {
    238      0      stevel 		ks0dbg(("IPsec:  lid_ident_from_mod failed (err %d).\n",
    239      0      stevel 		    err));
    240      0      stevel 		goto bail;
    241      0      stevel 	}
    242      0      stevel 
    243   3448    dh155122 	err = ldi_open_by_name(IP6DEV, FREAD|FWRITE, cr, &ip6_lh, li);
    244      0      stevel 	if (err) {
    245      0      stevel 		ks0dbg(("IPsec:  Open of IP6 failed (err %d).\n", err));
    246      0      stevel 		goto bail;
    247      0      stevel 	}
    248      0      stevel 
    249      0      stevel 	/* PLINK KEYSOCK/AH */
    250   3448    dh155122 	err = ldi_open_by_name(IPSECAHDEV, FREAD|FWRITE, cr, &lh, li);
    251      0      stevel 	if (err) {
    252      0      stevel 		ks0dbg(("IPsec:  Open of AH failed (err %d).\n", err));
    253      0      stevel 		goto bail;
    254      0      stevel 	}
    255      0      stevel 	err = ldi_ioctl(lh,
    256   3448    dh155122 	    I_PUSH, (intptr_t)KEYSOCK, FKIOCTL, cr, &rval);
    257      0      stevel 	if (err) {
    258      0      stevel 		ks0dbg(("IPsec:  Push of KEYSOCK onto AH failed (err %d).\n",
    259      0      stevel 		    err));
    260   3448    dh155122 		(void) ldi_close(lh, FREAD|FWRITE, cr);
    261      0      stevel 		goto bail;
    262      0      stevel 	}
    263      0      stevel 	err = ldi_ioctl(ip6_lh, I_PLINK, (intptr_t)lh,
    264   5240    nordmark 	    FREAD+FWRITE+FNOCTTY+FKIOCTL, cr, &muxid);
    265      0      stevel 	if (err) {
    266      0      stevel 		ks0dbg(("IPsec:  PLINK of KEYSOCK/AH failed (err %d).\n", err));
    267   3448    dh155122 		(void) ldi_close(lh, FREAD|FWRITE, cr);
    268      0      stevel 		goto bail;
    269      0      stevel 	}
    270   3448    dh155122 	(void) ldi_close(lh, FREAD|FWRITE, cr);
    271      0      stevel 
    272      0      stevel 	/* PLINK KEYSOCK/ESP */
    273      0      stevel 	if (esp_present) {
    274      0      stevel 		err = ldi_open_by_name(IPSECESPDEV,
    275   3448    dh155122 		    FREAD|FWRITE, cr, &lh, li);
    276      0      stevel 		if (err) {
    277      0      stevel 			ks0dbg(("IPsec:  Open of ESP failed (err %d).\n", err));
    278      0      stevel 			goto bail;
    279      0      stevel 		}
    280      0      stevel 		err = ldi_ioctl(lh,
    281   3448    dh155122 		    I_PUSH, (intptr_t)KEYSOCK, FKIOCTL, cr, &rval);
    282      0      stevel 		if (err) {
    283      0      stevel 			ks0dbg(("IPsec:  "
    284      0      stevel 			    "Push of KEYSOCK onto ESP failed (err %d).\n",
    285      0      stevel 			    err));
    286   3448    dh155122 			(void) ldi_close(lh, FREAD|FWRITE, cr);
    287      0      stevel 			goto bail;
    288      0      stevel 		}
    289      0      stevel 		err = ldi_ioctl(ip6_lh, I_PLINK, (intptr_t)lh,
    290   5240    nordmark 		    FREAD+FWRITE+FNOCTTY+FKIOCTL, cr, &muxid);
    291      0      stevel 		if (err) {
    292      0      stevel 			ks0dbg(("IPsec:  "
    293      0      stevel 			    "PLINK of KEYSOCK/ESP failed (err %d).\n", err));
    294   3448    dh155122 			(void) ldi_close(lh, FREAD|FWRITE, cr);
    295      0      stevel 			goto bail;
    296      0      stevel 		}
    297   3448    dh155122 		(void) ldi_close(lh, FREAD|FWRITE, cr);
    298      0      stevel 	}
    299      0      stevel 
    300      0      stevel bail:
    301   3448    dh155122 	keystack->keystack_plumbed = (err == 0) ? 1 : -1;
    302      0      stevel 	if (ip6_lh != NULL) {
    303   3448    dh155122 		(void) ldi_close(ip6_lh, FREAD|FWRITE, cr);
    304      0      stevel 	}
    305      0      stevel 	if (li != NULL)
    306      0      stevel 		ldi_ident_release(li);
    307   3448    dh155122 #ifdef NS_DEBUG
    308   3448    dh155122 	(void) printf("keysock_plumb_ipsec -> %d\n",
    309   3448    dh155122 	    keystack->keystack_plumbed);
    310   3448    dh155122 #endif
    311   3448    dh155122 	crfree(cr);
    312      0      stevel 	return (err);
    313      0      stevel }
    314      0      stevel 
    315      0      stevel /* ARGSUSED */
    316      0      stevel static int
    317      0      stevel keysock_param_get(q, mp, cp, cr)
    318      0      stevel 	queue_t	*q;
    319      0      stevel 	mblk_t	*mp;
    320      0      stevel 	caddr_t	cp;
    321      0      stevel 	cred_t *cr;
    322      0      stevel {
    323      0      stevel 	keysockparam_t	*keysockpa = (keysockparam_t *)cp;
    324      0      stevel 	uint_t value;
    325   3448    dh155122 	keysock_t *ks = (keysock_t *)q->q_ptr;
    326   3448    dh155122 	keysock_stack_t	*keystack = ks->keysock_keystack;
    327      0      stevel 
    328   3448    dh155122 	mutex_enter(&keystack->keystack_param_lock);
    329      0      stevel 	value = keysockpa->keysock_param_value;
    330   3448    dh155122 	mutex_exit(&keystack->keystack_param_lock);
    331      0      stevel 
    332      0      stevel 	(void) mi_mpprintf(mp, "%u", value);
    333      0      stevel 	return (0);
    334      0      stevel }
    335      0      stevel 
    336      0      stevel /* This routine sets an NDD variable in a keysockparam_t structure. */
    337      0      stevel /* ARGSUSED */
    338      0      stevel static int
    339      0      stevel keysock_param_set(q, mp, value, cp, cr)
    340      0      stevel 	queue_t	*q;
    341      0      stevel 	mblk_t	*mp;
    342      0      stevel 	char	*value;
    343      0      stevel 	caddr_t	cp;
    344      0      stevel 	cred_t *cr;
    345      0      stevel {
    346      0      stevel 	ulong_t	new_value;
    347      0      stevel 	keysockparam_t	*keysockpa = (keysockparam_t *)cp;
    348   3448    dh155122 	keysock_t *ks = (keysock_t *)q->q_ptr;
    349   3448    dh155122 	keysock_stack_t	*keystack = ks->keysock_keystack;
    350      0      stevel 
    351      0      stevel 	/* Convert the value from a string into a long integer. */
    352      0      stevel 	if (ddi_strtoul(value, NULL, 10, &new_value) != 0)
    353      0      stevel 		return (EINVAL);
    354      0      stevel 
    355   3448    dh155122 	mutex_enter(&keystack->keystack_param_lock);
    356      0      stevel 	/*
    357      0      stevel 	 * Fail the request if the new value does not lie within the
    358      0      stevel 	 * required bounds.
    359      0      stevel 	 */
    360      0      stevel 	if (new_value < keysockpa->keysock_param_min ||
    361      0      stevel 	    new_value > keysockpa->keysock_param_max) {
    362   3448    dh155122 		mutex_exit(&keystack->keystack_param_lock);
    363      0      stevel 		return (EINVAL);
    364      0      stevel 	}
    365      0      stevel 
    366      0      stevel 	/* Set the new value */
    367      0      stevel 	keysockpa->keysock_param_value = new_value;
    368   3448    dh155122 	mutex_exit(&keystack->keystack_param_lock);
    369      0      stevel 
    370      0      stevel 	return (0);
    371      0      stevel }
    372      0      stevel 
    373      0      stevel /*
    374   3448    dh155122  * Initialize keysock at module load time
    375      0      stevel  */
    376      0      stevel boolean_t
    377      0      stevel keysock_ddi_init(void)
    378      0      stevel {
    379      0      stevel 	keysock_max_optsize = optcom_max_optsize(
    380      0      stevel 	    keysock_opt_obj.odb_opt_des_arr, keysock_opt_obj.odb_opt_arr_cnt);
    381      0      stevel 
    382      0      stevel 	keysock_vmem = vmem_create("keysock", (void *)1, MAXMIN, 1,
    383      0      stevel 	    NULL, NULL, NULL, 1, VM_SLEEP | VMC_IDENTIFIER);
    384      0      stevel 
    385   3448    dh155122 	/*
    386   3448    dh155122 	 * We want to be informed each time a stack is created or
    387   3448    dh155122 	 * destroyed in the kernel, so we can maintain the
    388   3448    dh155122 	 * set of keysock_stack_t's.
    389   3448    dh155122 	 */
    390   3448    dh155122 	netstack_register(NS_KEYSOCK, keysock_stack_init, NULL,
    391   3448    dh155122 	    keysock_stack_fini);
    392      0      stevel 
    393      0      stevel 	return (B_TRUE);
    394   3448    dh155122 }
    395   3448    dh155122 
    396   3448    dh155122 /*
    397   3448    dh155122  * Walk through the param array specified registering each element with the
    398   3448    dh155122  * named dispatch handler.
    399   3448    dh155122  */
    400   3448    dh155122 static boolean_t
    401   3448    dh155122 keysock_param_register(IDP *ndp, keysockparam_t *ksp, int cnt)
    402   3448    dh155122 {
    403   3448    dh155122 	for (; cnt-- > 0; ksp++) {
    404   3448    dh155122 		if (ksp->keysock_param_name != NULL &&
    405   3448    dh155122 		    ksp->keysock_param_name[0]) {
    406   3448    dh155122 			if (!nd_load(ndp,
    407   3448    dh155122 			    ksp->keysock_param_name,
    408   3448    dh155122 			    keysock_param_get, keysock_param_set,
    409   3448    dh155122 			    (caddr_t)ksp)) {
    410   3448    dh155122 				nd_free(ndp);
    411   3448    dh155122 				return (B_FALSE);
    412   3448    dh155122 			}
    413   3448    dh155122 		}
    414   3448    dh155122 	}
    415   3448    dh155122 	return (B_TRUE);
    416   3448    dh155122 }
    417   3448    dh155122 
    418   3448    dh155122 /*
    419   3448    dh155122  * Initialize keysock for one stack instance
    420   3448    dh155122  */
    421   3448    dh155122 /* ARGSUSED */
    422   3448    dh155122 static void *
    423   3448    dh155122 keysock_stack_init(netstackid_t stackid, netstack_t *ns)
    424   3448    dh155122 {
    425   3448    dh155122 	keysock_stack_t	*keystack;
    426   3448    dh155122 	keysockparam_t *ksp;
    427   3448    dh155122 
    428   3448    dh155122 	keystack = (keysock_stack_t *)kmem_zalloc(sizeof (*keystack), KM_SLEEP);
    429   3448    dh155122 	keystack->keystack_netstack = ns;
    430   3448    dh155122 
    431   3448    dh155122 	keystack->keystack_acquire_seq = 0xffffffff;
    432   3448    dh155122 
    433   3448    dh155122 	ksp = (keysockparam_t *)kmem_alloc(sizeof (lcl_param_arr), KM_SLEEP);
    434   3448    dh155122 	keystack->keystack_params = ksp;
    435   3448    dh155122 	bcopy(lcl_param_arr, ksp, sizeof (lcl_param_arr));
    436   3448    dh155122 
    437   3448    dh155122 	(void) keysock_param_register(&keystack->keystack_g_nd, ksp,
    438   3448    dh155122 	    A_CNT(lcl_param_arr));
    439   3448    dh155122 
    440   3448    dh155122 	mutex_init(&keystack->keystack_list_lock, NULL, MUTEX_DEFAULT, NULL);
    441   3448    dh155122 	mutex_init(&keystack->keystack_consumers_lock,
    442   3448    dh155122 	    NULL, MUTEX_DEFAULT, NULL);
    443   3448    dh155122 	mutex_init(&keystack->keystack_param_lock, NULL, MUTEX_DEFAULT, NULL);
    444   3448    dh155122 	return (keystack);
    445      0      stevel }
    446      0      stevel 
    447      0      stevel /*
    448      0      stevel  * Free NDD variable space, and other destructors, for keysock.
    449      0      stevel  */
    450      0      stevel void
    451      0      stevel keysock_ddi_destroy(void)
    452      0      stevel {
    453   3448    dh155122 	netstack_unregister(NS_KEYSOCK);
    454   3448    dh155122 	vmem_destroy(keysock_vmem);
    455   3448    dh155122 }
    456      0      stevel 
    457   3448    dh155122 /*
    458   3448    dh155122  * Remove one stack instance from keysock
    459   3448    dh155122  */
    460   3448    dh155122 /* ARGSUSED */
    461   3448    dh155122 static void
    462   3448    dh155122 keysock_stack_fini(netstackid_t stackid, void *arg)
    463   3448    dh155122 {
    464   3448    dh155122 	keysock_stack_t *keystack = (keysock_stack_t *)arg;
    465   3448    dh155122 
    466   3448    dh155122 	nd_free(&keystack->keystack_g_nd);
    467   3448    dh155122 	kmem_free(keystack->keystack_params, sizeof (lcl_param_arr));
    468   3448    dh155122 	keystack->keystack_params = NULL;
    469   3448    dh155122 
    470   3448    dh155122 	mutex_destroy(&keystack->keystack_list_lock);
    471   3448    dh155122 	mutex_destroy(&keystack->keystack_consumers_lock);
    472   3448    dh155122 	mutex_destroy(&keystack->keystack_param_lock);
    473   3448    dh155122 
    474   3448    dh155122 	kmem_free(keystack, sizeof (*keystack));
    475      0      stevel }
    476      0      stevel 
    477      0      stevel /*
    478      0      stevel  * Close routine for keysock.
    479      0      stevel  */
    480      0      stevel static int
    481      0      stevel keysock_close(queue_t *q)
    482      0      stevel {
    483      0      stevel 	keysock_t *ks;
    484      0      stevel 	keysock_consumer_t *kc;
    485      0      stevel 	void *ptr = q->q_ptr;
    486      0      stevel 	int size;
    487   3448    dh155122 	keysock_stack_t	*keystack;
    488   3448    dh155122 
    489      0      stevel 
    490      0      stevel 	qprocsoff(q);
    491      0      stevel 
    492      0      stevel 	/* Safe assumption. */
    493      0      stevel 	ASSERT(ptr != NULL);
    494      0      stevel 
    495      0      stevel 	if (WR(q)->q_next) {
    496      0      stevel 		kc = (keysock_consumer_t *)ptr;
    497   3448    dh155122 		keystack = kc->kc_keystack;
    498   3448    dh155122 
    499   3448    dh155122 		ks1dbg(keystack, ("Module close, removing a consumer (%d).\n",
    500      0      stevel 		    kc->kc_sa_type));
    501      0      stevel 		/*
    502      0      stevel 		 * Because of PERMOD open/close exclusive perimeter, I
    503      0      stevel 		 * can inspect KC_FLUSHING w/o locking down kc->kc_lock.
    504      0      stevel 		 */
    505      0      stevel 		if (kc->kc_flags & KC_FLUSHING) {
    506      0      stevel 			/*
    507      0      stevel 			 * If this decrement was the last one, send
    508      0      stevel 			 * down the next pending one, if any.
    509      0      stevel 			 *
    510      0      stevel 			 * With a PERMOD perimeter, the mutexes ops aren't
    511      0      stevel 			 * really necessary, but if we ever loosen up, we will
    512      0      stevel 			 * have this bit covered already.
    513      0      stevel 			 */
    514   3448    dh155122 			keystack->keystack_flushdump--;
    515   3448    dh155122 			if (keystack->keystack_flushdump == 0) {
    516      0      stevel 				/*
    517      0      stevel 				 * The flush/dump terminated by having a
    518      0      stevel 				 * consumer go away.  I need to send up to the
    519      0      stevel 				 * appropriate keysock all of the relevant
    520      0      stevel 				 * information.  Unfortunately, I don't
    521      0      stevel 				 * have that handy.
    522      0      stevel 				 */
    523      0      stevel 				ks0dbg(("Consumer went away while flushing or"
    524      0      stevel 				    " dumping.\n"));
    525      0      stevel 			}
    526      0      stevel 		}
    527      0      stevel 		size = sizeof (keysock_consumer_t);
    528   3448    dh155122 		mutex_enter(&keystack->keystack_consumers_lock);
    529   3448    dh155122 		keystack->keystack_consumers[kc->kc_sa_type] = NULL;
    530   3448    dh155122 		mutex_exit(&keystack->keystack_consumers_lock);
    531      0      stevel 		mutex_destroy(&kc->kc_lock);
    532   3448    dh155122 		netstack_rele(kc->kc_keystack->keystack_netstack);
    533      0      stevel 	} else {
    534      0      stevel 		ks = (keysock_t *)ptr;
    535   3448    dh155122 		keystack = ks->keysock_keystack;
    536   3448    dh155122 
    537   3448    dh155122 		ks3dbg(keystack,
    538   3448    dh155122 		    ("Driver close, PF_KEY socket is going away.\n"));
    539      0      stevel 		if ((ks->keysock_flags & KEYSOCK_EXTENDED) != 0)
    540   3448    dh155122 			atomic_add_32(&keystack->keystack_num_extended, -1);
    541      0      stevel 		size = sizeof (keysock_t);
    542   3448    dh155122 		mutex_enter(&keystack->keystack_list_lock);
    543      0      stevel 		*(ks->keysock_ptpn) = ks->keysock_next;
    544      0      stevel 		if (ks->keysock_next != NULL)
    545      0      stevel 			ks->keysock_next->keysock_ptpn = ks->keysock_ptpn;
    546   3448    dh155122 		mutex_exit(&keystack->keystack_list_lock);
    547      0      stevel 		mutex_destroy(&ks->keysock_lock);
    548   2465      danmcd 		vmem_free(keysock_vmem, (void *)(uintptr_t)ks->keysock_serial,
    549   2465      danmcd 		    1);
    550   3448    dh155122 		netstack_rele(ks->keysock_keystack->keystack_netstack);
    551      0      stevel 	}
    552      0      stevel 
    553      0      stevel 	/* Now I'm free. */
    554      0      stevel 	kmem_free(ptr, size);
    555      0      stevel 	return (0);
    556      0      stevel }
    557      0      stevel /*
    558      0      stevel  * Open routine for keysock.
    559      0      stevel  */
    560      0      stevel /* ARGSUSED */
    561      0      stevel static int
    562      0      stevel keysock_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp)
    563      0      stevel {
    564      0      stevel 	keysock_t *ks;
    565      0      stevel 	keysock_consumer_t *kc;
    566      0      stevel 	mblk_t *mp;
    567      0      stevel 	ipsec_info_t *ii;
    568   3448    dh155122 	netstack_t *ns;
    569   3448    dh155122 	keysock_stack_t *keystack;
    570      0      stevel 
    571   3448    dh155122 	if (secpolicy_ip_config(credp, B_FALSE) != 0) {
    572      0      stevel 		/* Privilege debugging will log the error */
    573      0      stevel 		return (EPERM);
    574      0      stevel 	}
    575      0      stevel 
    576      0      stevel 	if (q->q_ptr != NULL)
    577      0      stevel 		return (0);  /* Re-open of an already open instance. */
    578      0      stevel 
    579   3448    dh155122 	ns = netstack_find_by_cred(credp);
    580   3448    dh155122 	ASSERT(ns != NULL);
    581   3448    dh155122 	keystack = ns->netstack_keysock;
    582   3448    dh155122 	ASSERT(keystack != NULL);
    583   3448    dh155122 
    584   3448    dh155122 	ks3dbg(keystack, ("Entering keysock open.\n"));
    585   3448    dh155122 
    586   3448    dh155122 	if (keystack->keystack_plumbed < 1) {
    587   3448    dh155122 		netstack_t *ns = keystack->keystack_netstack;
    588   3448    dh155122 
    589   3448    dh155122 		keystack->keystack_plumbed = 0;
    590   3448    dh155122 #ifdef NS_DEBUG
    591   3448    dh155122 		printf("keysock_open(%d) - plumb\n",
    592   3448    dh155122 		    keystack->keystack_netstack->netstack_stackid);
    593   3448    dh155122 #endif
    594      0      stevel 		/*
    595      0      stevel 		 * Don't worry about ipsec_failure being true here.
    596      0      stevel 		 * (See ip.c).  An open of keysock should try and force
    597      0      stevel 		 * the issue.  Maybe it was a transient failure.
    598      0      stevel 		 */
    599   3448    dh155122 		ipsec_loader_loadnow(ns->netstack_ipsec);
    600      0      stevel 	}
    601      0      stevel 
    602      0      stevel 	if (sflag & MODOPEN) {
    603      0      stevel 		/* Initialize keysock_consumer state here. */
    604      0      stevel 		kc = kmem_zalloc(sizeof (keysock_consumer_t), KM_NOSLEEP);
    605   3448    dh155122 		if (kc == NULL) {
    606   3448    dh155122 			netstack_rele(keystack->keystack_netstack);
    607      0      stevel 			return (ENOMEM);
    608   3448    dh155122 		}
    609      0      stevel 		mutex_init(&kc->kc_lock, NULL, MUTEX_DEFAULT, 0);
    610      0      stevel 		kc->kc_rq = q;
    611      0      stevel 		kc->kc_wq = WR(q);
    612      0      stevel 
    613      0      stevel 		q->q_ptr = kc;
    614      0      stevel 		WR(q)->q_ptr = kc;
    615      0      stevel 
    616   3448    dh155122 		kc->kc_keystack = keystack;
    617      0      stevel 		qprocson(q);
    618      0      stevel 
    619      0      stevel 		/*
    620      0      stevel 		 * Send down initial message to whatever I was pushed on top
    621      0      stevel 		 * of asking for its consumer type.  The reply will set it.
    622      0      stevel 		 */
    623      0      stevel 
    624      0      stevel 		/* Allocate it. */
    625      0      stevel 		mp = allocb(sizeof (ipsec_info_t), BPRI_HI);
    626      0      stevel 		if (mp == NULL) {
    627   3448    dh155122 			ks1dbg(keystack, (
    628      0      stevel 			    "keysock_open:  Cannot allocate KEYSOCK_HELLO.\n"));
    629      0      stevel 			/* Do I need to set these to null? */
    630      0      stevel 			q->q_ptr = NULL;
    631      0      stevel 			WR(q)->q_ptr = NULL;
    632      0      stevel 			mutex_destroy(&kc->kc_lock);
    633      0      stevel 			kmem_free(kc, sizeof (*kc));
    634   3448    dh155122 			netstack_rele(keystack->keystack_netstack);
    635      0      stevel 			return (ENOMEM);
    636      0      stevel 		}
    637      0      stevel 
    638      0      stevel 		/* If I allocated okay, putnext to what I was pushed atop. */
    639      0      stevel 		mp->b_wptr += sizeof (ipsec_info_t);
    640      0      stevel 		mp->b_datap->db_type = M_CTL;
    641      0      stevel 		ii = (ipsec_info_t *)mp->b_rptr;
    642      0      stevel 		ii->ipsec_info_type = KEYSOCK_HELLO;
    643      0      stevel 		/* Length only of type/len. */
    644      0      stevel 		ii->ipsec_info_len = sizeof (ii->ipsec_allu);
    645   3448    dh155122 		ks2dbg(keystack, ("Ready to putnext KEYSOCK_HELLO.\n"));
    646      0      stevel 		putnext(kc->kc_wq, mp);
    647      0      stevel 	} else {
    648      0      stevel 		minor_t ksminor;
    649      0      stevel 
    650      0      stevel 		/* Initialize keysock state. */
    651      0      stevel 
    652   3448    dh155122 		ks2dbg(keystack, ("Made it into PF_KEY socket open.\n"));
    653      0      stevel 
    654      0      stevel 		ksminor = (minor_t)(uintptr_t)
    655      0      stevel 		    vmem_alloc(keysock_vmem, 1, VM_NOSLEEP);
    656   3448    dh155122 		if (ksminor == 0) {
    657   3448    dh155122 			netstack_rele(keystack->keystack_netstack);
    658      0      stevel 			return (ENOMEM);
    659   3448    dh155122 		}
    660      0      stevel 		ks = kmem_zalloc(sizeof (keysock_t), KM_NOSLEEP);
    661      0      stevel 		if (ks == NULL) {
    662      0      stevel 			vmem_free(keysock_vmem, (void *)(uintptr_t)ksminor, 1);
    663   3448    dh155122 			netstack_rele(keystack->keystack_netstack);
    664      0      stevel 			return (ENOMEM);
    665      0      stevel 		}
    666      0      stevel 
    667      0      stevel 		mutex_init(&ks->keysock_lock, NULL, MUTEX_DEFAULT, 0);
    668      0      stevel 		ks->keysock_rq = q;
    669      0      stevel 		ks->keysock_wq = WR(q);
    670      0      stevel 		ks->keysock_state = TS_UNBND;
    671      0      stevel 		ks->keysock_serial = ksminor;
    672      0      stevel 
    673      0      stevel 		q->q_ptr = ks;
    674      0      stevel 		WR(q)->q_ptr = ks;
    675   3448    dh155122 		ks->keysock_keystack = keystack;
    676      0      stevel 
    677      0      stevel 		/*
    678      0      stevel 		 * The receive hiwat is only looked at on the stream head
    679      0      stevel 		 * queue.  Store in q_hiwat in order to return on SO_RCVBUF
    680      0      stevel 		 * getsockopts.
    681      0      stevel 		 */
    682      0      stevel 
    683   3448    dh155122 		q->q_hiwat = keystack->keystack_recv_hiwat;
    684      0      stevel 
    685      0      stevel 		/*
    686      0      stevel 		 * The transmit hiwat/lowat is only looked at on IP's queue.
    687      0      stevel 		 * Store in q_hiwat/q_lowat in order to return on
    688      0      stevel 		 * SO_SNDBUF/SO_SNDLOWAT getsockopts.
    689      0      stevel 		 */
    690      0      stevel 
    691   3448    dh155122 		WR(q)->q_hiwat = keystack->keystack_xmit_hiwat;
    692   3448    dh155122 		WR(q)->q_lowat = keystack->keystack_xmit_lowat;
    693      0      stevel 
    694      0      stevel 		*devp = makedevice(getmajor(*devp), ksminor);
    695      0      stevel 
    696      0      stevel 		/*
    697      0      stevel 		 * Thread keysock into the global keysock list.
    698      0      stevel 		 */
    699   3448    dh155122 		mutex_enter(&keystack->keystack_list_lock);
    700   3448    dh155122 		ks->keysock_next = keystack->keystack_list;
    701   3448    dh155122 		ks->keysock_ptpn = &keystack->keystack_list;
    702   3448    dh155122 		if (keystack->keystack_list != NULL) {
    703   3448    dh155122 			keystack->keystack_list->keysock_ptpn =
    704   3448    dh155122 			    &ks->keysock_next;
    705   3448    dh155122 		}
    706   3448    dh155122 		keystack->keystack_list = ks;
    707   3448    dh155122 		mutex_exit(&keystack->keystack_list_lock);
    708      0      stevel 
    709      0      stevel 		qprocson(q);
    710   8348        Eric 		(void) proto_set_rx_hiwat(q, NULL,
    711   8348        Eric 		    keystack->keystack_recv_hiwat);
    712      0      stevel 		/*
    713      0      stevel 		 * Wait outside the keysock module perimeter for IPsec
    714      0      stevel 		 * plumbing to be completed.  If it fails, keysock_close()
    715      0      stevel 		 * undoes everything we just did.
    716      0      stevel 		 */
    717   3448    dh155122 		if (!ipsec_loader_wait(q,
    718   3448    dh155122 		    keystack->keystack_netstack->netstack_ipsec)) {
    719      0      stevel 			(void) keysock_close(q);
    720      0      stevel 			return (EPFNOSUPPORT);
    721      0      stevel 		}
    722      0      stevel 	}
    723      0      stevel 
    724      0      stevel 	return (0);
    725      0      stevel }
    726      0      stevel 
    727      0      stevel /* BELOW THIS LINE ARE ROUTINES INCLUDING AND RELATED TO keysock_wput(). */
    728      0      stevel 
    729      0      stevel /*
    730      0      stevel  * Copy relevant state bits.
    731      0      stevel  */
    732      0      stevel static void
    733      0      stevel keysock_copy_info(struct T_info_ack *tap, keysock_t *ks)
    734      0      stevel {
    735      0      stevel 	*tap = keysock_g_t_info_ack;
    736      0      stevel 	tap->CURRENT_state = ks->keysock_state;
    737      0      stevel 	tap->OPT_size = keysock_max_optsize;
    738      0      stevel }
    739      0      stevel 
    740      0      stevel /*
    741      0      stevel  * This routine responds to T_CAPABILITY_REQ messages.  It is called by
    742      0      stevel  * keysock_wput.  Much of the T_CAPABILITY_ACK information is copied from
    743      0      stevel  * keysock_g_t_info_ack.  The current state of the stream is copied from
    744      0      stevel  * keysock_state.
    745      0      stevel  */
    746      0      stevel static void
    747      0      stevel keysock_capability_req(queue_t *q, mblk_t *mp)
    748      0      stevel {
    749      0      stevel 	keysock_t *ks = (keysock_t *)q->q_ptr;
    750      0      stevel 	t_uscalar_t cap_bits1;
    751      0      stevel 	struct T_capability_ack	*tcap;
    752      0      stevel 
    753      0      stevel 	cap_bits1 = ((struct T_capability_req *)mp->b_rptr)->CAP_bits1;
    754      0      stevel 
    755      0      stevel 	mp = tpi_ack_alloc(mp, sizeof (struct T_capability_ack),
    756   5240    nordmark 	    mp->b_datap->db_type, T_CAPABILITY_ACK);
    757      0      stevel 	if (mp == NULL)
    758      0      stevel 		return;
    759      0      stevel 
    760      0      stevel 	tcap = (struct T_capability_ack *)mp->b_rptr;
    761      0      stevel 	tcap->CAP_bits1 = 0;
    762      0      stevel 
    763      0      stevel 	if (cap_bits1 & TC1_INFO) {
    764      0      stevel 		keysock_copy_info(&tcap->INFO_ack, ks);
    765      0      stevel 		tcap->CAP_bits1 |= TC1_INFO;
    766      0      stevel 	}
    767      0      stevel 
    768      0      stevel 	qreply(q, mp);
    769      0      stevel }
    770      0      stevel 
    771      0      stevel /*
    772      0      stevel  * This routine responds to T_INFO_REQ messages. It is called by
    773      0      stevel  * keysock_wput_other.
    774      0      stevel  * Most of the T_INFO_ACK information is copied from keysock_g_t_info_ack.
    775      0      stevel  * The current state of the stream is copied from keysock_state.
    776      0      stevel  */
    777      0      stevel static void
    778      0      stevel keysock_info_req(q, mp)
    779      0      stevel 	queue_t	*q;
    780      0      stevel 	mblk_t	*mp;
    781      0      stevel {
    782      0      stevel 	mp = tpi_ack_alloc(mp, sizeof (struct T_info_ack), M_PCPROTO,
    783      0      stevel 	    T_INFO_ACK);
    784      0      stevel 	if (mp == NULL)
    785      0      stevel 		return;
    786      0      stevel 	keysock_copy_info((struct T_info_ack *)mp->b_rptr,
    787      0      stevel 	    (keysock_t *)q->q_ptr);
    788      0      stevel 	qreply(q, mp);
    789      0      stevel }
    790      0      stevel 
    791      0      stevel /*
    792      0      stevel  * keysock_err_ack. This routine creates a
    793      0      stevel  * T_ERROR_ACK message and passes it
    794      0      stevel  * upstream.
    795      0      stevel  */
    796      0      stevel static void
    797      0      stevel keysock_err_ack(q, mp, t_error, sys_error)
    798      0      stevel 	queue_t	*q;
    799      0      stevel 	mblk_t	*mp;
    800      0      stevel 	int	t_error;
    801      0      stevel 	int	sys_error;
    802      0      stevel {
    803      0      stevel 	if ((mp = mi_tpi_err_ack_alloc(mp, t_error, sys_error)) != NULL)
    804      0      stevel 		qreply(q, mp);
    805      0      stevel }
    806      0      stevel 
    807      0      stevel /*
    808      0      stevel  * This routine retrieves the current status of socket options.
    809      0      stevel  * It returns the size of the option retrieved.
    810      0      stevel  */
    811      0      stevel /* ARGSUSED */
    812      0      stevel int
    813      0      stevel keysock_opt_get(queue_t *q, int level, int name, uchar_t *ptr)
    814      0      stevel {
    815      0      stevel 	int *i1 = (int *)ptr;
    816      0      stevel 	keysock_t *ks = (keysock_t *)q->q_ptr;
    817      0      stevel 
    818      0      stevel 	switch (level) {
    819      0      stevel 	case SOL_SOCKET:
    820      0      stevel 		mutex_enter(&ks->keysock_lock);
    821      0      stevel 		switch (name) {
    822      0      stevel 		case SO_TYPE:
    823      0      stevel 			*i1 = SOCK_RAW;
    824      0      stevel 			break;
    825      0      stevel 		case SO_USELOOPBACK:
    826      0      stevel 			*i1 = (int)(!((ks->keysock_flags & KEYSOCK_NOLOOP) ==
    827      0      stevel 			    KEYSOCK_NOLOOP));
    828      0      stevel 			break;
    829      0      stevel 		/*
    830      0      stevel 		 * The following two items can be manipulated,
    831      0      stevel 		 * but changing them should do nothing.
    832      0      stevel 		 */
    833      0      stevel 		case SO_SNDBUF:
    834      0      stevel 			*i1 = (int)q->q_hiwat;
    835      0      stevel 			break;
    836      0      stevel 		case SO_RCVBUF:
    837      0      stevel 			*i1 = (int)(RD(q)->q_hiwat);
    838      0      stevel 			break;
    839      0      stevel 		}
    840      0      stevel 		mutex_exit(&ks->keysock_lock);
    841      0      stevel 		break;
    842      0      stevel 	default:
    843      0      stevel 		return (0);
    844      0      stevel 	}
    845      0      stevel 	return (sizeof (int));
    846      0      stevel }
    847      0      stevel 
    848      0      stevel /*
    849      0      stevel  * This routine sets socket options.
    850      0      stevel  */
    851      0      stevel /* ARGSUSED */
    852      0      stevel int
    853      0      stevel keysock_opt_set(queue_t *q, uint_t mgmt_flags, int level,
    854      0      stevel     int name, uint_t inlen, uchar_t *invalp, uint_t *outlenp,
    855  11042        Erik     uchar_t *outvalp, void *thisdg_attrs, cred_t *cr)
    856      0      stevel {
    857   8730      danmcd 	int *i1 = (int *)invalp, errno = 0;
    858      0      stevel 	keysock_t *ks = (keysock_t *)q->q_ptr;
    859   3448    dh155122 	keysock_stack_t	*keystack = ks->keysock_keystack;
    860      0      stevel 
    861      0      stevel 	switch (level) {
    862      0      stevel 	case SOL_SOCKET:
    863      0      stevel 		mutex_enter(&ks->keysock_lock);
    864      0      stevel 		switch (name) {
    865      0      stevel 		case SO_USELOOPBACK:
    866      0      stevel 			if (!(*i1))
    867      0      stevel 				ks->keysock_flags |= KEYSOCK_NOLOOP;
    868      0      stevel 			else ks->keysock_flags &= ~KEYSOCK_NOLOOP;
    869      0      stevel 			break;
    870      0      stevel 		case SO_SNDBUF:
    871   3448    dh155122 			if (*i1 > keystack->keystack_max_buf)
    872   8730      danmcd 				errno = ENOBUFS;
    873   8730      danmcd 			else q->q_hiwat = *i1;
    874      0      stevel 			break;
    875      0      stevel 		case SO_RCVBUF:
    876   8730      danmcd 			if (*i1 > keystack->keystack_max_buf) {
    877   8730      danmcd 				errno = ENOBUFS;
    878   8730      danmcd 			} else {
    879   8730      danmcd 				RD(q)->q_hiwat = *i1;
    880   8730      danmcd 				(void) proto_set_rx_hiwat(RD(q), NULL, *i1);
    881   8730      danmcd 			}
    882      0      stevel 			break;
    883   8730      danmcd 		default:
    884   8730      danmcd 			errno = EINVAL;
    885      0      stevel 		}
    886      0      stevel 		mutex_exit(&ks->keysock_lock);
    887      0      stevel 		break;
    888   8730      danmcd 	default:
    889   8730      danmcd 		errno = EINVAL;
    890      0      stevel 	}
    891   8730      danmcd 	return (errno);
    892      0      stevel }
    893      0      stevel 
    894      0      stevel /*
    895      0      stevel  * Handle STREAMS messages.
    896      0      stevel  */
    897      0      stevel static void
    898      0      stevel keysock_wput_other(queue_t *q, mblk_t *mp)
    899      0      stevel {
    900      0      stevel 	struct iocblk *iocp;
    901      0      stevel 	int error;
    902   3448    dh155122 	keysock_t *ks = (keysock_t *)q->q_ptr;
    903   3448    dh155122 	keysock_stack_t	*keystack = ks->keysock_keystack;
    904   3448    dh155122 	cred_t		*cr;
    905      0      stevel 
    906      0      stevel 	switch (mp->b_datap->db_type) {
    907      0      stevel 	case M_PROTO:
    908      0      stevel 	case M_PCPROTO:
    909      0      stevel 		if ((mp->b_wptr - mp->b_rptr) < sizeof (long)) {
    910   3448    dh155122 			ks3dbg(keystack, (
    911      0      stevel 			    "keysock_wput_other: Not big enough M_PROTO\n"));
    912      0      stevel 			freemsg(mp);
    913      0      stevel 			return;
    914      0      stevel 		}
    915      0      stevel 		switch (((union T_primitives *)mp->b_rptr)->type) {
    916      0      stevel 		case T_CAPABILITY_REQ:
    917      0      stevel 			keysock_capability_req(q, mp);
    918   3448    dh155122 			break;
    919      0      stevel 		case T_INFO_REQ:
    920      0      stevel 			keysock_info_req(q, mp);
    921   3448    dh155122 			break;
    922      0      stevel 		case T_SVR4_OPTMGMT_REQ:
    923      0      stevel 		case T_OPTMGMT_REQ:
    924   8778        Erik 			/*
    925   8778        Erik 			 * All Solaris components should pass a db_credp
    926   8778        Erik 			 * for this TPI message, hence we ASSERT.
    927   8778        Erik 			 * But in case there is some other M_PROTO that looks
    928   8778        Erik 			 * like a TPI message sent by some other kernel
    929   8778        Erik 			 * component, we check and return an error.
    930   8778        Erik 			 */
    931   8778        Erik 			cr = msg_getcred(mp, NULL);
    932   8778        Erik 			ASSERT(cr != NULL);
    933   8778        Erik 			if (cr == NULL) {
    934   8778        Erik 				keysock_err_ack(q, mp, TSYSERR, EINVAL);
    935   8778        Erik 				return;
    936   8778        Erik 			}
    937   8778        Erik 			if (((union T_primitives *)mp->b_rptr)->type ==
    938   8778        Erik 			    T_SVR4_OPTMGMT_REQ) {
    939  11042        Erik 				svr4_optcom_req(q, mp, cr, &keysock_opt_obj);
    940   8778        Erik 			} else {
    941  11042        Erik 				tpi_optcom_req(q, mp, cr, &keysock_opt_obj);
    942   8778        Erik 			}
    943   3448    dh155122 			break;
    944      0      stevel 		case T_DATA_REQ:
    945      0      stevel 		case T_EXDATA_REQ:
    946      0      stevel 		case T_ORDREL_REQ:
    947      0      stevel 			/* Illegal for keysock. */
    948      0      stevel 			freemsg(mp);
    949      0      stevel 			(void) putnextctl1(RD(q), M_ERROR, EPROTO);
    950   3448    dh155122 			break;
    951      0      stevel 		default:
    952      0      stevel 			/* Not supported by keysock. */
    953      0      stevel 			keysock_err_ack(q, mp, TNOTSUPPORT, 0);
    954   3448    dh155122 			break;
    955      0      stevel 		}
    956   3448    dh155122 		return;
    957      0      stevel 	case M_IOCTL:
    958      0      stevel 		iocp = (struct iocblk *)mp->b_rptr;
    959      0      stevel 		error = EINVAL;
    960      0      stevel 
    961      0      stevel 		switch (iocp->ioc_cmd) {
    962      0      stevel 		case ND_SET:
    963      0      stevel 		case ND_GET:
    964   3448    dh155122 			if (nd_getset(q, keystack->keystack_g_nd, mp)) {
    965      0      stevel 				qreply(q, mp);
    966      0      stevel 				return;
    967      0      stevel 			} else
    968      0      stevel 				error = ENOENT;
    969      0      stevel 			/* FALLTHRU */
    970      0      stevel 		default:
    971      0      stevel 			miocnak(q, mp, 0, error);
    972      0      stevel 			return;
    973      0      stevel 		}
    974      0      stevel 	case M_FLUSH:
    975      0      stevel 		if (*mp->b_rptr & FLUSHW) {
    976      0      stevel 			flushq(q, FLUSHALL);
    977      0      stevel 			*mp->b_rptr &= ~FLUSHW;
    978      0      stevel 		}
    979      0      stevel 		if (*mp->b_rptr & FLUSHR) {
    980      0      stevel 			qreply(q, mp);
    981      0      stevel 			return;
    982      0      stevel 		}
    983      0      stevel 		/* Else FALLTHRU */
    984      0      stevel 	}
    985      0      stevel 
    986      0      stevel 	/* If fell through, just black-hole the message. */
    987      0      stevel 	freemsg(mp);
    988      0      stevel }
    989      0      stevel 
    990      0      stevel /*
    991      0      stevel  * Transmit a PF_KEY error message to the instance either pointed to
    992      0      stevel  * by ks, the instance with serial number serial, or more, depending.
    993      0      stevel  *
    994      0      stevel  * The faulty message (or a reasonable facsimile thereof) is in mp.
    995      0      stevel  * This function will free mp or recycle it for delivery, thereby causing
    996      0      stevel  * the stream head to free it.
    997      0      stevel  */
    998      0      stevel static void
    999      0      stevel keysock_error(keysock_t *ks, mblk_t *mp, int error, int diagnostic)
   1000      0      stevel {
   1001      0      stevel 	sadb_msg_t *samsg = (sadb_msg_t *)mp->b_rptr;
   1002   3448    dh155122 	keysock_stack_t	*keystack = ks->keysock_keystack;
   1003      0      stevel 
   1004      0      stevel 	ASSERT(mp->b_datap->db_type == M_DATA);
   1005      0      stevel 
   1006      0      stevel 	if (samsg->sadb_msg_type < SADB_GETSPI ||
   1007      0      stevel 	    samsg->sadb_msg_type > SADB_MAX)
   1008      0      stevel 		samsg->sadb_msg_type = SADB_RESERVED;
   1009      0      stevel 
   1010      0      stevel 	/*
   1011      0      stevel 	 * Strip out extension headers.
   1012      0      stevel 	 */
   1013      0      stevel 	ASSERT(mp->b_rptr + sizeof (*samsg) <= mp->b_datap->db_lim);
   1014      0      stevel 	mp->b_wptr = mp->b_rptr + sizeof (*samsg);
   1015      0      stevel 	samsg->sadb_msg_len = SADB_8TO64(sizeof (sadb_msg_t));
   1016      0      stevel 	samsg->sadb_msg_errno = (uint8_t)error;
   1017      0      stevel 	samsg->sadb_x_msg_diagnostic = (uint16_t)diagnostic;
   1018      0      stevel 
   1019   3448    dh155122 	keysock_passup(mp, samsg, ks->keysock_serial, NULL, B_FALSE, keystack);
   1020      0      stevel }
   1021      0      stevel 
   1022      0      stevel /*
   1023      0      stevel  * Pass down a message to a consumer.  Wrap it in KEYSOCK_IN, and copy
   1024      0      stevel  * in the extv if passed in.
   1025      0      stevel  */
   1026      0      stevel static void
   1027      0      stevel keysock_passdown(keysock_t *ks, mblk_t *mp, uint8_t satype, sadb_ext_t *extv[],
   1028      0      stevel     boolean_t flushmsg)
   1029      0      stevel {
   1030      0      stevel 	keysock_consumer_t *kc;
   1031      0      stevel 	mblk_t *wrapper;
   1032      0      stevel 	keysock_in_t *ksi;
   1033      0      stevel 	int i;
   1034   3448    dh155122 	keysock_stack_t	*keystack = ks->keysock_keystack;
   1035      0      stevel 
   1036      0      stevel 	wrapper = allocb(sizeof (ipsec_info_t), BPRI_HI);
   1037      0      stevel 	if (wrapper == NULL) {
   1038   3448    dh155122 		ks3dbg(keystack, ("keysock_passdown: allocb failed.\n"));
   1039      0      stevel 		if (extv[SADB_EXT_KEY_ENCRYPT] != NULL)
   1040      0      stevel 			bzero(extv[SADB_EXT_KEY_ENCRYPT],
   1041      0      stevel 			    SADB_64TO8(
   1042   5240    nordmark 			    extv[SADB_EXT_KEY_ENCRYPT]->sadb_ext_len));
   1043      0      stevel 		if (extv[SADB_EXT_KEY_AUTH] != NULL)
   1044      0      stevel 			bzero(extv[SADB_EXT_KEY_AUTH],
   1045      0      stevel 			    SADB_64TO8(
   1046   5240    nordmark 			    extv[SADB_EXT_KEY_AUTH]->sadb_ext_len));
   1047      0      stevel 		if (flushmsg) {
   1048      0      stevel 			ks0dbg((
   1049      0      stevel 			    "keysock: Downwards flush/dump message failed!\n"));
   1050      0      stevel 			/* If this is true, I hold the perimeter. */
   1051   3448    dh155122 			keystack->keystack_flushdump--;
   1052      0      stevel 		}
   1053      0      stevel 		freemsg(mp);
   1054      0      stevel 		return;
   1055      0      stevel 	}
   1056      0      stevel 
   1057      0      stevel 	wrapper->b_datap->db_type = M_CTL;
   1058      0      stevel 	ksi = (keysock_in_t *)wrapper->b_rptr;
   1059      0      stevel 	ksi->ks_in_type = KEYSOCK_IN;
   1060      0      stevel 	ksi->ks_in_len = sizeof (keysock_in_t);
   1061      0      stevel 	if (extv[SADB_EXT_ADDRESS_SRC] != NULL)
   1062      0      stevel 		ksi->ks_in_srctype = KS_IN_ADDR_UNKNOWN;
   1063      0      stevel 	else ksi->ks_in_srctype = KS_IN_ADDR_NOTTHERE;
   1064      0      stevel 	if (extv[SADB_EXT_ADDRESS_DST] != NULL)
   1065      0      stevel 		ksi->ks_in_dsttype = KS_IN_ADDR_UNKNOWN;
   1066      0      stevel 	else ksi->ks_in_dsttype = KS_IN_ADDR_NOTTHERE;
   1067      0      stevel 	for (i = 0; i <= SADB_EXT_MAX; i++)
   1068      0      stevel 		ksi->ks_in_extv[i] = extv[i];
   1069      0      stevel 	ksi->ks_in_serial = ks->keysock_serial;
   1070      0      stevel 	wrapper->b_wptr += sizeof (ipsec_info_t);
   1071      0      stevel 	wrapper->b_cont = mp;
   1072      0      stevel 
   1073      0      stevel 	/*
   1074      0      stevel 	 * Find the appropriate consumer where the message is passed down.
   1075      0      stevel 	 */
   1076   3448    dh155122 	kc = keystack->keystack_consumers[satype];
   1077      0      stevel 	if (kc == NULL) {
   1078      0      stevel 		freeb(wrapper);
   1079      0      stevel 		keysock_error(ks, mp, EINVAL, SADB_X_DIAGNOSTIC_UNKNOWN_SATYPE);
   1080      0      stevel 		if (flushmsg) {
   1081      0      stevel 			ks0dbg((
   1082      0      stevel 			    "keysock: Downwards flush/dump message failed!\n"));
   1083      0      stevel 			/* If this is true, I hold the perimeter. */
   1084   3448    dh155122 			keystack->keystack_flushdump--;
   1085      0      stevel 		}
   1086      0      stevel 		return;
   1087      0      stevel 	}
   1088      0      stevel 
   1089      0      stevel 	/*
   1090      0      stevel 	 * NOTE: There used to be code in here to spin while a flush or
   1091      0      stevel 	 *	 dump finished.  Keysock now assumes that consumers have enough
   1092      0      stevel 	 *	 MT-savviness to deal with that.
   1093      0      stevel 	 */
   1094      0      stevel 
   1095      0      stevel 	/*
   1096      0      stevel 	 * Current consumers (AH and ESP) are guaranteed to return a
   1097      0      stevel 	 * FLUSH or DUMP message back, so when we reach here, we don't
   1098      0      stevel 	 * have to worry about keysock_flushdumps.
   1099      0      stevel 	 */
   1100      0      stevel 
   1101      0      stevel 	putnext(kc->kc_wq, wrapper);
   1102      0      stevel }
   1103      0      stevel 
   1104      0      stevel /*
   1105      0      stevel  * High-level reality checking of extensions.
   1106      0      stevel  */
   1107      0      stevel static boolean_t
   1108   3448    dh155122 ext_check(sadb_ext_t *ext, keysock_stack_t *keystack)
   1109      0      stevel {
   1110      0      stevel 	int i;
   1111      0      stevel 	uint64_t *lp;
   1112      0      stevel 	sadb_ident_t *id;
   1113      0      stevel 	char *idstr;
   1114      0      stevel 
   1115      0      stevel 	switch (ext->sadb_ext_type) {
   1116      0      stevel 	case SADB_EXT_ADDRESS_SRC:
   1117      0      stevel 	case SADB_EXT_ADDRESS_DST:
   1118   3055      danmcd 	case SADB_X_EXT_ADDRESS_INNER_SRC:
   1119   3055      danmcd 	case SADB_X_EXT_ADDRESS_INNER_DST:
   1120      0      stevel 		/* Check for at least enough addtl length for a sockaddr. */
   1121      0      stevel 		if (ext->sadb_ext_len <= SADB_8TO64(sizeof (sadb_address_t)))
   1122      0      stevel 			return (B_FALSE);
   1123      0      stevel 		break;
   1124      0      stevel 	case SADB_EXT_LIFETIME_HARD:
   1125      0      stevel 	case SADB_EXT_LIFETIME_SOFT:
   1126      0      stevel 	case SADB_EXT_LIFETIME_CURRENT:
   1127      0      stevel 		if (ext->sadb_ext_len != SADB_8TO64(sizeof (sadb_lifetime_t)))
   1128      0      stevel 			return (B_FALSE);
   1129      0      stevel 		break;
   1130      0      stevel 	case SADB_EXT_SPIRANGE:
   1131      0      stevel 		/* See if the SPI range is legit. */
   1132      0      stevel 		if (htonl(((sadb_spirange_t *)ext)->sadb_spirange_min) >
   1133      0      stevel 		    htonl(((sadb_spirange_t *)ext)->sadb_spirange_max))
   1134      0      stevel 			return (B_FALSE);
   1135      0      stevel 		break;
   1136      0      stevel 	case SADB_EXT_KEY_AUTH:
   1137      0      stevel 	case SADB_EXT_KEY_ENCRYPT:
   1138      0      stevel 		/* Key length check. */
   1139      0      stevel 		if (((sadb_key_t *)ext)->sadb_key_bits == 0)
   1140      0      stevel 			return (B_FALSE);
   1141      0      stevel 		/*
   1142      0      stevel 		 * Check to see if the key length (in bits) is less than the
   1143      0      stevel 		 * extension length (in 8-bits words).
   1144      0      stevel 		 */
   1145      0      stevel 		if ((roundup(SADB_1TO8(((sadb_key_t *)ext)->sadb_key_bits), 8) +
   1146      0      stevel 		    sizeof (sadb_key_t)) != SADB_64TO8(ext->sadb_ext_len)) {
   1147   3448    dh155122 			ks1dbg(keystack, (
   1148      0      stevel 			    "ext_check:  Key bits/length inconsistent.\n"));
   1149   3448    dh155122 			ks1dbg(keystack, ("%d bits, len is %d bytes.\n",
   1150      0      stevel 			    ((sadb_key_t *)ext)->sadb_key_bits,
   1151      0      stevel 			    SADB_64TO8(ext->sadb_ext_len)));
   1152      0      stevel 			return (B_FALSE);
   1153      0      stevel 		}
   1154      0      stevel 
   1155      0      stevel 		/* All-zeroes key check. */
   1156      0      stevel 		lp = (uint64_t *)(((char *)ext) + sizeof (sadb_key_t));
   1157      0      stevel 		for (i = 0;
   1158      0      stevel 		    i < (ext->sadb_ext_len - SADB_8TO64(sizeof (sadb_key_t)));
   1159      0      stevel 		    i++)
   1160      0      stevel 			if (lp[i] != 0)
   1161      0      stevel 				break;	/* Out of for loop. */
   1162      0      stevel 		/* If finished the loop naturally, it's an all zero key. */
   1163      0      stevel 		if (lp[i] == 0)
   1164      0      stevel 			return (B_FALSE);
   1165      0      stevel 		break;
   1166      0      stevel 	case SADB_EXT_IDENTITY_SRC:
   1167      0      stevel 	case SADB_EXT_IDENTITY_DST:
   1168      0      stevel 		/*
   1169      0      stevel 		 * Make sure the strings in these identities are
   1170      0      stevel 		 * null-terminated.  RFC 2367 underspecified how to handle
   1171      0      stevel 		 * such a case.  I "proactively" null-terminate the string
   1172      0      stevel 		 * at the last byte if it's not terminated sooner.
   1173      0      stevel 		 */
   1174      0      stevel 		id = (sadb_ident_t *)ext;
   1175      0      stevel 		i = SADB_64TO8(id->sadb_ident_len);
   1176      0      stevel 		i -= sizeof (sadb_ident_t);
   1177      0      stevel 		idstr = (char *)(id + 1);
   1178      0      stevel 		while (*idstr != '\0' && i > 0) {
   1179      0      stevel 			i--;
   1180      0      stevel 			idstr++;
   1181      0      stevel 		}
   1182      0      stevel 		if (i == 0) {
   1183      0      stevel 			/*
   1184      0      stevel 			 * I.e., if the bozo user didn't NULL-terminate the
   1185      0      stevel 			 * string...
   1186      0      stevel 			 */
   1187      0      stevel 			idstr--;
   1188      0      stevel 			*idstr = '\0';
   1189      0      stevel 		}
   1190      0      stevel 		break;
   1191      0      stevel 	}
   1192      0      stevel 	return (B_TRUE);	/* For now... */
   1193      0      stevel }
   1194      0      stevel 
   1195      0      stevel /* Return values for keysock_get_ext(). */
   1196      0      stevel #define	KGE_OK	0
   1197      0      stevel #define	KGE_DUP	1
   1198      0      stevel #define	KGE_UNK	2
   1199      0      stevel #define	KGE_LEN	3
   1200      0      stevel #define	KGE_CHK	4
   1201      0      stevel 
   1202      0      stevel /*
   1203      0      stevel  * Parse basic extension headers and return in the passed-in pointer vector.
   1204      0      stevel  * Return values include:
   1205      0      stevel  *
   1206      0      stevel  *	KGE_OK	Everything's nice and parsed out.
   1207      0      stevel  *		If there are no extensions, place NULL in extv[0].
   1208      0      stevel  *	KGE_DUP	There is a duplicate extension.
   1209      0      stevel  *		First instance in appropriate bin.  First duplicate in
   1210      0      stevel  *		extv[0].
   1211      0      stevel  *	KGE_UNK	Unknown extension type encountered.  extv[0] contains
   1212      0      stevel  *		unknown header.
   1213      0      stevel  *	KGE_LEN	Extension length error.
   1214      0      stevel  *	KGE_CHK	High-level reality check failed on specific extension.
   1215      0      stevel  *
   1216      0      stevel  * My apologies for some of the pointer arithmetic in here.  I'm thinking
   1217      0      stevel  * like an assembly programmer, yet trying to make the compiler happy.
   1218      0      stevel  */
   1219      0      stevel static int
   1220   3448    dh155122 keysock_get_ext(sadb_ext_t *extv[], sadb_msg_t *basehdr, uint_t msgsize,
   1221   3448    dh155122     keysock_stack_t *keystack)
   1222      0      stevel {
   1223      0      stevel 	bzero(extv, sizeof (sadb_ext_t *) * (SADB_EXT_MAX + 1));
   1224      0      stevel 
   1225      0      stevel 	/* Use extv[0] as the "current working pointer". */
   1226      0      stevel 
   1227      0      stevel 	extv[0] = (sadb_ext_t *)(basehdr + 1);
   1228      0      stevel 
   1229      0      stevel 	while (extv[0] < (sadb_ext_t *)(((uint8_t *)basehdr) + msgsize)) {
   1230      0      stevel 		/* Check for unknown headers. */
   1231      0      stevel 		if (extv[0]->sadb_ext_type == 0 ||
   1232      0      stevel 		    extv[0]->sadb_ext_type > SADB_EXT_MAX)
   1233      0      stevel 			return (KGE_UNK);
   1234      0      stevel 
   1235      0      stevel 		/*
   1236      0      stevel 		 * Check length.  Use uint64_t because extlen is in units
   1237      0      stevel 		 * of 64-bit words.  If length goes beyond the msgsize,
   1238      0      stevel 		 * return an error.  (Zero length also qualifies here.)
   1239      0      stevel 		 */
   1240      0      stevel 		if (extv[0]->sadb_ext_len == 0 ||
   1241      0      stevel 		    (void *)((uint64_t *)extv[0] + extv[0]->sadb_ext_len) >
   1242      0      stevel 		    (void *)((uint8_t *)basehdr + msgsize))
   1243      0      stevel 			return (KGE_LEN);
   1244      0      stevel 
   1245      0      stevel 		/* Check for redundant headers. */
   1246      0      stevel 		if (extv[extv[0]->sadb_ext_type] != NULL)
   1247      0      stevel 			return (KGE_DUP);
   1248      0      stevel 
   1249      0      stevel 		/*
   1250      0      stevel 		 * Reality check the extension if possible at the keysock
   1251      0      stevel 		 * level.
   1252      0      stevel 		 */
   1253   3448    dh155122 		if (!ext_check(extv[0], keystack))
   1254      0      stevel 			return (KGE_CHK);
   1255      0      stevel 
   1256      0      stevel 		/* If I make it here, assign the appropriate bin. */
   1257      0      stevel 		extv[extv[0]->sadb_ext_type] = extv[0];
   1258      0      stevel 
   1259      0      stevel 		/* Advance pointer (See above for uint64_t ptr reasoning.) */
   1260      0      stevel 		extv[0] = (sadb_ext_t *)
   1261      0      stevel 		    ((uint64_t *)extv[0] + extv[0]->sadb_ext_len);
   1262      0      stevel 	}
   1263      0      stevel 
   1264      0      stevel 	/* Everything's cool. */
   1265      0      stevel 
   1266      0      stevel 	/*
   1267      0      stevel 	 * If extv[0] == NULL, then there are no extension headers in this
   1268      0      stevel 	 * message.  Ensure that this is the case.
   1269      0      stevel 	 */
   1270      0      stevel 	if (extv[0] == (sadb_ext_t *)(basehdr + 1))
   1271      0      stevel 		extv[0] = NULL;
   1272      0      stevel 
   1273      0      stevel 	return (KGE_OK);
   1274      0      stevel }
   1275      0      stevel 
   1276      0      stevel /*
   1277      0      stevel  * qwriter() callback to handle flushes and dumps.  This routine will hold
   1278      0      stevel  * the inner perimeter.
   1279      0      stevel  */
   1280      0      stevel void
   1281      0      stevel keysock_do_flushdump(queue_t *q, mblk_t *mp)
   1282      0      stevel {
   1283      0      stevel 	int i, start, finish;
   1284      0      stevel 	mblk_t *mp1 = NULL;
   1285      0      stevel 	keysock_t *ks = (keysock_t *)q->q_ptr;
   1286      0      stevel 	sadb_ext_t *extv[SADB_EXT_MAX + 1];
   1287      0      stevel 	sadb_msg_t *samsg = (sadb_msg_t *)mp->b_rptr;
   1288   3448    dh155122 	keysock_stack_t	*keystack = ks->keysock_keystack;
   1289      0      stevel 
   1290      0      stevel 	/*
   1291      0      stevel 	 * I am guaranteed this will work.  I did the work in keysock_parse()
   1292      0      stevel 	 * already.
   1293      0      stevel 	 */
   1294   3448    dh155122 	(void) keysock_get_ext(extv, samsg, SADB_64TO8(samsg->sadb_msg_len),
   1295   3448    dh155122 	    keystack);
   1296      0      stevel 
   1297      0      stevel 	/*
   1298      0      stevel 	 * I hold the perimeter, therefore I don't need to use atomic ops.
   1299      0      stevel 	 */
   1300   3448    dh155122 	if (keystack->keystack_flushdump != 0) {
   1301      0      stevel 		/* XXX Should I instead use EBUSY? */
   1302      0      stevel 		/* XXX Or is there a way to queue these up? */
   1303      0      stevel 		keysock_error(ks, mp, ENOMEM, SADB_X_DIAGNOSTIC_NONE);
   1304      0      stevel 		return;
   1305      0      stevel 	}
   1306      0      stevel 
   1307      0      stevel 	if (samsg->sadb_msg_satype == SADB_SATYPE_UNSPEC) {
   1308      0      stevel 		start = 0;
   1309      0      stevel 		finish = KEYSOCK_MAX_CONSUMERS - 1;
   1310      0      stevel 	} else {
   1311      0      stevel 		start = samsg->sadb_msg_satype;
   1312      0      stevel 		finish = samsg->sadb_msg_satype;
   1313      0      stevel 	}
   1314      0      stevel 
   1315      0      stevel 	/*
   1316      0      stevel 	 * Fill up keysock_flushdump with the number of outstanding dumps
   1317      0      stevel 	 * and/or flushes.
   1318      0      stevel 	 */
   1319      0      stevel 
   1320   3448    dh155122 	keystack->keystack_flushdump_errno = 0;
   1321      0      stevel 
   1322      0      stevel 	/*
   1323      0      stevel 	 * Okay, I hold the perimeter.  Eventually keysock_flushdump will
   1324      0      stevel 	 * contain the number of consumers with outstanding flush operations.
   1325      0      stevel 	 *
   1326      0      stevel 	 * SO, here's the plan:
   1327      0      stevel 	 *	* For each relevant consumer (Might be one, might be all)
   1328      0      stevel 	 *		* Twiddle on the FLUSHING flag.
   1329      0      stevel 	 *		* Pass down the FLUSH/DUMP message.
   1330      0      stevel 	 *
   1331      0      stevel 	 * When I see upbound FLUSH/DUMP messages, I will decrement the
   1332      0      stevel 	 * keysock_flushdump.  When I decrement it to 0, I will pass the
   1333      0      stevel 	 * FLUSH/DUMP message back up to the PF_KEY sockets.  Because I will
   1334      0      stevel 	 * pass down the right SA type to the consumer (either its own, or
   1335      0      stevel 	 * that of UNSPEC), the right one will be reflected from each consumer,
   1336      0      stevel 	 * and accordingly back to the socket.
   1337      0      stevel 	 */
   1338      0      stevel 
   1339   3448    dh155122 	mutex_enter(&keystack->keystack_consumers_lock);
   1340      0      stevel 	for (i = start; i <= finish; i++) {
   1341   3448    dh155122 		if (keystack->keystack_consumers[i] != NULL) {
   1342      0      stevel 			mp1 = copymsg(mp);
   1343      0      stevel 			if (mp1 == NULL) {
   1344      0      stevel 				ks0dbg(("SADB_FLUSH copymsg() failed.\n"));
   1345      0      stevel 				/*
   1346      0      stevel 				 * Error?  And what about outstanding
   1347      0      stevel 				 * flushes?  Oh, yeah, they get sucked up and
   1348      0      stevel 				 * the counter is decremented.  Consumers
   1349      0      stevel 				 * (see keysock_passdown()) are guaranteed
   1350      0      stevel 				 * to deliver back a flush request, even if
   1351      0      stevel 				 * it's an error.
   1352      0      stevel 				 */
   1353      0      stevel 				keysock_error(ks, mp, ENOMEM,
   1354      0      stevel 				    SADB_X_DIAGNOSTIC_NONE);
   1355      0      stevel 				return;
   1356      0      stevel 			}
   1357      0      stevel 			/*
   1358      0      stevel 			 * Because my entry conditions are met above, the
   1359      0      stevel 			 * following assertion should hold true.
   1360      0      stevel 			 */
   1361   3448    dh155122 			mutex_enter(&keystack->keystack_consumers[i]->kc_lock);
   1362   3448    dh155122 			ASSERT((keystack->keystack_consumers[i]->kc_flags &
   1363   5240    nordmark 			    KC_FLUSHING) == 0);
   1364   3448    dh155122 			keystack->keystack_consumers[i]->kc_flags |=
   1365   3448    dh155122 			    KC_FLUSHING;
   1366   3448    dh155122 			mutex_exit(&(keystack->keystack_consumers[i]->kc_lock));
   1367      0      stevel 			/* Always increment the number of flushes... */
   1368   3448    dh155122 			keystack->keystack_flushdump++;
   1369      0      stevel 			/* Guaranteed to return a message. */
   1370      0      stevel 			keysock_passdown(ks, mp1, i, extv, B_TRUE);
   1371      0      stevel 		} else if (start == finish) {
   1372      0      stevel 			/*
   1373      0      stevel 			 * In case where start == finish, and there's no
   1374      0      stevel 			 * consumer, should we force an error?  Yes.
   1375      0      stevel 			 */
   1376   3448    dh155122 			mutex_exit(&keystack->keystack_consumers_lock);
   1377      0      stevel 			keysock_error(ks, mp, EINVAL,
   1378      0      stevel 			    SADB_X_DIAGNOSTIC_UNKNOWN_SATYPE);
   1379      0      stevel 			return;
   1380      0      stevel 		}
   1381      0      stevel 	}
   1382   3448    dh155122 	mutex_exit(&keystack->keystack_consumers_lock);
   1383      0      stevel 
   1384   3448    dh155122 	if (keystack->keystack_flushdump == 0) {
   1385      0      stevel 		/*
   1386      0      stevel 		 * There were no consumers at all for this message.
   1387      0      stevel 		 * XXX For now return ESRCH.
   1388      0      stevel 		 */
   1389      0      stevel 		keysock_error(ks, mp, ESRCH, SADB_X_DIAGNOSTIC_NO_SADBS);
   1390      0      stevel 	} else {
   1391      0      stevel 		/* Otherwise, free the original message. */
   1392      0      stevel 		freemsg(mp);
   1393      0      stevel 	}
   1394      0      stevel }
   1395      0      stevel 
   1396      0      stevel /*
   1397      0      stevel  * Get the right diagnostic for a duplicate.  Should probably use a static
   1398      0      stevel  * table lookup.
   1399      0      stevel  */
   1400      0      stevel int
   1401      0      stevel keysock_duplicate(int ext_type)
   1402      0      stevel {
   1403      0      stevel 	int rc = 0;
   1404      0      stevel 
   1405      0      stevel 	switch (ext_type) {
   1406      0      stevel 	case SADB_EXT_ADDRESS_SRC:
   1407      0      stevel 		rc = SADB_X_DIAGNOSTIC_DUPLICATE_SRC;
   1408      0      stevel 		break;
   1409      0      stevel 	case SADB_EXT_ADDRESS_DST:
   1410      0      stevel 		rc = SADB_X_DIAGNOSTIC_DUPLICATE_DST;
   1411      0      stevel 		break;
   1412   3055      danmcd 	case SADB_X_EXT_ADDRESS_INNER_SRC:
   1413   3055      danmcd 		rc = SADB_X_DIAGNOSTIC_DUPLICATE_INNER_SRC;
   1414   3055      danmcd 		break;
   1415   3055      danmcd 	case SADB_X_EXT_ADDRESS_INNER_DST:
   1416   3055      danmcd 		rc = SADB_X_DIAGNOSTIC_DUPLICATE_INNER_DST;
   1417   3055      danmcd 		break;
   1418      0      stevel 	case SADB_EXT_SA:
   1419      0      stevel 		rc = SADB_X_DIAGNOSTIC_DUPLICATE_SA;
   1420      0      stevel 		break;
   1421      0      stevel 	case SADB_EXT_SPIRANGE:
   1422      0      stevel 		rc = SADB_X_DIAGNOSTIC_DUPLICATE_RANGE;
   1423      0      stevel 		break;
   1424      0      stevel 	case SADB_EXT_KEY_AUTH:
   1425      0      stevel 		rc = SADB_X_DIAGNOSTIC_DUPLICATE_AKEY;
   1426      0      stevel 		break;
   1427      0      stevel 	case SADB_EXT_KEY_ENCRYPT:
   1428      0      stevel 		rc = SADB_X_DIAGNOSTIC_DUPLICATE_EKEY;
   1429      0      stevel 		break;
   1430      0      stevel 	}
   1431      0      stevel 	return (rc);
   1432      0      stevel }
   1433      0      stevel 
   1434      0      stevel /*
   1435      0      stevel  * Get the right diagnostic for a reality check failure.  Should probably use
   1436      0      stevel  * a static table lookup.
   1437      0      stevel  */
   1438      0      stevel int
   1439      0      stevel keysock_malformed(int ext_type)
   1440      0      stevel {
   1441      0      stevel 	int rc = 0;
   1442      0      stevel 
   1443      0      stevel 	switch (ext_type) {
   1444      0      stevel 	case SADB_EXT_ADDRESS_SRC:
   1445      0      stevel 		rc = SADB_X_DIAGNOSTIC_MALFORMED_SRC;
   1446      0      stevel 		break;
   1447      0      stevel 	case SADB_EXT_ADDRESS_DST:
   1448      0      stevel 		rc = SADB_X_DIAGNOSTIC_MALFORMED_DST;
   1449   3055      danmcd 		break;
   1450   3055      danmcd 	case SADB_X_EXT_ADDRESS_INNER_SRC:
   1451   3055      danmcd 		rc = SADB_X_DIAGNOSTIC_MALFORMED_INNER_SRC;
   1452   3055      danmcd 		break;
   1453   3055      danmcd 	case SADB_X_EXT_ADDRESS_INNER_DST:
   1454   3055      danmcd 		rc = SADB_X_DIAGNOSTIC_MALFORMED_INNER_DST;
   1455      0      stevel 		break;
   1456      0      stevel 	case SADB_EXT_SA:
   1457      0      stevel 		rc = SADB_X_DIAGNOSTIC_MALFORMED_SA;
   1458      0      stevel 		break;
   1459      0      stevel 	case SADB_EXT_SPIRANGE:
   1460      0      stevel 		rc = SADB_X_DIAGNOSTIC_MALFORMED_RANGE;
   1461      0      stevel 		break;
   1462      0      stevel 	case SADB_EXT_KEY_AUTH:
   1463      0      stevel 		rc = SADB_X_DIAGNOSTIC_MALFORMED_AKEY;
   1464      0      stevel 		break;
   1465      0      stevel 	case SADB_EXT_KEY_ENCRYPT:
   1466      0      stevel 		rc = SADB_X_DIAGNOSTIC_MALFORMED_EKEY;
   1467      0      stevel 		break;
   1468      0      stevel 	}
   1469      0      stevel 	return (rc);
   1470      0      stevel }
   1471      0      stevel 
   1472      0      stevel /*
   1473      0      stevel  * Keysock massaging of an inverse ACQUIRE.  Consult policy,
   1474      0      stevel  * and construct an appropriate response.
   1475      0      stevel  */
   1476      0      stevel static void
   1477      0      stevel keysock_inverse_acquire(mblk_t *mp, sadb_msg_t *samsg, sadb_ext_t *extv[],
   1478      0      stevel     keysock_t *ks)
   1479      0      stevel {
   1480      0      stevel 	mblk_t *reply_mp;
   1481   3448    dh155122 	keysock_stack_t	*keystack = ks->keysock_keystack;
   1482      0      stevel 
   1483      0      stevel 	/*
   1484      0      stevel 	 * Reality check things...
   1485      0      stevel 	 */
   1486      0      stevel 	if (extv[SADB_EXT_ADDRESS_SRC] == NULL) {
   1487      0      stevel 		keysock_error(ks, mp, EINVAL, SADB_X_DIAGNOSTIC_MISSING_SRC);
   1488      0      stevel 		return;
   1489      0      stevel 	}
   1490      0      stevel 	if (extv[SADB_EXT_ADDRESS_DST] == NULL) {
   1491      0      stevel 		keysock_error(ks, mp, EINVAL, SADB_X_DIAGNOSTIC_MISSING_DST);
   1492   3055      danmcd 		return;
   1493   3055      danmcd 	}
   1494   3055      danmcd 
   1495   3055      danmcd 	if (extv[SADB_X_EXT_ADDRESS_INNER_SRC] != NULL &&
   1496   3055      danmcd 	    extv[SADB_X_EXT_ADDRESS_INNER_DST] == NULL) {
   1497   3055      danmcd 		keysock_error(ks, mp, EINVAL,
   1498   3055      danmcd 		    SADB_X_DIAGNOSTIC_MISSING_INNER_DST);
   1499   3055      danmcd 		return;
   1500   3055      danmcd 	}
   1501   3055      danmcd 
   1502   3055      danmcd 	if (extv[SADB_X_EXT_ADDRESS_INNER_SRC] == NULL &&
   1503   3055      danmcd 	    extv[SADB_X_EXT_ADDRESS_INNER_DST] != NULL) {
   1504   3055      danmcd 		keysock_error(ks, mp, EINVAL,
   1505   3055      danmcd 		    SADB_X_DIAGNOSTIC_MISSING_INNER_SRC);
   1506   3055      danmcd 		return;
   1507      0      stevel 	}
   1508      0      stevel 
   1509   3448    dh155122 	reply_mp = ipsec_construct_inverse_acquire(samsg, extv,
   1510   3448    dh155122 	    keystack->keystack_netstack);
   1511      0      stevel 
   1512      0      stevel 	if (reply_mp != NULL) {
   1513      0      stevel 		freemsg(mp);
   1514      0      stevel 		keysock_passup(reply_mp, (sadb_msg_t *)reply_mp->b_rptr,
   1515   3448    dh155122 		    ks->keysock_serial, NULL, B_FALSE, keystack);
   1516      0      stevel 	} else {
   1517      0      stevel 		keysock_error(ks, mp, samsg->sadb_msg_errno,
   1518      0      stevel 		    samsg->sadb_x_msg_diagnostic);
   1519      0      stevel 	}
   1520      0      stevel }
   1521      0      stevel 
   1522      0      stevel /*
   1523      0      stevel  * Spew an extended REGISTER down to the relevant consumers.
   1524      0      stevel  */
   1525      0      stevel static void
   1526      0      stevel keysock_extended_register(keysock_t *ks, mblk_t *mp, sadb_ext_t *extv[])
   1527      0      stevel {
   1528      0      stevel 	sadb_x_ereg_t *ereg = (sadb_x_ereg_t *)extv[SADB_X_EXT_EREG];
   1529      0      stevel 	uint8_t *satypes, *fencepost;
   1530      0      stevel 	mblk_t *downmp;
   1531      0      stevel 	sadb_ext_t *downextv[SADB_EXT_MAX + 1];
   1532   3448    dh155122 	keysock_stack_t	*keystack = ks->keysock_keystack;
   1533      0      stevel 
   1534      0      stevel 	if (ks->keysock_registered[0] != 0 || ks->keysock_registered[1] != 0 ||
   1535      0      stevel 	    ks->keysock_registered[2] != 0 || ks->keysock_registered[3] != 0) {
   1536      0      stevel 		keysock_error(ks, mp, EBUSY, 0);
   1537      0      stevel 	}
   1538      0      stevel 
   1539      0      stevel 	ks->keysock_flags |= KEYSOCK_EXTENDED;
   1540      0      stevel 	if (ereg == NULL) {
   1541      0      stevel 		keysock_error(ks, mp, EINVAL, SADB_X_DIAGNOSTIC_SATYPE_NEEDED);
   1542      0      stevel 	} else {
   1543      0      stevel 		ASSERT(mp->b_rptr + msgdsize(mp) == mp->b_wptr);
   1544      0      stevel 		fencepost = (uint8_t *)mp->b_wptr;
   1545      0      stevel 		satypes = ereg->sadb_x_ereg_satypes;
   1546      0      stevel 		while (*satypes != SADB_SATYPE_UNSPEC && satypes != fencepost) {
   1547      0      stevel 			downmp = copymsg(mp);
   1548      0      stevel 			if (downmp == NULL) {
   1549      0      stevel 				keysock_error(ks, mp, ENOMEM, 0);
   1550      0      stevel 				return;
   1551      0      stevel 			}
   1552      0      stevel 			/*
   1553      0      stevel 			 * Since we've made it here, keysock_get_ext will work!
   1554      0      stevel 			 */
   1555      0      stevel 			(void) keysock_get_ext(downextv,
   1556   3448    dh155122 			    (sadb_msg_t *)downmp->b_rptr, msgdsize(downmp),
   1557   3448    dh155122 			    keystack);
   1558      0      stevel 			keysock_passdown(ks, downmp, *satypes, downextv,
   1559      0      stevel 			    B_FALSE);
   1560      0      stevel 			++satypes;
   1561      0      stevel 		}
   1562      0      stevel 		freemsg(mp);
   1563      0      stevel 	}
   1564      0      stevel 
   1565      0      stevel 	/*
   1566      0      stevel 	 * Set global to indicate we prefer an extended ACQUIRE.
   1567      0      stevel 	 */
   1568   3448    dh155122 	atomic_add_32(&keystack->keystack_num_extended, 1);
   1569      0      stevel }
   1570      0      stevel 
   1571   7749  Thejaswini static void
   1572   7749  Thejaswini keysock_delpair_all(keysock_t *ks, mblk_t *mp, sadb_ext_t *extv[])
   1573   7749  Thejaswini {
   1574   7749  Thejaswini 	int i, start, finish;
   1575   7749  Thejaswini 	mblk_t *mp1 = NULL;
   1576   7749  Thejaswini 	keysock_stack_t *keystack = ks->keysock_keystack;
   1577   7749  Thejaswini 
   1578   7749  Thejaswini 	start = 0;
   1579   7749  Thejaswini 	finish = KEYSOCK_MAX_CONSUMERS - 1;
   1580   7749  Thejaswini 
   1581   7749  Thejaswini 	for (i = start; i <= finish; i++) {
   1582   7749  Thejaswini 		if (keystack->keystack_consumers[i] != NULL) {
   1583   7749  Thejaswini 			mp1 = copymsg(mp);
   1584   7749  Thejaswini 			if (mp1 == NULL) {
   1585   7749  Thejaswini 				keysock_error(ks, mp, ENOMEM,
   1586   7749  Thejaswini 				    SADB_X_DIAGNOSTIC_NONE);
   1587   7749  Thejaswini 				return;
   1588   7749  Thejaswini 			}
   1589   7749  Thejaswini 			keysock_passdown(ks, mp1, i, extv, B_FALSE);
   1590   7749  Thejaswini 		}
   1591   7749  Thejaswini 	}
   1592   7749  Thejaswini }
   1593   7749  Thejaswini 
   1594      0      stevel /*
   1595      0      stevel  * Handle PF_KEY messages.
   1596      0      stevel  */
   1597      0      stevel static void
   1598      0      stevel keysock_parse(queue_t *q, mblk_t *mp)
   1599      0      stevel {
   1600      0      stevel 	sadb_msg_t *samsg;
   1601      0      stevel 	sadb_ext_t *extv[SADB_EXT_MAX + 1];
   1602      0      stevel 	keysock_t *ks = (keysock_t *)q->q_ptr;
   1603      0      stevel 	uint_t msgsize;
   1604      0      stevel 	uint8_t satype;
   1605   3448    dh155122 	keysock_stack_t	*keystack = ks->keysock_keystack;
   1606      0      stevel 
   1607      0      stevel 	/* Make sure I'm a PF_KEY socket.  (i.e. nothing's below me) */
   1608      0      stevel 	ASSERT(WR(q)->q_next == NULL);
   1609      0      stevel 
   1610      0      stevel 	samsg = (sadb_msg_t *)mp->b_rptr;
   1611   3448    dh155122 	ks2dbg(keystack, ("Received possible PF_KEY message, type %d.\n",
   1612      0      stevel 	    samsg->sadb_msg_type));
   1613      0      stevel 
   1614      0      stevel 	msgsize = SADB_64TO8(samsg->sadb_msg_len);
   1615      0      stevel 
   1616      0      stevel 	if (msgdsize(mp) != msgsize) {
   1617      0      stevel 		/*
   1618      0      stevel 		 * Message len incorrect w.r.t. actual size.  Send an error
   1619      0      stevel 		 * (EMSGSIZE).	It may be necessary to massage things a
   1620      0      stevel 		 * bit.	 For example, if the sadb_msg_type is hosed,
   1621      0      stevel 		 * I need to set it to SADB_RESERVED to get delivery to
   1622      0      stevel 		 * do the right thing.	Then again, maybe just letting
   1623      0      stevel 		 * the error delivery do the right thing.
   1624      0      stevel 		 */
   1625   3448    dh155122 		ks2dbg(keystack,
   1626   3448    dh155122 		    ("mblk (%lu) and base (%d) message sizes don't jibe.\n",
   1627      0      stevel 		    msgdsize(mp), msgsize));
   1628      0      stevel 		keysock_error(ks, mp, EMSGSIZE, SADB_X_DIAGNOSTIC_NONE);
   1629      0      stevel 		return;
   1630      0      stevel 	}
   1631      0      stevel 
   1632      0      stevel 	if (msgsize > (uint_t)(mp->b_wptr - mp->b_rptr)) {
   1633      0      stevel 		/* Get all message into one mblk. */
   1634      0      stevel 		if (pullupmsg(mp, -1) == 0) {
   1635      0      stevel 			/*
   1636      0      stevel 			 * Something screwy happened.
   1637      0      stevel 			 */
   1638   3448    dh155122 			ks3dbg(keystack,
   1639   3448    dh155122 			    ("keysock_parse: pullupmsg() failed.\n"));
   1640      0      stevel 			return;
   1641      0      stevel 		} else {
   1642      0      stevel 			samsg = (sadb_msg_t *)mp->b_rptr;
   1643      0      stevel 		}
   1644      0      stevel 	}
   1645      0      stevel 
   1646   3448    dh155122 	switch (keysock_get_ext(extv, samsg, msgsize, keystack)) {
   1647      0      stevel 	case KGE_DUP:
   1648      0      stevel 		/* Handle duplicate extension. */
   1649   3448    dh155122 		ks1dbg(keystack, ("Got duplicate extension of type %d.\n",
   1650      0      stevel 		    extv[0]->sadb_ext_type));
   1651      0      stevel 		keysock_error(ks, mp, EINVAL,
   1652      0      stevel 		    keysock_duplicate(extv[0]->sadb_ext_type));
   1653      0      stevel 		return;
   1654      0      stevel 	case KGE_UNK:
   1655      0      stevel 		/* Handle unknown extension. */
   1656   3448    dh155122 		ks1dbg(keystack, ("Got unknown extension of type %d.\n",
   1657      0      stevel 		    extv[0]->sadb_ext_type));
   1658      0      stevel 		keysock_error(ks, mp, EINVAL, SADB_X_DIAGNOSTIC_UNKNOWN_EXT);
   1659      0      stevel 		return;
   1660      0      stevel 	case KGE_LEN:
   1661      0      stevel 		/* Length error. */
   1662   3448    dh155122 		ks1dbg(keystack,
   1663   3448    dh155122 		    ("Length %d on extension type %d overrun or 0.\n",
   1664      0      stevel 		    extv[0]->sadb_ext_len, extv[0]->sadb_ext_type));
   1665      0      stevel 		keysock_error(ks, mp, EINVAL, SADB_X_DIAGNOSTIC_BAD_EXTLEN);
   1666      0      stevel 		return;
   1667      0      stevel 	case KGE_CHK:
   1668      0      stevel 		/* Reality check failed. */
   1669   3448    dh155122 		ks1dbg(keystack,
   1670   3448    dh155122 		    ("Reality check failed on extension type %d.\n",
   1671      0      stevel 		    extv[0]->sadb_ext_type));
   1672      0      stevel 		keysock_error(ks, mp, EINVAL,
   1673      0      stevel 		    keysock_malformed(extv[0]->sadb_ext_type));
   1674      0      stevel 		return;
   1675      0      stevel 	default:
   1676      0      stevel 		/* Default case is no errors. */
   1677      0      stevel 		break;
   1678      0      stevel 	}
   1679      0      stevel 
   1680      0      stevel 	switch (samsg->sadb_msg_type) {
   1681      0      stevel 	case SADB_REGISTER:
   1682      0      stevel 		/*
   1683      0      stevel 		 * There's a semantic weirdness in that a message OTHER than
   1684      0      stevel 		 * the return REGISTER message may be passed up if I set the
   1685      0      stevel 		 * registered bit BEFORE I pass it down.
   1686      0      stevel 		 *
   1687      0      stevel 		 * SOOOO, I'll not twiddle any registered bits until I see
   1688      0      stevel 		 * the upbound REGISTER (with a serial number in it).
   1689      0      stevel 		 */
   1690      0      stevel 		if (samsg->sadb_msg_satype == SADB_SATYPE_UNSPEC) {
   1691      0      stevel 			/* Handle extended register here. */
   1692      0      stevel 			keysock_extended_register(ks, mp, extv);
   1693      0      stevel 			return;
   1694      0      stevel 		} else if (ks->keysock_flags & KEYSOCK_EXTENDED) {
   1695      0      stevel 			keysock_error(ks, mp, EBUSY, 0);
   1696      0      stevel 			return;
   1697      0      stevel 		}
   1698      0      stevel 		/* FALLTHRU */
   1699      0      stevel 	case SADB_GETSPI:
   1700      0      stevel 	case SADB_ADD:
   1701      0      stevel 	case SADB_UPDATE:
   1702   6668     markfen 	case SADB_X_UPDATEPAIR:
   1703      0      stevel 	case SADB_DELETE:
   1704   6668     markfen 	case SADB_X_DELPAIR:
   1705      0      stevel 	case SADB_GET:
   1706      0      stevel 		/*
   1707      0      stevel 		 * Pass down to appropriate consumer.
   1708      0      stevel 		 */
   1709      0      stevel 		if (samsg->sadb_msg_satype != SADB_SATYPE_UNSPEC)
   1710      0      stevel 			keysock_passdown(ks, mp, samsg->sadb_msg_satype, extv,
   1711      0      stevel 			    B_FALSE);
   1712      0      stevel 		else keysock_error(ks, mp, EINVAL,
   1713      0      stevel 		    SADB_X_DIAGNOSTIC_SATYPE_NEEDED);
   1714      0      stevel 		return;
   1715   7749  Thejaswini 	case SADB_X_DELPAIR_STATE:
   1716   7749  Thejaswini 		if (samsg->sadb_msg_satype == SADB_SATYPE_UNSPEC) {
   1717   7749  Thejaswini 			keysock_delpair_all(ks, mp, extv);
   1718   7749  Thejaswini 		} else {
   1719   7749  Thejaswini 			keysock_passdown(ks, mp, samsg->sadb_msg_satype, extv,
   1720   7749  Thejaswini 			    B_FALSE);
   1721   7749  Thejaswini 		}
   1722   7749  Thejaswini 		return;
   1723      0      stevel 	case SADB_ACQUIRE:
   1724      0      stevel 		/*
   1725      0      stevel 		 * If I _receive_ an acquire, this means I should spread it
   1726      0      stevel 		 * out to registered sockets.  Unless there's an errno...
   1727      0      stevel 		 *
   1728      0      stevel 		 * Need ADDRESS, may have ID, SENS, and PROP, unless errno,
   1729      0      stevel 		 * in which case there should be NO extensions.
   1730      0      stevel 		 *
   1731      0      stevel 		 * Return to registered.
   1732      0      stevel 		 */
   1733      0      stevel 		if (samsg->sadb_msg_errno != 0) {
   1734      0      stevel 			satype = samsg->sadb_msg_satype;
   1735      0      stevel 			if (satype == SADB_SATYPE_UNSPEC) {
   1736      0      stevel 				if (!(ks->keysock_flags & KEYSOCK_EXTENDED)) {
   1737      0      stevel 					keysock_error(ks, mp, EINVAL,
   1738      0      stevel 					    SADB_X_DIAGNOSTIC_SATYPE_NEEDED);
   1739      0      stevel 					return;
   1740      0      stevel 				}
   1741      0      stevel 				/*
   1742      0      stevel 				 * Reassign satype based on the first
   1743      0      stevel 				 * flags that KEYSOCK_SETREG says.
   1744      0      stevel 				 */
   1745      0      stevel 				while (satype <= SADB_SATYPE_MAX) {
   1746      0      stevel 					if (KEYSOCK_ISREG(ks, satype))
   1747      0      stevel 						break;
   1748      0      stevel 					satype++;
   1749      0      stevel 				}
   1750      0      stevel 				if (satype > SADB_SATYPE_MAX) {
   1751      0      stevel 					keysock_error(ks, mp, EBUSY, 0);
   1752      0      stevel 					return;
   1753      0      stevel 				}
   1754      0      stevel 			}
   1755      0      stevel 			keysock_passdown(ks, mp, satype, extv, B_FALSE);
   1756      0      stevel 		} else {
   1757   3448    dh155122 			if (samsg->sadb_msg_satype == SADB_SATYPE_UNSPEC) {
   1758      0      stevel 				keysock_error(ks, mp, EINVAL,
   1759      0      stevel 				    SADB_X_DIAGNOSTIC_SATYPE_NEEDED);
   1760   3448    dh155122 			} else {
   1761   3448    dh155122 				keysock_passup(mp, samsg, 0, NULL, B_FALSE,
   1762   3448    dh155122 				    keystack);
   1763   3448    dh155122 			}
   1764      0      stevel 		}
   1765      0      stevel 		return;
   1766      0      stevel 	case SADB_EXPIRE:
   1767      0      stevel 		/*
   1768      0      stevel 		 * If someone sends this in, then send out to all senders.
   1769      0      stevel 		 * (Save maybe ESP or AH, I have to be careful here.)
   1770      0      stevel 		 *
   1771      0      stevel 		 * Need ADDRESS, may have ID and SENS.
   1772      0      stevel 		 *
   1773      0      stevel 		 * XXX for now this is unsupported.
   1774      0      stevel 		 */
   1775      0      stevel 		break;
   1776      0      stevel 	case SADB_FLUSH:
   1777      0      stevel 		/*
   1778   7749  Thejaswini 		 * Nuke all SAs.
   1779      0      stevel 		 *
   1780      0      stevel 		 * No extensions at all.  Return to all listeners.
   1781      0      stevel 		 *
   1782      0      stevel 		 * Question:	Should I hold a lock here to prevent
   1783      0      stevel 		 *		additions/deletions while flushing?
   1784      0      stevel 		 * Answer:	No.  (See keysock_passdown() for details.)
   1785      0      stevel 		 */
   1786      0      stevel 		if (extv[0] != NULL) {
   1787      0      stevel 			/*
   1788   7749  Thejaswini 			 * FLUSH messages shouldn't have extensions.
   1789      0      stevel 			 * Return EINVAL.
   1790      0      stevel 			 */
   1791   3448    dh155122 			ks2dbg(keystack, ("FLUSH message with extension.\n"));
   1792      0      stevel 			keysock_error(ks, mp, EINVAL, SADB_X_DIAGNOSTIC_NO_EXT);
   1793      0      stevel 			return;
   1794      0      stevel 		}
   1795      0      stevel 
   1796      0      stevel 		/* Passing down of DUMP/FLUSH messages are special. */
   1797   7749  Thejaswini 		qwriter(q, mp, keysock_do_flushdump, PERIM_INNER);
   1798   7749  Thejaswini 		return;
   1799   7749  Thejaswini 	case SADB_DUMP:	 /* not used by normal applications */
   1800   7749  Thejaswini 		if ((extv[0] != NULL) &&
   1801   7749  Thejaswini 		    ((msgsize >
   1802   7749  Thejaswini 		    (sizeof (sadb_msg_t) + sizeof (sadb_x_edump_t))) ||
   1803   7749  Thejaswini 		    (extv[SADB_X_EXT_EDUMP] == NULL))) {
   1804   7749  Thejaswini 				keysock_error(ks, mp, EINVAL,
   1805   7749  Thejaswini 				    SADB_X_DIAGNOSTIC_NO_EXT);
   1806   7749  Thejaswini 				return;
   1807   7749  Thejaswini 		}
   1808      0      stevel 		qwriter(q, mp, keysock_do_flushdump, PERIM_INNER);
   1809      0      stevel 		return;
   1810      0      stevel 	case SADB_X_PROMISC:
   1811      0      stevel 		/*
   1812      0      stevel 		 * Promiscuous processing message.
   1813      0      stevel 		 */
   1814      0      stevel 		if (samsg->sadb_msg_satype == 0)
   1815      0      stevel 			ks->keysock_flags &= ~KEYSOCK_PROMISC;
   1816      0      stevel 		else
   1817      0      stevel 			ks->keysock_flags |= KEYSOCK_PROMISC;
   1818   3448    dh155122 		keysock_passup(mp, samsg, ks->keysock_serial, NULL, B_FALSE,
   1819   3448    dh155122 		    keystack);
   1820      0      stevel 		return;
   1821      0      stevel 	case SADB_X_INVERSE_ACQUIRE:
   1822      0      stevel 		keysock_inverse_acquire(mp, samsg, extv, ks);
   1823      0      stevel 		return;
   1824      0      stevel 	default:
   1825   3448    dh155122 		ks2dbg(keystack, ("Got unknown message type %d.\n",
   1826      0      stevel 		    samsg->sadb_msg_type));
   1827      0      stevel 		keysock_error(ks, mp, EINVAL, SADB_X_DIAGNOSTIC_UNKNOWN_MSG);
   1828      0      stevel 		return;
   1829      0      stevel 	}
   1830      0      stevel 
   1831      0      stevel 	/* As a placeholder... */
   1832      0      stevel 	ks0dbg(("keysock_parse():  Hit EOPNOTSUPP\n"));
   1833      0      stevel 	keysock_error(ks, mp, EOPNOTSUPP, SADB_X_DIAGNOSTIC_NONE);
   1834      0      stevel }
   1835      0      stevel 
   1836      0      stevel /*
   1837      0      stevel  * wput routing for PF_KEY/keysock/whatever.  Unlike the routing socket,
   1838      0      stevel  * I don't convert to ioctl()'s for IP.  I am the end-all driver as far
   1839      0      stevel  * as PF_KEY sockets are concerned.  I do some conversion, but not as much
   1840      0      stevel  * as IP/rts does.
   1841      0      stevel  */
   1842      0      stevel static void
   1843      0      stevel keysock_wput(queue_t *q, mblk_t *mp)
   1844      0      stevel {
   1845      0      stevel 	uchar_t *rptr = mp->b_rptr;
   1846      0      stevel 	mblk_t *mp1;
   1847   3448    dh155122 	keysock_t *ks;
   1848   3448    dh155122 	keysock_stack_t	*keystack;
   1849      0      stevel 
   1850      0      stevel 	if (WR(q)->q_next) {
   1851      0      stevel 		keysock_consumer_t *kc = (keysock_consumer_t *)q->q_ptr;
   1852   3448    dh155122 		keystack = kc->kc_keystack;
   1853   3448    dh155122 
   1854   3448    dh155122 		ks3dbg(keystack, ("In keysock_wput\n"));
   1855      0      stevel 
   1856      0      stevel 		/*
   1857      0      stevel 		 * We shouldn't get writes on a consumer instance.
   1858      0      stevel 		 * But for now, just passthru.
   1859      0      stevel 		 */
   1860   3448    dh155122 		ks1dbg(keystack, ("Huh?  wput for an consumer instance (%d)?\n",
   1861      0      stevel 		    kc->kc_sa_type));
   1862      0      stevel 		putnext(q, mp);
   1863      0      stevel 		return;
   1864      0      stevel 	}
   1865   3448    dh155122 	ks = (keysock_t *)q->q_ptr;
   1866   3448    dh155122 	keystack = ks->keysock_keystack;
   1867   3448    dh155122 
   1868   3448    dh155122 	ks3dbg(keystack, ("In keysock_wput\n"));
   1869      0      stevel 
   1870      0      stevel 	switch (mp->b_datap->db_type) {
   1871      0      stevel 	case M_DATA:
   1872      0      stevel 		/*
   1873      0      stevel 		 * Silently discard.
   1874      0      stevel 		 */
   1875   3448    dh155122 		ks2dbg(keystack, ("raw M_DATA in keysock.\n"));
   1876      0      stevel 		freemsg(mp);
   1877      0      stevel 		return;
   1878      0      stevel 	case M_PROTO:
   1879      0      stevel 	case M_PCPROTO:
   1880      0      stevel 		if ((mp->b_wptr - rptr) >= sizeof (struct T_data_req)) {
   1881      0      stevel 			if (((union T_primitives *)rptr)->type == T_DATA_REQ) {
   1882      0      stevel 				if ((mp1 = mp->b_cont) == NULL) {
   1883      0      stevel 					/* No data after T_DATA_REQ. */
   1884   3448    dh155122 					ks2dbg(keystack,
   1885   3448    dh155122 					    ("No data after DATA_REQ.\n"));
   1886      0      stevel 					freemsg(mp);
   1887      0      stevel 					return;
   1888      0      stevel 				}
   1889      0      stevel 				freeb(mp);
   1890      0      stevel 				mp = mp1;
   1891   3448    dh155122 				ks2dbg(keystack, ("T_DATA_REQ\n"));
   1892      0      stevel 				break;	/* Out of switch. */
   1893      0      stevel 			}
   1894      0      stevel 		}
   1895      0      stevel 		/* FALLTHRU */
   1896      0      stevel 	default:
   1897   3448    dh155122 		ks3dbg(keystack, ("In default wput case (%d %d).\n",
   1898      0      stevel 		    mp->b_datap->db_type, ((union T_primitives *)rptr)->type));
   1899      0      stevel 		keysock_wput_other(q, mp);
   1900      0      stevel 		return;
   1901      0      stevel 	}
   1902      0      stevel 
   1903      0      stevel 	/* I now have a PF_KEY message in an M_DATA block, pointed to by mp. */
   1904      0      stevel 	keysock_parse(q, mp);
   1905      0      stevel }
   1906      0      stevel 
   1907      0      stevel /* BELOW THIS LINE ARE ROUTINES INCLUDING AND RELATED TO keysock_rput(). */
   1908      0      stevel 
   1909      0      stevel /*
   1910      0      stevel  * Called upon receipt of a KEYSOCK_HELLO_ACK to set up the appropriate
   1911      0      stevel  * state vectors.
   1912      0      stevel  */
   1913      0      stevel static void
   1914      0      stevel keysock_link_consumer(uint8_t satype, keysock_consumer_t *kc)
   1915      0      stevel {
   1916      0      stevel 	keysock_t *ks;
   1917   3448    dh155122 	keysock_stack_t	*keystack = kc->kc_keystack;
   1918      0      stevel 
   1919   3448    dh155122 	mutex_enter(&keystack->keystack_consumers_lock);
   1920      0      stevel 	mutex_enter(&kc->kc_lock);
   1921   3448    dh155122 	if (keystack->keystack_consumers[satype] != NULL) {
   1922      0      stevel 		ks0dbg((
   1923      0      stevel 		    "Hmmmm, someone closed %d before the HELLO_ACK happened.\n",
   1924      0      stevel 		    satype));
   1925      0      stevel 		/*
   1926      0      stevel 		 * Perhaps updating the new below-me consumer with what I have
   1927      0      stevel 		 * so far would work too?
   1928      0      stevel 		 */
   1929      0      stevel 		mutex_exit(&kc->kc_lock);
   1930   3448    dh155122 		mutex_exit(&keystack->keystack_consumers_lock);
   1931      0      stevel 	} else {
   1932      0      stevel 		/* Add new below-me consumer. */
   1933   3448    dh155122 		keystack->keystack_consumers[satype] = kc;
   1934      0      stevel 
   1935      0      stevel 		kc->kc_flags = 0;
   1936      0      stevel 		kc->kc_sa_type = satype;
   1937      0      stevel 		mutex_exit(&kc->kc_lock);
   1938   3448    dh155122 		mutex_exit(&keystack->keystack_consumers_lock);
   1939      0      stevel 
   1940      0      stevel 		/* Scan the keysock list. */
   1941   3448    dh155122 		mutex_enter(&keystack->keystack_list_lock);
   1942   3448    dh155122 		for (ks = keystack->keystack_list; ks != NULL;
   1943   3448    dh155122 		    ks = ks->keysock_next) {
   1944      0      stevel 			if (KEYSOCK_ISREG(ks, satype)) {
   1945      0      stevel 				/*
   1946      0      stevel 				 * XXX Perhaps send an SADB_REGISTER down on
   1947      0      stevel 				 * the socket's behalf.
   1948      0      stevel 				 */
   1949   3448    dh155122 				ks1dbg(keystack,
   1950   3448    dh155122 				    ("Socket %u registered already for "
   1951      0      stevel 				    "new consumer.\n", ks->keysock_serial));
   1952      0      stevel 			}
   1953      0      stevel 		}
   1954   3448    dh155122 		mutex_exit(&keystack->keystack_list_lock);
   1955      0      stevel 	}
   1956      0      stevel }
   1957      0      stevel 
   1958      0      stevel /*
   1959      0      stevel  * Generate a KEYSOCK_OUT_ERR message for my consumer.
   1960      0      stevel  */
   1961      0      stevel static void
   1962      0      stevel keysock_out_err(keysock_consumer_t *kc, int ks_errno, mblk_t *mp)
   1963      0      stevel {
   1964      0      stevel 	keysock_out_err_t *kse;
   1965      0      stevel 	mblk_t *imp;
   1966   3448    dh155122 	keysock_stack_t	*keystack = kc->kc_keystack;
   1967      0      stevel 
   1968      0      stevel 	imp = allocb(sizeof (ipsec_info_t), BPRI_HI);
   1969      0      stevel 	if (imp == NULL) {
   1970   3448    dh155122 		ks1dbg(keystack, ("keysock_out_err:  Can't alloc message.\n"));
   1971      0      stevel 		return;
   1972      0      stevel 	}
   1973      0      stevel 
   1974      0      stevel 	imp->b_datap->db_type = M_CTL;
   1975      0      stevel 	imp->b_wptr += sizeof (ipsec_info_t);
   1976      0      stevel 
   1977      0      stevel 	kse = (keysock_out_err_t *)imp->b_rptr;
   1978      0      stevel 	imp->b_cont = mp;
   1979      0      stevel 	kse->ks_err_type = KEYSOCK_OUT_ERR;
   1980      0      stevel 	kse->ks_err_len = sizeof (*kse);
   1981      0      stevel 	/* Is serial necessary? */
   1982      0      stevel 	kse->ks_err_serial = 0;
   1983      0      stevel 	kse->ks_err_errno = ks_errno;
   1984      0      stevel 
   1985      0      stevel 	/*
   1986      0      stevel 	 * XXX What else do I need to do here w.r.t. information
   1987      0      stevel 	 * to tell the consumer what caused this error?
   1988      0      stevel 	 *
   1989      0      stevel 	 * I believe the answer is the PF_KEY ACQUIRE (or other) message
   1990      0      stevel 	 * attached in mp, which is appended at the end.  I believe the
   1991      0      stevel 	 * db_ref won't matter here, because the PF_KEY message is only read
   1992      0      stevel 	 * for KEYSOCK_OUT_ERR.
   1993      0      stevel 	 */
   1994      0      stevel 
   1995      0      stevel 	putnext(kc->kc_wq, imp);
   1996      0      stevel }
   1997      0      stevel 
   1998      0      stevel /* XXX this is a hack errno. */
   1999      0      stevel #define	EIPSECNOSA 255
   2000      0      stevel 
   2001      0      stevel /*
   2002      0      stevel  * Route message (pointed by mp, header in samsg) toward appropriate
   2003      0      stevel  * sockets.  Assume the message's creator did its job correctly.
   2004      0      stevel  *
   2005      0      stevel  * This should be a function that is followed by a return in its caller.
   2006      0      stevel  * The compiler _should_ be able to use tail-call optimizations to make the
   2007      0      stevel  * large ## of parameters not a huge deal.
   2008      0      stevel  */
   2009      0      stevel static void
   2010      0      stevel keysock_passup(mblk_t *mp, sadb_msg_t *samsg, minor_t serial,
   2011   3448    dh155122     keysock_consumer_t *kc, boolean_t persistent, keysock_stack_t *keystack)
   2012      0      stevel {
   2013      0      stevel 	keysock_t *ks;
   2014      0      stevel 	uint8_t satype = samsg->sadb_msg_satype;
   2015      0      stevel 	boolean_t toall = B_FALSE, allreg = B_FALSE, allereg = B_FALSE,
   2016      0      stevel 	    setalg = B_FALSE;
   2017      0      stevel 	mblk_t *mp1;
   2018      0      stevel 	int err = EIPSECNOSA;
   2019      0      stevel 
   2020      0      stevel 	/* Convert mp, which is M_DATA, into an M_PROTO of type T_DATA_IND */
   2021      0      stevel 	mp1 = allocb(sizeof (struct T_data_req), BPRI_HI);
   2022      0      stevel 	if (mp1 == NULL) {
   2023      0      stevel 		err = ENOMEM;
   2024      0      stevel 		goto error;
   2025      0      stevel 	}
   2026      0      stevel 	mp1->b_wptr += sizeof (struct T_data_req);
   2027      0      stevel 	((struct T_data_ind *)mp1->b_rptr)->PRIM_type = T_DATA_IND;
   2028      0      stevel 	((struct T_data_ind *)mp1->b_rptr)->MORE_flag = 0;
   2029      0      stevel 	mp1->b_datap->db_type = M_PROTO;
   2030      0      stevel 	mp1->b_cont = mp;
   2031      0      stevel 	mp = mp1;
   2032      0      stevel 
   2033      0      stevel 	switch (samsg->sadb_msg_type) {
   2034      0      stevel 	case SADB_FLUSH:
   2035      0      stevel 	case SADB_GETSPI:
   2036      0      stevel 	case SADB_UPDATE:
   2037   6668     markfen 	case SADB_X_UPDATEPAIR:
   2038      0      stevel 	case SADB_ADD:
   2039      0      stevel 	case SADB_DELETE:
   2040   6668     markfen 	case SADB_X_DELPAIR:
   2041      0      stevel 	case SADB_EXPIRE:
   2042      0      stevel 		/*
   2043      0      stevel 		 * These are most likely replies.  Don't worry about
   2044      0      stevel 		 * KEYSOCK_OUT_ERR handling.  Deliver to all sockets.
   2045      0      stevel 		 */
   2046   3448    dh155122 		ks3dbg(keystack,
   2047   3448    dh155122 		    ("Delivering normal message (%d) to all sockets.\n",
   2048      0      stevel 		    samsg->sadb_msg_type));
   2049      0      stevel 		toall = B_TRUE;
   2050      0      stevel 		break;
   2051      0      stevel 	case SADB_REGISTER:
   2052      0      stevel 		/*
   2053      0      stevel 		 * REGISTERs come up for one of three reasons:
   2054      0      stevel 		 *
   2055      0      stevel 		 *	1.) In response to a normal SADB_REGISTER
   2056      0      stevel 		 *		(samsg->sadb_msg_satype != SADB_SATYPE_UNSPEC &&
   2057      0      stevel 		 *		    serial != 0)
   2058      0      stevel 		 *		Deliver to normal SADB_REGISTERed sockets.
   2059      0      stevel 		 *	2.) In response to an extended REGISTER
   2060      0      stevel 		 *		(samsg->sadb_msg_satype == SADB_SATYPE_UNSPEC)
   2061      0      stevel 		 *		Deliver to extended REGISTERed socket.
   2062      0      stevel 		 *	3.) Spontaneous algorithm changes
   2063      0      stevel 		 *		(samsg->sadb_msg_satype != SADB_SATYPE_UNSPEC &&
   2064      0      stevel 		 *		    serial == 0)
   2065      0      stevel 		 *		Deliver to REGISTERed sockets of all sorts.
   2066      0      stevel 		 */
   2067      0      stevel 		if (kc == NULL) {
   2068      0      stevel 			/* Here because of keysock_error() call. */
   2069      0      stevel 			ASSERT(samsg->sadb_msg_errno != 0);
   2070      0      stevel 			break;	/* Out of switch. */
   2071      0      stevel 		}
   2072   3448    dh155122 		ks3dbg(keystack, ("Delivering REGISTER.\n"));
   2073      0      stevel 		if (satype == SADB_SATYPE_UNSPEC) {
   2074      0      stevel 			/* REGISTER Reason #2 */
   2075      0      stevel 			allereg = B_TRUE;
   2076      0      stevel 			/*
   2077      0      stevel 			 * Rewhack SA type so PF_KEY socket holder knows what
   2078      0      stevel 			 * consumer generated this algorithm list.
   2079      0      stevel 			 */
   2080      0      stevel 			satype = kc->kc_sa_type;
   2081      0      stevel 			samsg->sadb_msg_satype = satype;
   2082      0      stevel 			setalg = B_TRUE;
   2083      0      stevel 		} else if (serial == 0) {
   2084      0      stevel 			/* REGISTER Reason #3 */
   2085      0      stevel 			allreg = B_TRUE;
   2086      0      stevel 			allereg = B_TRUE;
   2087      0      stevel 		} else {
   2088      0      stevel 			/* REGISTER Reason #1 */
   2089      0      stevel 			allreg = B_TRUE;
   2090      0      stevel 			setalg = B_TRUE;
   2091      0      stevel 		}
   2092      0      stevel 		break;
   2093      0      stevel 	case SADB_ACQUIRE:
   2094      0      stevel 		/*
   2095      0      stevel 		 * ACQUIREs are either extended (sadb_msg_satype == 0) or
   2096      0      stevel 		 * regular (sadb_msg_satype != 0).  And we're guaranteed
   2097      0      stevel 		 * that serial == 0 for an ACQUIRE.
   2098      0      stevel 		 */
   2099   3448    dh155122 		ks3dbg(keystack, ("Delivering ACQUIRE.\n"));
   2100      0      stevel 		allereg = (satype == SADB_SATYPE_UNSPEC);
   2101      0      stevel 		allreg = !allereg;
   2102      0      stevel 		/*
   2103      0      stevel 		 * Corner case - if we send a regular ACQUIRE and there's
   2104      0      stevel 		 * extended ones registered, don't send an error down to
   2105      0      stevel 		 * consumers if nobody's listening and prematurely destroy
   2106      0      stevel 		 * their ACQUIRE record.  This might be too hackish of a
   2107      0      stevel 		 * solution.
   2108      0      stevel 		 */
   2109   3448    dh155122 		if (allreg && keystack->keystack_num_extended > 0)
   2110      0      stevel 			err = 0;
   2111      0      stevel 		break;
   2112      0      stevel 	case SADB_X_PROMISC:
   2113      0      stevel 	case SADB_X_INVERSE_ACQUIRE:
   2114      0      stevel 	case SADB_DUMP:
   2115      0      stevel 	case SADB_GET:
   2116      0      stevel 	default:
   2117      0      stevel 		/*
   2118      0      stevel 		 * Deliver to the sender and promiscuous only.
   2119      0      stevel 		 */
   2120   3448    dh155122 		ks3dbg(keystack, ("Delivering sender/promisc only (%d).\n",
   2121      0      stevel 		    samsg->sadb_msg_type));
   2122      0      stevel 		break;
   2123      0      stevel 	}
   2124      0      stevel 
   2125   3448    dh155122 	mutex_enter(&keystack->keystack_list_lock);
   2126   3448    dh155122 	for (ks = keystack->keystack_list; ks != NULL; ks = ks->keysock_next) {
   2127      0      stevel 		/* Delivery loop. */
   2128      0      stevel 
   2129      0      stevel 		/*
   2130      0      stevel 		 * Check special keysock-setting cases (REGISTER replies)
   2131      0      stevel 		 * here.
   2132      0      stevel 		 */
   2133      0      stevel 		if (setalg && serial == ks->keysock_serial) {
   2134      0      stevel 			ASSERT(kc != NULL);
   2135      0      stevel 			ASSERT(kc->kc_sa_type == satype);
   2136      0      stevel 			KEYSOCK_SETREG(ks, satype);
   2137      0      stevel 		}
   2138      0      stevel 
   2139      0      stevel 		/*
   2140      0      stevel 		 * NOLOOP takes precedence over PROMISC.  So if you've set
   2141      0      stevel 		 * !SO_USELOOPBACK, don't expect to see any data...
   2142      0      stevel 		 */
   2143      0      stevel 		if (ks->keysock_flags & KEYSOCK_NOLOOP)
   2144      0      stevel 			continue;
   2145      0      stevel 
   2146      0      stevel 		/*
   2147      0      stevel 		 * Messages to all, or promiscuous sockets just GET the
   2148      0      stevel 		 * message.  Perform rules-type checking iff it's not for all
   2149      0      stevel 		 * listeners or the socket is in promiscuous mode.
   2150      0      stevel 		 *
   2151      0      stevel 		 * NOTE:Because of the (kc != NULL && ISREG()), make sure
   2152      0      stevel 		 *	extended ACQUIREs arrive off a consumer that is
   2153      0      stevel 		 *	part of the extended REGISTER set of consumers.
   2154      0      stevel 		 */
   2155      0      stevel 		if (serial != ks->keysock_serial &&
   2156      0      stevel 		    !toall &&
   2157      0      stevel 		    !(ks->keysock_flags & KEYSOCK_PROMISC) &&
   2158      0      stevel 		    !((ks->keysock_flags & KEYSOCK_EXTENDED) ?
   2159   5240    nordmark 		    allereg : allreg && kc != NULL &&
   2160   5240    nordmark 		    KEYSOCK_ISREG(ks, kc->kc_sa_type)))
   2161      0      stevel 			continue;
   2162      0      stevel 
   2163      0      stevel 		mp1 = dupmsg(mp);
   2164      0      stevel 		if (mp1 == NULL) {
   2165   3448    dh155122 			ks2dbg(keystack, (
   2166      0      stevel 			    "keysock_passup():  dupmsg() failed.\n"));
   2167      0      stevel 			mp1 = mp;
   2168      0      stevel 			mp = NULL;
   2169      0      stevel 			err = ENOMEM;
   2170      0      stevel 		}
   2171      0      stevel 
   2172      0      stevel 		/*
   2173      0      stevel 		 * At this point, we can deliver or attempt to deliver
   2174      0      stevel 		 * this message.  We're free of obligation to report
   2175      0      stevel 		 * no listening PF_KEY sockets.  So set err to 0.
   2176      0      stevel 		 */
   2177      0      stevel 		err = 0;
   2178      0      stevel 
   2179      0      stevel 		/*
   2180      0      stevel 		 * See if we canputnext(), as well as see if the message
   2181      0      stevel 		 * needs to be queued if we can't.
   2182      0      stevel 		 */
   2183      0      stevel 		if (!canputnext(ks->keysock_rq)) {
   2184      0      stevel 			if (persistent) {
   2185      0      stevel 				if (putq(ks->keysock_rq, mp1) == 0) {
   2186   3448    dh155122 					ks1dbg(keystack, (
   2187      0      stevel 					    "keysock_passup: putq failed.\n"));
   2188      0      stevel 				} else {
   2189      0      stevel 					continue;
   2190      0      stevel 				}
   2191      0      stevel 			}
   2192      0      stevel 			freemsg(mp1);
   2193      0      stevel 			continue;
   2194      0      stevel 		}
   2195      0      stevel 
   2196   3448    dh155122 		ks3dbg(keystack,
   2197   3448    dh155122 		    ("Putting to serial %d.\n", ks->keysock_serial));
   2198      0      stevel 		/*
   2199      0      stevel 		 * Unlike the specific keysock instance case, this
   2200      0      stevel 		 * will only hit for listeners, so we will only
   2201      0      stevel 		 * putnext() if we can.
   2202      0      stevel 		 */
   2203      0      stevel 		putnext(ks->keysock_rq, mp1);
   2204      0      stevel 		if (mp == NULL)
   2205      0      stevel 			break;	/* out of for loop. */
   2206      0      stevel 	}
   2207   3448    dh155122 	mutex_exit(&keystack->keystack_list_lock);
   2208      0      stevel 
   2209      0      stevel error:
   2210      0      stevel 	if ((err != 0) && (kc != NULL)) {
   2211      0      stevel 		/*
   2212      0      stevel 		 * Generate KEYSOCK_OUT_ERR for consumer.
   2213      0      stevel 		 * Basically, I send this back if I have not been able to
   2214      0      stevel 		 * transmit (for whatever reason)
   2215      0      stevel 		 */
   2216   3448    dh155122 		ks1dbg(keystack,
   2217   3448    dh155122 		    ("keysock_passup():  No registered of type %d.\n",
   2218      0      stevel 		    satype));
   2219      0      stevel 		if (mp != NULL) {
   2220      0      stevel 			if (mp->b_datap->db_type == M_PROTO) {
   2221      0      stevel 				mp1 = mp;
   2222      0      stevel 				mp = mp->b_cont;
   2223      0      stevel 				freeb(mp1);
   2224      0      stevel 			}
   2225      0      stevel 			/*
   2226      0      stevel 			 * Do a copymsg() because people who get
   2227      0      stevel 			 * KEYSOCK_OUT_ERR may alter the message contents.
   2228      0      stevel 			 */
   2229      0      stevel 			mp1 = copymsg(mp);
   2230      0      stevel 			if (mp1 == NULL) {
   2231   3448    dh155122 				ks2dbg(keystack,
   2232   3448    dh155122 				    ("keysock_passup: copymsg() failed.\n"));
   2233      0      stevel 				mp1 = mp;
   2234      0      stevel 				mp = NULL;
   2235      0      stevel 			}
   2236      0      stevel 			keysock_out_err(kc, err, mp1);
   2237      0      stevel 		}
   2238      0      stevel 	}
   2239      0      stevel 
   2240      0      stevel 	/*
   2241      0      stevel 	 * XXX Blank the message somehow.  This is difficult because we don't
   2242      0      stevel 	 * know at this point if the message has db_ref > 1, etc.
   2243      0      stevel 	 *
   2244      0      stevel 	 * Optimally, keysock messages containing actual keying material would
   2245      0      stevel 	 * be allocated with esballoc(), with a zeroing free function.
   2246      0      stevel 	 */
   2247      0      stevel 	if (mp != NULL)
   2248      0      stevel 		freemsg(mp);
   2249      0      stevel }
   2250      0      stevel 
   2251      0      stevel /*
   2252      0      stevel  * Keysock's read service procedure is there only for PF_KEY reply
   2253      0      stevel  * messages that really need to reach the top.
   2254      0      stevel  */
   2255      0      stevel static void
   2256      0      stevel keysock_rsrv(queue_t *q)
   2257      0      stevel {
   2258      0      stevel 	mblk_t *mp;
   2259      0      stevel 
   2260      0      stevel 	while ((mp = getq(q)) != NULL) {
   2261      0      stevel 		if (canputnext(q)) {
   2262      0      stevel 			putnext(q, mp);
   2263      0      stevel 		} else {
   2264      0      stevel 			(void) putbq(q, mp);
   2265      0      stevel 			return;
   2266      0      stevel 		}
   2267      0      stevel 	}
   2268      0      stevel }
   2269      0      stevel 
   2270      0      stevel /*
   2271      0      stevel  * The read procedure should only be invoked by a keysock consumer, like
   2272      0      stevel  * ESP, AH, etc.  I should only see KEYSOCK_OUT and KEYSOCK_HELLO_ACK
   2273      0      stevel  * messages on my read queues.
   2274      0      stevel  */
   2275      0      stevel static void
   2276      0      stevel keysock_rput(queue_t *q, mblk_t *mp)
   2277      0      stevel {
   2278      0      stevel 	keysock_consumer_t *kc = (keysock_consumer_t *)q->q_ptr;
   2279      0      stevel 	ipsec_info_t *ii;
   2280      0      stevel 	keysock_hello_ack_t *ksa;
   2281      0      stevel 	minor_t serial;
   2282      0      stevel 	mblk_t *mp1;
   2283      0      stevel 	sadb_msg_t *samsg;
   2284   3448    dh155122 	keysock_stack_t	*keystack = kc->kc_keystack;
   2285      0      stevel 
   2286      0      stevel 	/* Make sure I'm a consumer instance.  (i.e. something's below me) */
   2287      0      stevel 	ASSERT(WR(q)->q_next != NULL);
   2288      0      stevel 
   2289      0      stevel 	if (mp->b_datap->db_type != M_CTL) {
   2290      0      stevel 		/*
   2291      0      stevel 		 * Keysock should only see keysock consumer interface
   2292      0      stevel 		 * messages (see ipsec_info.h) on its read procedure.
   2293      0      stevel 		 * To be robust, however, putnext() up so the STREAM head can
   2294      0      stevel 		 * deal with it appropriately.
   2295      0      stevel 		 */
   2296   3448    dh155122 		ks1dbg(keystack,
   2297   3448    dh155122 		    ("Hmmm, a non M_CTL (%d, 0x%x) on keysock_rput.\n",
   2298      0      stevel 		    mp->b_datap->db_type, mp->b_datap->db_type));
   2299      0      stevel 		putnext(q, mp);
   2300      0      stevel 		return;
   2301      0      stevel 	}
   2302      0      stevel 
   2303      0      stevel 	ii = (ipsec_info_t *)mp->b_rptr;
   2304      0      stevel 
   2305      0      stevel 	switch (ii->ipsec_info_type) {
   2306      0      stevel 	case KEYSOCK_OUT:
   2307      0      stevel 		/*
   2308      0      stevel 		 * A consumer needs to pass a response message or an ACQUIRE
   2309      0      stevel 		 * UP.  I assume that the consumer has done the right
   2310      0      stevel 		 * thing w.r.t. message creation, etc.
   2311      0      stevel 		 */
   2312      0      stevel 		serial = ((keysock_out_t *)mp->b_rptr)->ks_out_serial;
   2313      0      stevel 		mp1 = mp->b_cont;	/* Get M_DATA portion. */
   2314      0      stevel 		freeb(mp);
   2315      0      stevel 		samsg = (sadb_msg_t *)mp1->b_rptr;
   2316      0      stevel 		if (samsg->sadb_msg_type == SADB_FLUSH ||
   2317      0      stevel 		    (samsg->sadb_msg_type == SADB_DUMP &&
   2318   5240    nordmark 		    samsg->sadb_msg_len == SADB_8TO64(sizeof (*samsg)))) {
   2319      0      stevel 			/*
   2320      0      stevel 			 * If I'm an end-of-FLUSH or an end-of-DUMP marker...
   2321      0      stevel 			 */
   2322   3448    dh155122 			ASSERT(keystack->keystack_flushdump != 0);
   2323   3448    dh155122 						/* Am I flushing? */
   2324      0      stevel 
   2325      0      stevel 			mutex_enter(&kc->kc_lock);
   2326      0      stevel 			kc->kc_flags &= ~KC_FLUSHING;
   2327      0      stevel 			mutex_exit(&kc->kc_lock);
   2328      0      stevel 
   2329      0      stevel 			if (samsg->sadb_msg_errno != 0)
   2330   3448    dh155122 				keystack->keystack_flushdump_errno =
   2331   3448    dh155122 				    samsg->sadb_msg_errno;
   2332      0      stevel 
   2333      0      stevel 			/*
   2334      0      stevel 			 * Lower the atomic "flushing" count.  If it's
   2335      0      stevel 			 * the last one, send up the end-of-{FLUSH,DUMP} to
   2336      0      stevel 			 * the appropriate PF_KEY socket.
   2337      0      stevel 			 */
   2338   3448    dh155122 			if (atomic_add_32_nv(&keystack->keystack_flushdump,
   2339   3448    dh155122 			    -1) != 0) {
   2340   3448    dh155122 				ks1dbg(keystack,
   2341   3448    dh155122 				    ("One flush/dump message back from %d,"
   2342      0      stevel 				    " more to go.\n", samsg->sadb_msg_satype));
   2343      0      stevel 				freemsg(mp1);
   2344      0      stevel 				return;
   2345      0      stevel 			}
   2346      0      stevel 
   2347      0      stevel 			samsg->sadb_msg_errno =
   2348   3448    dh155122 			    (uint8_t)keystack->keystack_flushdump_errno;
   2349      0      stevel 			if (samsg->sadb_msg_type == SADB_DUMP) {
   2350      0      stevel 				samsg->sadb_msg_seq = 0;
   2351      0      stevel 			}
   2352      0      stevel 		}
   2353      0      stevel 		keysock_passup(mp1, samsg, serial, kc,
   2354   3448    dh155122 		    (samsg->sadb_msg_type == SADB_DUMP), keystack);
   2355      0      stevel 		return;
   2356      0      stevel 	case KEYSOCK_HELLO_ACK:
   2357      0      stevel 		/* Aha, now we can link in the consumer! */
   2358      0      stevel 		ksa = (keysock_hello_ack_t *)ii;
   2359      0      stevel 		keysock_link_consumer(ksa->ks_hello_satype, kc);
   2360      0      stevel 		freemsg(mp);
   2361      0      stevel 		return;
   2362      0      stevel 	default:
   2363   3448    dh155122 		ks1dbg(keystack, ("Hmmm, an IPsec info I'm not used to, 0x%x\n",
   2364      0      stevel 		    ii->ipsec_info_type));
   2365      0      stevel 		putnext(q, mp);
   2366      0      stevel 	}
   2367      0      stevel }
   2368      0      stevel 
   2369      0      stevel /*
   2370      0      stevel  * So we can avoid external linking problems....
   2371      0      stevel  */
   2372      0      stevel boolean_t
   2373   3448    dh155122 keysock_extended_reg(netstack_t *ns)
   2374      0      stevel {
   2375   3448    dh155122 	keysock_stack_t	*keystack = ns->netstack_keysock;
   2376   3448    dh155122 
   2377   3448    dh155122 	return (keystack->keystack_num_extended != 0);
   2378      0      stevel }
   2379      0      stevel 
   2380      0      stevel uint32_t
   2381   3448    dh155122 keysock_next_seq(netstack_t *ns)
   2382      0      stevel {
   2383   3448    dh155122 	keysock_stack_t	*keystack = ns->netstack_keysock;
   2384   3448    dh155122 
   2385   3448    dh155122 	return (atomic_add_32_nv(&keystack->keystack_acquire_seq, -1));
   2386      0      stevel }
   2387