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