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