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 334bff34e3Sthurlow /* 3439f633a0SBayard Bell * Copyright 2012 Nexenta Systems, Inc. All rights reserved. 35613a2f6bSGordon Ross * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 364bff34e3Sthurlow * Use is subject to license terms. 374bff34e3Sthurlow */ 384bff34e3Sthurlow 394bff34e3Sthurlow #include <sys/types.h> 404bff34e3Sthurlow #include <sys/param.h> 414bff34e3Sthurlow #include <sys/errno.h> 424bff34e3Sthurlow #include <sys/sysmacros.h> 434bff34e3Sthurlow #include <sys/uio.h> 444bff34e3Sthurlow #include <sys/buf.h> 454bff34e3Sthurlow #include <sys/modctl.h> 464bff34e3Sthurlow #include <sys/open.h> 474bff34e3Sthurlow #include <sys/file.h> 484bff34e3Sthurlow #include <sys/kmem.h> 494bff34e3Sthurlow #include <sys/conf.h> 504bff34e3Sthurlow #include <sys/cmn_err.h> 514bff34e3Sthurlow #include <sys/stat.h> 524bff34e3Sthurlow #include <sys/ddi.h> 534bff34e3Sthurlow #include <sys/sunddi.h> 544bff34e3Sthurlow #include <sys/sunldi.h> 554bff34e3Sthurlow #include <sys/policy.h> 564bff34e3Sthurlow #include <sys/zone.h> 574bff34e3Sthurlow #include <sys/pathname.h> 584bff34e3Sthurlow #include <sys/mount.h> 594bff34e3Sthurlow #include <sys/sdt.h> 604bff34e3Sthurlow #include <fs/fs_subr.h> 614bff34e3Sthurlow #include <sys/modctl.h> 624bff34e3Sthurlow #include <sys/devops.h> 634bff34e3Sthurlow #include <sys/thread.h> 644bff34e3Sthurlow #include <sys/types.h> 654bff34e3Sthurlow #include <sys/zone.h> 664bff34e3Sthurlow 674bff34e3Sthurlow #include <netsmb/smb_osdep.h> 684bff34e3Sthurlow #include <netsmb/mchain.h> /* for "htoles()" */ 694bff34e3Sthurlow 704bff34e3Sthurlow #include <netsmb/smb.h> 714bff34e3Sthurlow #include <netsmb/smb_conn.h> 724bff34e3Sthurlow #include <netsmb/smb_subr.h> 734bff34e3Sthurlow #include <netsmb/smb_dev.h> 744bff34e3Sthurlow #include <netsmb/smb_pass.h> 754bff34e3Sthurlow 765ab8bad6SGordon Ross #define NSMB_MIN_MINOR 1 775ab8bad6SGordon Ross #define NSMB_MAX_MINOR L_MAXMIN32 785ab8bad6SGordon Ross 794bff34e3Sthurlow /* for version checks */ 804bff34e3Sthurlow const uint32_t nsmb_version = NSMB_VERSION; 814bff34e3Sthurlow 824bff34e3Sthurlow static void *statep; 834bff34e3Sthurlow static major_t nsmb_major; 845ab8bad6SGordon Ross static minor_t last_minor = NSMB_MIN_MINOR; 855ab8bad6SGordon Ross static dev_info_t *nsmb_dip; 864bff34e3Sthurlow static kmutex_t dev_lck; 874bff34e3Sthurlow 884bff34e3Sthurlow /* Zone support */ 894bff34e3Sthurlow zone_key_t nsmb_zone_key; 904bff34e3Sthurlow extern void nsmb_zone_shutdown(zoneid_t zoneid, void *data); 914bff34e3Sthurlow extern void nsmb_zone_destroy(zoneid_t zoneid, void *data); 924bff34e3Sthurlow 934bff34e3Sthurlow /* 944bff34e3Sthurlow * cb_ops device operations. 954bff34e3Sthurlow */ 964bff34e3Sthurlow static int nsmb_open(dev_t *devp, int flag, int otyp, cred_t *credp); 974bff34e3Sthurlow static int nsmb_close(dev_t dev, int flag, int otyp, cred_t *credp); 984bff34e3Sthurlow static int nsmb_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, 994bff34e3Sthurlow cred_t *credp, int *rvalp); 100613a2f6bSGordon Ross static int nsmb_close2(smb_dev_t *sdp, cred_t *cr); 101613a2f6bSGordon Ross 1024bff34e3Sthurlow /* smbfs cb_ops */ 1034bff34e3Sthurlow static struct cb_ops nsmb_cbops = { 1044bff34e3Sthurlow nsmb_open, /* open */ 1054bff34e3Sthurlow nsmb_close, /* close */ 1064bff34e3Sthurlow nodev, /* strategy */ 1074bff34e3Sthurlow nodev, /* print */ 1084bff34e3Sthurlow nodev, /* dump */ 1094bff34e3Sthurlow nodev, /* read */ 1104bff34e3Sthurlow nodev, /* write */ 1114bff34e3Sthurlow nsmb_ioctl, /* ioctl */ 1124bff34e3Sthurlow nodev, /* devmap */ 1134bff34e3Sthurlow nodev, /* mmap */ 1144bff34e3Sthurlow nodev, /* segmap */ 1154bff34e3Sthurlow nochpoll, /* poll */ 1164bff34e3Sthurlow ddi_prop_op, /* prop_op */ 1174bff34e3Sthurlow NULL, /* stream */ 1184bff34e3Sthurlow D_MP, /* cb_flag */ 1194bff34e3Sthurlow CB_REV, /* rev */ 1204bff34e3Sthurlow nodev, /* int (*cb_aread)() */ 1214bff34e3Sthurlow nodev /* int (*cb_awrite)() */ 1224bff34e3Sthurlow }; 1234bff34e3Sthurlow 1244bff34e3Sthurlow /* 1254bff34e3Sthurlow * Device options 1264bff34e3Sthurlow */ 1274bff34e3Sthurlow static int nsmb_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); 1284bff34e3Sthurlow static int nsmb_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); 1294bff34e3Sthurlow static int nsmb_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, 1304bff34e3Sthurlow void *arg, void **result); 1314bff34e3Sthurlow 1324bff34e3Sthurlow static struct dev_ops nsmb_ops = { 1334bff34e3Sthurlow DEVO_REV, /* devo_rev, */ 1344bff34e3Sthurlow 0, /* refcnt */ 1354bff34e3Sthurlow nsmb_getinfo, /* info */ 1364bff34e3Sthurlow nulldev, /* identify */ 1374bff34e3Sthurlow nulldev, /* probe */ 1384bff34e3Sthurlow nsmb_attach, /* attach */ 1394bff34e3Sthurlow nsmb_detach, /* detach */ 1404bff34e3Sthurlow nodev, /* reset */ 1414bff34e3Sthurlow &nsmb_cbops, /* driver ops - devctl interfaces */ 1424bff34e3Sthurlow NULL, /* bus operations */ 14319397407SSherry Moore NULL, /* power */ 14419397407SSherry Moore ddi_quiesce_not_needed, /* quiesce */ 1454bff34e3Sthurlow }; 1464bff34e3Sthurlow 1474bff34e3Sthurlow /* 1484bff34e3Sthurlow * Module linkage information. 1494bff34e3Sthurlow */ 1504bff34e3Sthurlow 1514bff34e3Sthurlow static struct modldrv nsmb_modldrv = { 1524bff34e3Sthurlow &mod_driverops, /* Driver module */ 153613a2f6bSGordon Ross "SMBFS network driver", 1544bff34e3Sthurlow &nsmb_ops /* Driver ops */ 1554bff34e3Sthurlow }; 1564bff34e3Sthurlow 1574bff34e3Sthurlow static struct modlinkage nsmb_modlinkage = { 1584bff34e3Sthurlow MODREV_1, 1594bff34e3Sthurlow (void *)&nsmb_modldrv, 1604bff34e3Sthurlow NULL 1614bff34e3Sthurlow }; 1624bff34e3Sthurlow 1634bff34e3Sthurlow int 1644bff34e3Sthurlow _init(void) 1654bff34e3Sthurlow { 1664bff34e3Sthurlow int error; 1674bff34e3Sthurlow 16802d09e03SGordon Ross (void) ddi_soft_state_init(&statep, sizeof (smb_dev_t), 1); 1694bff34e3Sthurlow 1704bff34e3Sthurlow /* Can initialize some mutexes also. */ 1714bff34e3Sthurlow mutex_init(&dev_lck, NULL, MUTEX_DRIVER, NULL); 1724bff34e3Sthurlow 1734bff34e3Sthurlow /* Connection data structures. */ 1744bff34e3Sthurlow (void) smb_sm_init(); 1754bff34e3Sthurlow 1764bff34e3Sthurlow /* Initialize password Key chain DB. */ 1774bff34e3Sthurlow smb_pkey_init(); 1784bff34e3Sthurlow 17902d09e03SGordon Ross /* Time conversion stuff. */ 18002d09e03SGordon Ross smb_time_init(); 18102d09e03SGordon Ross 1829c9af259SGordon Ross /* Initialize crypto mechanisms. */ 1839c9af259SGordon Ross smb_crypto_mech_init(); 1849c9af259SGordon Ross 1854bff34e3Sthurlow zone_key_create(&nsmb_zone_key, NULL, nsmb_zone_shutdown, 1864bff34e3Sthurlow nsmb_zone_destroy); 1874bff34e3Sthurlow 1884bff34e3Sthurlow /* 1894bff34e3Sthurlow * Install the module. Do this after other init, 1904bff34e3Sthurlow * to prevent entrances before we're ready. 1914bff34e3Sthurlow */ 1924bff34e3Sthurlow if ((error = mod_install((&nsmb_modlinkage))) != 0) { 1934bff34e3Sthurlow 1944bff34e3Sthurlow /* Same as 2nd half of _fini */ 1954bff34e3Sthurlow (void) zone_key_delete(nsmb_zone_key); 1964bff34e3Sthurlow smb_pkey_fini(); 1974bff34e3Sthurlow smb_sm_done(); 1984bff34e3Sthurlow mutex_destroy(&dev_lck); 1994bff34e3Sthurlow ddi_soft_state_fini(&statep); 2004bff34e3Sthurlow 2014bff34e3Sthurlow return (error); 2024bff34e3Sthurlow } 2034bff34e3Sthurlow 2044bff34e3Sthurlow return (0); 2054bff34e3Sthurlow } 2064bff34e3Sthurlow 2074bff34e3Sthurlow int 2084bff34e3Sthurlow _fini(void) 2094bff34e3Sthurlow { 2104bff34e3Sthurlow int status; 2114bff34e3Sthurlow 2124bff34e3Sthurlow /* 2134bff34e3Sthurlow * Prevent unload if we have active VCs 2144bff34e3Sthurlow * or stored passwords 2154bff34e3Sthurlow */ 2164bff34e3Sthurlow if ((status = smb_sm_idle()) != 0) 2174bff34e3Sthurlow return (status); 2184bff34e3Sthurlow if ((status = smb_pkey_idle()) != 0) 2194bff34e3Sthurlow return (status); 2204bff34e3Sthurlow 2214bff34e3Sthurlow /* 2224bff34e3Sthurlow * Remove the module. Do this before destroying things, 2234bff34e3Sthurlow * to prevent new entrances while we're destorying. 2244bff34e3Sthurlow */ 2254bff34e3Sthurlow if ((status = mod_remove(&nsmb_modlinkage)) != 0) { 2264bff34e3Sthurlow return (status); 2274bff34e3Sthurlow } 2284bff34e3Sthurlow 2294bff34e3Sthurlow (void) zone_key_delete(nsmb_zone_key); 2304bff34e3Sthurlow 23102d09e03SGordon Ross /* Time conversion stuff. */ 23202d09e03SGordon Ross smb_time_fini(); 23302d09e03SGordon Ross 2344bff34e3Sthurlow /* Destroy password Key chain DB. */ 2354bff34e3Sthurlow smb_pkey_fini(); 2364bff34e3Sthurlow 2374bff34e3Sthurlow smb_sm_done(); 2384bff34e3Sthurlow 2394bff34e3Sthurlow mutex_destroy(&dev_lck); 2404bff34e3Sthurlow ddi_soft_state_fini(&statep); 2414bff34e3Sthurlow 2424bff34e3Sthurlow return (status); 2434bff34e3Sthurlow } 2444bff34e3Sthurlow 2454bff34e3Sthurlow int 2464bff34e3Sthurlow _info(struct modinfo *modinfop) 2474bff34e3Sthurlow { 2484bff34e3Sthurlow return (mod_info(&nsmb_modlinkage, modinfop)); 2494bff34e3Sthurlow } 2504bff34e3Sthurlow 2514bff34e3Sthurlow /*ARGSUSED*/ 2524bff34e3Sthurlow static int 2534bff34e3Sthurlow nsmb_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) 2544bff34e3Sthurlow { 2554bff34e3Sthurlow int ret = DDI_SUCCESS; 2564bff34e3Sthurlow 2574bff34e3Sthurlow switch (cmd) { 2584bff34e3Sthurlow case DDI_INFO_DEVT2DEVINFO: 2595ab8bad6SGordon Ross *result = nsmb_dip; 2604bff34e3Sthurlow break; 2614bff34e3Sthurlow case DDI_INFO_DEVT2INSTANCE: 2625ab8bad6SGordon Ross *result = NULL; 2634bff34e3Sthurlow break; 2644bff34e3Sthurlow default: 2654bff34e3Sthurlow ret = DDI_FAILURE; 2664bff34e3Sthurlow } 2674bff34e3Sthurlow return (ret); 2684bff34e3Sthurlow } 2694bff34e3Sthurlow 2704bff34e3Sthurlow static int 2714bff34e3Sthurlow nsmb_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 2724bff34e3Sthurlow { 2734bff34e3Sthurlow 2744bff34e3Sthurlow if (cmd != DDI_ATTACH) 2754bff34e3Sthurlow return (DDI_FAILURE); 2765ab8bad6SGordon Ross 2774bff34e3Sthurlow /* 2785ab8bad6SGordon Ross * We only support only one "instance". Note that 2795ab8bad6SGordon Ross * "instances" are different from minor units. 2805ab8bad6SGordon Ross * We get one (unique) minor unit per open. 2814bff34e3Sthurlow */ 2824bff34e3Sthurlow if (ddi_get_instance(dip) > 0) 2834bff34e3Sthurlow return (DDI_FAILURE); 2844bff34e3Sthurlow 2854bff34e3Sthurlow if (ddi_create_minor_node(dip, "nsmb", S_IFCHR, 0, DDI_PSEUDO, 2864bff34e3Sthurlow NULL) == DDI_FAILURE) { 2874bff34e3Sthurlow cmn_err(CE_WARN, "nsmb_attach: create minor"); 2885ab8bad6SGordon Ross return (DDI_FAILURE); 2894bff34e3Sthurlow } 2904bff34e3Sthurlow 2915ab8bad6SGordon Ross /* 2925ab8bad6SGordon Ross * We need the major number a couple places, 2935ab8bad6SGordon Ross * i.e. in smb_dev2share() 2945ab8bad6SGordon Ross */ 2955ab8bad6SGordon Ross nsmb_major = ddi_name_to_major(NSMB_NAME); 2965ab8bad6SGordon Ross 2975ab8bad6SGordon Ross nsmb_dip = dip; 2984bff34e3Sthurlow ddi_report_dev(dip); 2994bff34e3Sthurlow return (DDI_SUCCESS); 3004bff34e3Sthurlow } 3014bff34e3Sthurlow 3024bff34e3Sthurlow /*ARGSUSED*/ 3034bff34e3Sthurlow static int 3044bff34e3Sthurlow nsmb_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 3054bff34e3Sthurlow { 3064bff34e3Sthurlow 3074bff34e3Sthurlow if (cmd != DDI_DETACH) 3084bff34e3Sthurlow return (DDI_FAILURE); 3094bff34e3Sthurlow if (ddi_get_instance(dip) > 0) 3104bff34e3Sthurlow return (DDI_FAILURE); 3114bff34e3Sthurlow 3125ab8bad6SGordon Ross nsmb_dip = NULL; 3134bff34e3Sthurlow ddi_remove_minor_node(dip, NULL); 3144bff34e3Sthurlow 3154bff34e3Sthurlow return (DDI_SUCCESS); 3164bff34e3Sthurlow } 3174bff34e3Sthurlow 3184bff34e3Sthurlow /*ARGSUSED*/ 3194bff34e3Sthurlow static int 320613a2f6bSGordon Ross nsmb_ioctl(dev_t dev, int cmd, intptr_t arg, int flags, /* model.h */ 321*216041c4SGordon Ross cred_t *cr, int *rvalp) 3224bff34e3Sthurlow { 3234bff34e3Sthurlow smb_dev_t *sdp; 324613a2f6bSGordon Ross int err; 3254bff34e3Sthurlow 3264bff34e3Sthurlow sdp = ddi_get_soft_state(statep, getminor(dev)); 3274bff34e3Sthurlow if (sdp == NULL) { 3284bff34e3Sthurlow return (DDI_FAILURE); 3294bff34e3Sthurlow } 3304bff34e3Sthurlow if ((sdp->sd_flags & NSMBFL_OPEN) == 0) { 3314bff34e3Sthurlow return (EBADF); 3324bff34e3Sthurlow } 3334bff34e3Sthurlow 3344bff34e3Sthurlow /* 3354bff34e3Sthurlow * Dont give access if the zone id is not as the same as we 3364bff34e3Sthurlow * set in the nsmb_open or dont belong to the global zone. 3374bff34e3Sthurlow * Check if the user belongs to this zone.. 3384bff34e3Sthurlow */ 3394bff34e3Sthurlow if (sdp->zoneid != getzoneid()) 3404bff34e3Sthurlow return (EIO); 3414bff34e3Sthurlow 342613a2f6bSGordon Ross /* 343613a2f6bSGordon Ross * We have a zone_shutdown call back that kills all the VCs 344613a2f6bSGordon Ross * in a zone that's shutting down. That action will cause 345613a2f6bSGordon Ross * all of these ioctls to fail on such VCs, so no need to 346613a2f6bSGordon Ross * check the zone status here on every ioctl call. 347613a2f6bSGordon Ross */ 3484bff34e3Sthurlow 349*216041c4SGordon Ross /* 350*216041c4SGordon Ross * Serialize ioctl calls. The smb_usr_... functions 351*216041c4SGordon Ross * don't expect concurrent calls on a given sdp. 352*216041c4SGordon Ross */ 353*216041c4SGordon Ross mutex_enter(&sdp->sd_lock); 354*216041c4SGordon Ross if ((sdp->sd_flags & NSMBFL_IOCTL) != 0) { 355*216041c4SGordon Ross mutex_exit(&sdp->sd_lock); 356*216041c4SGordon Ross return (EBUSY); 357*216041c4SGordon Ross } 358*216041c4SGordon Ross sdp->sd_flags |= NSMBFL_IOCTL; 359*216041c4SGordon Ross mutex_exit(&sdp->sd_lock); 360*216041c4SGordon Ross 361613a2f6bSGordon Ross err = 0; 3624bff34e3Sthurlow switch (cmd) { 363613a2f6bSGordon Ross case SMBIOC_GETVERS: 36402d09e03SGordon Ross (void) ddi_copyout(&nsmb_version, (void *)arg, 365613a2f6bSGordon Ross sizeof (nsmb_version), flags); 366613a2f6bSGordon Ross break; 3674bff34e3Sthurlow 368613a2f6bSGordon Ross case SMBIOC_FLAGS2: 369613a2f6bSGordon Ross err = smb_usr_get_flags2(sdp, arg, flags); 370613a2f6bSGordon Ross break; 3714bff34e3Sthurlow 372613a2f6bSGordon Ross case SMBIOC_GETSSNKEY: 373613a2f6bSGordon Ross err = smb_usr_get_ssnkey(sdp, arg, flags); 374613a2f6bSGordon Ross break; 3754bff34e3Sthurlow 376430b4c46SGordon Ross case SMBIOC_DUP_DEV: 377430b4c46SGordon Ross err = smb_usr_dup_dev(sdp, arg, flags); 378430b4c46SGordon Ross break; 379430b4c46SGordon Ross 380613a2f6bSGordon Ross case SMBIOC_REQUEST: 381613a2f6bSGordon Ross err = smb_usr_simplerq(sdp, arg, flags, cr); 382613a2f6bSGordon Ross break; 3834bff34e3Sthurlow 384613a2f6bSGordon Ross case SMBIOC_T2RQ: 385613a2f6bSGordon Ross err = smb_usr_t2request(sdp, arg, flags, cr); 386613a2f6bSGordon Ross break; 3874bff34e3Sthurlow 388613a2f6bSGordon Ross case SMBIOC_READ: 389613a2f6bSGordon Ross case SMBIOC_WRITE: 390613a2f6bSGordon Ross err = smb_usr_rw(sdp, cmd, arg, flags, cr); 391613a2f6bSGordon Ross break; 3924bff34e3Sthurlow 393430b4c46SGordon Ross case SMBIOC_NTCREATE: 394430b4c46SGordon Ross err = smb_usr_ntcreate(sdp, arg, flags, cr); 395430b4c46SGordon Ross break; 396430b4c46SGordon Ross 397430b4c46SGordon Ross case SMBIOC_PRINTJOB: 398430b4c46SGordon Ross err = smb_usr_printjob(sdp, arg, flags, cr); 399430b4c46SGordon Ross break; 400430b4c46SGordon Ross 401430b4c46SGordon Ross case SMBIOC_CLOSEFH: 402430b4c46SGordon Ross err = smb_usr_closefh(sdp, cr); 403430b4c46SGordon Ross break; 404430b4c46SGordon Ross 405613a2f6bSGordon Ross case SMBIOC_SSN_CREATE: 406613a2f6bSGordon Ross case SMBIOC_SSN_FIND: 407613a2f6bSGordon Ross err = smb_usr_get_ssn(sdp, cmd, arg, flags, cr); 408613a2f6bSGordon Ross break; 4094bff34e3Sthurlow 410613a2f6bSGordon Ross case SMBIOC_SSN_KILL: 411613a2f6bSGordon Ross case SMBIOC_SSN_RELE: 412613a2f6bSGordon Ross err = smb_usr_drop_ssn(sdp, cmd); 413613a2f6bSGordon Ross break; 4144bff34e3Sthurlow 415613a2f6bSGordon Ross case SMBIOC_TREE_CONNECT: 416613a2f6bSGordon Ross case SMBIOC_TREE_FIND: 417613a2f6bSGordon Ross err = smb_usr_get_tree(sdp, cmd, arg, flags, cr); 418613a2f6bSGordon Ross break; 4194bff34e3Sthurlow 420613a2f6bSGordon Ross case SMBIOC_TREE_KILL: 421613a2f6bSGordon Ross case SMBIOC_TREE_RELE: 422613a2f6bSGordon Ross err = smb_usr_drop_tree(sdp, cmd); 423613a2f6bSGordon Ross break; 4244bff34e3Sthurlow 425613a2f6bSGordon Ross case SMBIOC_IOD_WORK: 426613a2f6bSGordon Ross err = smb_usr_iod_work(sdp, arg, flags, cr); 427613a2f6bSGordon Ross break; 4284bff34e3Sthurlow 429613a2f6bSGordon Ross case SMBIOC_IOD_IDLE: 430613a2f6bSGordon Ross case SMBIOC_IOD_RCFAIL: 431613a2f6bSGordon Ross err = smb_usr_iod_ioctl(sdp, cmd, arg, flags); 432613a2f6bSGordon Ross break; 4334bff34e3Sthurlow 434613a2f6bSGordon Ross case SMBIOC_PK_ADD: 435613a2f6bSGordon Ross case SMBIOC_PK_DEL: 436613a2f6bSGordon Ross case SMBIOC_PK_CHK: 437613a2f6bSGordon Ross case SMBIOC_PK_DEL_OWNER: 438613a2f6bSGordon Ross case SMBIOC_PK_DEL_EVERYONE: 439613a2f6bSGordon Ross err = smb_pkey_ioctl(cmd, arg, flags, cr); 440613a2f6bSGordon Ross break; 4414bff34e3Sthurlow 442613a2f6bSGordon Ross default: 443613a2f6bSGordon Ross err = ENOTTY; 444613a2f6bSGordon Ross break; 4454bff34e3Sthurlow } 4464bff34e3Sthurlow 447*216041c4SGordon Ross mutex_enter(&sdp->sd_lock); 448*216041c4SGordon Ross sdp->sd_flags &= ~NSMBFL_IOCTL; 449*216041c4SGordon Ross mutex_exit(&sdp->sd_lock); 450*216041c4SGordon Ross 451613a2f6bSGordon Ross return (err); 4524bff34e3Sthurlow } 4534bff34e3Sthurlow 4545ab8bad6SGordon Ross /* 4555ab8bad6SGordon Ross * This does "clone" open, meaning it automatically 4565ab8bad6SGordon Ross * assigns an available minor unit for each open. 4575ab8bad6SGordon Ross */ 4584bff34e3Sthurlow /*ARGSUSED*/ 4594bff34e3Sthurlow static int 4604bff34e3Sthurlow nsmb_open(dev_t *dev, int flags, int otyp, cred_t *cr) 4614bff34e3Sthurlow { 4625ab8bad6SGordon Ross smb_dev_t *sdp; 4635ab8bad6SGordon Ross minor_t m; 4644bff34e3Sthurlow 4654bff34e3Sthurlow mutex_enter(&dev_lck); 4665ab8bad6SGordon Ross 4675ab8bad6SGordon Ross for (m = last_minor + 1; m != last_minor; m++) { 4685ab8bad6SGordon Ross if (m > NSMB_MAX_MINOR) 4695ab8bad6SGordon Ross m = NSMB_MIN_MINOR; 4705ab8bad6SGordon Ross 4715ab8bad6SGordon Ross if (ddi_get_soft_state(statep, m) == NULL) { 4725ab8bad6SGordon Ross last_minor = m; 4735ab8bad6SGordon Ross goto found; 4744bff34e3Sthurlow } 4754bff34e3Sthurlow } 4764bff34e3Sthurlow 4775ab8bad6SGordon Ross /* No available minor units. */ 4785ab8bad6SGordon Ross mutex_exit(&dev_lck); 4795ab8bad6SGordon Ross return (ENXIO); 4804bff34e3Sthurlow 4815ab8bad6SGordon Ross found: 4825ab8bad6SGordon Ross /* NB: dev_lck still held */ 4835ab8bad6SGordon Ross if (ddi_soft_state_zalloc(statep, m) == DDI_FAILURE) { 4844bff34e3Sthurlow mutex_exit(&dev_lck); 4854bff34e3Sthurlow return (ENXIO); 4864bff34e3Sthurlow } 4875ab8bad6SGordon Ross if ((sdp = ddi_get_soft_state(statep, m)) == NULL) { 4884bff34e3Sthurlow mutex_exit(&dev_lck); 4894bff34e3Sthurlow return (ENXIO); 4904bff34e3Sthurlow } 4915ab8bad6SGordon Ross *dev = makedevice(nsmb_major, m); 4925ab8bad6SGordon Ross mutex_exit(&dev_lck); 4934bff34e3Sthurlow 494430b4c46SGordon Ross sdp->sd_smbfid = -1; 4954bff34e3Sthurlow sdp->sd_flags |= NSMBFL_OPEN; 4964bff34e3Sthurlow sdp->zoneid = crgetzoneid(cr); 497*216041c4SGordon Ross mutex_init(&sdp->sd_lock, NULL, MUTEX_DRIVER, NULL); 4984bff34e3Sthurlow 4994bff34e3Sthurlow return (0); 5004bff34e3Sthurlow } 5014bff34e3Sthurlow 5024bff34e3Sthurlow /*ARGSUSED*/ 5034bff34e3Sthurlow static int 5044bff34e3Sthurlow nsmb_close(dev_t dev, int flags, int otyp, cred_t *cr) 5054bff34e3Sthurlow { 5064bff34e3Sthurlow minor_t inst = getminor(dev); 5074bff34e3Sthurlow smb_dev_t *sdp; 508613a2f6bSGordon Ross int err; 5094bff34e3Sthurlow 5104bff34e3Sthurlow /* 5114bff34e3Sthurlow * 1. Check the validity of the minor number. 5124bff34e3Sthurlow * 2. Release any shares/vc associated with the connection. 5134bff34e3Sthurlow * 3. Can close the minor number. 5144bff34e3Sthurlow * 4. Deallocate any resources allocated in open() call. 5154bff34e3Sthurlow */ 5164bff34e3Sthurlow 5174bff34e3Sthurlow sdp = ddi_get_soft_state(statep, inst); 518613a2f6bSGordon Ross if (sdp != NULL) 519613a2f6bSGordon Ross err = nsmb_close2(sdp, cr); 520613a2f6bSGordon Ross else 521613a2f6bSGordon Ross err = ENXIO; 5224bff34e3Sthurlow 5234bff34e3Sthurlow /* 524613a2f6bSGordon Ross * Free the instance 5254bff34e3Sthurlow */ 52639f633a0SBayard Bell mutex_enter(&dev_lck); 527613a2f6bSGordon Ross ddi_soft_state_free(statep, inst); 528613a2f6bSGordon Ross mutex_exit(&dev_lck); 529613a2f6bSGordon Ross return (err); 530613a2f6bSGordon Ross } 531613a2f6bSGordon Ross 532613a2f6bSGordon Ross static int 533613a2f6bSGordon Ross nsmb_close2(smb_dev_t *sdp, cred_t *cr) 534613a2f6bSGordon Ross { 535613a2f6bSGordon Ross struct smb_vc *vcp; 536613a2f6bSGordon Ross struct smb_share *ssp; 537613a2f6bSGordon Ross 538430b4c46SGordon Ross if (sdp->sd_smbfid != -1) 539430b4c46SGordon Ross (void) smb_usr_closefh(sdp, cr); 540430b4c46SGordon Ross 5414bff34e3Sthurlow ssp = sdp->sd_share; 5424bff34e3Sthurlow if (ssp != NULL) 5434bff34e3Sthurlow smb_share_rele(ssp); 544430b4c46SGordon Ross 5454bff34e3Sthurlow vcp = sdp->sd_vc; 5464bff34e3Sthurlow if (vcp != NULL) { 5474bff34e3Sthurlow /* 548613a2f6bSGordon Ross * If this dev minor was opened by smbiod, 549613a2f6bSGordon Ross * mark this VC as "dead" because it now 550613a2f6bSGordon Ross * will have no IOD to service it. 5514bff34e3Sthurlow */ 552613a2f6bSGordon Ross if (sdp->sd_flags & NSMBFL_IOD) 5536723e17fSGordon Ross smb_iod_disconnect(vcp); 5544bff34e3Sthurlow smb_vc_rele(vcp); 5554bff34e3Sthurlow } 556*216041c4SGordon Ross mutex_destroy(&sdp->sd_lock); 5574bff34e3Sthurlow 5584bff34e3Sthurlow return (0); 5594bff34e3Sthurlow } 5604bff34e3Sthurlow 561430b4c46SGordon Ross /* 562430b4c46SGordon Ross * Helper for SMBIOC_DUP_DEV 563430b4c46SGordon Ross * Duplicate state from the FD @arg ("from") onto 564430b4c46SGordon Ross * the FD for this device instance. 565430b4c46SGordon Ross */ 566430b4c46SGordon Ross int 567430b4c46SGordon Ross smb_usr_dup_dev(smb_dev_t *sdp, intptr_t arg, int flags) 568430b4c46SGordon Ross { 569430b4c46SGordon Ross file_t *fp = NULL; 570430b4c46SGordon Ross vnode_t *vp; 571430b4c46SGordon Ross smb_dev_t *from_sdp; 572430b4c46SGordon Ross dev_t dev; 573430b4c46SGordon Ross int32_t ufd; 574430b4c46SGordon Ross int err; 575430b4c46SGordon Ross 576430b4c46SGordon Ross /* Should be no VC */ 577430b4c46SGordon Ross if (sdp->sd_vc != NULL) 578430b4c46SGordon Ross return (EISCONN); 579430b4c46SGordon Ross 580430b4c46SGordon Ross /* 581430b4c46SGordon Ross * Get from_sdp (what we will duplicate) 582430b4c46SGordon Ross */ 583430b4c46SGordon Ross if (ddi_copyin((void *) arg, &ufd, sizeof (ufd), flags)) 584430b4c46SGordon Ross return (EFAULT); 585430b4c46SGordon Ross if ((fp = getf(ufd)) == NULL) 586430b4c46SGordon Ross return (EBADF); 587430b4c46SGordon Ross /* rele fp below */ 588430b4c46SGordon Ross vp = fp->f_vnode; 589430b4c46SGordon Ross dev = vp->v_rdev; 590430b4c46SGordon Ross if (dev == 0 || dev == NODEV || 591430b4c46SGordon Ross getmajor(dev) != nsmb_major) { 592430b4c46SGordon Ross err = EINVAL; 593430b4c46SGordon Ross goto out; 594430b4c46SGordon Ross } 595430b4c46SGordon Ross from_sdp = ddi_get_soft_state(statep, getminor(dev)); 596430b4c46SGordon Ross if (from_sdp == NULL) { 597430b4c46SGordon Ross err = EINVAL; 598430b4c46SGordon Ross goto out; 599430b4c46SGordon Ross } 600430b4c46SGordon Ross 601430b4c46SGordon Ross /* 602430b4c46SGordon Ross * Duplicate VC and share references onto this FD. 603430b4c46SGordon Ross */ 604430b4c46SGordon Ross if ((sdp->sd_vc = from_sdp->sd_vc) != NULL) 605430b4c46SGordon Ross smb_vc_hold(sdp->sd_vc); 606430b4c46SGordon Ross if ((sdp->sd_share = from_sdp->sd_share) != NULL) 607430b4c46SGordon Ross smb_share_hold(sdp->sd_share); 608430b4c46SGordon Ross sdp->sd_level = from_sdp->sd_level; 609430b4c46SGordon Ross err = 0; 610430b4c46SGordon Ross 611430b4c46SGordon Ross out: 612430b4c46SGordon Ross if (fp) 613430b4c46SGordon Ross releasef(ufd); 614430b4c46SGordon Ross return (err); 615430b4c46SGordon Ross } 616430b4c46SGordon Ross 617430b4c46SGordon Ross 618430b4c46SGordon Ross /* 619430b4c46SGordon Ross * Helper used by smbfs_mount 620430b4c46SGordon Ross */ 6214bff34e3Sthurlow int 6224bff34e3Sthurlow smb_dev2share(int fd, struct smb_share **sspp) 6234bff34e3Sthurlow { 624613a2f6bSGordon Ross file_t *fp = NULL; 625613a2f6bSGordon Ross vnode_t *vp; 6264bff34e3Sthurlow smb_dev_t *sdp; 627613a2f6bSGordon Ross smb_share_t *ssp; 6284bff34e3Sthurlow dev_t dev; 629613a2f6bSGordon Ross int err; 6304bff34e3Sthurlow 6314bff34e3Sthurlow if ((fp = getf(fd)) == NULL) 632613a2f6bSGordon Ross return (EBADF); 633430b4c46SGordon Ross /* rele fp below */ 634613a2f6bSGordon Ross 6354bff34e3Sthurlow vp = fp->f_vnode; 6364bff34e3Sthurlow dev = vp->v_rdev; 637613a2f6bSGordon Ross if (dev == 0 || dev == NODEV || 638613a2f6bSGordon Ross getmajor(dev) != nsmb_major) { 639430b4c46SGordon Ross err = EINVAL; 640613a2f6bSGordon Ross goto out; 6414bff34e3Sthurlow } 642613a2f6bSGordon Ross 6434bff34e3Sthurlow sdp = ddi_get_soft_state(statep, getminor(dev)); 6444bff34e3Sthurlow if (sdp == NULL) { 645613a2f6bSGordon Ross err = EINVAL; 646613a2f6bSGordon Ross goto out; 6474bff34e3Sthurlow } 648613a2f6bSGordon Ross 6494bff34e3Sthurlow ssp = sdp->sd_share; 6504bff34e3Sthurlow if (ssp == NULL) { 651613a2f6bSGordon Ross err = ENOTCONN; 652613a2f6bSGordon Ross goto out; 6534bff34e3Sthurlow } 654613a2f6bSGordon Ross 6554bff34e3Sthurlow /* 656613a2f6bSGordon Ross * Our caller gains a ref. to this share. 6574bff34e3Sthurlow */ 6584bff34e3Sthurlow *sspp = ssp; 659613a2f6bSGordon Ross smb_share_hold(ssp); 660613a2f6bSGordon Ross err = 0; 661613a2f6bSGordon Ross 662613a2f6bSGordon Ross out: 663613a2f6bSGordon Ross if (fp) 664613a2f6bSGordon Ross releasef(fd); 665613a2f6bSGordon Ross return (err); 6664bff34e3Sthurlow } 667