14bff34e3Sthurlow /* 24bff34e3Sthurlow * Copyright (c) 2000-2001 Boris Popov 34bff34e3Sthurlow * All rights reserved. 44bff34e3Sthurlow * 54bff34e3Sthurlow * Redistribution and use in source and binary forms, with or without 64bff34e3Sthurlow * modification, are permitted provided that the following conditions 74bff34e3Sthurlow * are met: 84bff34e3Sthurlow * 1. Redistributions of source code must retain the above copyright 94bff34e3Sthurlow * notice, this list of conditions and the following disclaimer. 104bff34e3Sthurlow * 2. Redistributions in binary form must reproduce the above copyright 114bff34e3Sthurlow * notice, this list of conditions and the following disclaimer in the 124bff34e3Sthurlow * documentation and/or other materials provided with the distribution. 134bff34e3Sthurlow * 3. All advertising materials mentioning features or use of this software 144bff34e3Sthurlow * must display the following acknowledgement: 154bff34e3Sthurlow * This product includes software developed by Boris Popov. 164bff34e3Sthurlow * 4. Neither the name of the author nor the names of any co-contributors 174bff34e3Sthurlow * may be used to endorse or promote products derived from this software 184bff34e3Sthurlow * without specific prior written permission. 194bff34e3Sthurlow * 204bff34e3Sthurlow * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 214bff34e3Sthurlow * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 224bff34e3Sthurlow * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 234bff34e3Sthurlow * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 244bff34e3Sthurlow * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 254bff34e3Sthurlow * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 264bff34e3Sthurlow * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 274bff34e3Sthurlow * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 284bff34e3Sthurlow * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 294bff34e3Sthurlow * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 304bff34e3Sthurlow * SUCH DAMAGE. 314bff34e3Sthurlow * 324bff34e3Sthurlow * $Id: smb_dev.c,v 1.21 2004/12/13 00:25:18 lindak Exp $ 334bff34e3Sthurlow */ 344bff34e3Sthurlow 354bff34e3Sthurlow /* 364bff34e3Sthurlow * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 374bff34e3Sthurlow * Use is subject to license terms. 384bff34e3Sthurlow */ 394bff34e3Sthurlow 404bff34e3Sthurlow #include <sys/types.h> 414bff34e3Sthurlow #include <sys/param.h> 424bff34e3Sthurlow #include <sys/errno.h> 434bff34e3Sthurlow #include <sys/sysmacros.h> 444bff34e3Sthurlow #include <sys/uio.h> 454bff34e3Sthurlow #include <sys/buf.h> 464bff34e3Sthurlow #include <sys/modctl.h> 474bff34e3Sthurlow #include <sys/open.h> 484bff34e3Sthurlow #include <sys/file.h> 494bff34e3Sthurlow #include <sys/kmem.h> 504bff34e3Sthurlow #include <sys/conf.h> 514bff34e3Sthurlow #include <sys/cmn_err.h> 524bff34e3Sthurlow #include <sys/stat.h> 534bff34e3Sthurlow #include <sys/ddi.h> 544bff34e3Sthurlow #include <sys/sunddi.h> 554bff34e3Sthurlow #include <sys/sunldi.h> 564bff34e3Sthurlow #include <sys/policy.h> 574bff34e3Sthurlow #include <sys/zone.h> 584bff34e3Sthurlow #include <sys/pathname.h> 594bff34e3Sthurlow #include <sys/mount.h> 604bff34e3Sthurlow #include <sys/sdt.h> 614bff34e3Sthurlow #include <fs/fs_subr.h> 624bff34e3Sthurlow #include <sys/modctl.h> 634bff34e3Sthurlow #include <sys/devops.h> 644bff34e3Sthurlow #include <sys/thread.h> 654bff34e3Sthurlow #include <sys/mkdev.h> 664bff34e3Sthurlow #include <sys/types.h> 674bff34e3Sthurlow #include <sys/zone.h> 684bff34e3Sthurlow 694bff34e3Sthurlow #ifdef APPLE 704bff34e3Sthurlow #include <sys/smb_apple.h> 714bff34e3Sthurlow #else 724bff34e3Sthurlow #include <netsmb/smb_osdep.h> 734bff34e3Sthurlow #endif 744bff34e3Sthurlow 754bff34e3Sthurlow #include <netsmb/mchain.h> /* for "htoles()" */ 764bff34e3Sthurlow 774bff34e3Sthurlow #include <netsmb/smb.h> 784bff34e3Sthurlow #include <netsmb/smb_conn.h> 794bff34e3Sthurlow #include <netsmb/smb_subr.h> 804bff34e3Sthurlow #include <netsmb/smb_dev.h> 814bff34e3Sthurlow #include <netsmb/smb_pass.h> 824bff34e3Sthurlow 834bff34e3Sthurlow /* for version checks */ 844bff34e3Sthurlow const uint32_t nsmb_version = NSMB_VERSION; 854bff34e3Sthurlow 864bff34e3Sthurlow /* 874bff34e3Sthurlow * Userland code loops through minor #s 0 to 1023, looking for one which opens. 884bff34e3Sthurlow * Intially we create minor 0 and leave it for anyone. Minor zero will never 894bff34e3Sthurlow * actually get used - opening triggers creation of another (but private) minor, 904bff34e3Sthurlow * which userland code will get to and mark busy. 914bff34e3Sthurlow */ 924bff34e3Sthurlow #define SMBMINORS 1024 934bff34e3Sthurlow static void *statep; 944bff34e3Sthurlow static major_t nsmb_major; 954bff34e3Sthurlow static minor_t nsmb_minor = 1; 964bff34e3Sthurlow 974bff34e3Sthurlow #define NSMB_MAX_MINOR (1 << 8) 984bff34e3Sthurlow #define NSMB_MIN_MINOR (NSMB_MAX_MINOR + 1) 994bff34e3Sthurlow 1004bff34e3Sthurlow #define ILP32 1 1014bff34e3Sthurlow #define LP64 2 1024bff34e3Sthurlow 1034bff34e3Sthurlow static kmutex_t dev_lck; 1044bff34e3Sthurlow 1054bff34e3Sthurlow /* Zone support */ 1064bff34e3Sthurlow zone_key_t nsmb_zone_key; 1074bff34e3Sthurlow extern void nsmb_zone_shutdown(zoneid_t zoneid, void *data); 1084bff34e3Sthurlow extern void nsmb_zone_destroy(zoneid_t zoneid, void *data); 1094bff34e3Sthurlow 1104bff34e3Sthurlow /* 1114bff34e3Sthurlow * cb_ops device operations. 1124bff34e3Sthurlow */ 1134bff34e3Sthurlow static int nsmb_open(dev_t *devp, int flag, int otyp, cred_t *credp); 1144bff34e3Sthurlow static int nsmb_close(dev_t dev, int flag, int otyp, cred_t *credp); 1154bff34e3Sthurlow static int nsmb_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, 1164bff34e3Sthurlow cred_t *credp, int *rvalp); 1174bff34e3Sthurlow /* smbfs cb_ops */ 1184bff34e3Sthurlow static struct cb_ops nsmb_cbops = { 1194bff34e3Sthurlow nsmb_open, /* open */ 1204bff34e3Sthurlow nsmb_close, /* close */ 1214bff34e3Sthurlow nodev, /* strategy */ 1224bff34e3Sthurlow nodev, /* print */ 1234bff34e3Sthurlow nodev, /* dump */ 1244bff34e3Sthurlow nodev, /* read */ 1254bff34e3Sthurlow nodev, /* write */ 1264bff34e3Sthurlow nsmb_ioctl, /* ioctl */ 1274bff34e3Sthurlow nodev, /* devmap */ 1284bff34e3Sthurlow nodev, /* mmap */ 1294bff34e3Sthurlow nodev, /* segmap */ 1304bff34e3Sthurlow nochpoll, /* poll */ 1314bff34e3Sthurlow ddi_prop_op, /* prop_op */ 1324bff34e3Sthurlow NULL, /* stream */ 1334bff34e3Sthurlow D_MP, /* cb_flag */ 1344bff34e3Sthurlow CB_REV, /* rev */ 1354bff34e3Sthurlow nodev, /* int (*cb_aread)() */ 1364bff34e3Sthurlow nodev /* int (*cb_awrite)() */ 1374bff34e3Sthurlow }; 1384bff34e3Sthurlow 1394bff34e3Sthurlow /* 1404bff34e3Sthurlow * Device options 1414bff34e3Sthurlow */ 1424bff34e3Sthurlow static int nsmb_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); 1434bff34e3Sthurlow static int nsmb_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); 1444bff34e3Sthurlow static int nsmb_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, 1454bff34e3Sthurlow void *arg, void **result); 1464bff34e3Sthurlow 1474bff34e3Sthurlow static struct dev_ops nsmb_ops = { 1484bff34e3Sthurlow DEVO_REV, /* devo_rev, */ 1494bff34e3Sthurlow 0, /* refcnt */ 1504bff34e3Sthurlow nsmb_getinfo, /* info */ 1514bff34e3Sthurlow nulldev, /* identify */ 1524bff34e3Sthurlow nulldev, /* probe */ 1534bff34e3Sthurlow nsmb_attach, /* attach */ 1544bff34e3Sthurlow nsmb_detach, /* detach */ 1554bff34e3Sthurlow nodev, /* reset */ 1564bff34e3Sthurlow &nsmb_cbops, /* driver ops - devctl interfaces */ 1574bff34e3Sthurlow NULL, /* bus operations */ 1584bff34e3Sthurlow NULL /* power */ 1594bff34e3Sthurlow }; 1604bff34e3Sthurlow 1614bff34e3Sthurlow /* 1624bff34e3Sthurlow * Module linkage information. 1634bff34e3Sthurlow */ 1644bff34e3Sthurlow 1654bff34e3Sthurlow static struct modldrv nsmb_modldrv = { 1664bff34e3Sthurlow &mod_driverops, /* Driver module */ 1674bff34e3Sthurlow "SMBFS network driver v" NSMB_VER_STR, 1684bff34e3Sthurlow &nsmb_ops /* Driver ops */ 1694bff34e3Sthurlow }; 1704bff34e3Sthurlow 1714bff34e3Sthurlow static struct modlinkage nsmb_modlinkage = { 1724bff34e3Sthurlow MODREV_1, 1734bff34e3Sthurlow (void *)&nsmb_modldrv, 1744bff34e3Sthurlow NULL 1754bff34e3Sthurlow }; 1764bff34e3Sthurlow 1774bff34e3Sthurlow int 1784bff34e3Sthurlow _init(void) 1794bff34e3Sthurlow { 1804bff34e3Sthurlow int error; 1814bff34e3Sthurlow 1824bff34e3Sthurlow ddi_soft_state_init(&statep, sizeof (smb_dev_t), 1); 1834bff34e3Sthurlow 1844bff34e3Sthurlow /* Can initialize some mutexes also. */ 1854bff34e3Sthurlow mutex_init(&dev_lck, NULL, MUTEX_DRIVER, NULL); 1864bff34e3Sthurlow /* 1874bff34e3Sthurlow * Create a major name and number. 1884bff34e3Sthurlow */ 1894bff34e3Sthurlow nsmb_major = ddi_name_to_major(NSMB_NAME); 1904bff34e3Sthurlow nsmb_minor = 0; 1914bff34e3Sthurlow 1924bff34e3Sthurlow /* Connection data structures. */ 1934bff34e3Sthurlow (void) smb_sm_init(); 1944bff34e3Sthurlow 1954bff34e3Sthurlow /* Initialize password Key chain DB. */ 1964bff34e3Sthurlow smb_pkey_init(); 1974bff34e3Sthurlow 1984bff34e3Sthurlow zone_key_create(&nsmb_zone_key, NULL, nsmb_zone_shutdown, 1994bff34e3Sthurlow nsmb_zone_destroy); 2004bff34e3Sthurlow 2014bff34e3Sthurlow /* 2024bff34e3Sthurlow * Install the module. Do this after other init, 2034bff34e3Sthurlow * to prevent entrances before we're ready. 2044bff34e3Sthurlow */ 2054bff34e3Sthurlow if ((error = mod_install((&nsmb_modlinkage))) != 0) { 2064bff34e3Sthurlow 2074bff34e3Sthurlow /* Same as 2nd half of _fini */ 2084bff34e3Sthurlow (void) zone_key_delete(nsmb_zone_key); 2094bff34e3Sthurlow smb_pkey_fini(); 2104bff34e3Sthurlow smb_sm_done(); 2114bff34e3Sthurlow mutex_destroy(&dev_lck); 2124bff34e3Sthurlow ddi_soft_state_fini(&statep); 2134bff34e3Sthurlow 2144bff34e3Sthurlow return (error); 2154bff34e3Sthurlow } 2164bff34e3Sthurlow 2174bff34e3Sthurlow return (0); 2184bff34e3Sthurlow } 2194bff34e3Sthurlow 2204bff34e3Sthurlow int 2214bff34e3Sthurlow _fini(void) 2224bff34e3Sthurlow { 2234bff34e3Sthurlow int status; 2244bff34e3Sthurlow 2254bff34e3Sthurlow /* 2264bff34e3Sthurlow * Prevent unload if we have active VCs 2274bff34e3Sthurlow * or stored passwords 2284bff34e3Sthurlow */ 2294bff34e3Sthurlow if ((status = smb_sm_idle()) != 0) 2304bff34e3Sthurlow return (status); 2314bff34e3Sthurlow if ((status = smb_pkey_idle()) != 0) 2324bff34e3Sthurlow return (status); 2334bff34e3Sthurlow 2344bff34e3Sthurlow /* 2354bff34e3Sthurlow * Remove the module. Do this before destroying things, 2364bff34e3Sthurlow * to prevent new entrances while we're destorying. 2374bff34e3Sthurlow */ 2384bff34e3Sthurlow if ((status = mod_remove(&nsmb_modlinkage)) != 0) { 2394bff34e3Sthurlow return (status); 2404bff34e3Sthurlow } 2414bff34e3Sthurlow 2424bff34e3Sthurlow (void) zone_key_delete(nsmb_zone_key); 2434bff34e3Sthurlow 2444bff34e3Sthurlow /* Destroy password Key chain DB. */ 2454bff34e3Sthurlow smb_pkey_fini(); 2464bff34e3Sthurlow 2474bff34e3Sthurlow smb_sm_done(); 2484bff34e3Sthurlow 2494bff34e3Sthurlow mutex_destroy(&dev_lck); 2504bff34e3Sthurlow ddi_soft_state_fini(&statep); 2514bff34e3Sthurlow 2524bff34e3Sthurlow return (status); 2534bff34e3Sthurlow } 2544bff34e3Sthurlow 2554bff34e3Sthurlow int 2564bff34e3Sthurlow _info(struct modinfo *modinfop) 2574bff34e3Sthurlow { 2584bff34e3Sthurlow return (mod_info(&nsmb_modlinkage, modinfop)); 2594bff34e3Sthurlow } 2604bff34e3Sthurlow 2614bff34e3Sthurlow /*ARGSUSED*/ 2624bff34e3Sthurlow static int 2634bff34e3Sthurlow nsmb_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) 2644bff34e3Sthurlow { 2654bff34e3Sthurlow int ret = DDI_SUCCESS; 2664bff34e3Sthurlow 2674bff34e3Sthurlow switch (cmd) { 2684bff34e3Sthurlow case DDI_INFO_DEVT2DEVINFO: 2694bff34e3Sthurlow *result = 0; 2704bff34e3Sthurlow break; 2714bff34e3Sthurlow case DDI_INFO_DEVT2INSTANCE: 2724bff34e3Sthurlow *result = 0; 2734bff34e3Sthurlow break; 2744bff34e3Sthurlow default: 2754bff34e3Sthurlow ret = DDI_FAILURE; 2764bff34e3Sthurlow } 2774bff34e3Sthurlow return (ret); 2784bff34e3Sthurlow } 2794bff34e3Sthurlow 2804bff34e3Sthurlow static int 2814bff34e3Sthurlow nsmb_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 2824bff34e3Sthurlow { 2834bff34e3Sthurlow smb_dev_t *sdp; 2844bff34e3Sthurlow 2854bff34e3Sthurlow if (cmd != DDI_ATTACH) 2864bff34e3Sthurlow return (DDI_FAILURE); 2874bff34e3Sthurlow /* 2884bff34e3Sthurlow * only one instance - but we clone using the open routine 2894bff34e3Sthurlow */ 2904bff34e3Sthurlow if (ddi_get_instance(dip) > 0) 2914bff34e3Sthurlow return (DDI_FAILURE); 2924bff34e3Sthurlow 2934bff34e3Sthurlow mutex_enter(&dev_lck); 2944bff34e3Sthurlow 2954bff34e3Sthurlow /* 2964bff34e3Sthurlow * This is the Zero'th minor device which is created. 2974bff34e3Sthurlow */ 2984bff34e3Sthurlow if (ddi_soft_state_zalloc(statep, 0) == DDI_FAILURE) { 2994bff34e3Sthurlow cmn_err(CE_WARN, "nsmb_attach: soft state alloc"); 3004bff34e3Sthurlow goto attach_failed; 3014bff34e3Sthurlow } 3024bff34e3Sthurlow if (ddi_create_minor_node(dip, "nsmb", S_IFCHR, 0, DDI_PSEUDO, 3034bff34e3Sthurlow NULL) == DDI_FAILURE) { 3044bff34e3Sthurlow cmn_err(CE_WARN, "nsmb_attach: create minor"); 3054bff34e3Sthurlow goto attach_failed; 3064bff34e3Sthurlow } 3074bff34e3Sthurlow if ((sdp = ddi_get_soft_state(statep, 0)) == NULL) { 3084bff34e3Sthurlow cmn_err(CE_WARN, "nsmb_attach: get soft state"); 3094bff34e3Sthurlow ddi_remove_minor_node(dip, NULL); 3104bff34e3Sthurlow goto attach_failed; 3114bff34e3Sthurlow } 3124bff34e3Sthurlow 3134bff34e3Sthurlow /* 3144bff34e3Sthurlow * Need to see if this field is required. 3154bff34e3Sthurlow * REVISIT 3164bff34e3Sthurlow */ 3174bff34e3Sthurlow sdp->smb_dip = dip; 3184bff34e3Sthurlow sdp->sd_seq = 0; 3194bff34e3Sthurlow sdp->sd_opened = 1; 3204bff34e3Sthurlow 3214bff34e3Sthurlow mutex_exit(&dev_lck); 3224bff34e3Sthurlow ddi_report_dev(dip); 3234bff34e3Sthurlow return (DDI_SUCCESS); 3244bff34e3Sthurlow 3254bff34e3Sthurlow attach_failed: 3264bff34e3Sthurlow ddi_soft_state_free(statep, 0); 3274bff34e3Sthurlow mutex_exit(&dev_lck); 3284bff34e3Sthurlow return (DDI_FAILURE); 3294bff34e3Sthurlow } 3304bff34e3Sthurlow 3314bff34e3Sthurlow /*ARGSUSED*/ 3324bff34e3Sthurlow static int 3334bff34e3Sthurlow nsmb_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 3344bff34e3Sthurlow { 3354bff34e3Sthurlow 3364bff34e3Sthurlow if (cmd != DDI_DETACH) 3374bff34e3Sthurlow return (DDI_FAILURE); 3384bff34e3Sthurlow if (ddi_get_instance(dip) > 0) 3394bff34e3Sthurlow return (DDI_FAILURE); 3404bff34e3Sthurlow 3414bff34e3Sthurlow ddi_soft_state_free(statep, 0); 3424bff34e3Sthurlow ddi_remove_minor_node(dip, NULL); 3434bff34e3Sthurlow 3444bff34e3Sthurlow return (DDI_SUCCESS); 3454bff34e3Sthurlow } 3464bff34e3Sthurlow 3474bff34e3Sthurlow /*ARGSUSED*/ 3484bff34e3Sthurlow static int 3494bff34e3Sthurlow nsmb_ioctl(dev_t dev, 3504bff34e3Sthurlow int cmd, 3514bff34e3Sthurlow intptr_t arg, 3524bff34e3Sthurlow int mode, 3534bff34e3Sthurlow cred_t *credp, 3544bff34e3Sthurlow int *rvalp) 3554bff34e3Sthurlow { 3564bff34e3Sthurlow smb_dev_t *sdp; 3574bff34e3Sthurlow struct smb_vc *vcp = NULL; 3584bff34e3Sthurlow struct smb_share *ssp = NULL; 3594bff34e3Sthurlow struct smb_cred scred; 3604bff34e3Sthurlow int err, error; 3614bff34e3Sthurlow uid_t uid; 3624bff34e3Sthurlow 3634bff34e3Sthurlow /* Free any+all of these at end of switch. */ 3644bff34e3Sthurlow smbioc_lookup_t *sioc = NULL; 3654bff34e3Sthurlow smbioc_rq_t *srq = NULL; 3664bff34e3Sthurlow smbioc_rw_t *rwrq = NULL; 3674bff34e3Sthurlow smbioc_t2rq_t *strq = NULL; 3684bff34e3Sthurlow smbioc_pk_t *pk = NULL; 3694bff34e3Sthurlow 3704bff34e3Sthurlow sdp = ddi_get_soft_state(statep, getminor(dev)); 3714bff34e3Sthurlow if (sdp == NULL) { 3724bff34e3Sthurlow return (DDI_FAILURE); 3734bff34e3Sthurlow } 3744bff34e3Sthurlow if ((sdp->sd_flags & NSMBFL_OPEN) == 0) { 3754bff34e3Sthurlow return (EBADF); 3764bff34e3Sthurlow } 3774bff34e3Sthurlow 3784bff34e3Sthurlow /* 3794bff34e3Sthurlow * Dont give access if the zone id is not as the same as we 3804bff34e3Sthurlow * set in the nsmb_open or dont belong to the global zone. 3814bff34e3Sthurlow * Check if the user belongs to this zone.. 3824bff34e3Sthurlow */ 3834bff34e3Sthurlow if (sdp->zoneid != getzoneid()) 3844bff34e3Sthurlow return (EIO); 3854bff34e3Sthurlow if (cmd != SMBIOC_TDIS && 3864bff34e3Sthurlow zone_status_get(curproc->p_zone) >= ZONE_IS_SHUTTING_DOWN) 3874bff34e3Sthurlow return (EIO); 3884bff34e3Sthurlow 3894bff34e3Sthurlow 3904bff34e3Sthurlow error = 0; 3914bff34e3Sthurlow smb_credinit(&scred, curproc, credp); 3924bff34e3Sthurlow switch (cmd) { 3934bff34e3Sthurlow case SMBIOC_GETVERS: 3944bff34e3Sthurlow ddi_copyout(&nsmb_version, (void *)arg, 3954bff34e3Sthurlow sizeof (nsmb_version), mode); 3964bff34e3Sthurlow break; 3974bff34e3Sthurlow 3984bff34e3Sthurlow case SMBIOC_REQUEST: 3994bff34e3Sthurlow if (sdp->sd_share == NULL) { 4004bff34e3Sthurlow error = ENOTCONN; 4014bff34e3Sthurlow break; 4024bff34e3Sthurlow } 4034bff34e3Sthurlow srq = kmem_alloc(sizeof (*srq), KM_SLEEP); 4044bff34e3Sthurlow if (ddi_copyin((void *) arg, srq, 4054bff34e3Sthurlow sizeof (*srq), mode)) { 4064bff34e3Sthurlow error = EFAULT; 4074bff34e3Sthurlow break; 4084bff34e3Sthurlow } 4094bff34e3Sthurlow error = smb_usr_simplerequest(sdp->sd_share, 4104bff34e3Sthurlow srq, &scred); 4114bff34e3Sthurlow ddi_copyout(srq, (void *)arg, 4124bff34e3Sthurlow SMBIOC_RQ_COPYOUT_SIZE, mode); 4134bff34e3Sthurlow break; 4144bff34e3Sthurlow 4154bff34e3Sthurlow case SMBIOC_T2RQ: 4164bff34e3Sthurlow if (sdp->sd_share == NULL) { 4174bff34e3Sthurlow error = ENOTCONN; 4184bff34e3Sthurlow break; 4194bff34e3Sthurlow } 4204bff34e3Sthurlow strq = kmem_alloc(sizeof (*strq), KM_SLEEP); 4214bff34e3Sthurlow if (ddi_copyin((void *)arg, strq, 4224bff34e3Sthurlow sizeof (*strq), mode)) { 4234bff34e3Sthurlow error = EFAULT; 4244bff34e3Sthurlow break; 4254bff34e3Sthurlow } 4264bff34e3Sthurlow error = smb_usr_t2request(sdp->sd_share, strq, &scred); 4274bff34e3Sthurlow ddi_copyout(strq, (void *)arg, 4284bff34e3Sthurlow SMBIOC_T2RQ_COPYOUT_SIZE, mode); 4294bff34e3Sthurlow break; 4304bff34e3Sthurlow 4314bff34e3Sthurlow case SMBIOC_READ: 4324bff34e3Sthurlow case SMBIOC_WRITE: 4334bff34e3Sthurlow if ((ssp = sdp->sd_share) == NULL) { 4344bff34e3Sthurlow error = ENOTCONN; 4354bff34e3Sthurlow break; 4364bff34e3Sthurlow } 4374bff34e3Sthurlow rwrq = kmem_alloc(sizeof (*rwrq), KM_SLEEP); 4384bff34e3Sthurlow if (ddi_copyin((void *)arg, rwrq, 4394bff34e3Sthurlow sizeof (*rwrq), mode)) { 4404bff34e3Sthurlow error = EFAULT; 4414bff34e3Sthurlow break; 4424bff34e3Sthurlow } 4434bff34e3Sthurlow error = smb_usr_rw(ssp, rwrq, cmd, &scred); 4444bff34e3Sthurlow ddi_copyout(rwrq, (void *)arg, 4454bff34e3Sthurlow SMBIOC_RW_COPYOUT_SIZE, mode); 4464bff34e3Sthurlow break; 4474bff34e3Sthurlow 4481b34bc4aSbs case SMBIOC_FINDVC: 4491b34bc4aSbs /* Should be no VC and no share */ 4501b34bc4aSbs if (sdp->sd_vc || sdp->sd_share) { 4511b34bc4aSbs error = EISCONN; 4521b34bc4aSbs break; 4531b34bc4aSbs } 4541b34bc4aSbs sioc = kmem_alloc(sizeof (*sioc), KM_SLEEP); 4551b34bc4aSbs if (ddi_copyin((void *)arg, sioc, 4561b34bc4aSbs sizeof (*sioc), mode)) { 4571b34bc4aSbs error = EFAULT; 4581b34bc4aSbs break; 4591b34bc4aSbs } 4601b34bc4aSbs vcp = NULL; 4611b34bc4aSbs ssp = NULL; 4621b34bc4aSbs error = smb_usr_findvc(sioc, &scred, &vcp); 4631b34bc4aSbs if (error) 4641b34bc4aSbs break; 4651b34bc4aSbs if (vcp) { 4661b34bc4aSbs /* 4671b34bc4aSbs * The VC has a hold from _findvc 4681b34bc4aSbs * which we keep until nsmb_close(). 4691b34bc4aSbs */ 4701b34bc4aSbs sdp->sd_level = SMBL_VC; 4711b34bc4aSbs sdp->sd_vc = vcp; 4721b34bc4aSbs } 4731b34bc4aSbs (void) ddi_copyout(sioc, (void *)arg, 4741b34bc4aSbs SMBIOC_LOOK_COPYOUT_SIZE, mode); 4751b34bc4aSbs 4761b34bc4aSbs break; 4771b34bc4aSbs 4784bff34e3Sthurlow case SMBIOC_NEGOTIATE: 4794bff34e3Sthurlow /* Should be no VC (and no share) */ 4804bff34e3Sthurlow if (sdp->sd_vc || sdp->sd_share) { 4814bff34e3Sthurlow error = EISCONN; 4824bff34e3Sthurlow break; 4834bff34e3Sthurlow } 4844bff34e3Sthurlow sioc = kmem_alloc(sizeof (*sioc), KM_SLEEP); 4854bff34e3Sthurlow if (ddi_copyin((void *)arg, sioc, 4864bff34e3Sthurlow sizeof (*sioc), mode)) { 4874bff34e3Sthurlow error = EFAULT; 4884bff34e3Sthurlow break; 4894bff34e3Sthurlow } 4904bff34e3Sthurlow vcp = NULL; 4914bff34e3Sthurlow ssp = NULL; 4924bff34e3Sthurlow error = smb_usr_negotiate(sioc, &scred, &vcp); 4934bff34e3Sthurlow if (error) 4944bff34e3Sthurlow break; 4954bff34e3Sthurlow if (vcp) { 4964bff34e3Sthurlow /* 4974bff34e3Sthurlow * The VC has a hold from _negotiate 4984bff34e3Sthurlow * which we keep until nsmb_close(). 4994bff34e3Sthurlow */ 5004bff34e3Sthurlow sdp->sd_level = SMBL_VC; 5014bff34e3Sthurlow sdp->sd_vc = vcp; 5024bff34e3Sthurlow /* 5034bff34e3Sthurlow * If we just created this VC, and 5044bff34e3Sthurlow * this minor is doing the setup, 5054bff34e3Sthurlow * keep track of that fact here. 5064bff34e3Sthurlow */ 5074bff34e3Sthurlow if (vcp->vc_state < SMBIOD_ST_VCACTIVE) 5084bff34e3Sthurlow sdp->sd_flags |= NSMBFL_NEWVC; 5094bff34e3Sthurlow 5104bff34e3Sthurlow } 5114bff34e3Sthurlow /* 5124bff34e3Sthurlow * Copyout the "out token" (security blob). 5134bff34e3Sthurlow * 5144bff34e3Sthurlow * This code used to be near the end of 5154bff34e3Sthurlow * smb_usr_negotiate(). Moved the copyout 5164bff34e3Sthurlow * calls here so we know the "mode" 5174bff34e3Sthurlow */ 5184bff34e3Sthurlow if (vcp->vc_outtok) { 5194bff34e3Sthurlow /* 5204bff34e3Sthurlow * Note: will copyout sioc below 5214bff34e3Sthurlow * including sioc.vc_outtoklen, 5224bff34e3Sthurlow * so we no longer put the length 5234bff34e3Sthurlow * at the start of the outtok data. 5244bff34e3Sthurlow */ 5254bff34e3Sthurlow sioc->ioc_ssn.ioc_outtoklen = 5264bff34e3Sthurlow vcp->vc_outtoklen; 5274bff34e3Sthurlow err = ddi_copyout( 5284bff34e3Sthurlow vcp->vc_outtok, 5294bff34e3Sthurlow sioc->ioc_ssn.ioc_outtok, 5304bff34e3Sthurlow vcp->vc_outtoklen, mode); 5314bff34e3Sthurlow if (err) { 5324bff34e3Sthurlow error = EFAULT; 5334bff34e3Sthurlow break; 5344bff34e3Sthurlow } 5354bff34e3Sthurlow /* 5364bff34e3Sthurlow * Save this blob in vc_negtok. 5374bff34e3Sthurlow * We need it in case we have to 5384bff34e3Sthurlow * reconnect. 5394bff34e3Sthurlow * 5404bff34e3Sthurlow * Set vc_negtok = vc_outtok 5414bff34e3Sthurlow * but free vc_negtok first. 5424bff34e3Sthurlow */ 5434bff34e3Sthurlow if (vcp->vc_negtok) { 5444bff34e3Sthurlow kmem_free( 5454bff34e3Sthurlow vcp->vc_negtok, 5464bff34e3Sthurlow vcp->vc_negtoklen); 5474bff34e3Sthurlow vcp->vc_negtok = NULL; 5484bff34e3Sthurlow vcp->vc_negtoklen = 0; 5494bff34e3Sthurlow } 5504bff34e3Sthurlow vcp->vc_negtok = vcp->vc_outtok; 5514bff34e3Sthurlow vcp->vc_negtoklen = vcp->vc_outtoklen; 5524bff34e3Sthurlow vcp->vc_outtok = NULL; 5534bff34e3Sthurlow vcp->vc_outtoklen = 0; 5544bff34e3Sthurlow } 5554bff34e3Sthurlow /* 5564bff34e3Sthurlow * Added copyout here of (almost) 5574bff34e3Sthurlow * the whole struct, even though 5584bff34e3Sthurlow * the lib only needs _outtoklen. 5594bff34e3Sthurlow * We may put other things in this 5604bff34e3Sthurlow * struct that user-land needs. 5614bff34e3Sthurlow */ 5624bff34e3Sthurlow err = ddi_copyout(sioc, (void *)arg, 5634bff34e3Sthurlow SMBIOC_LOOK_COPYOUT_SIZE, mode); 5644bff34e3Sthurlow if (err) 5654bff34e3Sthurlow error = EFAULT; 5664bff34e3Sthurlow break; 5674bff34e3Sthurlow 5684bff34e3Sthurlow case SMBIOC_SSNSETUP: 5694bff34e3Sthurlow /* Must have a VC, but no share. */ 5704bff34e3Sthurlow if (sdp->sd_share) { 5714bff34e3Sthurlow error = EISCONN; 5724bff34e3Sthurlow break; 5734bff34e3Sthurlow } 5744bff34e3Sthurlow if (!sdp->sd_vc) { 5754bff34e3Sthurlow error = ENOTCONN; 5764bff34e3Sthurlow break; 5774bff34e3Sthurlow } 5784bff34e3Sthurlow sioc = kmem_alloc(sizeof (*sioc), KM_SLEEP); 5794bff34e3Sthurlow if (ddi_copyin((void *)arg, sioc, 5804bff34e3Sthurlow sizeof (*sioc), mode)) { 5814bff34e3Sthurlow error = EFAULT; 5824bff34e3Sthurlow break; 5834bff34e3Sthurlow } 5844bff34e3Sthurlow vcp = sdp->sd_vc; 5854bff34e3Sthurlow ssp = NULL; 5864bff34e3Sthurlow error = smb_usr_ssnsetup(sioc, &scred, vcp); 5874bff34e3Sthurlow if (error) 5884bff34e3Sthurlow break; 5894bff34e3Sthurlow /* 5904bff34e3Sthurlow * If this minor has finished ssn setup, 5914bff34e3Sthurlow * turn off the NEWVC flag, otherwise we 5924bff34e3Sthurlow * will kill this VC when we close. 5934bff34e3Sthurlow */ 5944bff34e3Sthurlow if (vcp->vc_state == SMBIOD_ST_VCACTIVE) 5954bff34e3Sthurlow sdp->sd_flags &= ~NSMBFL_NEWVC; 5964bff34e3Sthurlow /* 5974bff34e3Sthurlow * Copyout the "out token" (security blob). 5984bff34e3Sthurlow * 5994bff34e3Sthurlow * This code used to be near the end of 6004bff34e3Sthurlow * smb_usr_ssnsetup(). Moved the copyout 6014bff34e3Sthurlow * calls here so we know the "mode" 6024bff34e3Sthurlow */ 6034bff34e3Sthurlow if (vcp->vc_outtok) { 6044bff34e3Sthurlow /* 6054bff34e3Sthurlow * Note: will copyout sioc below 6064bff34e3Sthurlow * including sioc.vc_outtoklen, 6074bff34e3Sthurlow * so we no longer put the length 6084bff34e3Sthurlow * at the start of the outtok data. 6094bff34e3Sthurlow */ 6104bff34e3Sthurlow sioc->ioc_ssn.ioc_outtoklen = 6114bff34e3Sthurlow vcp->vc_outtoklen; 6124bff34e3Sthurlow err = ddi_copyout( 6134bff34e3Sthurlow vcp->vc_outtok, 6144bff34e3Sthurlow sioc->ioc_ssn.ioc_outtok, 6154bff34e3Sthurlow vcp->vc_outtoklen, mode); 6164bff34e3Sthurlow if (err) { 6174bff34e3Sthurlow error = EFAULT; 6184bff34e3Sthurlow break; 6194bff34e3Sthurlow } 6204bff34e3Sthurlow /* 6214bff34e3Sthurlow * Done with vc_outtok. Similar, 6224bff34e3Sthurlow * but NOT the same as after the 6234bff34e3Sthurlow * smb_usr_negotiate call above. 6244bff34e3Sthurlow */ 6254bff34e3Sthurlow kmem_free( 6264bff34e3Sthurlow vcp->vc_outtok, 6274bff34e3Sthurlow vcp->vc_outtoklen); 6284bff34e3Sthurlow vcp->vc_outtok = NULL; 6294bff34e3Sthurlow vcp->vc_outtoklen = 0; 6304bff34e3Sthurlow } 6314bff34e3Sthurlow /* Added copyout here... (see above) */ 6324bff34e3Sthurlow err = ddi_copyout(sioc, (void *)arg, 6334bff34e3Sthurlow SMBIOC_LOOK_COPYOUT_SIZE, mode); 6344bff34e3Sthurlow if (err) 6354bff34e3Sthurlow error = EFAULT; 6364bff34e3Sthurlow break; 6374bff34e3Sthurlow 6384bff34e3Sthurlow case SMBIOC_TCON: 6394bff34e3Sthurlow /* Must have a VC, but no share. */ 6404bff34e3Sthurlow if (sdp->sd_share) { 6414bff34e3Sthurlow error = EISCONN; 6424bff34e3Sthurlow break; 6434bff34e3Sthurlow } 6444bff34e3Sthurlow if (!sdp->sd_vc) { 6454bff34e3Sthurlow error = ENOTCONN; 6464bff34e3Sthurlow break; 6474bff34e3Sthurlow } 6484bff34e3Sthurlow sioc = kmem_alloc(sizeof (*sioc), KM_SLEEP); 6494bff34e3Sthurlow if (ddi_copyin((void *)arg, sioc, 6504bff34e3Sthurlow sizeof (*sioc), mode)) { 6514bff34e3Sthurlow error = EFAULT; 6524bff34e3Sthurlow break; 6534bff34e3Sthurlow } 6544bff34e3Sthurlow vcp = sdp->sd_vc; 6554bff34e3Sthurlow ssp = NULL; 6564bff34e3Sthurlow error = smb_usr_tcon(sioc, &scred, vcp, &ssp); 6574bff34e3Sthurlow if (error) 6584bff34e3Sthurlow break; 6594bff34e3Sthurlow if (ssp) { 6604bff34e3Sthurlow /* 6614bff34e3Sthurlow * The share has a hold from _tcon 6624bff34e3Sthurlow * which we keep until nsmb_close() 6634bff34e3Sthurlow * or the SMBIOC_TDIS below. 6644bff34e3Sthurlow */ 6654bff34e3Sthurlow sdp->sd_share = ssp; 6664bff34e3Sthurlow sdp->sd_level = SMBL_SHARE; 6674bff34e3Sthurlow } 6684bff34e3Sthurlow /* No need for copyout here. */ 6694bff34e3Sthurlow break; 6704bff34e3Sthurlow 6714bff34e3Sthurlow case SMBIOC_TDIS: 6724bff34e3Sthurlow if (sdp->sd_share == NULL) { 6734bff34e3Sthurlow error = ENOTCONN; 6744bff34e3Sthurlow break; 6754bff34e3Sthurlow } 6764bff34e3Sthurlow smb_share_rele(sdp->sd_share); 6774bff34e3Sthurlow sdp->sd_share = NULL; 6784bff34e3Sthurlow sdp->sd_level = SMBL_VC; 6794bff34e3Sthurlow break; 6804bff34e3Sthurlow case SMBIOC_FLAGS2: 6814bff34e3Sthurlow if (sdp->sd_share == NULL) { 6824bff34e3Sthurlow error = ENOTCONN; 6834bff34e3Sthurlow break; 6844bff34e3Sthurlow } 6854bff34e3Sthurlow if (!sdp->sd_vc) { 6864bff34e3Sthurlow error = ENOTCONN; 6874bff34e3Sthurlow break; 6884bff34e3Sthurlow } 6894bff34e3Sthurlow vcp = sdp->sd_vc; 6904bff34e3Sthurlow /* 6914bff34e3Sthurlow * Return the flags2 value. 6924bff34e3Sthurlow */ 6934bff34e3Sthurlow ddi_copyout(&vcp->vc_hflags2, (void *)arg, 6944bff34e3Sthurlow sizeof (u_int16_t), mode); 6954bff34e3Sthurlow break; 6964bff34e3Sthurlow 6974bff34e3Sthurlow case SMBIOC_PK_ADD: 6984bff34e3Sthurlow pk = kmem_alloc(sizeof (*pk), KM_SLEEP); 6994bff34e3Sthurlow if (ddi_copyin((void *)arg, pk, 7004bff34e3Sthurlow sizeof (*pk), mode)) { 7014bff34e3Sthurlow error = EFAULT; 7024bff34e3Sthurlow break; 7034bff34e3Sthurlow } 7044bff34e3Sthurlow error = smb_pkey_add(pk, credp); 7054bff34e3Sthurlow break; 7064bff34e3Sthurlow 7074bff34e3Sthurlow case SMBIOC_PK_DEL: 7084bff34e3Sthurlow pk = kmem_alloc(sizeof (*pk), KM_SLEEP); 7094bff34e3Sthurlow if (ddi_copyin((void *)arg, pk, 7104bff34e3Sthurlow sizeof (*pk), mode)) { 7114bff34e3Sthurlow error = EFAULT; 7124bff34e3Sthurlow break; 7134bff34e3Sthurlow } 7144bff34e3Sthurlow error = smb_pkey_del(pk, credp); 7154bff34e3Sthurlow break; 7164bff34e3Sthurlow 7174bff34e3Sthurlow case SMBIOC_PK_CHK: 7184bff34e3Sthurlow pk = kmem_alloc(sizeof (*pk), KM_SLEEP); 7194bff34e3Sthurlow if (ddi_copyin((void *)arg, pk, 7204bff34e3Sthurlow sizeof (*pk), mode)) { 7214bff34e3Sthurlow error = EFAULT; 7224bff34e3Sthurlow break; 7234bff34e3Sthurlow } 7244bff34e3Sthurlow error = smb_pkey_check(pk, credp); 7254bff34e3Sthurlow /* 7264bff34e3Sthurlow * Note: Intentionally DO NOT copyout 7274bff34e3Sthurlow * the pasword here. It can only be 7284bff34e3Sthurlow * retrieved by internal calls. This 7294bff34e3Sthurlow * ioctl only tells the caller if the 7304bff34e3Sthurlow * keychain entry exists. 7314bff34e3Sthurlow */ 7324bff34e3Sthurlow break; 7334bff34e3Sthurlow 7344bff34e3Sthurlow case SMBIOC_PK_DEL_OWNER: 7354bff34e3Sthurlow uid = crgetruid(credp); 7364bff34e3Sthurlow error = smb_pkey_deluid(uid, credp); 7374bff34e3Sthurlow break; 7384bff34e3Sthurlow 7394bff34e3Sthurlow case SMBIOC_PK_DEL_EVERYONE: 7404bff34e3Sthurlow uid = (uid_t)-1; 7414bff34e3Sthurlow error = smb_pkey_deluid(uid, credp); 7424bff34e3Sthurlow break; 7434bff34e3Sthurlow 7444bff34e3Sthurlow default: 7454bff34e3Sthurlow error = ENODEV; 7464bff34e3Sthurlow } 7474bff34e3Sthurlow 7484bff34e3Sthurlow /* 7494bff34e3Sthurlow * Let's just do all the kmem_free stuff HERE, 7504bff34e3Sthurlow * instead of at every switch break. 7514bff34e3Sthurlow */ 7524bff34e3Sthurlow 7534bff34e3Sthurlow /* SMBIOC_REQUEST */ 7544bff34e3Sthurlow if (srq) 7554bff34e3Sthurlow kmem_free(srq, sizeof (*srq)); 7564bff34e3Sthurlow 7574bff34e3Sthurlow /* SMBIOC_T2RQ */ 7584bff34e3Sthurlow if (strq) 7594bff34e3Sthurlow kmem_free(strq, sizeof (*strq)); 7604bff34e3Sthurlow 7614bff34e3Sthurlow /* SMBIOC_READ */ 7624bff34e3Sthurlow /* SMBIOC_WRITE */ 7634bff34e3Sthurlow if (rwrq) 7644bff34e3Sthurlow kmem_free(rwrq, sizeof (*rwrq)); 7654bff34e3Sthurlow 7661b34bc4aSbs /* SMBIOC_FINDVC */ 7674bff34e3Sthurlow /* SMBIOC_NEGOTIATE */ 7684bff34e3Sthurlow /* SMBIOC_SSNSETUP */ 7694bff34e3Sthurlow /* SMBIOC_TCON */ 7704bff34e3Sthurlow if (sioc) { 7714bff34e3Sthurlow /* 7724bff34e3Sthurlow * This data structure may contain 7734bff34e3Sthurlow * cleartext passwords, so zap it. 7744bff34e3Sthurlow */ 7754bff34e3Sthurlow bzero(sioc, sizeof (*sioc)); 7764bff34e3Sthurlow kmem_free(sioc, sizeof (*sioc)); 7774bff34e3Sthurlow } 7784bff34e3Sthurlow 7794bff34e3Sthurlow /* SMBIOC_PK_... */ 7804bff34e3Sthurlow if (pk) { 7814bff34e3Sthurlow /* 7824bff34e3Sthurlow * This data structure may contain 7834bff34e3Sthurlow * cleartext passwords, so zap it. 7844bff34e3Sthurlow */ 7854bff34e3Sthurlow bzero(pk, sizeof (*pk)); 7864bff34e3Sthurlow kmem_free(pk, sizeof (*pk)); 7874bff34e3Sthurlow } 7884bff34e3Sthurlow 7894bff34e3Sthurlow smb_credrele(&scred); 7904bff34e3Sthurlow 7914bff34e3Sthurlow return (error); 7924bff34e3Sthurlow } 7934bff34e3Sthurlow 7944bff34e3Sthurlow /*ARGSUSED*/ 7954bff34e3Sthurlow static int 7964bff34e3Sthurlow nsmb_open(dev_t *dev, int flags, int otyp, cred_t *cr) 7974bff34e3Sthurlow { 7984bff34e3Sthurlow major_t new_major; 7994bff34e3Sthurlow smb_dev_t *sdp, *sdv; 8004bff34e3Sthurlow 8014bff34e3Sthurlow mutex_enter(&dev_lck); 8024bff34e3Sthurlow for (; ; ) { 8034bff34e3Sthurlow minor_t start = nsmb_minor; 8044bff34e3Sthurlow do { 8054bff34e3Sthurlow if (nsmb_minor >= MAXMIN32) { 8064bff34e3Sthurlow if (nsmb_major == getmajor(*dev)) 8074bff34e3Sthurlow nsmb_minor = NSMB_MIN_MINOR; 8084bff34e3Sthurlow else 8094bff34e3Sthurlow nsmb_minor = 0; 8104bff34e3Sthurlow } else { 8114bff34e3Sthurlow nsmb_minor++; 8124bff34e3Sthurlow } 8134bff34e3Sthurlow sdv = ddi_get_soft_state(statep, nsmb_minor); 8144bff34e3Sthurlow } while ((sdv != NULL) && (nsmb_minor != start)); 8154bff34e3Sthurlow if (nsmb_minor == start) { 8164bff34e3Sthurlow /* 8174bff34e3Sthurlow * The condition we need to solve here is all the 8184bff34e3Sthurlow * MAXMIN32(~262000) minors numbers are reached. We 8194bff34e3Sthurlow * need to create a new major number. 8204bff34e3Sthurlow * zfs uses getudev() to create a new major number. 8214bff34e3Sthurlow */ 8224bff34e3Sthurlow if ((new_major = getudev()) == (major_t)-1) { 8234bff34e3Sthurlow cmn_err(CE_WARN, 8244bff34e3Sthurlow "nsmb: Can't get unique major " 8254bff34e3Sthurlow "device number."); 8264bff34e3Sthurlow mutex_exit(&dev_lck); 8274bff34e3Sthurlow return (-1); 8284bff34e3Sthurlow } 8294bff34e3Sthurlow nsmb_major = new_major; 8304bff34e3Sthurlow nsmb_minor = 0; 8314bff34e3Sthurlow } else { 8324bff34e3Sthurlow break; 8334bff34e3Sthurlow } 8344bff34e3Sthurlow } 8354bff34e3Sthurlow 8364bff34e3Sthurlow /* 8374bff34e3Sthurlow * This is called by mount or open call. 8384bff34e3Sthurlow * The open() routine is passed a pointer to a device number so 8394bff34e3Sthurlow * that the driver can change the minor number. This allows 8404bff34e3Sthurlow * drivers to dynamically create minor instances of the dev- 8414bff34e3Sthurlow * ice. An example of this might be a pseudo-terminal driver 8424bff34e3Sthurlow * that creates a new pseudo-terminal whenever it is opened. 8434bff34e3Sthurlow * A driver that chooses the minor number dynamically, normally 8444bff34e3Sthurlow * creates only one minor device node in attach(9E) with 8454bff34e3Sthurlow * ddi_create_minor_node(9F) then changes the minor number com- 8464bff34e3Sthurlow * ponent of *devp using makedevice(9F) and getmajor(9F) The 8474bff34e3Sthurlow * driver needs to keep track of available minor numbers inter- 8484bff34e3Sthurlow * nally. 8494bff34e3Sthurlow * Stuff the structure smb_dev. 8504bff34e3Sthurlow * return. 8514bff34e3Sthurlow */ 8524bff34e3Sthurlow 8534bff34e3Sthurlow if (ddi_soft_state_zalloc(statep, nsmb_minor) == DDI_FAILURE) { 8544bff34e3Sthurlow mutex_exit(&dev_lck); 8554bff34e3Sthurlow return (ENXIO); 8564bff34e3Sthurlow } 8574bff34e3Sthurlow if ((sdp = ddi_get_soft_state(statep, nsmb_minor)) == NULL) { 8584bff34e3Sthurlow mutex_exit(&dev_lck); 8594bff34e3Sthurlow return (ENXIO); 8604bff34e3Sthurlow } 8614bff34e3Sthurlow 8624bff34e3Sthurlow sdp->sd_opened = 1; 8634bff34e3Sthurlow sdp->sd_seq = nsmb_minor; 8644bff34e3Sthurlow sdp->smb_cred = cr; 8654bff34e3Sthurlow sdp->sd_flags |= NSMBFL_OPEN; 8664bff34e3Sthurlow sdp->zoneid = crgetzoneid(cr); 8674bff34e3Sthurlow mutex_exit(&dev_lck); 8684bff34e3Sthurlow 8694bff34e3Sthurlow *dev = makedevice(nsmb_major, nsmb_minor); 8704bff34e3Sthurlow 8714bff34e3Sthurlow return (0); 8724bff34e3Sthurlow } 8734bff34e3Sthurlow 8744bff34e3Sthurlow /*ARGSUSED*/ 8754bff34e3Sthurlow static int 8764bff34e3Sthurlow nsmb_close(dev_t dev, int flags, int otyp, cred_t *cr) 8774bff34e3Sthurlow { 8784bff34e3Sthurlow struct smb_vc *vcp; 8794bff34e3Sthurlow struct smb_share *ssp; 8804bff34e3Sthurlow struct smb_cred scred; 8814bff34e3Sthurlow minor_t inst = getminor(dev); 8824bff34e3Sthurlow smb_dev_t *sdp; 8834bff34e3Sthurlow 8844bff34e3Sthurlow mutex_enter(&dev_lck); 8854bff34e3Sthurlow /* 8864bff34e3Sthurlow * 1. Check the validity of the minor number. 8874bff34e3Sthurlow * 2. Release any shares/vc associated with the connection. 8884bff34e3Sthurlow * 3. Can close the minor number. 8894bff34e3Sthurlow * 4. Deallocate any resources allocated in open() call. 8904bff34e3Sthurlow */ 8914bff34e3Sthurlow smb_credinit(&scred, curproc, cr); 8924bff34e3Sthurlow 8934bff34e3Sthurlow sdp = ddi_get_soft_state(statep, inst); 8944bff34e3Sthurlow 8954bff34e3Sthurlow /* 8964bff34e3Sthurlow * time to call ddi_get_soft_state() 8974bff34e3Sthurlow */ 8984bff34e3Sthurlow ssp = sdp->sd_share; 8994bff34e3Sthurlow if (ssp != NULL) 9004bff34e3Sthurlow smb_share_rele(ssp); 9014bff34e3Sthurlow vcp = sdp->sd_vc; 9024bff34e3Sthurlow if (vcp != NULL) { 9034bff34e3Sthurlow /* 9044bff34e3Sthurlow * If this dev minor was doing session setup 9054bff34e3Sthurlow * and failed to authenticate (or whatever) 906*6723e17fSGordon Ross * then we need to put the VC in a state that 907*6723e17fSGordon Ross * allows later commands to try again. 9084bff34e3Sthurlow */ 9094bff34e3Sthurlow if (sdp->sd_flags & NSMBFL_NEWVC) 910*6723e17fSGordon Ross smb_iod_disconnect(vcp); 9114bff34e3Sthurlow smb_vc_rele(vcp); 9124bff34e3Sthurlow } 9134bff34e3Sthurlow smb_credrele(&scred); 9144bff34e3Sthurlow 9154bff34e3Sthurlow /* 9164bff34e3Sthurlow * Free the instance 9174bff34e3Sthurlow */ 9184bff34e3Sthurlow ddi_soft_state_free(statep, inst); 9194bff34e3Sthurlow mutex_exit(&dev_lck); 9204bff34e3Sthurlow return (0); 9214bff34e3Sthurlow } 9224bff34e3Sthurlow 9234bff34e3Sthurlow int 9244bff34e3Sthurlow smb_dev2share(int fd, struct smb_share **sspp) 9254bff34e3Sthurlow { 9264bff34e3Sthurlow register vnode_t *vp; 9274bff34e3Sthurlow smb_dev_t *sdp; 9284bff34e3Sthurlow struct smb_share *ssp; 9294bff34e3Sthurlow dev_t dev; 9304bff34e3Sthurlow file_t *fp; 9314bff34e3Sthurlow 9324bff34e3Sthurlow if ((fp = getf(fd)) == NULL) 9334bff34e3Sthurlow return (set_errno(EBADF)); 9344bff34e3Sthurlow vp = fp->f_vnode; 9354bff34e3Sthurlow dev = vp->v_rdev; 9364bff34e3Sthurlow if (dev == NULL) { 9374bff34e3Sthurlow releasef(fd); 9384bff34e3Sthurlow return (EBADF); 9394bff34e3Sthurlow } 9404bff34e3Sthurlow sdp = ddi_get_soft_state(statep, getminor(dev)); 9414bff34e3Sthurlow if (sdp == NULL) { 9424bff34e3Sthurlow releasef(fd); 9434bff34e3Sthurlow return (DDI_FAILURE); 9444bff34e3Sthurlow } 9454bff34e3Sthurlow ssp = sdp->sd_share; 9464bff34e3Sthurlow if (ssp == NULL) { 9474bff34e3Sthurlow releasef(fd); 9484bff34e3Sthurlow return (ENOTCONN); 9494bff34e3Sthurlow } 9504bff34e3Sthurlow /* 9514bff34e3Sthurlow * The share is already locked and referenced by the TCON ioctl 9524bff34e3Sthurlow * We NULL to hand off share to caller (mount) 9534bff34e3Sthurlow * This allows further ioctls against connection, for instance 9544bff34e3Sthurlow * another tree connect and mount, in the automounter case 9554bff34e3Sthurlow * 9564bff34e3Sthurlow * We're effectively giving our reference to the mount. 9574bff34e3Sthurlow * 9584bff34e3Sthurlow * XXX: I'm not sure I like this. I'd rather see the ioctl 9594bff34e3Sthurlow * caller do something explicit to give up this reference, 9604bff34e3Sthurlow * (i.e. SMBIOC_TDIS above) and increment the hold here. 9614bff34e3Sthurlow */ 9624bff34e3Sthurlow sdp->sd_share = NULL; 9634bff34e3Sthurlow releasef(fd); 9644bff34e3Sthurlow *sspp = ssp; 9654bff34e3Sthurlow return (0); 9664bff34e3Sthurlow } 967