1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 30*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 31*7c478bd9Sstevel@tonic-gate 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate /* 34*7c478bd9Sstevel@tonic-gate * STREAMS Administrative Driver 35*7c478bd9Sstevel@tonic-gate * 36*7c478bd9Sstevel@tonic-gate * Currently only handles autopush and module name verification. 37*7c478bd9Sstevel@tonic-gate */ 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/stream.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/stropts.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/strsubr.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/strsun.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/conf.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/sad.h> 48*7c478bd9Sstevel@tonic-gate #include <sys/cred.h> 49*7c478bd9Sstevel@tonic-gate #include <sys/debug.h> 50*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 51*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 52*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 53*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 54*7c478bd9Sstevel@tonic-gate #include <sys/systm.h> 55*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 56*7c478bd9Sstevel@tonic-gate #include <sys/priv_names.h> 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate static int sadopen(queue_t *, dev_t *, int, int, cred_t *); 59*7c478bd9Sstevel@tonic-gate static int sadclose(queue_t *, int, cred_t *); 60*7c478bd9Sstevel@tonic-gate static int sadwput(queue_t *qp, mblk_t *mp); 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate static int sad_info(dev_info_t *, ddi_info_cmd_t, void *, void **); 63*7c478bd9Sstevel@tonic-gate static int sad_attach(dev_info_t *, ddi_attach_cmd_t); 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate static struct autopush *ap_alloc(), *ap_hfind(); 66*7c478bd9Sstevel@tonic-gate static void ap_hadd(), ap_hrmv(); 67*7c478bd9Sstevel@tonic-gate static void apush_ioctl(), apush_iocdata(); 68*7c478bd9Sstevel@tonic-gate static void vml_ioctl(), vml_iocdata(); 69*7c478bd9Sstevel@tonic-gate static int valid_major(major_t); 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate extern kmutex_t sad_lock; 72*7c478bd9Sstevel@tonic-gate static dev_info_t *sad_dip; /* private copy of devinfo pointer */ 73*7c478bd9Sstevel@tonic-gate static struct autopush *strpfreep; /* autopush freelist */ 74*7c478bd9Sstevel@tonic-gate 75*7c478bd9Sstevel@tonic-gate static struct module_info sad_minfo = { 76*7c478bd9Sstevel@tonic-gate 0x7361, "sad", 0, INFPSZ, 0, 0 77*7c478bd9Sstevel@tonic-gate }; 78*7c478bd9Sstevel@tonic-gate 79*7c478bd9Sstevel@tonic-gate static struct qinit sad_rinit = { 80*7c478bd9Sstevel@tonic-gate NULL, NULL, sadopen, sadclose, NULL, &sad_minfo, NULL 81*7c478bd9Sstevel@tonic-gate }; 82*7c478bd9Sstevel@tonic-gate 83*7c478bd9Sstevel@tonic-gate static struct qinit sad_winit = { 84*7c478bd9Sstevel@tonic-gate sadwput, NULL, NULL, NULL, NULL, &sad_minfo, NULL 85*7c478bd9Sstevel@tonic-gate }; 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate struct streamtab sadinfo = { 88*7c478bd9Sstevel@tonic-gate &sad_rinit, &sad_winit, NULL, NULL 89*7c478bd9Sstevel@tonic-gate }; 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate DDI_DEFINE_STREAM_OPS(sad_ops, nulldev, nulldev, sad_attach, 92*7c478bd9Sstevel@tonic-gate nodev, nodev, sad_info, D_NEW | D_MTPERQ | D_MP, &sadinfo); 93*7c478bd9Sstevel@tonic-gate 94*7c478bd9Sstevel@tonic-gate /* 95*7c478bd9Sstevel@tonic-gate * Module linkage information for the kernel. 96*7c478bd9Sstevel@tonic-gate */ 97*7c478bd9Sstevel@tonic-gate 98*7c478bd9Sstevel@tonic-gate static struct modldrv modldrv = { 99*7c478bd9Sstevel@tonic-gate &mod_driverops, /* Type of module. This one is a pseudo driver */ 100*7c478bd9Sstevel@tonic-gate "STREAMS Administrative Driver 'sad' %I%", 101*7c478bd9Sstevel@tonic-gate &sad_ops, /* driver ops */ 102*7c478bd9Sstevel@tonic-gate }; 103*7c478bd9Sstevel@tonic-gate 104*7c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 105*7c478bd9Sstevel@tonic-gate MODREV_1, &modldrv, NULL 106*7c478bd9Sstevel@tonic-gate }; 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate int 109*7c478bd9Sstevel@tonic-gate _init(void) 110*7c478bd9Sstevel@tonic-gate { 111*7c478bd9Sstevel@tonic-gate return (mod_install(&modlinkage)); 112*7c478bd9Sstevel@tonic-gate } 113*7c478bd9Sstevel@tonic-gate 114*7c478bd9Sstevel@tonic-gate int 115*7c478bd9Sstevel@tonic-gate _fini(void) 116*7c478bd9Sstevel@tonic-gate { 117*7c478bd9Sstevel@tonic-gate return (mod_remove(&modlinkage)); 118*7c478bd9Sstevel@tonic-gate } 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate int 121*7c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 122*7c478bd9Sstevel@tonic-gate { 123*7c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 124*7c478bd9Sstevel@tonic-gate } 125*7c478bd9Sstevel@tonic-gate 126*7c478bd9Sstevel@tonic-gate static int 127*7c478bd9Sstevel@tonic-gate sad_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) 128*7c478bd9Sstevel@tonic-gate { 129*7c478bd9Sstevel@tonic-gate if (cmd != DDI_ATTACH) 130*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate if (ddi_create_minor_node(devi, "user", S_IFCHR, 133*7c478bd9Sstevel@tonic-gate 0, DDI_PSEUDO, NULL) == DDI_FAILURE) { 134*7c478bd9Sstevel@tonic-gate ddi_remove_minor_node(devi, NULL); 135*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 136*7c478bd9Sstevel@tonic-gate } 137*7c478bd9Sstevel@tonic-gate if (ddi_create_priv_minor_node(devi, "admin", S_IFCHR, 138*7c478bd9Sstevel@tonic-gate 1, DDI_PSEUDO, PRIVONLY_DEV, PRIV_SYS_CONFIG, 139*7c478bd9Sstevel@tonic-gate PRIV_SYS_CONFIG, 0666) == DDI_FAILURE) { 140*7c478bd9Sstevel@tonic-gate ddi_remove_minor_node(devi, NULL); 141*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 142*7c478bd9Sstevel@tonic-gate } 143*7c478bd9Sstevel@tonic-gate sad_dip = devi; 144*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 145*7c478bd9Sstevel@tonic-gate } 146*7c478bd9Sstevel@tonic-gate 147*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 148*7c478bd9Sstevel@tonic-gate static int 149*7c478bd9Sstevel@tonic-gate sad_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 150*7c478bd9Sstevel@tonic-gate { 151*7c478bd9Sstevel@tonic-gate int error; 152*7c478bd9Sstevel@tonic-gate 153*7c478bd9Sstevel@tonic-gate switch (infocmd) { 154*7c478bd9Sstevel@tonic-gate case DDI_INFO_DEVT2DEVINFO: 155*7c478bd9Sstevel@tonic-gate if (sad_dip == NULL) { 156*7c478bd9Sstevel@tonic-gate error = DDI_FAILURE; 157*7c478bd9Sstevel@tonic-gate } else { 158*7c478bd9Sstevel@tonic-gate *result = sad_dip; 159*7c478bd9Sstevel@tonic-gate error = DDI_SUCCESS; 160*7c478bd9Sstevel@tonic-gate } 161*7c478bd9Sstevel@tonic-gate break; 162*7c478bd9Sstevel@tonic-gate case DDI_INFO_DEVT2INSTANCE: 163*7c478bd9Sstevel@tonic-gate *result = (void *)0; 164*7c478bd9Sstevel@tonic-gate error = DDI_SUCCESS; 165*7c478bd9Sstevel@tonic-gate break; 166*7c478bd9Sstevel@tonic-gate default: 167*7c478bd9Sstevel@tonic-gate error = DDI_FAILURE; 168*7c478bd9Sstevel@tonic-gate } 169*7c478bd9Sstevel@tonic-gate return (error); 170*7c478bd9Sstevel@tonic-gate } 171*7c478bd9Sstevel@tonic-gate 172*7c478bd9Sstevel@tonic-gate 173*7c478bd9Sstevel@tonic-gate /* 174*7c478bd9Sstevel@tonic-gate * sadinit() - 175*7c478bd9Sstevel@tonic-gate * Initialize autopush freelist. 176*7c478bd9Sstevel@tonic-gate */ 177*7c478bd9Sstevel@tonic-gate void 178*7c478bd9Sstevel@tonic-gate sadinit() 179*7c478bd9Sstevel@tonic-gate { 180*7c478bd9Sstevel@tonic-gate struct autopush *ap; 181*7c478bd9Sstevel@tonic-gate int i; 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate /* 184*7c478bd9Sstevel@tonic-gate * build the autopush freelist. 185*7c478bd9Sstevel@tonic-gate */ 186*7c478bd9Sstevel@tonic-gate strpfreep = autopush; 187*7c478bd9Sstevel@tonic-gate ap = autopush; 188*7c478bd9Sstevel@tonic-gate for (i = 1; i < nautopush; i++) { 189*7c478bd9Sstevel@tonic-gate ap->ap_nextp = &autopush[i]; 190*7c478bd9Sstevel@tonic-gate ap->ap_flags = APFREE; 191*7c478bd9Sstevel@tonic-gate ap = ap->ap_nextp; 192*7c478bd9Sstevel@tonic-gate } 193*7c478bd9Sstevel@tonic-gate ap->ap_nextp = NULL; 194*7c478bd9Sstevel@tonic-gate ap->ap_flags = APFREE; 195*7c478bd9Sstevel@tonic-gate } 196*7c478bd9Sstevel@tonic-gate 197*7c478bd9Sstevel@tonic-gate /* 198*7c478bd9Sstevel@tonic-gate * sadopen() - 199*7c478bd9Sstevel@tonic-gate * Allocate a sad device. Only one 200*7c478bd9Sstevel@tonic-gate * open at a time allowed per device. 201*7c478bd9Sstevel@tonic-gate */ 202*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 203*7c478bd9Sstevel@tonic-gate static int 204*7c478bd9Sstevel@tonic-gate sadopen( 205*7c478bd9Sstevel@tonic-gate queue_t *qp, /* pointer to read queue */ 206*7c478bd9Sstevel@tonic-gate dev_t *devp, /* major/minor device of stream */ 207*7c478bd9Sstevel@tonic-gate int flag, /* file open flags */ 208*7c478bd9Sstevel@tonic-gate int sflag, /* stream open flags */ 209*7c478bd9Sstevel@tonic-gate cred_t *credp) /* user credentials */ 210*7c478bd9Sstevel@tonic-gate { 211*7c478bd9Sstevel@tonic-gate int i; 212*7c478bd9Sstevel@tonic-gate 213*7c478bd9Sstevel@tonic-gate if (sflag) /* no longer called from clone driver */ 214*7c478bd9Sstevel@tonic-gate return (EINVAL); 215*7c478bd9Sstevel@tonic-gate 216*7c478bd9Sstevel@tonic-gate /* 217*7c478bd9Sstevel@tonic-gate * Both USRMIN and ADMMIN are clone interfaces. 218*7c478bd9Sstevel@tonic-gate */ 219*7c478bd9Sstevel@tonic-gate for (i = 0; i < sadcnt; i++) 220*7c478bd9Sstevel@tonic-gate if (saddev[i].sa_qp == NULL) 221*7c478bd9Sstevel@tonic-gate break; 222*7c478bd9Sstevel@tonic-gate if (i >= sadcnt) /* no such device */ 223*7c478bd9Sstevel@tonic-gate return (ENXIO); 224*7c478bd9Sstevel@tonic-gate 225*7c478bd9Sstevel@tonic-gate switch (getminor(*devp)) { 226*7c478bd9Sstevel@tonic-gate case USRMIN: /* mere mortal */ 227*7c478bd9Sstevel@tonic-gate saddev[i].sa_flags = 0; 228*7c478bd9Sstevel@tonic-gate break; 229*7c478bd9Sstevel@tonic-gate 230*7c478bd9Sstevel@tonic-gate case ADMMIN: /* privileged user */ 231*7c478bd9Sstevel@tonic-gate saddev[i].sa_flags = SADPRIV; 232*7c478bd9Sstevel@tonic-gate break; 233*7c478bd9Sstevel@tonic-gate 234*7c478bd9Sstevel@tonic-gate default: 235*7c478bd9Sstevel@tonic-gate return (EINVAL); 236*7c478bd9Sstevel@tonic-gate } 237*7c478bd9Sstevel@tonic-gate 238*7c478bd9Sstevel@tonic-gate saddev[i].sa_qp = qp; 239*7c478bd9Sstevel@tonic-gate qp->q_ptr = (caddr_t)&saddev[i]; 240*7c478bd9Sstevel@tonic-gate WR(qp)->q_ptr = (caddr_t)&saddev[i]; 241*7c478bd9Sstevel@tonic-gate 242*7c478bd9Sstevel@tonic-gate /* 243*7c478bd9Sstevel@tonic-gate * NOTE: should the ADMMIN or USRMIN minors change 244*7c478bd9Sstevel@tonic-gate * then so should the offset of 2 below 245*7c478bd9Sstevel@tonic-gate * Both USRMIN and ADMMIN are clone interfaces and 246*7c478bd9Sstevel@tonic-gate * therefore their minor numbers (0 and 1) are reserved. 247*7c478bd9Sstevel@tonic-gate */ 248*7c478bd9Sstevel@tonic-gate *devp = makedevice(getemajor(*devp), i + 2); 249*7c478bd9Sstevel@tonic-gate qprocson(qp); 250*7c478bd9Sstevel@tonic-gate return (0); 251*7c478bd9Sstevel@tonic-gate } 252*7c478bd9Sstevel@tonic-gate 253*7c478bd9Sstevel@tonic-gate /* 254*7c478bd9Sstevel@tonic-gate * sadclose() - 255*7c478bd9Sstevel@tonic-gate * Clean up the data structures. 256*7c478bd9Sstevel@tonic-gate */ 257*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 258*7c478bd9Sstevel@tonic-gate static int 259*7c478bd9Sstevel@tonic-gate sadclose( 260*7c478bd9Sstevel@tonic-gate queue_t *qp, /* pointer to read queue */ 261*7c478bd9Sstevel@tonic-gate int flag, /* file open flags */ 262*7c478bd9Sstevel@tonic-gate cred_t *credp) /* user credentials */ 263*7c478bd9Sstevel@tonic-gate { 264*7c478bd9Sstevel@tonic-gate struct saddev *sadp; 265*7c478bd9Sstevel@tonic-gate 266*7c478bd9Sstevel@tonic-gate qprocsoff(qp); 267*7c478bd9Sstevel@tonic-gate sadp = (struct saddev *)qp->q_ptr; 268*7c478bd9Sstevel@tonic-gate sadp->sa_qp = NULL; 269*7c478bd9Sstevel@tonic-gate sadp->sa_addr = NULL; 270*7c478bd9Sstevel@tonic-gate qp->q_ptr = NULL; 271*7c478bd9Sstevel@tonic-gate WR(qp)->q_ptr = NULL; 272*7c478bd9Sstevel@tonic-gate return (0); 273*7c478bd9Sstevel@tonic-gate } 274*7c478bd9Sstevel@tonic-gate 275*7c478bd9Sstevel@tonic-gate /* 276*7c478bd9Sstevel@tonic-gate * sadwput() - 277*7c478bd9Sstevel@tonic-gate * Write side put procedure. 278*7c478bd9Sstevel@tonic-gate */ 279*7c478bd9Sstevel@tonic-gate static int 280*7c478bd9Sstevel@tonic-gate sadwput( 281*7c478bd9Sstevel@tonic-gate queue_t *qp, /* pointer to write queue */ 282*7c478bd9Sstevel@tonic-gate mblk_t *mp) /* message pointer */ 283*7c478bd9Sstevel@tonic-gate { 284*7c478bd9Sstevel@tonic-gate struct iocblk *iocp; 285*7c478bd9Sstevel@tonic-gate 286*7c478bd9Sstevel@tonic-gate switch (mp->b_datap->db_type) { 287*7c478bd9Sstevel@tonic-gate case M_FLUSH: 288*7c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHR) { 289*7c478bd9Sstevel@tonic-gate *mp->b_rptr &= ~FLUSHW; 290*7c478bd9Sstevel@tonic-gate qreply(qp, mp); 291*7c478bd9Sstevel@tonic-gate } else 292*7c478bd9Sstevel@tonic-gate freemsg(mp); 293*7c478bd9Sstevel@tonic-gate break; 294*7c478bd9Sstevel@tonic-gate 295*7c478bd9Sstevel@tonic-gate case M_IOCTL: 296*7c478bd9Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr; 297*7c478bd9Sstevel@tonic-gate switch (SAD_CMD(iocp->ioc_cmd)) { 298*7c478bd9Sstevel@tonic-gate case SAD_CMD(SAD_SAP): 299*7c478bd9Sstevel@tonic-gate case SAD_CMD(SAD_GAP): 300*7c478bd9Sstevel@tonic-gate apush_ioctl(qp, mp); 301*7c478bd9Sstevel@tonic-gate break; 302*7c478bd9Sstevel@tonic-gate 303*7c478bd9Sstevel@tonic-gate case SAD_VML: 304*7c478bd9Sstevel@tonic-gate vml_ioctl(qp, mp); 305*7c478bd9Sstevel@tonic-gate break; 306*7c478bd9Sstevel@tonic-gate 307*7c478bd9Sstevel@tonic-gate default: 308*7c478bd9Sstevel@tonic-gate miocnak(qp, mp, 0, EINVAL); 309*7c478bd9Sstevel@tonic-gate break; 310*7c478bd9Sstevel@tonic-gate } 311*7c478bd9Sstevel@tonic-gate break; 312*7c478bd9Sstevel@tonic-gate 313*7c478bd9Sstevel@tonic-gate case M_IOCDATA: 314*7c478bd9Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr; 315*7c478bd9Sstevel@tonic-gate switch (SAD_CMD(iocp->ioc_cmd)) { 316*7c478bd9Sstevel@tonic-gate case SAD_CMD(SAD_SAP): 317*7c478bd9Sstevel@tonic-gate case SAD_CMD(SAD_GAP): 318*7c478bd9Sstevel@tonic-gate apush_iocdata(qp, mp); 319*7c478bd9Sstevel@tonic-gate break; 320*7c478bd9Sstevel@tonic-gate 321*7c478bd9Sstevel@tonic-gate case SAD_VML: 322*7c478bd9Sstevel@tonic-gate vml_iocdata(qp, mp); 323*7c478bd9Sstevel@tonic-gate break; 324*7c478bd9Sstevel@tonic-gate 325*7c478bd9Sstevel@tonic-gate default: 326*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 327*7c478bd9Sstevel@tonic-gate "sadwput: invalid ioc_cmd in case M_IOCDATA: %d", 328*7c478bd9Sstevel@tonic-gate iocp->ioc_cmd); 329*7c478bd9Sstevel@tonic-gate freemsg(mp); 330*7c478bd9Sstevel@tonic-gate break; 331*7c478bd9Sstevel@tonic-gate } 332*7c478bd9Sstevel@tonic-gate break; 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate default: 335*7c478bd9Sstevel@tonic-gate freemsg(mp); 336*7c478bd9Sstevel@tonic-gate break; 337*7c478bd9Sstevel@tonic-gate } /* switch (db_type) */ 338*7c478bd9Sstevel@tonic-gate return (0); 339*7c478bd9Sstevel@tonic-gate } 340*7c478bd9Sstevel@tonic-gate 341*7c478bd9Sstevel@tonic-gate /* 342*7c478bd9Sstevel@tonic-gate * apush_ioctl() - 343*7c478bd9Sstevel@tonic-gate * Handle the M_IOCTL messages associated with 344*7c478bd9Sstevel@tonic-gate * the autopush feature. 345*7c478bd9Sstevel@tonic-gate */ 346*7c478bd9Sstevel@tonic-gate static void 347*7c478bd9Sstevel@tonic-gate apush_ioctl( 348*7c478bd9Sstevel@tonic-gate queue_t *qp, /* pointer to write queue */ 349*7c478bd9Sstevel@tonic-gate mblk_t *mp) /* message pointer */ 350*7c478bd9Sstevel@tonic-gate { 351*7c478bd9Sstevel@tonic-gate struct iocblk *iocp; 352*7c478bd9Sstevel@tonic-gate struct saddev *sadp; 353*7c478bd9Sstevel@tonic-gate uint_t size; 354*7c478bd9Sstevel@tonic-gate 355*7c478bd9Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr; 356*7c478bd9Sstevel@tonic-gate if (iocp->ioc_count != TRANSPARENT) { 357*7c478bd9Sstevel@tonic-gate miocnak(qp, mp, 0, EINVAL); 358*7c478bd9Sstevel@tonic-gate return; 359*7c478bd9Sstevel@tonic-gate } 360*7c478bd9Sstevel@tonic-gate if (SAD_VER(iocp->ioc_cmd) > AP_VERSION) { 361*7c478bd9Sstevel@tonic-gate miocnak(qp, mp, 0, EINVAL); 362*7c478bd9Sstevel@tonic-gate return; 363*7c478bd9Sstevel@tonic-gate } 364*7c478bd9Sstevel@tonic-gate 365*7c478bd9Sstevel@tonic-gate sadp = (struct saddev *)qp->q_ptr; 366*7c478bd9Sstevel@tonic-gate switch (SAD_CMD(iocp->ioc_cmd)) { 367*7c478bd9Sstevel@tonic-gate case SAD_CMD(SAD_SAP): 368*7c478bd9Sstevel@tonic-gate if (!(sadp->sa_flags & SADPRIV)) { 369*7c478bd9Sstevel@tonic-gate miocnak(qp, mp, 0, EPERM); 370*7c478bd9Sstevel@tonic-gate break; 371*7c478bd9Sstevel@tonic-gate } 372*7c478bd9Sstevel@tonic-gate /* FALLTHRU */ 373*7c478bd9Sstevel@tonic-gate 374*7c478bd9Sstevel@tonic-gate case SAD_CMD(SAD_GAP): 375*7c478bd9Sstevel@tonic-gate sadp->sa_addr = (caddr_t)*(uintptr_t *)mp->b_cont->b_rptr; 376*7c478bd9Sstevel@tonic-gate if (SAD_VER(iocp->ioc_cmd) == 1) 377*7c478bd9Sstevel@tonic-gate size = STRAPUSH_V1_LEN; 378*7c478bd9Sstevel@tonic-gate else 379*7c478bd9Sstevel@tonic-gate size = STRAPUSH_V0_LEN; 380*7c478bd9Sstevel@tonic-gate mcopyin(mp, (void *)GETSTRUCT, size, NULL); 381*7c478bd9Sstevel@tonic-gate qreply(qp, mp); 382*7c478bd9Sstevel@tonic-gate break; 383*7c478bd9Sstevel@tonic-gate 384*7c478bd9Sstevel@tonic-gate default: 385*7c478bd9Sstevel@tonic-gate ASSERT(0); 386*7c478bd9Sstevel@tonic-gate miocnak(qp, mp, 0, EINVAL); 387*7c478bd9Sstevel@tonic-gate break; 388*7c478bd9Sstevel@tonic-gate } /* switch (ioc_cmd) */ 389*7c478bd9Sstevel@tonic-gate } 390*7c478bd9Sstevel@tonic-gate 391*7c478bd9Sstevel@tonic-gate /* 392*7c478bd9Sstevel@tonic-gate * apush_iocdata() - 393*7c478bd9Sstevel@tonic-gate * Handle the M_IOCDATA messages associated with 394*7c478bd9Sstevel@tonic-gate * the autopush feature. 395*7c478bd9Sstevel@tonic-gate */ 396*7c478bd9Sstevel@tonic-gate static void 397*7c478bd9Sstevel@tonic-gate apush_iocdata( 398*7c478bd9Sstevel@tonic-gate queue_t *qp, /* pointer to write queue */ 399*7c478bd9Sstevel@tonic-gate mblk_t *mp) /* message pointer */ 400*7c478bd9Sstevel@tonic-gate { 401*7c478bd9Sstevel@tonic-gate int i, ret; 402*7c478bd9Sstevel@tonic-gate struct copyresp *csp; 403*7c478bd9Sstevel@tonic-gate struct strapush *sap; 404*7c478bd9Sstevel@tonic-gate struct autopush *ap; 405*7c478bd9Sstevel@tonic-gate struct saddev *sadp; 406*7c478bd9Sstevel@tonic-gate uint_t size; 407*7c478bd9Sstevel@tonic-gate 408*7c478bd9Sstevel@tonic-gate csp = (struct copyresp *)mp->b_rptr; 409*7c478bd9Sstevel@tonic-gate if (csp->cp_rval) { /* if there was an error */ 410*7c478bd9Sstevel@tonic-gate freemsg(mp); 411*7c478bd9Sstevel@tonic-gate return; 412*7c478bd9Sstevel@tonic-gate } 413*7c478bd9Sstevel@tonic-gate if (mp->b_cont) 414*7c478bd9Sstevel@tonic-gate /* sap needed only if mp->b_cont is set */ 415*7c478bd9Sstevel@tonic-gate sap = (struct strapush *)mp->b_cont->b_rptr; 416*7c478bd9Sstevel@tonic-gate switch (SAD_CMD(csp->cp_cmd)) { 417*7c478bd9Sstevel@tonic-gate case SAD_CMD(SAD_SAP): 418*7c478bd9Sstevel@tonic-gate switch ((long)csp->cp_private) { 419*7c478bd9Sstevel@tonic-gate case GETSTRUCT: 420*7c478bd9Sstevel@tonic-gate switch (sap->sap_cmd) { 421*7c478bd9Sstevel@tonic-gate case SAP_ONE: 422*7c478bd9Sstevel@tonic-gate case SAP_RANGE: 423*7c478bd9Sstevel@tonic-gate case SAP_ALL: 424*7c478bd9Sstevel@tonic-gate if ((sap->sap_npush == 0) || 425*7c478bd9Sstevel@tonic-gate (sap->sap_npush > MAXAPUSH) || 426*7c478bd9Sstevel@tonic-gate (sap->sap_npush > nstrpush)) { 427*7c478bd9Sstevel@tonic-gate 428*7c478bd9Sstevel@tonic-gate /* invalid number of modules to push */ 429*7c478bd9Sstevel@tonic-gate 430*7c478bd9Sstevel@tonic-gate miocnak(qp, mp, 0, EINVAL); 431*7c478bd9Sstevel@tonic-gate break; 432*7c478bd9Sstevel@tonic-gate } 433*7c478bd9Sstevel@tonic-gate if (ret = valid_major(sap->sap_major)) { 434*7c478bd9Sstevel@tonic-gate miocnak(qp, mp, 0, ret); 435*7c478bd9Sstevel@tonic-gate break; 436*7c478bd9Sstevel@tonic-gate } 437*7c478bd9Sstevel@tonic-gate if ((sap->sap_cmd == SAP_RANGE) && 438*7c478bd9Sstevel@tonic-gate (sap->sap_lastminor <= sap->sap_minor)) { 439*7c478bd9Sstevel@tonic-gate 440*7c478bd9Sstevel@tonic-gate /* bad range */ 441*7c478bd9Sstevel@tonic-gate 442*7c478bd9Sstevel@tonic-gate miocnak(qp, mp, 0, ERANGE); 443*7c478bd9Sstevel@tonic-gate break; 444*7c478bd9Sstevel@tonic-gate } 445*7c478bd9Sstevel@tonic-gate 446*7c478bd9Sstevel@tonic-gate /* 447*7c478bd9Sstevel@tonic-gate * Validate that the specified list of 448*7c478bd9Sstevel@tonic-gate * modules exist. 449*7c478bd9Sstevel@tonic-gate */ 450*7c478bd9Sstevel@tonic-gate for (i = 0; i < sap->sap_npush; i++) { 451*7c478bd9Sstevel@tonic-gate sap->sap_list[i][FMNAMESZ] = '\0'; 452*7c478bd9Sstevel@tonic-gate if (fmodsw_find(sap->sap_list[i], 453*7c478bd9Sstevel@tonic-gate FMODSW_LOAD) == NULL) { 454*7c478bd9Sstevel@tonic-gate miocnak(qp, mp, 0, EINVAL); 455*7c478bd9Sstevel@tonic-gate return; 456*7c478bd9Sstevel@tonic-gate } 457*7c478bd9Sstevel@tonic-gate } 458*7c478bd9Sstevel@tonic-gate 459*7c478bd9Sstevel@tonic-gate mutex_enter(&sad_lock); 460*7c478bd9Sstevel@tonic-gate if (ap_hfind(sap->sap_major, sap->sap_minor, 461*7c478bd9Sstevel@tonic-gate sap->sap_lastminor, sap->sap_cmd)) { 462*7c478bd9Sstevel@tonic-gate mutex_exit(&sad_lock); 463*7c478bd9Sstevel@tonic-gate 464*7c478bd9Sstevel@tonic-gate /* already configured */ 465*7c478bd9Sstevel@tonic-gate 466*7c478bd9Sstevel@tonic-gate miocnak(qp, mp, 0, EEXIST); 467*7c478bd9Sstevel@tonic-gate break; 468*7c478bd9Sstevel@tonic-gate } 469*7c478bd9Sstevel@tonic-gate if ((ap = ap_alloc()) == NULL) { 470*7c478bd9Sstevel@tonic-gate mutex_exit(&sad_lock); 471*7c478bd9Sstevel@tonic-gate 472*7c478bd9Sstevel@tonic-gate /* no autopush structures */ 473*7c478bd9Sstevel@tonic-gate 474*7c478bd9Sstevel@tonic-gate miocnak(qp, mp, 0, ENOSR); 475*7c478bd9Sstevel@tonic-gate break; 476*7c478bd9Sstevel@tonic-gate } 477*7c478bd9Sstevel@tonic-gate ap->ap_cnt++; 478*7c478bd9Sstevel@tonic-gate ap->ap_common = sap->sap_common; 479*7c478bd9Sstevel@tonic-gate if (SAD_VER(csp->cp_cmd) > 0) 480*7c478bd9Sstevel@tonic-gate ap->ap_anchor = sap->sap_anchor; 481*7c478bd9Sstevel@tonic-gate else 482*7c478bd9Sstevel@tonic-gate ap->ap_anchor = 0; 483*7c478bd9Sstevel@tonic-gate for (i = 0; i < ap->ap_npush; i++) 484*7c478bd9Sstevel@tonic-gate (void) strcpy(ap->ap_list[i], 485*7c478bd9Sstevel@tonic-gate sap->sap_list[i]); 486*7c478bd9Sstevel@tonic-gate ap_hadd(ap); 487*7c478bd9Sstevel@tonic-gate mutex_exit(&sad_lock); 488*7c478bd9Sstevel@tonic-gate miocack(qp, mp, 0, 0); 489*7c478bd9Sstevel@tonic-gate break; 490*7c478bd9Sstevel@tonic-gate 491*7c478bd9Sstevel@tonic-gate case SAP_CLEAR: 492*7c478bd9Sstevel@tonic-gate if (ret = valid_major(sap->sap_major)) { 493*7c478bd9Sstevel@tonic-gate miocnak(qp, mp, 0, ret); 494*7c478bd9Sstevel@tonic-gate break; 495*7c478bd9Sstevel@tonic-gate } 496*7c478bd9Sstevel@tonic-gate mutex_enter(&sad_lock); 497*7c478bd9Sstevel@tonic-gate if ((ap = ap_hfind(sap->sap_major, 498*7c478bd9Sstevel@tonic-gate sap->sap_minor, sap->sap_lastminor, 499*7c478bd9Sstevel@tonic-gate sap->sap_cmd)) == NULL) { 500*7c478bd9Sstevel@tonic-gate mutex_exit(&sad_lock); 501*7c478bd9Sstevel@tonic-gate 502*7c478bd9Sstevel@tonic-gate /* not configured */ 503*7c478bd9Sstevel@tonic-gate 504*7c478bd9Sstevel@tonic-gate miocnak(qp, mp, 0, ENODEV); 505*7c478bd9Sstevel@tonic-gate break; 506*7c478bd9Sstevel@tonic-gate } 507*7c478bd9Sstevel@tonic-gate if ((ap->ap_type == SAP_RANGE) && 508*7c478bd9Sstevel@tonic-gate (sap->sap_minor != ap->ap_minor)) { 509*7c478bd9Sstevel@tonic-gate mutex_exit(&sad_lock); 510*7c478bd9Sstevel@tonic-gate 511*7c478bd9Sstevel@tonic-gate /* starting minors do not match */ 512*7c478bd9Sstevel@tonic-gate 513*7c478bd9Sstevel@tonic-gate miocnak(qp, mp, 0, ERANGE); 514*7c478bd9Sstevel@tonic-gate break; 515*7c478bd9Sstevel@tonic-gate } 516*7c478bd9Sstevel@tonic-gate if ((ap->ap_type == SAP_ALL) && 517*7c478bd9Sstevel@tonic-gate (sap->sap_minor != 0)) { 518*7c478bd9Sstevel@tonic-gate mutex_exit(&sad_lock); 519*7c478bd9Sstevel@tonic-gate 520*7c478bd9Sstevel@tonic-gate /* SAP_ALL must have minor == 0 */ 521*7c478bd9Sstevel@tonic-gate 522*7c478bd9Sstevel@tonic-gate miocnak(qp, mp, 0, EINVAL); 523*7c478bd9Sstevel@tonic-gate break; 524*7c478bd9Sstevel@tonic-gate } 525*7c478bd9Sstevel@tonic-gate ap_hrmv(ap); 526*7c478bd9Sstevel@tonic-gate if (--(ap->ap_cnt) <= 0) 527*7c478bd9Sstevel@tonic-gate ap_free(ap); 528*7c478bd9Sstevel@tonic-gate mutex_exit(&sad_lock); 529*7c478bd9Sstevel@tonic-gate miocack(qp, mp, 0, 0); 530*7c478bd9Sstevel@tonic-gate break; 531*7c478bd9Sstevel@tonic-gate 532*7c478bd9Sstevel@tonic-gate default: 533*7c478bd9Sstevel@tonic-gate miocnak(qp, mp, 0, EINVAL); 534*7c478bd9Sstevel@tonic-gate break; 535*7c478bd9Sstevel@tonic-gate } /* switch (sap_cmd) */ 536*7c478bd9Sstevel@tonic-gate break; 537*7c478bd9Sstevel@tonic-gate 538*7c478bd9Sstevel@tonic-gate default: 539*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 540*7c478bd9Sstevel@tonic-gate "apush_iocdata: cp_private bad in SAD_SAP: %p", 541*7c478bd9Sstevel@tonic-gate (void *)csp->cp_private); 542*7c478bd9Sstevel@tonic-gate freemsg(mp); 543*7c478bd9Sstevel@tonic-gate break; 544*7c478bd9Sstevel@tonic-gate } /* switch (cp_private) */ 545*7c478bd9Sstevel@tonic-gate break; 546*7c478bd9Sstevel@tonic-gate 547*7c478bd9Sstevel@tonic-gate case SAD_CMD(SAD_GAP): 548*7c478bd9Sstevel@tonic-gate switch ((long)csp->cp_private) { 549*7c478bd9Sstevel@tonic-gate 550*7c478bd9Sstevel@tonic-gate case GETSTRUCT: { 551*7c478bd9Sstevel@tonic-gate if (ret = valid_major(sap->sap_major)) { 552*7c478bd9Sstevel@tonic-gate miocnak(qp, mp, 0, ret); 553*7c478bd9Sstevel@tonic-gate break; 554*7c478bd9Sstevel@tonic-gate } 555*7c478bd9Sstevel@tonic-gate mutex_enter(&sad_lock); 556*7c478bd9Sstevel@tonic-gate if ((ap = ap_hfind(sap->sap_major, sap->sap_minor, 557*7c478bd9Sstevel@tonic-gate sap->sap_lastminor, SAP_ONE)) == NULL) { 558*7c478bd9Sstevel@tonic-gate mutex_exit(&sad_lock); 559*7c478bd9Sstevel@tonic-gate 560*7c478bd9Sstevel@tonic-gate /* not configured */ 561*7c478bd9Sstevel@tonic-gate 562*7c478bd9Sstevel@tonic-gate miocnak(qp, mp, 0, ENODEV); 563*7c478bd9Sstevel@tonic-gate break; 564*7c478bd9Sstevel@tonic-gate } 565*7c478bd9Sstevel@tonic-gate 566*7c478bd9Sstevel@tonic-gate sap->sap_common = ap->ap_common; 567*7c478bd9Sstevel@tonic-gate if (SAD_VER(csp->cp_cmd) > 0) 568*7c478bd9Sstevel@tonic-gate sap->sap_anchor = ap->ap_anchor; 569*7c478bd9Sstevel@tonic-gate for (i = 0; i < ap->ap_npush; i++) 570*7c478bd9Sstevel@tonic-gate (void) strcpy(sap->sap_list[i], ap->ap_list[i]); 571*7c478bd9Sstevel@tonic-gate for (; i < MAXAPUSH; i++) 572*7c478bd9Sstevel@tonic-gate bzero(sap->sap_list[i], FMNAMESZ + 1); 573*7c478bd9Sstevel@tonic-gate mutex_exit(&sad_lock); 574*7c478bd9Sstevel@tonic-gate 575*7c478bd9Sstevel@tonic-gate if (SAD_VER(csp->cp_cmd) == 1) 576*7c478bd9Sstevel@tonic-gate size = STRAPUSH_V1_LEN; 577*7c478bd9Sstevel@tonic-gate else 578*7c478bd9Sstevel@tonic-gate size = STRAPUSH_V0_LEN; 579*7c478bd9Sstevel@tonic-gate 580*7c478bd9Sstevel@tonic-gate sadp = (struct saddev *)qp->q_ptr; 581*7c478bd9Sstevel@tonic-gate mcopyout(mp, (void *)GETRESULT, size, sadp->sa_addr, 582*7c478bd9Sstevel@tonic-gate NULL); 583*7c478bd9Sstevel@tonic-gate qreply(qp, mp); 584*7c478bd9Sstevel@tonic-gate break; 585*7c478bd9Sstevel@tonic-gate } 586*7c478bd9Sstevel@tonic-gate case GETRESULT: 587*7c478bd9Sstevel@tonic-gate miocack(qp, mp, 0, 0); 588*7c478bd9Sstevel@tonic-gate break; 589*7c478bd9Sstevel@tonic-gate 590*7c478bd9Sstevel@tonic-gate default: 591*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 592*7c478bd9Sstevel@tonic-gate "apush_iocdata: cp_private bad case SAD_GAP: %p", 593*7c478bd9Sstevel@tonic-gate (void *)csp->cp_private); 594*7c478bd9Sstevel@tonic-gate freemsg(mp); 595*7c478bd9Sstevel@tonic-gate break; 596*7c478bd9Sstevel@tonic-gate } /* switch (cp_private) */ 597*7c478bd9Sstevel@tonic-gate break; 598*7c478bd9Sstevel@tonic-gate 599*7c478bd9Sstevel@tonic-gate default: /* can't happen */ 600*7c478bd9Sstevel@tonic-gate ASSERT(0); 601*7c478bd9Sstevel@tonic-gate freemsg(mp); 602*7c478bd9Sstevel@tonic-gate break; 603*7c478bd9Sstevel@tonic-gate } /* switch (cp_cmd) */ 604*7c478bd9Sstevel@tonic-gate } 605*7c478bd9Sstevel@tonic-gate 606*7c478bd9Sstevel@tonic-gate /* 607*7c478bd9Sstevel@tonic-gate * ap_alloc() - 608*7c478bd9Sstevel@tonic-gate * Allocate an autopush structure. 609*7c478bd9Sstevel@tonic-gate */ 610*7c478bd9Sstevel@tonic-gate static struct autopush * 611*7c478bd9Sstevel@tonic-gate ap_alloc(void) 612*7c478bd9Sstevel@tonic-gate { 613*7c478bd9Sstevel@tonic-gate struct autopush *ap; 614*7c478bd9Sstevel@tonic-gate 615*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&sad_lock)); 616*7c478bd9Sstevel@tonic-gate if (strpfreep == NULL) 617*7c478bd9Sstevel@tonic-gate return (NULL); 618*7c478bd9Sstevel@tonic-gate ap = strpfreep; 619*7c478bd9Sstevel@tonic-gate if (ap->ap_flags != APFREE) 620*7c478bd9Sstevel@tonic-gate cmn_err(CE_PANIC, "ap_alloc: autopush struct not free: %d", 621*7c478bd9Sstevel@tonic-gate ap->ap_flags); 622*7c478bd9Sstevel@tonic-gate strpfreep = strpfreep->ap_nextp; 623*7c478bd9Sstevel@tonic-gate ap->ap_nextp = NULL; 624*7c478bd9Sstevel@tonic-gate ap->ap_flags = APUSED; 625*7c478bd9Sstevel@tonic-gate return (ap); 626*7c478bd9Sstevel@tonic-gate } 627*7c478bd9Sstevel@tonic-gate 628*7c478bd9Sstevel@tonic-gate /* 629*7c478bd9Sstevel@tonic-gate * ap_free() - 630*7c478bd9Sstevel@tonic-gate * Give an autopush structure back to the freelist. 631*7c478bd9Sstevel@tonic-gate */ 632*7c478bd9Sstevel@tonic-gate void 633*7c478bd9Sstevel@tonic-gate ap_free(struct autopush *ap) 634*7c478bd9Sstevel@tonic-gate { 635*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&sad_lock)); 636*7c478bd9Sstevel@tonic-gate if (!(ap->ap_flags & APUSED)) 637*7c478bd9Sstevel@tonic-gate cmn_err(CE_PANIC, "ap_free: autopush struct not used: %d", 638*7c478bd9Sstevel@tonic-gate ap->ap_flags); 639*7c478bd9Sstevel@tonic-gate if (ap->ap_flags & APHASH) 640*7c478bd9Sstevel@tonic-gate cmn_err(CE_PANIC, "ap_free: autopush struct not hashed: %d", 641*7c478bd9Sstevel@tonic-gate ap->ap_flags); 642*7c478bd9Sstevel@tonic-gate ap->ap_flags = APFREE; 643*7c478bd9Sstevel@tonic-gate ap->ap_nextp = strpfreep; 644*7c478bd9Sstevel@tonic-gate strpfreep = ap; 645*7c478bd9Sstevel@tonic-gate } 646*7c478bd9Sstevel@tonic-gate 647*7c478bd9Sstevel@tonic-gate /* 648*7c478bd9Sstevel@tonic-gate * ap_hadd() - 649*7c478bd9Sstevel@tonic-gate * Add an autopush structure to the hash list. 650*7c478bd9Sstevel@tonic-gate */ 651*7c478bd9Sstevel@tonic-gate static void 652*7c478bd9Sstevel@tonic-gate ap_hadd(struct autopush *ap) 653*7c478bd9Sstevel@tonic-gate { 654*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&sad_lock)); 655*7c478bd9Sstevel@tonic-gate if (!(ap->ap_flags & APUSED)) 656*7c478bd9Sstevel@tonic-gate cmn_err(CE_PANIC, "ap_hadd: autopush struct not used: %d", 657*7c478bd9Sstevel@tonic-gate ap->ap_flags); 658*7c478bd9Sstevel@tonic-gate if (ap->ap_flags & APHASH) 659*7c478bd9Sstevel@tonic-gate cmn_err(CE_PANIC, "ap_hadd: autopush struct not hashed: %d", 660*7c478bd9Sstevel@tonic-gate ap->ap_flags); 661*7c478bd9Sstevel@tonic-gate ap->ap_nextp = strphash(ap->ap_major); 662*7c478bd9Sstevel@tonic-gate strphash(ap->ap_major) = ap; 663*7c478bd9Sstevel@tonic-gate ap->ap_flags |= APHASH; 664*7c478bd9Sstevel@tonic-gate } 665*7c478bd9Sstevel@tonic-gate 666*7c478bd9Sstevel@tonic-gate /* 667*7c478bd9Sstevel@tonic-gate * ap_hrmv() - 668*7c478bd9Sstevel@tonic-gate * Remove an autopush structure from the hash list. 669*7c478bd9Sstevel@tonic-gate */ 670*7c478bd9Sstevel@tonic-gate static void 671*7c478bd9Sstevel@tonic-gate ap_hrmv(struct autopush *ap) 672*7c478bd9Sstevel@tonic-gate { 673*7c478bd9Sstevel@tonic-gate struct autopush *hap; 674*7c478bd9Sstevel@tonic-gate struct autopush *prevp = NULL; 675*7c478bd9Sstevel@tonic-gate 676*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&sad_lock)); 677*7c478bd9Sstevel@tonic-gate if (!(ap->ap_flags & APUSED)) 678*7c478bd9Sstevel@tonic-gate cmn_err(CE_PANIC, "ap_hrmv: autopush struct not used: %d", 679*7c478bd9Sstevel@tonic-gate ap->ap_flags); 680*7c478bd9Sstevel@tonic-gate if (!(ap->ap_flags & APHASH)) 681*7c478bd9Sstevel@tonic-gate cmn_err(CE_PANIC, "ap_hrmv: autopush struct not hashed: %d", 682*7c478bd9Sstevel@tonic-gate ap->ap_flags); 683*7c478bd9Sstevel@tonic-gate 684*7c478bd9Sstevel@tonic-gate hap = strphash(ap->ap_major); 685*7c478bd9Sstevel@tonic-gate while (hap) { 686*7c478bd9Sstevel@tonic-gate if (ap == hap) { 687*7c478bd9Sstevel@tonic-gate hap->ap_flags &= ~APHASH; 688*7c478bd9Sstevel@tonic-gate if (prevp) 689*7c478bd9Sstevel@tonic-gate prevp->ap_nextp = hap->ap_nextp; 690*7c478bd9Sstevel@tonic-gate else 691*7c478bd9Sstevel@tonic-gate strphash(ap->ap_major) = hap->ap_nextp; 692*7c478bd9Sstevel@tonic-gate return; 693*7c478bd9Sstevel@tonic-gate } /* if */ 694*7c478bd9Sstevel@tonic-gate prevp = hap; 695*7c478bd9Sstevel@tonic-gate hap = hap->ap_nextp; 696*7c478bd9Sstevel@tonic-gate } /* while */ 697*7c478bd9Sstevel@tonic-gate } 698*7c478bd9Sstevel@tonic-gate 699*7c478bd9Sstevel@tonic-gate /* 700*7c478bd9Sstevel@tonic-gate * ap_hfind() - 701*7c478bd9Sstevel@tonic-gate * Look for an autopush structure in the hash list 702*7c478bd9Sstevel@tonic-gate * based on major, minor, lastminor, and command. 703*7c478bd9Sstevel@tonic-gate */ 704*7c478bd9Sstevel@tonic-gate static struct autopush * 705*7c478bd9Sstevel@tonic-gate ap_hfind( 706*7c478bd9Sstevel@tonic-gate major_t maj, /* major device number */ 707*7c478bd9Sstevel@tonic-gate minor_t minor, /* minor device number */ 708*7c478bd9Sstevel@tonic-gate minor_t last, /* last minor device number (SAP_RANGE only) */ 709*7c478bd9Sstevel@tonic-gate uint_t cmd) /* who is asking */ 710*7c478bd9Sstevel@tonic-gate { 711*7c478bd9Sstevel@tonic-gate struct autopush *ap; 712*7c478bd9Sstevel@tonic-gate 713*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&sad_lock)); 714*7c478bd9Sstevel@tonic-gate ap = strphash(maj); 715*7c478bd9Sstevel@tonic-gate while (ap) { 716*7c478bd9Sstevel@tonic-gate if (ap->ap_major == maj) { 717*7c478bd9Sstevel@tonic-gate if (cmd == SAP_ALL) 718*7c478bd9Sstevel@tonic-gate break; 719*7c478bd9Sstevel@tonic-gate switch (ap->ap_type) { 720*7c478bd9Sstevel@tonic-gate case SAP_ALL: 721*7c478bd9Sstevel@tonic-gate break; 722*7c478bd9Sstevel@tonic-gate 723*7c478bd9Sstevel@tonic-gate case SAP_ONE: 724*7c478bd9Sstevel@tonic-gate if (ap->ap_minor == minor) 725*7c478bd9Sstevel@tonic-gate break; 726*7c478bd9Sstevel@tonic-gate if ((cmd == SAP_RANGE) && 727*7c478bd9Sstevel@tonic-gate (ap->ap_minor >= minor) && 728*7c478bd9Sstevel@tonic-gate (ap->ap_minor <= last)) 729*7c478bd9Sstevel@tonic-gate break; 730*7c478bd9Sstevel@tonic-gate ap = ap->ap_nextp; 731*7c478bd9Sstevel@tonic-gate continue; 732*7c478bd9Sstevel@tonic-gate 733*7c478bd9Sstevel@tonic-gate case SAP_RANGE: 734*7c478bd9Sstevel@tonic-gate if ((cmd == SAP_RANGE) && 735*7c478bd9Sstevel@tonic-gate (((minor >= ap->ap_minor) && 736*7c478bd9Sstevel@tonic-gate (minor <= ap->ap_lastminor)) || 737*7c478bd9Sstevel@tonic-gate ((ap->ap_minor >= minor) && 738*7c478bd9Sstevel@tonic-gate (ap->ap_minor <= last)))) 739*7c478bd9Sstevel@tonic-gate break; 740*7c478bd9Sstevel@tonic-gate if ((minor >= ap->ap_minor) && 741*7c478bd9Sstevel@tonic-gate (minor <= ap->ap_lastminor)) 742*7c478bd9Sstevel@tonic-gate break; 743*7c478bd9Sstevel@tonic-gate ap = ap->ap_nextp; 744*7c478bd9Sstevel@tonic-gate continue; 745*7c478bd9Sstevel@tonic-gate 746*7c478bd9Sstevel@tonic-gate default: 747*7c478bd9Sstevel@tonic-gate ASSERT(0); 748*7c478bd9Sstevel@tonic-gate break; 749*7c478bd9Sstevel@tonic-gate } 750*7c478bd9Sstevel@tonic-gate break; 751*7c478bd9Sstevel@tonic-gate } 752*7c478bd9Sstevel@tonic-gate ap = ap->ap_nextp; 753*7c478bd9Sstevel@tonic-gate } 754*7c478bd9Sstevel@tonic-gate return (ap); 755*7c478bd9Sstevel@tonic-gate } 756*7c478bd9Sstevel@tonic-gate 757*7c478bd9Sstevel@tonic-gate /* 758*7c478bd9Sstevel@tonic-gate * vml_ioctl() - 759*7c478bd9Sstevel@tonic-gate * Handle the M_IOCTL message associated with a request 760*7c478bd9Sstevel@tonic-gate * to validate a module list. 761*7c478bd9Sstevel@tonic-gate */ 762*7c478bd9Sstevel@tonic-gate static void 763*7c478bd9Sstevel@tonic-gate vml_ioctl( 764*7c478bd9Sstevel@tonic-gate queue_t *qp, /* pointer to write queue */ 765*7c478bd9Sstevel@tonic-gate mblk_t *mp) /* message pointer */ 766*7c478bd9Sstevel@tonic-gate { 767*7c478bd9Sstevel@tonic-gate struct iocblk *iocp; 768*7c478bd9Sstevel@tonic-gate 769*7c478bd9Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr; 770*7c478bd9Sstevel@tonic-gate if (iocp->ioc_count != TRANSPARENT) { 771*7c478bd9Sstevel@tonic-gate miocnak(qp, mp, 0, EINVAL); 772*7c478bd9Sstevel@tonic-gate return; 773*7c478bd9Sstevel@tonic-gate } 774*7c478bd9Sstevel@tonic-gate ASSERT(iocp->ioc_cmd == SAD_VML); 775*7c478bd9Sstevel@tonic-gate mcopyin(mp, (void *)GETSTRUCT, 776*7c478bd9Sstevel@tonic-gate SIZEOF_STRUCT(str_list, iocp->ioc_flag), NULL); 777*7c478bd9Sstevel@tonic-gate qreply(qp, mp); 778*7c478bd9Sstevel@tonic-gate } 779*7c478bd9Sstevel@tonic-gate 780*7c478bd9Sstevel@tonic-gate /* 781*7c478bd9Sstevel@tonic-gate * vml_iocdata() - 782*7c478bd9Sstevel@tonic-gate * Handle the M_IOCDATA messages associated with 783*7c478bd9Sstevel@tonic-gate * a request to validate a module list. 784*7c478bd9Sstevel@tonic-gate */ 785*7c478bd9Sstevel@tonic-gate static void 786*7c478bd9Sstevel@tonic-gate vml_iocdata( 787*7c478bd9Sstevel@tonic-gate queue_t *qp, /* pointer to write queue */ 788*7c478bd9Sstevel@tonic-gate mblk_t *mp) /* message pointer */ 789*7c478bd9Sstevel@tonic-gate { 790*7c478bd9Sstevel@tonic-gate long i; 791*7c478bd9Sstevel@tonic-gate int nmods; 792*7c478bd9Sstevel@tonic-gate struct copyresp *csp; 793*7c478bd9Sstevel@tonic-gate struct str_mlist *lp; 794*7c478bd9Sstevel@tonic-gate STRUCT_HANDLE(str_list, slp); 795*7c478bd9Sstevel@tonic-gate struct saddev *sadp; 796*7c478bd9Sstevel@tonic-gate 797*7c478bd9Sstevel@tonic-gate csp = (struct copyresp *)mp->b_rptr; 798*7c478bd9Sstevel@tonic-gate if (csp->cp_rval) { /* if there was an error */ 799*7c478bd9Sstevel@tonic-gate freemsg(mp); 800*7c478bd9Sstevel@tonic-gate return; 801*7c478bd9Sstevel@tonic-gate } 802*7c478bd9Sstevel@tonic-gate 803*7c478bd9Sstevel@tonic-gate ASSERT(csp->cp_cmd == SAD_VML); 804*7c478bd9Sstevel@tonic-gate sadp = (struct saddev *)qp->q_ptr; 805*7c478bd9Sstevel@tonic-gate switch ((long)csp->cp_private) { 806*7c478bd9Sstevel@tonic-gate case GETSTRUCT: 807*7c478bd9Sstevel@tonic-gate STRUCT_SET_HANDLE(slp, csp->cp_flag, 808*7c478bd9Sstevel@tonic-gate (struct str_list *)mp->b_cont->b_rptr); 809*7c478bd9Sstevel@tonic-gate nmods = STRUCT_FGET(slp, sl_nmods); 810*7c478bd9Sstevel@tonic-gate if (nmods <= 0) { 811*7c478bd9Sstevel@tonic-gate miocnak(qp, mp, 0, EINVAL); 812*7c478bd9Sstevel@tonic-gate break; 813*7c478bd9Sstevel@tonic-gate } 814*7c478bd9Sstevel@tonic-gate sadp->sa_addr = (caddr_t)(uintptr_t)nmods; 815*7c478bd9Sstevel@tonic-gate 816*7c478bd9Sstevel@tonic-gate mcopyin(mp, (void *)GETLIST, nmods * sizeof (struct str_mlist), 817*7c478bd9Sstevel@tonic-gate STRUCT_FGETP(slp, sl_modlist)); 818*7c478bd9Sstevel@tonic-gate qreply(qp, mp); 819*7c478bd9Sstevel@tonic-gate break; 820*7c478bd9Sstevel@tonic-gate 821*7c478bd9Sstevel@tonic-gate case GETLIST: 822*7c478bd9Sstevel@tonic-gate lp = (struct str_mlist *)mp->b_cont->b_rptr; 823*7c478bd9Sstevel@tonic-gate for (i = 0; i < (long)sadp->sa_addr; i++, lp++) { 824*7c478bd9Sstevel@tonic-gate lp->l_name[FMNAMESZ] = '\0'; 825*7c478bd9Sstevel@tonic-gate if (fmodsw_find(lp->l_name, FMODSW_LOAD) == NULL) { 826*7c478bd9Sstevel@tonic-gate miocack(qp, mp, 0, 1); 827*7c478bd9Sstevel@tonic-gate return; 828*7c478bd9Sstevel@tonic-gate } 829*7c478bd9Sstevel@tonic-gate } 830*7c478bd9Sstevel@tonic-gate miocack(qp, mp, 0, 0); 831*7c478bd9Sstevel@tonic-gate break; 832*7c478bd9Sstevel@tonic-gate 833*7c478bd9Sstevel@tonic-gate default: 834*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "vml_iocdata: invalid cp_private value: %p", 835*7c478bd9Sstevel@tonic-gate (void *)csp->cp_private); 836*7c478bd9Sstevel@tonic-gate freemsg(mp); 837*7c478bd9Sstevel@tonic-gate break; 838*7c478bd9Sstevel@tonic-gate } /* switch (cp_private) */ 839*7c478bd9Sstevel@tonic-gate } 840*7c478bd9Sstevel@tonic-gate 841*7c478bd9Sstevel@tonic-gate /* 842*7c478bd9Sstevel@tonic-gate * Validate a major number and also verify if 843*7c478bd9Sstevel@tonic-gate * it is a STREAMS device. 844*7c478bd9Sstevel@tonic-gate * Return values: 0 if a valid STREAMS dev 845*7c478bd9Sstevel@tonic-gate * error code otherwise 846*7c478bd9Sstevel@tonic-gate */ 847*7c478bd9Sstevel@tonic-gate static int 848*7c478bd9Sstevel@tonic-gate valid_major(major_t major) 849*7c478bd9Sstevel@tonic-gate { 850*7c478bd9Sstevel@tonic-gate int ret = 0; 851*7c478bd9Sstevel@tonic-gate 852*7c478bd9Sstevel@tonic-gate if (etoimajor(major) == -1) 853*7c478bd9Sstevel@tonic-gate return (EINVAL); 854*7c478bd9Sstevel@tonic-gate 855*7c478bd9Sstevel@tonic-gate /* 856*7c478bd9Sstevel@tonic-gate * attempt to load the driver 'major' and verify that 857*7c478bd9Sstevel@tonic-gate * it is a STREAMS driver. 858*7c478bd9Sstevel@tonic-gate */ 859*7c478bd9Sstevel@tonic-gate if (ddi_hold_driver(major) == NULL) 860*7c478bd9Sstevel@tonic-gate return (EINVAL); 861*7c478bd9Sstevel@tonic-gate 862*7c478bd9Sstevel@tonic-gate if (!STREAMSTAB(major)) 863*7c478bd9Sstevel@tonic-gate ret = ENOSTR; 864*7c478bd9Sstevel@tonic-gate 865*7c478bd9Sstevel@tonic-gate ddi_rele_driver(major); 866*7c478bd9Sstevel@tonic-gate 867*7c478bd9Sstevel@tonic-gate return (ret); 868*7c478bd9Sstevel@tonic-gate } 869