1*4bff34e3Sthurlow /* 2*4bff34e3Sthurlow * Copyright (c) 2000-2001 Boris Popov 3*4bff34e3Sthurlow * All rights reserved. 4*4bff34e3Sthurlow * 5*4bff34e3Sthurlow * Redistribution and use in source and binary forms, with or without 6*4bff34e3Sthurlow * modification, are permitted provided that the following conditions 7*4bff34e3Sthurlow * are met: 8*4bff34e3Sthurlow * 1. Redistributions of source code must retain the above copyright 9*4bff34e3Sthurlow * notice, this list of conditions and the following disclaimer. 10*4bff34e3Sthurlow * 2. Redistributions in binary form must reproduce the above copyright 11*4bff34e3Sthurlow * notice, this list of conditions and the following disclaimer in the 12*4bff34e3Sthurlow * documentation and/or other materials provided with the distribution. 13*4bff34e3Sthurlow * 3. All advertising materials mentioning features or use of this software 14*4bff34e3Sthurlow * must display the following acknowledgement: 15*4bff34e3Sthurlow * This product includes software developed by Boris Popov. 16*4bff34e3Sthurlow * 4. Neither the name of the author nor the names of any co-contributors 17*4bff34e3Sthurlow * may be used to endorse or promote products derived from this software 18*4bff34e3Sthurlow * without specific prior written permission. 19*4bff34e3Sthurlow * 20*4bff34e3Sthurlow * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21*4bff34e3Sthurlow * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22*4bff34e3Sthurlow * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23*4bff34e3Sthurlow * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24*4bff34e3Sthurlow * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25*4bff34e3Sthurlow * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26*4bff34e3Sthurlow * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27*4bff34e3Sthurlow * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28*4bff34e3Sthurlow * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29*4bff34e3Sthurlow * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30*4bff34e3Sthurlow * SUCH DAMAGE. 31*4bff34e3Sthurlow * 32*4bff34e3Sthurlow * $Id: smb_dev.c,v 1.21 2004/12/13 00:25:18 lindak Exp $ 33*4bff34e3Sthurlow */ 34*4bff34e3Sthurlow 35*4bff34e3Sthurlow /* 36*4bff34e3Sthurlow * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 37*4bff34e3Sthurlow * Use is subject to license terms. 38*4bff34e3Sthurlow */ 39*4bff34e3Sthurlow 40*4bff34e3Sthurlow #pragma ident "%Z%%M% %I% %E% SMI" 41*4bff34e3Sthurlow 42*4bff34e3Sthurlow #include <sys/types.h> 43*4bff34e3Sthurlow #include <sys/param.h> 44*4bff34e3Sthurlow #include <sys/errno.h> 45*4bff34e3Sthurlow #include <sys/sysmacros.h> 46*4bff34e3Sthurlow #include <sys/uio.h> 47*4bff34e3Sthurlow #include <sys/buf.h> 48*4bff34e3Sthurlow #include <sys/modctl.h> 49*4bff34e3Sthurlow #include <sys/open.h> 50*4bff34e3Sthurlow #include <sys/file.h> 51*4bff34e3Sthurlow #include <sys/kmem.h> 52*4bff34e3Sthurlow #include <sys/conf.h> 53*4bff34e3Sthurlow #include <sys/cmn_err.h> 54*4bff34e3Sthurlow #include <sys/stat.h> 55*4bff34e3Sthurlow #include <sys/ddi.h> 56*4bff34e3Sthurlow #include <sys/sunddi.h> 57*4bff34e3Sthurlow #include <sys/sunldi.h> 58*4bff34e3Sthurlow #include <sys/policy.h> 59*4bff34e3Sthurlow #include <sys/zone.h> 60*4bff34e3Sthurlow #include <sys/pathname.h> 61*4bff34e3Sthurlow #include <sys/mount.h> 62*4bff34e3Sthurlow #include <sys/sdt.h> 63*4bff34e3Sthurlow #include <fs/fs_subr.h> 64*4bff34e3Sthurlow #include <sys/modctl.h> 65*4bff34e3Sthurlow #include <sys/devops.h> 66*4bff34e3Sthurlow #include <sys/thread.h> 67*4bff34e3Sthurlow #include <sys/mkdev.h> 68*4bff34e3Sthurlow #include <sys/types.h> 69*4bff34e3Sthurlow #include <sys/zone.h> 70*4bff34e3Sthurlow 71*4bff34e3Sthurlow #ifdef APPLE 72*4bff34e3Sthurlow #include <sys/smb_apple.h> 73*4bff34e3Sthurlow #else 74*4bff34e3Sthurlow #include <netsmb/smb_osdep.h> 75*4bff34e3Sthurlow #endif 76*4bff34e3Sthurlow 77*4bff34e3Sthurlow #include <netsmb/mchain.h> /* for "htoles()" */ 78*4bff34e3Sthurlow 79*4bff34e3Sthurlow #include <netsmb/smb.h> 80*4bff34e3Sthurlow #include <netsmb/smb_conn.h> 81*4bff34e3Sthurlow #include <netsmb/smb_subr.h> 82*4bff34e3Sthurlow #include <netsmb/smb_dev.h> 83*4bff34e3Sthurlow #include <netsmb/smb_pass.h> 84*4bff34e3Sthurlow 85*4bff34e3Sthurlow /* for version checks */ 86*4bff34e3Sthurlow const uint32_t nsmb_version = NSMB_VERSION; 87*4bff34e3Sthurlow 88*4bff34e3Sthurlow /* 89*4bff34e3Sthurlow * Userland code loops through minor #s 0 to 1023, looking for one which opens. 90*4bff34e3Sthurlow * Intially we create minor 0 and leave it for anyone. Minor zero will never 91*4bff34e3Sthurlow * actually get used - opening triggers creation of another (but private) minor, 92*4bff34e3Sthurlow * which userland code will get to and mark busy. 93*4bff34e3Sthurlow */ 94*4bff34e3Sthurlow #define SMBMINORS 1024 95*4bff34e3Sthurlow static void *statep; 96*4bff34e3Sthurlow static major_t nsmb_major; 97*4bff34e3Sthurlow static minor_t nsmb_minor = 1; 98*4bff34e3Sthurlow 99*4bff34e3Sthurlow #define NSMB_MAX_MINOR (1 << 8) 100*4bff34e3Sthurlow #define NSMB_MIN_MINOR (NSMB_MAX_MINOR + 1) 101*4bff34e3Sthurlow 102*4bff34e3Sthurlow #define ILP32 1 103*4bff34e3Sthurlow #define LP64 2 104*4bff34e3Sthurlow 105*4bff34e3Sthurlow static kmutex_t dev_lck; 106*4bff34e3Sthurlow 107*4bff34e3Sthurlow /* Zone support */ 108*4bff34e3Sthurlow zone_key_t nsmb_zone_key; 109*4bff34e3Sthurlow extern void nsmb_zone_shutdown(zoneid_t zoneid, void *data); 110*4bff34e3Sthurlow extern void nsmb_zone_destroy(zoneid_t zoneid, void *data); 111*4bff34e3Sthurlow 112*4bff34e3Sthurlow /* 113*4bff34e3Sthurlow * cb_ops device operations. 114*4bff34e3Sthurlow */ 115*4bff34e3Sthurlow static int nsmb_open(dev_t *devp, int flag, int otyp, cred_t *credp); 116*4bff34e3Sthurlow static int nsmb_close(dev_t dev, int flag, int otyp, cred_t *credp); 117*4bff34e3Sthurlow static int nsmb_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, 118*4bff34e3Sthurlow cred_t *credp, int *rvalp); 119*4bff34e3Sthurlow /* smbfs cb_ops */ 120*4bff34e3Sthurlow static struct cb_ops nsmb_cbops = { 121*4bff34e3Sthurlow nsmb_open, /* open */ 122*4bff34e3Sthurlow nsmb_close, /* close */ 123*4bff34e3Sthurlow nodev, /* strategy */ 124*4bff34e3Sthurlow nodev, /* print */ 125*4bff34e3Sthurlow nodev, /* dump */ 126*4bff34e3Sthurlow nodev, /* read */ 127*4bff34e3Sthurlow nodev, /* write */ 128*4bff34e3Sthurlow nsmb_ioctl, /* ioctl */ 129*4bff34e3Sthurlow nodev, /* devmap */ 130*4bff34e3Sthurlow nodev, /* mmap */ 131*4bff34e3Sthurlow nodev, /* segmap */ 132*4bff34e3Sthurlow nochpoll, /* poll */ 133*4bff34e3Sthurlow ddi_prop_op, /* prop_op */ 134*4bff34e3Sthurlow NULL, /* stream */ 135*4bff34e3Sthurlow D_MP, /* cb_flag */ 136*4bff34e3Sthurlow CB_REV, /* rev */ 137*4bff34e3Sthurlow nodev, /* int (*cb_aread)() */ 138*4bff34e3Sthurlow nodev /* int (*cb_awrite)() */ 139*4bff34e3Sthurlow }; 140*4bff34e3Sthurlow 141*4bff34e3Sthurlow /* 142*4bff34e3Sthurlow * Device options 143*4bff34e3Sthurlow */ 144*4bff34e3Sthurlow static int nsmb_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); 145*4bff34e3Sthurlow static int nsmb_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); 146*4bff34e3Sthurlow static int nsmb_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, 147*4bff34e3Sthurlow void *arg, void **result); 148*4bff34e3Sthurlow 149*4bff34e3Sthurlow static struct dev_ops nsmb_ops = { 150*4bff34e3Sthurlow DEVO_REV, /* devo_rev, */ 151*4bff34e3Sthurlow 0, /* refcnt */ 152*4bff34e3Sthurlow nsmb_getinfo, /* info */ 153*4bff34e3Sthurlow nulldev, /* identify */ 154*4bff34e3Sthurlow nulldev, /* probe */ 155*4bff34e3Sthurlow nsmb_attach, /* attach */ 156*4bff34e3Sthurlow nsmb_detach, /* detach */ 157*4bff34e3Sthurlow nodev, /* reset */ 158*4bff34e3Sthurlow &nsmb_cbops, /* driver ops - devctl interfaces */ 159*4bff34e3Sthurlow NULL, /* bus operations */ 160*4bff34e3Sthurlow NULL /* power */ 161*4bff34e3Sthurlow }; 162*4bff34e3Sthurlow 163*4bff34e3Sthurlow /* 164*4bff34e3Sthurlow * Module linkage information. 165*4bff34e3Sthurlow */ 166*4bff34e3Sthurlow 167*4bff34e3Sthurlow static struct modldrv nsmb_modldrv = { 168*4bff34e3Sthurlow &mod_driverops, /* Driver module */ 169*4bff34e3Sthurlow "SMBFS network driver v" NSMB_VER_STR, 170*4bff34e3Sthurlow &nsmb_ops /* Driver ops */ 171*4bff34e3Sthurlow }; 172*4bff34e3Sthurlow 173*4bff34e3Sthurlow static struct modlinkage nsmb_modlinkage = { 174*4bff34e3Sthurlow MODREV_1, 175*4bff34e3Sthurlow (void *)&nsmb_modldrv, 176*4bff34e3Sthurlow NULL 177*4bff34e3Sthurlow }; 178*4bff34e3Sthurlow 179*4bff34e3Sthurlow int 180*4bff34e3Sthurlow _init(void) 181*4bff34e3Sthurlow { 182*4bff34e3Sthurlow int error; 183*4bff34e3Sthurlow 184*4bff34e3Sthurlow ddi_soft_state_init(&statep, sizeof (smb_dev_t), 1); 185*4bff34e3Sthurlow 186*4bff34e3Sthurlow /* Can initialize some mutexes also. */ 187*4bff34e3Sthurlow mutex_init(&dev_lck, NULL, MUTEX_DRIVER, NULL); 188*4bff34e3Sthurlow /* 189*4bff34e3Sthurlow * Create a major name and number. 190*4bff34e3Sthurlow */ 191*4bff34e3Sthurlow nsmb_major = ddi_name_to_major(NSMB_NAME); 192*4bff34e3Sthurlow nsmb_minor = 0; 193*4bff34e3Sthurlow 194*4bff34e3Sthurlow /* Connection data structures. */ 195*4bff34e3Sthurlow (void) smb_sm_init(); 196*4bff34e3Sthurlow 197*4bff34e3Sthurlow /* Initialize password Key chain DB. */ 198*4bff34e3Sthurlow smb_pkey_init(); 199*4bff34e3Sthurlow 200*4bff34e3Sthurlow zone_key_create(&nsmb_zone_key, NULL, nsmb_zone_shutdown, 201*4bff34e3Sthurlow nsmb_zone_destroy); 202*4bff34e3Sthurlow 203*4bff34e3Sthurlow /* 204*4bff34e3Sthurlow * Install the module. Do this after other init, 205*4bff34e3Sthurlow * to prevent entrances before we're ready. 206*4bff34e3Sthurlow */ 207*4bff34e3Sthurlow if ((error = mod_install((&nsmb_modlinkage))) != 0) { 208*4bff34e3Sthurlow 209*4bff34e3Sthurlow /* Same as 2nd half of _fini */ 210*4bff34e3Sthurlow (void) zone_key_delete(nsmb_zone_key); 211*4bff34e3Sthurlow smb_pkey_fini(); 212*4bff34e3Sthurlow smb_sm_done(); 213*4bff34e3Sthurlow mutex_destroy(&dev_lck); 214*4bff34e3Sthurlow ddi_soft_state_fini(&statep); 215*4bff34e3Sthurlow 216*4bff34e3Sthurlow return (error); 217*4bff34e3Sthurlow } 218*4bff34e3Sthurlow 219*4bff34e3Sthurlow return (0); 220*4bff34e3Sthurlow } 221*4bff34e3Sthurlow 222*4bff34e3Sthurlow int 223*4bff34e3Sthurlow _fini(void) 224*4bff34e3Sthurlow { 225*4bff34e3Sthurlow int status; 226*4bff34e3Sthurlow 227*4bff34e3Sthurlow /* 228*4bff34e3Sthurlow * Prevent unload if we have active VCs 229*4bff34e3Sthurlow * or stored passwords 230*4bff34e3Sthurlow */ 231*4bff34e3Sthurlow if ((status = smb_sm_idle()) != 0) 232*4bff34e3Sthurlow return (status); 233*4bff34e3Sthurlow if ((status = smb_pkey_idle()) != 0) 234*4bff34e3Sthurlow return (status); 235*4bff34e3Sthurlow 236*4bff34e3Sthurlow /* 237*4bff34e3Sthurlow * Remove the module. Do this before destroying things, 238*4bff34e3Sthurlow * to prevent new entrances while we're destorying. 239*4bff34e3Sthurlow */ 240*4bff34e3Sthurlow if ((status = mod_remove(&nsmb_modlinkage)) != 0) { 241*4bff34e3Sthurlow return (status); 242*4bff34e3Sthurlow } 243*4bff34e3Sthurlow 244*4bff34e3Sthurlow (void) zone_key_delete(nsmb_zone_key); 245*4bff34e3Sthurlow 246*4bff34e3Sthurlow /* Destroy password Key chain DB. */ 247*4bff34e3Sthurlow smb_pkey_fini(); 248*4bff34e3Sthurlow 249*4bff34e3Sthurlow smb_sm_done(); 250*4bff34e3Sthurlow 251*4bff34e3Sthurlow mutex_destroy(&dev_lck); 252*4bff34e3Sthurlow ddi_soft_state_fini(&statep); 253*4bff34e3Sthurlow 254*4bff34e3Sthurlow return (status); 255*4bff34e3Sthurlow } 256*4bff34e3Sthurlow 257*4bff34e3Sthurlow int 258*4bff34e3Sthurlow _info(struct modinfo *modinfop) 259*4bff34e3Sthurlow { 260*4bff34e3Sthurlow return (mod_info(&nsmb_modlinkage, modinfop)); 261*4bff34e3Sthurlow } 262*4bff34e3Sthurlow 263*4bff34e3Sthurlow /*ARGSUSED*/ 264*4bff34e3Sthurlow static int 265*4bff34e3Sthurlow nsmb_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) 266*4bff34e3Sthurlow { 267*4bff34e3Sthurlow int ret = DDI_SUCCESS; 268*4bff34e3Sthurlow 269*4bff34e3Sthurlow switch (cmd) { 270*4bff34e3Sthurlow case DDI_INFO_DEVT2DEVINFO: 271*4bff34e3Sthurlow *result = 0; 272*4bff34e3Sthurlow break; 273*4bff34e3Sthurlow case DDI_INFO_DEVT2INSTANCE: 274*4bff34e3Sthurlow *result = 0; 275*4bff34e3Sthurlow break; 276*4bff34e3Sthurlow default: 277*4bff34e3Sthurlow ret = DDI_FAILURE; 278*4bff34e3Sthurlow } 279*4bff34e3Sthurlow return (ret); 280*4bff34e3Sthurlow } 281*4bff34e3Sthurlow 282*4bff34e3Sthurlow static int 283*4bff34e3Sthurlow nsmb_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 284*4bff34e3Sthurlow { 285*4bff34e3Sthurlow smb_dev_t *sdp; 286*4bff34e3Sthurlow 287*4bff34e3Sthurlow if (cmd != DDI_ATTACH) 288*4bff34e3Sthurlow return (DDI_FAILURE); 289*4bff34e3Sthurlow /* 290*4bff34e3Sthurlow * only one instance - but we clone using the open routine 291*4bff34e3Sthurlow */ 292*4bff34e3Sthurlow if (ddi_get_instance(dip) > 0) 293*4bff34e3Sthurlow return (DDI_FAILURE); 294*4bff34e3Sthurlow 295*4bff34e3Sthurlow mutex_enter(&dev_lck); 296*4bff34e3Sthurlow 297*4bff34e3Sthurlow /* 298*4bff34e3Sthurlow * This is the Zero'th minor device which is created. 299*4bff34e3Sthurlow */ 300*4bff34e3Sthurlow if (ddi_soft_state_zalloc(statep, 0) == DDI_FAILURE) { 301*4bff34e3Sthurlow cmn_err(CE_WARN, "nsmb_attach: soft state alloc"); 302*4bff34e3Sthurlow goto attach_failed; 303*4bff34e3Sthurlow } 304*4bff34e3Sthurlow if (ddi_create_minor_node(dip, "nsmb", S_IFCHR, 0, DDI_PSEUDO, 305*4bff34e3Sthurlow NULL) == DDI_FAILURE) { 306*4bff34e3Sthurlow cmn_err(CE_WARN, "nsmb_attach: create minor"); 307*4bff34e3Sthurlow goto attach_failed; 308*4bff34e3Sthurlow } 309*4bff34e3Sthurlow if ((sdp = ddi_get_soft_state(statep, 0)) == NULL) { 310*4bff34e3Sthurlow cmn_err(CE_WARN, "nsmb_attach: get soft state"); 311*4bff34e3Sthurlow ddi_remove_minor_node(dip, NULL); 312*4bff34e3Sthurlow goto attach_failed; 313*4bff34e3Sthurlow } 314*4bff34e3Sthurlow 315*4bff34e3Sthurlow /* 316*4bff34e3Sthurlow * Need to see if this field is required. 317*4bff34e3Sthurlow * REVISIT 318*4bff34e3Sthurlow */ 319*4bff34e3Sthurlow sdp->smb_dip = dip; 320*4bff34e3Sthurlow sdp->sd_seq = 0; 321*4bff34e3Sthurlow sdp->sd_opened = 1; 322*4bff34e3Sthurlow 323*4bff34e3Sthurlow mutex_exit(&dev_lck); 324*4bff34e3Sthurlow ddi_report_dev(dip); 325*4bff34e3Sthurlow return (DDI_SUCCESS); 326*4bff34e3Sthurlow 327*4bff34e3Sthurlow attach_failed: 328*4bff34e3Sthurlow ddi_soft_state_free(statep, 0); 329*4bff34e3Sthurlow mutex_exit(&dev_lck); 330*4bff34e3Sthurlow return (DDI_FAILURE); 331*4bff34e3Sthurlow } 332*4bff34e3Sthurlow 333*4bff34e3Sthurlow /*ARGSUSED*/ 334*4bff34e3Sthurlow static int 335*4bff34e3Sthurlow nsmb_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 336*4bff34e3Sthurlow { 337*4bff34e3Sthurlow 338*4bff34e3Sthurlow if (cmd != DDI_DETACH) 339*4bff34e3Sthurlow return (DDI_FAILURE); 340*4bff34e3Sthurlow if (ddi_get_instance(dip) > 0) 341*4bff34e3Sthurlow return (DDI_FAILURE); 342*4bff34e3Sthurlow 343*4bff34e3Sthurlow ddi_soft_state_free(statep, 0); 344*4bff34e3Sthurlow ddi_remove_minor_node(dip, NULL); 345*4bff34e3Sthurlow 346*4bff34e3Sthurlow return (DDI_SUCCESS); 347*4bff34e3Sthurlow } 348*4bff34e3Sthurlow 349*4bff34e3Sthurlow /*ARGSUSED*/ 350*4bff34e3Sthurlow static int 351*4bff34e3Sthurlow nsmb_ioctl(dev_t dev, 352*4bff34e3Sthurlow int cmd, 353*4bff34e3Sthurlow intptr_t arg, 354*4bff34e3Sthurlow int mode, 355*4bff34e3Sthurlow cred_t *credp, 356*4bff34e3Sthurlow int *rvalp) 357*4bff34e3Sthurlow { 358*4bff34e3Sthurlow smb_dev_t *sdp; 359*4bff34e3Sthurlow struct smb_vc *vcp = NULL; 360*4bff34e3Sthurlow struct smb_share *ssp = NULL; 361*4bff34e3Sthurlow struct smb_cred scred; 362*4bff34e3Sthurlow int err, error; 363*4bff34e3Sthurlow uid_t uid; 364*4bff34e3Sthurlow 365*4bff34e3Sthurlow /* Free any+all of these at end of switch. */ 366*4bff34e3Sthurlow smbioc_lookup_t *sioc = NULL; 367*4bff34e3Sthurlow smbioc_rq_t *srq = NULL; 368*4bff34e3Sthurlow smbioc_rw_t *rwrq = NULL; 369*4bff34e3Sthurlow smbioc_t2rq_t *strq = NULL; 370*4bff34e3Sthurlow smbioc_pk_t *pk = NULL; 371*4bff34e3Sthurlow 372*4bff34e3Sthurlow sdp = ddi_get_soft_state(statep, getminor(dev)); 373*4bff34e3Sthurlow if (sdp == NULL) { 374*4bff34e3Sthurlow return (DDI_FAILURE); 375*4bff34e3Sthurlow } 376*4bff34e3Sthurlow if ((sdp->sd_flags & NSMBFL_OPEN) == 0) { 377*4bff34e3Sthurlow return (EBADF); 378*4bff34e3Sthurlow } 379*4bff34e3Sthurlow 380*4bff34e3Sthurlow /* 381*4bff34e3Sthurlow * Dont give access if the zone id is not as the same as we 382*4bff34e3Sthurlow * set in the nsmb_open or dont belong to the global zone. 383*4bff34e3Sthurlow * Check if the user belongs to this zone.. 384*4bff34e3Sthurlow */ 385*4bff34e3Sthurlow if (sdp->zoneid != getzoneid()) 386*4bff34e3Sthurlow return (EIO); 387*4bff34e3Sthurlow if (cmd != SMBIOC_TDIS && 388*4bff34e3Sthurlow zone_status_get(curproc->p_zone) >= ZONE_IS_SHUTTING_DOWN) 389*4bff34e3Sthurlow return (EIO); 390*4bff34e3Sthurlow 391*4bff34e3Sthurlow 392*4bff34e3Sthurlow error = 0; 393*4bff34e3Sthurlow smb_credinit(&scred, curproc, credp); 394*4bff34e3Sthurlow switch (cmd) { 395*4bff34e3Sthurlow case SMBIOC_GETVERS: 396*4bff34e3Sthurlow ddi_copyout(&nsmb_version, (void *)arg, 397*4bff34e3Sthurlow sizeof (nsmb_version), mode); 398*4bff34e3Sthurlow break; 399*4bff34e3Sthurlow 400*4bff34e3Sthurlow case SMBIOC_REQUEST: 401*4bff34e3Sthurlow if (sdp->sd_share == NULL) { 402*4bff34e3Sthurlow error = ENOTCONN; 403*4bff34e3Sthurlow break; 404*4bff34e3Sthurlow } 405*4bff34e3Sthurlow srq = kmem_alloc(sizeof (*srq), KM_SLEEP); 406*4bff34e3Sthurlow if (ddi_copyin((void *) arg, srq, 407*4bff34e3Sthurlow sizeof (*srq), mode)) { 408*4bff34e3Sthurlow error = EFAULT; 409*4bff34e3Sthurlow break; 410*4bff34e3Sthurlow } 411*4bff34e3Sthurlow error = smb_usr_simplerequest(sdp->sd_share, 412*4bff34e3Sthurlow srq, &scred); 413*4bff34e3Sthurlow ddi_copyout(srq, (void *)arg, 414*4bff34e3Sthurlow SMBIOC_RQ_COPYOUT_SIZE, mode); 415*4bff34e3Sthurlow break; 416*4bff34e3Sthurlow 417*4bff34e3Sthurlow case SMBIOC_T2RQ: 418*4bff34e3Sthurlow if (sdp->sd_share == NULL) { 419*4bff34e3Sthurlow error = ENOTCONN; 420*4bff34e3Sthurlow break; 421*4bff34e3Sthurlow } 422*4bff34e3Sthurlow strq = kmem_alloc(sizeof (*strq), KM_SLEEP); 423*4bff34e3Sthurlow if (ddi_copyin((void *)arg, strq, 424*4bff34e3Sthurlow sizeof (*strq), mode)) { 425*4bff34e3Sthurlow error = EFAULT; 426*4bff34e3Sthurlow break; 427*4bff34e3Sthurlow } 428*4bff34e3Sthurlow error = smb_usr_t2request(sdp->sd_share, strq, &scred); 429*4bff34e3Sthurlow ddi_copyout(strq, (void *)arg, 430*4bff34e3Sthurlow SMBIOC_T2RQ_COPYOUT_SIZE, mode); 431*4bff34e3Sthurlow break; 432*4bff34e3Sthurlow 433*4bff34e3Sthurlow case SMBIOC_READ: 434*4bff34e3Sthurlow case SMBIOC_WRITE: 435*4bff34e3Sthurlow if ((ssp = sdp->sd_share) == NULL) { 436*4bff34e3Sthurlow error = ENOTCONN; 437*4bff34e3Sthurlow break; 438*4bff34e3Sthurlow } 439*4bff34e3Sthurlow rwrq = kmem_alloc(sizeof (*rwrq), KM_SLEEP); 440*4bff34e3Sthurlow if (ddi_copyin((void *)arg, rwrq, 441*4bff34e3Sthurlow sizeof (*rwrq), mode)) { 442*4bff34e3Sthurlow error = EFAULT; 443*4bff34e3Sthurlow break; 444*4bff34e3Sthurlow } 445*4bff34e3Sthurlow error = smb_usr_rw(ssp, rwrq, cmd, &scred); 446*4bff34e3Sthurlow ddi_copyout(rwrq, (void *)arg, 447*4bff34e3Sthurlow SMBIOC_RW_COPYOUT_SIZE, mode); 448*4bff34e3Sthurlow break; 449*4bff34e3Sthurlow 450*4bff34e3Sthurlow case SMBIOC_NEGOTIATE: 451*4bff34e3Sthurlow /* Should be no VC (and no share) */ 452*4bff34e3Sthurlow if (sdp->sd_vc || sdp->sd_share) { 453*4bff34e3Sthurlow error = EISCONN; 454*4bff34e3Sthurlow break; 455*4bff34e3Sthurlow } 456*4bff34e3Sthurlow sioc = kmem_alloc(sizeof (*sioc), KM_SLEEP); 457*4bff34e3Sthurlow if (ddi_copyin((void *)arg, sioc, 458*4bff34e3Sthurlow sizeof (*sioc), mode)) { 459*4bff34e3Sthurlow error = EFAULT; 460*4bff34e3Sthurlow break; 461*4bff34e3Sthurlow } 462*4bff34e3Sthurlow vcp = NULL; 463*4bff34e3Sthurlow ssp = NULL; 464*4bff34e3Sthurlow error = smb_usr_negotiate(sioc, &scred, &vcp); 465*4bff34e3Sthurlow if (error) 466*4bff34e3Sthurlow break; 467*4bff34e3Sthurlow if (vcp) { 468*4bff34e3Sthurlow /* 469*4bff34e3Sthurlow * The VC has a hold from _negotiate 470*4bff34e3Sthurlow * which we keep until nsmb_close(). 471*4bff34e3Sthurlow */ 472*4bff34e3Sthurlow sdp->sd_level = SMBL_VC; 473*4bff34e3Sthurlow sdp->sd_vc = vcp; 474*4bff34e3Sthurlow /* 475*4bff34e3Sthurlow * If we just created this VC, and 476*4bff34e3Sthurlow * this minor is doing the setup, 477*4bff34e3Sthurlow * keep track of that fact here. 478*4bff34e3Sthurlow */ 479*4bff34e3Sthurlow if (vcp->vc_state < SMBIOD_ST_VCACTIVE) 480*4bff34e3Sthurlow sdp->sd_flags |= NSMBFL_NEWVC; 481*4bff34e3Sthurlow 482*4bff34e3Sthurlow } 483*4bff34e3Sthurlow /* 484*4bff34e3Sthurlow * Copyout the "out token" (security blob). 485*4bff34e3Sthurlow * 486*4bff34e3Sthurlow * This code used to be near the end of 487*4bff34e3Sthurlow * smb_usr_negotiate(). Moved the copyout 488*4bff34e3Sthurlow * calls here so we know the "mode" 489*4bff34e3Sthurlow */ 490*4bff34e3Sthurlow if (vcp->vc_outtok) { 491*4bff34e3Sthurlow /* 492*4bff34e3Sthurlow * Note: will copyout sioc below 493*4bff34e3Sthurlow * including sioc.vc_outtoklen, 494*4bff34e3Sthurlow * so we no longer put the length 495*4bff34e3Sthurlow * at the start of the outtok data. 496*4bff34e3Sthurlow */ 497*4bff34e3Sthurlow sioc->ioc_ssn.ioc_outtoklen = 498*4bff34e3Sthurlow vcp->vc_outtoklen; 499*4bff34e3Sthurlow err = ddi_copyout( 500*4bff34e3Sthurlow vcp->vc_outtok, 501*4bff34e3Sthurlow sioc->ioc_ssn.ioc_outtok, 502*4bff34e3Sthurlow vcp->vc_outtoklen, mode); 503*4bff34e3Sthurlow if (err) { 504*4bff34e3Sthurlow error = EFAULT; 505*4bff34e3Sthurlow break; 506*4bff34e3Sthurlow } 507*4bff34e3Sthurlow /* 508*4bff34e3Sthurlow * Save this blob in vc_negtok. 509*4bff34e3Sthurlow * We need it in case we have to 510*4bff34e3Sthurlow * reconnect. 511*4bff34e3Sthurlow * 512*4bff34e3Sthurlow * Set vc_negtok = vc_outtok 513*4bff34e3Sthurlow * but free vc_negtok first. 514*4bff34e3Sthurlow */ 515*4bff34e3Sthurlow if (vcp->vc_negtok) { 516*4bff34e3Sthurlow kmem_free( 517*4bff34e3Sthurlow vcp->vc_negtok, 518*4bff34e3Sthurlow vcp->vc_negtoklen); 519*4bff34e3Sthurlow vcp->vc_negtok = NULL; 520*4bff34e3Sthurlow vcp->vc_negtoklen = 0; 521*4bff34e3Sthurlow } 522*4bff34e3Sthurlow vcp->vc_negtok = vcp->vc_outtok; 523*4bff34e3Sthurlow vcp->vc_negtoklen = vcp->vc_outtoklen; 524*4bff34e3Sthurlow vcp->vc_outtok = NULL; 525*4bff34e3Sthurlow vcp->vc_outtoklen = 0; 526*4bff34e3Sthurlow } 527*4bff34e3Sthurlow /* 528*4bff34e3Sthurlow * Added copyout here of (almost) 529*4bff34e3Sthurlow * the whole struct, even though 530*4bff34e3Sthurlow * the lib only needs _outtoklen. 531*4bff34e3Sthurlow * We may put other things in this 532*4bff34e3Sthurlow * struct that user-land needs. 533*4bff34e3Sthurlow */ 534*4bff34e3Sthurlow err = ddi_copyout(sioc, (void *)arg, 535*4bff34e3Sthurlow SMBIOC_LOOK_COPYOUT_SIZE, mode); 536*4bff34e3Sthurlow if (err) 537*4bff34e3Sthurlow error = EFAULT; 538*4bff34e3Sthurlow break; 539*4bff34e3Sthurlow 540*4bff34e3Sthurlow case SMBIOC_SSNSETUP: 541*4bff34e3Sthurlow /* Must have a VC, but no share. */ 542*4bff34e3Sthurlow if (sdp->sd_share) { 543*4bff34e3Sthurlow error = EISCONN; 544*4bff34e3Sthurlow break; 545*4bff34e3Sthurlow } 546*4bff34e3Sthurlow if (!sdp->sd_vc) { 547*4bff34e3Sthurlow error = ENOTCONN; 548*4bff34e3Sthurlow break; 549*4bff34e3Sthurlow } 550*4bff34e3Sthurlow sioc = kmem_alloc(sizeof (*sioc), KM_SLEEP); 551*4bff34e3Sthurlow if (ddi_copyin((void *)arg, sioc, 552*4bff34e3Sthurlow sizeof (*sioc), mode)) { 553*4bff34e3Sthurlow error = EFAULT; 554*4bff34e3Sthurlow break; 555*4bff34e3Sthurlow } 556*4bff34e3Sthurlow vcp = sdp->sd_vc; 557*4bff34e3Sthurlow ssp = NULL; 558*4bff34e3Sthurlow error = smb_usr_ssnsetup(sioc, &scred, vcp); 559*4bff34e3Sthurlow if (error) 560*4bff34e3Sthurlow break; 561*4bff34e3Sthurlow /* 562*4bff34e3Sthurlow * If this minor has finished ssn setup, 563*4bff34e3Sthurlow * turn off the NEWVC flag, otherwise we 564*4bff34e3Sthurlow * will kill this VC when we close. 565*4bff34e3Sthurlow */ 566*4bff34e3Sthurlow if (vcp->vc_state == SMBIOD_ST_VCACTIVE) 567*4bff34e3Sthurlow sdp->sd_flags &= ~NSMBFL_NEWVC; 568*4bff34e3Sthurlow /* 569*4bff34e3Sthurlow * Copyout the "out token" (security blob). 570*4bff34e3Sthurlow * 571*4bff34e3Sthurlow * This code used to be near the end of 572*4bff34e3Sthurlow * smb_usr_ssnsetup(). Moved the copyout 573*4bff34e3Sthurlow * calls here so we know the "mode" 574*4bff34e3Sthurlow */ 575*4bff34e3Sthurlow if (vcp->vc_outtok) { 576*4bff34e3Sthurlow /* 577*4bff34e3Sthurlow * Note: will copyout sioc below 578*4bff34e3Sthurlow * including sioc.vc_outtoklen, 579*4bff34e3Sthurlow * so we no longer put the length 580*4bff34e3Sthurlow * at the start of the outtok data. 581*4bff34e3Sthurlow */ 582*4bff34e3Sthurlow sioc->ioc_ssn.ioc_outtoklen = 583*4bff34e3Sthurlow vcp->vc_outtoklen; 584*4bff34e3Sthurlow err = ddi_copyout( 585*4bff34e3Sthurlow vcp->vc_outtok, 586*4bff34e3Sthurlow sioc->ioc_ssn.ioc_outtok, 587*4bff34e3Sthurlow vcp->vc_outtoklen, mode); 588*4bff34e3Sthurlow if (err) { 589*4bff34e3Sthurlow error = EFAULT; 590*4bff34e3Sthurlow break; 591*4bff34e3Sthurlow } 592*4bff34e3Sthurlow /* 593*4bff34e3Sthurlow * Done with vc_outtok. Similar, 594*4bff34e3Sthurlow * but NOT the same as after the 595*4bff34e3Sthurlow * smb_usr_negotiate call above. 596*4bff34e3Sthurlow */ 597*4bff34e3Sthurlow kmem_free( 598*4bff34e3Sthurlow vcp->vc_outtok, 599*4bff34e3Sthurlow vcp->vc_outtoklen); 600*4bff34e3Sthurlow vcp->vc_outtok = NULL; 601*4bff34e3Sthurlow vcp->vc_outtoklen = 0; 602*4bff34e3Sthurlow } 603*4bff34e3Sthurlow /* Added copyout here... (see above) */ 604*4bff34e3Sthurlow err = ddi_copyout(sioc, (void *)arg, 605*4bff34e3Sthurlow SMBIOC_LOOK_COPYOUT_SIZE, mode); 606*4bff34e3Sthurlow if (err) 607*4bff34e3Sthurlow error = EFAULT; 608*4bff34e3Sthurlow break; 609*4bff34e3Sthurlow 610*4bff34e3Sthurlow case SMBIOC_TCON: 611*4bff34e3Sthurlow /* Must have a VC, but no share. */ 612*4bff34e3Sthurlow if (sdp->sd_share) { 613*4bff34e3Sthurlow error = EISCONN; 614*4bff34e3Sthurlow break; 615*4bff34e3Sthurlow } 616*4bff34e3Sthurlow if (!sdp->sd_vc) { 617*4bff34e3Sthurlow error = ENOTCONN; 618*4bff34e3Sthurlow break; 619*4bff34e3Sthurlow } 620*4bff34e3Sthurlow sioc = kmem_alloc(sizeof (*sioc), KM_SLEEP); 621*4bff34e3Sthurlow if (ddi_copyin((void *)arg, sioc, 622*4bff34e3Sthurlow sizeof (*sioc), mode)) { 623*4bff34e3Sthurlow error = EFAULT; 624*4bff34e3Sthurlow break; 625*4bff34e3Sthurlow } 626*4bff34e3Sthurlow vcp = sdp->sd_vc; 627*4bff34e3Sthurlow ssp = NULL; 628*4bff34e3Sthurlow error = smb_usr_tcon(sioc, &scred, vcp, &ssp); 629*4bff34e3Sthurlow if (error) 630*4bff34e3Sthurlow break; 631*4bff34e3Sthurlow if (ssp) { 632*4bff34e3Sthurlow /* 633*4bff34e3Sthurlow * The share has a hold from _tcon 634*4bff34e3Sthurlow * which we keep until nsmb_close() 635*4bff34e3Sthurlow * or the SMBIOC_TDIS below. 636*4bff34e3Sthurlow */ 637*4bff34e3Sthurlow sdp->sd_share = ssp; 638*4bff34e3Sthurlow sdp->sd_level = SMBL_SHARE; 639*4bff34e3Sthurlow } 640*4bff34e3Sthurlow /* No need for copyout here. */ 641*4bff34e3Sthurlow break; 642*4bff34e3Sthurlow 643*4bff34e3Sthurlow case SMBIOC_TDIS: 644*4bff34e3Sthurlow if (sdp->sd_share == NULL) { 645*4bff34e3Sthurlow error = ENOTCONN; 646*4bff34e3Sthurlow break; 647*4bff34e3Sthurlow } 648*4bff34e3Sthurlow smb_share_rele(sdp->sd_share); 649*4bff34e3Sthurlow sdp->sd_share = NULL; 650*4bff34e3Sthurlow sdp->sd_level = SMBL_VC; 651*4bff34e3Sthurlow break; 652*4bff34e3Sthurlow case SMBIOC_FLAGS2: 653*4bff34e3Sthurlow if (sdp->sd_share == NULL) { 654*4bff34e3Sthurlow error = ENOTCONN; 655*4bff34e3Sthurlow break; 656*4bff34e3Sthurlow } 657*4bff34e3Sthurlow if (!sdp->sd_vc) { 658*4bff34e3Sthurlow error = ENOTCONN; 659*4bff34e3Sthurlow break; 660*4bff34e3Sthurlow } 661*4bff34e3Sthurlow vcp = sdp->sd_vc; 662*4bff34e3Sthurlow /* 663*4bff34e3Sthurlow * Return the flags2 value. 664*4bff34e3Sthurlow */ 665*4bff34e3Sthurlow ddi_copyout(&vcp->vc_hflags2, (void *)arg, 666*4bff34e3Sthurlow sizeof (u_int16_t), mode); 667*4bff34e3Sthurlow break; 668*4bff34e3Sthurlow 669*4bff34e3Sthurlow case SMBIOC_PK_ADD: 670*4bff34e3Sthurlow pk = kmem_alloc(sizeof (*pk), KM_SLEEP); 671*4bff34e3Sthurlow if (ddi_copyin((void *)arg, pk, 672*4bff34e3Sthurlow sizeof (*pk), mode)) { 673*4bff34e3Sthurlow error = EFAULT; 674*4bff34e3Sthurlow break; 675*4bff34e3Sthurlow } 676*4bff34e3Sthurlow error = smb_pkey_add(pk, credp); 677*4bff34e3Sthurlow break; 678*4bff34e3Sthurlow 679*4bff34e3Sthurlow case SMBIOC_PK_DEL: 680*4bff34e3Sthurlow pk = kmem_alloc(sizeof (*pk), KM_SLEEP); 681*4bff34e3Sthurlow if (ddi_copyin((void *)arg, pk, 682*4bff34e3Sthurlow sizeof (*pk), mode)) { 683*4bff34e3Sthurlow error = EFAULT; 684*4bff34e3Sthurlow break; 685*4bff34e3Sthurlow } 686*4bff34e3Sthurlow error = smb_pkey_del(pk, credp); 687*4bff34e3Sthurlow break; 688*4bff34e3Sthurlow 689*4bff34e3Sthurlow case SMBIOC_PK_CHK: 690*4bff34e3Sthurlow pk = kmem_alloc(sizeof (*pk), KM_SLEEP); 691*4bff34e3Sthurlow if (ddi_copyin((void *)arg, pk, 692*4bff34e3Sthurlow sizeof (*pk), mode)) { 693*4bff34e3Sthurlow error = EFAULT; 694*4bff34e3Sthurlow break; 695*4bff34e3Sthurlow } 696*4bff34e3Sthurlow error = smb_pkey_check(pk, credp); 697*4bff34e3Sthurlow /* 698*4bff34e3Sthurlow * Note: Intentionally DO NOT copyout 699*4bff34e3Sthurlow * the pasword here. It can only be 700*4bff34e3Sthurlow * retrieved by internal calls. This 701*4bff34e3Sthurlow * ioctl only tells the caller if the 702*4bff34e3Sthurlow * keychain entry exists. 703*4bff34e3Sthurlow */ 704*4bff34e3Sthurlow break; 705*4bff34e3Sthurlow 706*4bff34e3Sthurlow case SMBIOC_PK_DEL_OWNER: 707*4bff34e3Sthurlow uid = crgetruid(credp); 708*4bff34e3Sthurlow error = smb_pkey_deluid(uid, credp); 709*4bff34e3Sthurlow break; 710*4bff34e3Sthurlow 711*4bff34e3Sthurlow case SMBIOC_PK_DEL_EVERYONE: 712*4bff34e3Sthurlow uid = (uid_t)-1; 713*4bff34e3Sthurlow error = smb_pkey_deluid(uid, credp); 714*4bff34e3Sthurlow break; 715*4bff34e3Sthurlow 716*4bff34e3Sthurlow default: 717*4bff34e3Sthurlow error = ENODEV; 718*4bff34e3Sthurlow } 719*4bff34e3Sthurlow 720*4bff34e3Sthurlow /* 721*4bff34e3Sthurlow * Let's just do all the kmem_free stuff HERE, 722*4bff34e3Sthurlow * instead of at every switch break. 723*4bff34e3Sthurlow */ 724*4bff34e3Sthurlow 725*4bff34e3Sthurlow /* SMBIOC_REQUEST */ 726*4bff34e3Sthurlow if (srq) 727*4bff34e3Sthurlow kmem_free(srq, sizeof (*srq)); 728*4bff34e3Sthurlow 729*4bff34e3Sthurlow /* SMBIOC_T2RQ */ 730*4bff34e3Sthurlow if (strq) 731*4bff34e3Sthurlow kmem_free(strq, sizeof (*strq)); 732*4bff34e3Sthurlow 733*4bff34e3Sthurlow /* SMBIOC_READ */ 734*4bff34e3Sthurlow /* SMBIOC_WRITE */ 735*4bff34e3Sthurlow if (rwrq) 736*4bff34e3Sthurlow kmem_free(rwrq, sizeof (*rwrq)); 737*4bff34e3Sthurlow 738*4bff34e3Sthurlow /* SMBIOC_NEGOTIATE */ 739*4bff34e3Sthurlow /* SMBIOC_SSNSETUP */ 740*4bff34e3Sthurlow /* SMBIOC_TCON */ 741*4bff34e3Sthurlow if (sioc) { 742*4bff34e3Sthurlow /* 743*4bff34e3Sthurlow * This data structure may contain 744*4bff34e3Sthurlow * cleartext passwords, so zap it. 745*4bff34e3Sthurlow */ 746*4bff34e3Sthurlow bzero(sioc, sizeof (*sioc)); 747*4bff34e3Sthurlow kmem_free(sioc, sizeof (*sioc)); 748*4bff34e3Sthurlow } 749*4bff34e3Sthurlow 750*4bff34e3Sthurlow /* SMBIOC_PK_... */ 751*4bff34e3Sthurlow if (pk) { 752*4bff34e3Sthurlow /* 753*4bff34e3Sthurlow * This data structure may contain 754*4bff34e3Sthurlow * cleartext passwords, so zap it. 755*4bff34e3Sthurlow */ 756*4bff34e3Sthurlow bzero(pk, sizeof (*pk)); 757*4bff34e3Sthurlow kmem_free(pk, sizeof (*pk)); 758*4bff34e3Sthurlow } 759*4bff34e3Sthurlow 760*4bff34e3Sthurlow smb_credrele(&scred); 761*4bff34e3Sthurlow 762*4bff34e3Sthurlow return (error); 763*4bff34e3Sthurlow } 764*4bff34e3Sthurlow 765*4bff34e3Sthurlow /*ARGSUSED*/ 766*4bff34e3Sthurlow static int 767*4bff34e3Sthurlow nsmb_open(dev_t *dev, int flags, int otyp, cred_t *cr) 768*4bff34e3Sthurlow { 769*4bff34e3Sthurlow major_t new_major; 770*4bff34e3Sthurlow smb_dev_t *sdp, *sdv; 771*4bff34e3Sthurlow 772*4bff34e3Sthurlow mutex_enter(&dev_lck); 773*4bff34e3Sthurlow for (; ; ) { 774*4bff34e3Sthurlow minor_t start = nsmb_minor; 775*4bff34e3Sthurlow do { 776*4bff34e3Sthurlow if (nsmb_minor >= MAXMIN32) { 777*4bff34e3Sthurlow if (nsmb_major == getmajor(*dev)) 778*4bff34e3Sthurlow nsmb_minor = NSMB_MIN_MINOR; 779*4bff34e3Sthurlow else 780*4bff34e3Sthurlow nsmb_minor = 0; 781*4bff34e3Sthurlow } else { 782*4bff34e3Sthurlow nsmb_minor++; 783*4bff34e3Sthurlow } 784*4bff34e3Sthurlow sdv = ddi_get_soft_state(statep, nsmb_minor); 785*4bff34e3Sthurlow } while ((sdv != NULL) && (nsmb_minor != start)); 786*4bff34e3Sthurlow if (nsmb_minor == start) { 787*4bff34e3Sthurlow /* 788*4bff34e3Sthurlow * The condition we need to solve here is all the 789*4bff34e3Sthurlow * MAXMIN32(~262000) minors numbers are reached. We 790*4bff34e3Sthurlow * need to create a new major number. 791*4bff34e3Sthurlow * zfs uses getudev() to create a new major number. 792*4bff34e3Sthurlow */ 793*4bff34e3Sthurlow if ((new_major = getudev()) == (major_t)-1) { 794*4bff34e3Sthurlow cmn_err(CE_WARN, 795*4bff34e3Sthurlow "nsmb: Can't get unique major " 796*4bff34e3Sthurlow "device number."); 797*4bff34e3Sthurlow mutex_exit(&dev_lck); 798*4bff34e3Sthurlow return (-1); 799*4bff34e3Sthurlow } 800*4bff34e3Sthurlow nsmb_major = new_major; 801*4bff34e3Sthurlow nsmb_minor = 0; 802*4bff34e3Sthurlow } else { 803*4bff34e3Sthurlow break; 804*4bff34e3Sthurlow } 805*4bff34e3Sthurlow } 806*4bff34e3Sthurlow 807*4bff34e3Sthurlow /* 808*4bff34e3Sthurlow * This is called by mount or open call. 809*4bff34e3Sthurlow * The open() routine is passed a pointer to a device number so 810*4bff34e3Sthurlow * that the driver can change the minor number. This allows 811*4bff34e3Sthurlow * drivers to dynamically create minor instances of the dev- 812*4bff34e3Sthurlow * ice. An example of this might be a pseudo-terminal driver 813*4bff34e3Sthurlow * that creates a new pseudo-terminal whenever it is opened. 814*4bff34e3Sthurlow * A driver that chooses the minor number dynamically, normally 815*4bff34e3Sthurlow * creates only one minor device node in attach(9E) with 816*4bff34e3Sthurlow * ddi_create_minor_node(9F) then changes the minor number com- 817*4bff34e3Sthurlow * ponent of *devp using makedevice(9F) and getmajor(9F) The 818*4bff34e3Sthurlow * driver needs to keep track of available minor numbers inter- 819*4bff34e3Sthurlow * nally. 820*4bff34e3Sthurlow * Stuff the structure smb_dev. 821*4bff34e3Sthurlow * return. 822*4bff34e3Sthurlow */ 823*4bff34e3Sthurlow 824*4bff34e3Sthurlow if (ddi_soft_state_zalloc(statep, nsmb_minor) == DDI_FAILURE) { 825*4bff34e3Sthurlow mutex_exit(&dev_lck); 826*4bff34e3Sthurlow return (ENXIO); 827*4bff34e3Sthurlow } 828*4bff34e3Sthurlow if ((sdp = ddi_get_soft_state(statep, nsmb_minor)) == NULL) { 829*4bff34e3Sthurlow mutex_exit(&dev_lck); 830*4bff34e3Sthurlow return (ENXIO); 831*4bff34e3Sthurlow } 832*4bff34e3Sthurlow 833*4bff34e3Sthurlow sdp->sd_opened = 1; 834*4bff34e3Sthurlow sdp->sd_seq = nsmb_minor; 835*4bff34e3Sthurlow sdp->smb_cred = cr; 836*4bff34e3Sthurlow sdp->sd_flags |= NSMBFL_OPEN; 837*4bff34e3Sthurlow sdp->zoneid = crgetzoneid(cr); 838*4bff34e3Sthurlow mutex_exit(&dev_lck); 839*4bff34e3Sthurlow 840*4bff34e3Sthurlow *dev = makedevice(nsmb_major, nsmb_minor); 841*4bff34e3Sthurlow 842*4bff34e3Sthurlow return (0); 843*4bff34e3Sthurlow } 844*4bff34e3Sthurlow 845*4bff34e3Sthurlow /*ARGSUSED*/ 846*4bff34e3Sthurlow static int 847*4bff34e3Sthurlow nsmb_close(dev_t dev, int flags, int otyp, cred_t *cr) 848*4bff34e3Sthurlow { 849*4bff34e3Sthurlow struct smb_vc *vcp; 850*4bff34e3Sthurlow struct smb_share *ssp; 851*4bff34e3Sthurlow struct smb_cred scred; 852*4bff34e3Sthurlow minor_t inst = getminor(dev); 853*4bff34e3Sthurlow smb_dev_t *sdp; 854*4bff34e3Sthurlow 855*4bff34e3Sthurlow mutex_enter(&dev_lck); 856*4bff34e3Sthurlow /* 857*4bff34e3Sthurlow * 1. Check the validity of the minor number. 858*4bff34e3Sthurlow * 2. Release any shares/vc associated with the connection. 859*4bff34e3Sthurlow * 3. Can close the minor number. 860*4bff34e3Sthurlow * 4. Deallocate any resources allocated in open() call. 861*4bff34e3Sthurlow */ 862*4bff34e3Sthurlow smb_credinit(&scred, curproc, cr); 863*4bff34e3Sthurlow 864*4bff34e3Sthurlow sdp = ddi_get_soft_state(statep, inst); 865*4bff34e3Sthurlow 866*4bff34e3Sthurlow /* 867*4bff34e3Sthurlow * time to call ddi_get_soft_state() 868*4bff34e3Sthurlow */ 869*4bff34e3Sthurlow ssp = sdp->sd_share; 870*4bff34e3Sthurlow if (ssp != NULL) 871*4bff34e3Sthurlow smb_share_rele(ssp); 872*4bff34e3Sthurlow vcp = sdp->sd_vc; 873*4bff34e3Sthurlow if (vcp != NULL) { 874*4bff34e3Sthurlow /* 875*4bff34e3Sthurlow * If this dev minor was doing session setup 876*4bff34e3Sthurlow * and failed to authenticate (or whatever) 877*4bff34e3Sthurlow * then we need to "kill" the VC here so any 878*4bff34e3Sthurlow * other threads waiting for the VC setup to 879*4bff34e3Sthurlow * finish will drop their references. 880*4bff34e3Sthurlow */ 881*4bff34e3Sthurlow if (sdp->sd_flags & NSMBFL_NEWVC) 882*4bff34e3Sthurlow smb_vc_kill(vcp); 883*4bff34e3Sthurlow smb_vc_rele(vcp); 884*4bff34e3Sthurlow } 885*4bff34e3Sthurlow smb_credrele(&scred); 886*4bff34e3Sthurlow 887*4bff34e3Sthurlow /* 888*4bff34e3Sthurlow * Free the instance 889*4bff34e3Sthurlow */ 890*4bff34e3Sthurlow ddi_soft_state_free(statep, inst); 891*4bff34e3Sthurlow mutex_exit(&dev_lck); 892*4bff34e3Sthurlow return (0); 893*4bff34e3Sthurlow } 894*4bff34e3Sthurlow 895*4bff34e3Sthurlow int 896*4bff34e3Sthurlow smb_dev2share(int fd, struct smb_share **sspp) 897*4bff34e3Sthurlow { 898*4bff34e3Sthurlow register vnode_t *vp; 899*4bff34e3Sthurlow smb_dev_t *sdp; 900*4bff34e3Sthurlow struct smb_share *ssp; 901*4bff34e3Sthurlow dev_t dev; 902*4bff34e3Sthurlow file_t *fp; 903*4bff34e3Sthurlow 904*4bff34e3Sthurlow if ((fp = getf(fd)) == NULL) 905*4bff34e3Sthurlow return (set_errno(EBADF)); 906*4bff34e3Sthurlow vp = fp->f_vnode; 907*4bff34e3Sthurlow dev = vp->v_rdev; 908*4bff34e3Sthurlow if (dev == NULL) { 909*4bff34e3Sthurlow releasef(fd); 910*4bff34e3Sthurlow return (EBADF); 911*4bff34e3Sthurlow } 912*4bff34e3Sthurlow sdp = ddi_get_soft_state(statep, getminor(dev)); 913*4bff34e3Sthurlow if (sdp == NULL) { 914*4bff34e3Sthurlow releasef(fd); 915*4bff34e3Sthurlow return (DDI_FAILURE); 916*4bff34e3Sthurlow } 917*4bff34e3Sthurlow ssp = sdp->sd_share; 918*4bff34e3Sthurlow if (ssp == NULL) { 919*4bff34e3Sthurlow releasef(fd); 920*4bff34e3Sthurlow return (ENOTCONN); 921*4bff34e3Sthurlow } 922*4bff34e3Sthurlow /* 923*4bff34e3Sthurlow * The share is already locked and referenced by the TCON ioctl 924*4bff34e3Sthurlow * We NULL to hand off share to caller (mount) 925*4bff34e3Sthurlow * This allows further ioctls against connection, for instance 926*4bff34e3Sthurlow * another tree connect and mount, in the automounter case 927*4bff34e3Sthurlow * 928*4bff34e3Sthurlow * We're effectively giving our reference to the mount. 929*4bff34e3Sthurlow * 930*4bff34e3Sthurlow * XXX: I'm not sure I like this. I'd rather see the ioctl 931*4bff34e3Sthurlow * caller do something explicit to give up this reference, 932*4bff34e3Sthurlow * (i.e. SMBIOC_TDIS above) and increment the hold here. 933*4bff34e3Sthurlow */ 934*4bff34e3Sthurlow sdp->sd_share = NULL; 935*4bff34e3Sthurlow releasef(fd); 936*4bff34e3Sthurlow *sspp = ssp; 937*4bff34e3Sthurlow return (0); 938*4bff34e3Sthurlow } 939