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 /* 36*430b4c46SGordon Ross * Copyright 2011 Nexenta Systems, Inc. All rights reserved. 37613a2f6bSGordon Ross * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 384bff34e3Sthurlow * Use is subject to license terms. 394bff34e3Sthurlow */ 404bff34e3Sthurlow 414bff34e3Sthurlow #include <sys/types.h> 424bff34e3Sthurlow #include <sys/param.h> 434bff34e3Sthurlow #include <sys/errno.h> 444bff34e3Sthurlow #include <sys/sysmacros.h> 454bff34e3Sthurlow #include <sys/uio.h> 464bff34e3Sthurlow #include <sys/buf.h> 474bff34e3Sthurlow #include <sys/modctl.h> 484bff34e3Sthurlow #include <sys/open.h> 494bff34e3Sthurlow #include <sys/file.h> 504bff34e3Sthurlow #include <sys/kmem.h> 514bff34e3Sthurlow #include <sys/conf.h> 524bff34e3Sthurlow #include <sys/cmn_err.h> 534bff34e3Sthurlow #include <sys/stat.h> 544bff34e3Sthurlow #include <sys/ddi.h> 554bff34e3Sthurlow #include <sys/sunddi.h> 564bff34e3Sthurlow #include <sys/sunldi.h> 574bff34e3Sthurlow #include <sys/policy.h> 584bff34e3Sthurlow #include <sys/zone.h> 594bff34e3Sthurlow #include <sys/pathname.h> 604bff34e3Sthurlow #include <sys/mount.h> 614bff34e3Sthurlow #include <sys/sdt.h> 624bff34e3Sthurlow #include <fs/fs_subr.h> 634bff34e3Sthurlow #include <sys/modctl.h> 644bff34e3Sthurlow #include <sys/devops.h> 654bff34e3Sthurlow #include <sys/thread.h> 664bff34e3Sthurlow #include <sys/mkdev.h> 674bff34e3Sthurlow #include <sys/types.h> 684bff34e3Sthurlow #include <sys/zone.h> 694bff34e3Sthurlow 704bff34e3Sthurlow #include <netsmb/smb_osdep.h> 714bff34e3Sthurlow #include <netsmb/mchain.h> /* for "htoles()" */ 724bff34e3Sthurlow 734bff34e3Sthurlow #include <netsmb/smb.h> 744bff34e3Sthurlow #include <netsmb/smb_conn.h> 754bff34e3Sthurlow #include <netsmb/smb_subr.h> 764bff34e3Sthurlow #include <netsmb/smb_dev.h> 774bff34e3Sthurlow #include <netsmb/smb_pass.h> 784bff34e3Sthurlow 794bff34e3Sthurlow /* for version checks */ 804bff34e3Sthurlow const uint32_t nsmb_version = NSMB_VERSION; 814bff34e3Sthurlow 824bff34e3Sthurlow /* 834bff34e3Sthurlow * Userland code loops through minor #s 0 to 1023, looking for one which opens. 844bff34e3Sthurlow * Intially we create minor 0 and leave it for anyone. Minor zero will never 854bff34e3Sthurlow * actually get used - opening triggers creation of another (but private) minor, 864bff34e3Sthurlow * which userland code will get to and mark busy. 874bff34e3Sthurlow */ 884bff34e3Sthurlow #define SMBMINORS 1024 894bff34e3Sthurlow static void *statep; 904bff34e3Sthurlow static major_t nsmb_major; 914bff34e3Sthurlow static minor_t nsmb_minor = 1; 924bff34e3Sthurlow 934bff34e3Sthurlow #define NSMB_MAX_MINOR (1 << 8) 944bff34e3Sthurlow #define NSMB_MIN_MINOR (NSMB_MAX_MINOR + 1) 954bff34e3Sthurlow 964bff34e3Sthurlow #define ILP32 1 974bff34e3Sthurlow #define LP64 2 984bff34e3Sthurlow 994bff34e3Sthurlow static kmutex_t dev_lck; 1004bff34e3Sthurlow 1014bff34e3Sthurlow /* Zone support */ 1024bff34e3Sthurlow zone_key_t nsmb_zone_key; 1034bff34e3Sthurlow extern void nsmb_zone_shutdown(zoneid_t zoneid, void *data); 1044bff34e3Sthurlow extern void nsmb_zone_destroy(zoneid_t zoneid, void *data); 1054bff34e3Sthurlow 1064bff34e3Sthurlow /* 1074bff34e3Sthurlow * cb_ops device operations. 1084bff34e3Sthurlow */ 1094bff34e3Sthurlow static int nsmb_open(dev_t *devp, int flag, int otyp, cred_t *credp); 1104bff34e3Sthurlow static int nsmb_close(dev_t dev, int flag, int otyp, cred_t *credp); 1114bff34e3Sthurlow static int nsmb_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, 1124bff34e3Sthurlow cred_t *credp, int *rvalp); 113613a2f6bSGordon Ross static int nsmb_close2(smb_dev_t *sdp, cred_t *cr); 114613a2f6bSGordon Ross 1154bff34e3Sthurlow /* smbfs cb_ops */ 1164bff34e3Sthurlow static struct cb_ops nsmb_cbops = { 1174bff34e3Sthurlow nsmb_open, /* open */ 1184bff34e3Sthurlow nsmb_close, /* close */ 1194bff34e3Sthurlow nodev, /* strategy */ 1204bff34e3Sthurlow nodev, /* print */ 1214bff34e3Sthurlow nodev, /* dump */ 1224bff34e3Sthurlow nodev, /* read */ 1234bff34e3Sthurlow nodev, /* write */ 1244bff34e3Sthurlow nsmb_ioctl, /* ioctl */ 1254bff34e3Sthurlow nodev, /* devmap */ 1264bff34e3Sthurlow nodev, /* mmap */ 1274bff34e3Sthurlow nodev, /* segmap */ 1284bff34e3Sthurlow nochpoll, /* poll */ 1294bff34e3Sthurlow ddi_prop_op, /* prop_op */ 1304bff34e3Sthurlow NULL, /* stream */ 1314bff34e3Sthurlow D_MP, /* cb_flag */ 1324bff34e3Sthurlow CB_REV, /* rev */ 1334bff34e3Sthurlow nodev, /* int (*cb_aread)() */ 1344bff34e3Sthurlow nodev /* int (*cb_awrite)() */ 1354bff34e3Sthurlow }; 1364bff34e3Sthurlow 1374bff34e3Sthurlow /* 1384bff34e3Sthurlow * Device options 1394bff34e3Sthurlow */ 1404bff34e3Sthurlow static int nsmb_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); 1414bff34e3Sthurlow static int nsmb_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); 1424bff34e3Sthurlow static int nsmb_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, 1434bff34e3Sthurlow void *arg, void **result); 1444bff34e3Sthurlow 1454bff34e3Sthurlow static struct dev_ops nsmb_ops = { 1464bff34e3Sthurlow DEVO_REV, /* devo_rev, */ 1474bff34e3Sthurlow 0, /* refcnt */ 1484bff34e3Sthurlow nsmb_getinfo, /* info */ 1494bff34e3Sthurlow nulldev, /* identify */ 1504bff34e3Sthurlow nulldev, /* probe */ 1514bff34e3Sthurlow nsmb_attach, /* attach */ 1524bff34e3Sthurlow nsmb_detach, /* detach */ 1534bff34e3Sthurlow nodev, /* reset */ 1544bff34e3Sthurlow &nsmb_cbops, /* driver ops - devctl interfaces */ 1554bff34e3Sthurlow NULL, /* bus operations */ 15619397407SSherry Moore NULL, /* power */ 15719397407SSherry Moore ddi_quiesce_not_needed, /* quiesce */ 1584bff34e3Sthurlow }; 1594bff34e3Sthurlow 1604bff34e3Sthurlow /* 1614bff34e3Sthurlow * Module linkage information. 1624bff34e3Sthurlow */ 1634bff34e3Sthurlow 1644bff34e3Sthurlow static struct modldrv nsmb_modldrv = { 1654bff34e3Sthurlow &mod_driverops, /* Driver module */ 166613a2f6bSGordon Ross "SMBFS network driver", 1674bff34e3Sthurlow &nsmb_ops /* Driver ops */ 1684bff34e3Sthurlow }; 1694bff34e3Sthurlow 1704bff34e3Sthurlow static struct modlinkage nsmb_modlinkage = { 1714bff34e3Sthurlow MODREV_1, 1724bff34e3Sthurlow (void *)&nsmb_modldrv, 1734bff34e3Sthurlow NULL 1744bff34e3Sthurlow }; 1754bff34e3Sthurlow 1764bff34e3Sthurlow int 1774bff34e3Sthurlow _init(void) 1784bff34e3Sthurlow { 1794bff34e3Sthurlow int error; 1804bff34e3Sthurlow 18102d09e03SGordon Ross (void) ddi_soft_state_init(&statep, sizeof (smb_dev_t), 1); 1824bff34e3Sthurlow 1834bff34e3Sthurlow /* Can initialize some mutexes also. */ 1844bff34e3Sthurlow mutex_init(&dev_lck, NULL, MUTEX_DRIVER, NULL); 1854bff34e3Sthurlow /* 1864bff34e3Sthurlow * Create a major name and number. 1874bff34e3Sthurlow */ 1884bff34e3Sthurlow nsmb_major = ddi_name_to_major(NSMB_NAME); 1894bff34e3Sthurlow nsmb_minor = 0; 1904bff34e3Sthurlow 1914bff34e3Sthurlow /* Connection data structures. */ 1924bff34e3Sthurlow (void) smb_sm_init(); 1934bff34e3Sthurlow 1944bff34e3Sthurlow /* Initialize password Key chain DB. */ 1954bff34e3Sthurlow smb_pkey_init(); 1964bff34e3Sthurlow 19702d09e03SGordon Ross /* Time conversion stuff. */ 19802d09e03SGordon Ross smb_time_init(); 19902d09e03SGordon Ross 2009c9af259SGordon Ross /* Initialize crypto mechanisms. */ 2019c9af259SGordon Ross smb_crypto_mech_init(); 2029c9af259SGordon Ross 2034bff34e3Sthurlow zone_key_create(&nsmb_zone_key, NULL, nsmb_zone_shutdown, 2044bff34e3Sthurlow nsmb_zone_destroy); 2054bff34e3Sthurlow 2064bff34e3Sthurlow /* 2074bff34e3Sthurlow * Install the module. Do this after other init, 2084bff34e3Sthurlow * to prevent entrances before we're ready. 2094bff34e3Sthurlow */ 2104bff34e3Sthurlow if ((error = mod_install((&nsmb_modlinkage))) != 0) { 2114bff34e3Sthurlow 2124bff34e3Sthurlow /* Same as 2nd half of _fini */ 2134bff34e3Sthurlow (void) zone_key_delete(nsmb_zone_key); 2144bff34e3Sthurlow smb_pkey_fini(); 2154bff34e3Sthurlow smb_sm_done(); 2164bff34e3Sthurlow mutex_destroy(&dev_lck); 2174bff34e3Sthurlow ddi_soft_state_fini(&statep); 2184bff34e3Sthurlow 2194bff34e3Sthurlow return (error); 2204bff34e3Sthurlow } 2214bff34e3Sthurlow 2224bff34e3Sthurlow return (0); 2234bff34e3Sthurlow } 2244bff34e3Sthurlow 2254bff34e3Sthurlow int 2264bff34e3Sthurlow _fini(void) 2274bff34e3Sthurlow { 2284bff34e3Sthurlow int status; 2294bff34e3Sthurlow 2304bff34e3Sthurlow /* 2314bff34e3Sthurlow * Prevent unload if we have active VCs 2324bff34e3Sthurlow * or stored passwords 2334bff34e3Sthurlow */ 2344bff34e3Sthurlow if ((status = smb_sm_idle()) != 0) 2354bff34e3Sthurlow return (status); 2364bff34e3Sthurlow if ((status = smb_pkey_idle()) != 0) 2374bff34e3Sthurlow return (status); 2384bff34e3Sthurlow 2394bff34e3Sthurlow /* 2404bff34e3Sthurlow * Remove the module. Do this before destroying things, 2414bff34e3Sthurlow * to prevent new entrances while we're destorying. 2424bff34e3Sthurlow */ 2434bff34e3Sthurlow if ((status = mod_remove(&nsmb_modlinkage)) != 0) { 2444bff34e3Sthurlow return (status); 2454bff34e3Sthurlow } 2464bff34e3Sthurlow 2474bff34e3Sthurlow (void) zone_key_delete(nsmb_zone_key); 2484bff34e3Sthurlow 24902d09e03SGordon Ross /* Time conversion stuff. */ 25002d09e03SGordon Ross smb_time_fini(); 25102d09e03SGordon Ross 2524bff34e3Sthurlow /* Destroy password Key chain DB. */ 2534bff34e3Sthurlow smb_pkey_fini(); 2544bff34e3Sthurlow 2554bff34e3Sthurlow smb_sm_done(); 2564bff34e3Sthurlow 2574bff34e3Sthurlow mutex_destroy(&dev_lck); 2584bff34e3Sthurlow ddi_soft_state_fini(&statep); 2594bff34e3Sthurlow 2604bff34e3Sthurlow return (status); 2614bff34e3Sthurlow } 2624bff34e3Sthurlow 2634bff34e3Sthurlow int 2644bff34e3Sthurlow _info(struct modinfo *modinfop) 2654bff34e3Sthurlow { 2664bff34e3Sthurlow return (mod_info(&nsmb_modlinkage, modinfop)); 2674bff34e3Sthurlow } 2684bff34e3Sthurlow 2694bff34e3Sthurlow /*ARGSUSED*/ 2704bff34e3Sthurlow static int 2714bff34e3Sthurlow nsmb_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) 2724bff34e3Sthurlow { 2734bff34e3Sthurlow int ret = DDI_SUCCESS; 2744bff34e3Sthurlow 2754bff34e3Sthurlow switch (cmd) { 2764bff34e3Sthurlow case DDI_INFO_DEVT2DEVINFO: 2774bff34e3Sthurlow *result = 0; 2784bff34e3Sthurlow break; 2794bff34e3Sthurlow case DDI_INFO_DEVT2INSTANCE: 2804bff34e3Sthurlow *result = 0; 2814bff34e3Sthurlow break; 2824bff34e3Sthurlow default: 2834bff34e3Sthurlow ret = DDI_FAILURE; 2844bff34e3Sthurlow } 2854bff34e3Sthurlow return (ret); 2864bff34e3Sthurlow } 2874bff34e3Sthurlow 2884bff34e3Sthurlow static int 2894bff34e3Sthurlow nsmb_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 2904bff34e3Sthurlow { 2914bff34e3Sthurlow smb_dev_t *sdp; 2924bff34e3Sthurlow 2934bff34e3Sthurlow if (cmd != DDI_ATTACH) 2944bff34e3Sthurlow return (DDI_FAILURE); 2954bff34e3Sthurlow /* 2964bff34e3Sthurlow * only one instance - but we clone using the open routine 2974bff34e3Sthurlow */ 2984bff34e3Sthurlow if (ddi_get_instance(dip) > 0) 2994bff34e3Sthurlow return (DDI_FAILURE); 3004bff34e3Sthurlow 3014bff34e3Sthurlow mutex_enter(&dev_lck); 3024bff34e3Sthurlow 3034bff34e3Sthurlow /* 3044bff34e3Sthurlow * This is the Zero'th minor device which is created. 3054bff34e3Sthurlow */ 3064bff34e3Sthurlow if (ddi_soft_state_zalloc(statep, 0) == DDI_FAILURE) { 3074bff34e3Sthurlow cmn_err(CE_WARN, "nsmb_attach: soft state alloc"); 3084bff34e3Sthurlow goto attach_failed; 3094bff34e3Sthurlow } 3104bff34e3Sthurlow if (ddi_create_minor_node(dip, "nsmb", S_IFCHR, 0, DDI_PSEUDO, 3114bff34e3Sthurlow NULL) == DDI_FAILURE) { 3124bff34e3Sthurlow cmn_err(CE_WARN, "nsmb_attach: create minor"); 3134bff34e3Sthurlow goto attach_failed; 3144bff34e3Sthurlow } 3154bff34e3Sthurlow if ((sdp = ddi_get_soft_state(statep, 0)) == NULL) { 3164bff34e3Sthurlow cmn_err(CE_WARN, "nsmb_attach: get soft state"); 3174bff34e3Sthurlow ddi_remove_minor_node(dip, NULL); 3184bff34e3Sthurlow goto attach_failed; 3194bff34e3Sthurlow } 3204bff34e3Sthurlow 321*430b4c46SGordon Ross sdp->sd_dip = dip; 3224bff34e3Sthurlow sdp->sd_seq = 0; 323*430b4c46SGordon Ross sdp->sd_smbfid = -1; 3244bff34e3Sthurlow mutex_exit(&dev_lck); 3254bff34e3Sthurlow ddi_report_dev(dip); 3264bff34e3Sthurlow return (DDI_SUCCESS); 3274bff34e3Sthurlow 3284bff34e3Sthurlow attach_failed: 3294bff34e3Sthurlow ddi_soft_state_free(statep, 0); 3304bff34e3Sthurlow mutex_exit(&dev_lck); 3314bff34e3Sthurlow return (DDI_FAILURE); 3324bff34e3Sthurlow } 3334bff34e3Sthurlow 3344bff34e3Sthurlow /*ARGSUSED*/ 3354bff34e3Sthurlow static int 3364bff34e3Sthurlow nsmb_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 3374bff34e3Sthurlow { 3384bff34e3Sthurlow 3394bff34e3Sthurlow if (cmd != DDI_DETACH) 3404bff34e3Sthurlow return (DDI_FAILURE); 3414bff34e3Sthurlow if (ddi_get_instance(dip) > 0) 3424bff34e3Sthurlow return (DDI_FAILURE); 3434bff34e3Sthurlow 3444bff34e3Sthurlow ddi_soft_state_free(statep, 0); 3454bff34e3Sthurlow ddi_remove_minor_node(dip, NULL); 3464bff34e3Sthurlow 3474bff34e3Sthurlow return (DDI_SUCCESS); 3484bff34e3Sthurlow } 3494bff34e3Sthurlow 3504bff34e3Sthurlow /*ARGSUSED*/ 3514bff34e3Sthurlow static int 352613a2f6bSGordon Ross nsmb_ioctl(dev_t dev, int cmd, intptr_t arg, int flags, /* model.h */ 353613a2f6bSGordon Ross cred_t *cr, int *rvalp) 3544bff34e3Sthurlow { 3554bff34e3Sthurlow smb_dev_t *sdp; 356613a2f6bSGordon Ross int err; 3574bff34e3Sthurlow 3584bff34e3Sthurlow sdp = ddi_get_soft_state(statep, getminor(dev)); 3594bff34e3Sthurlow if (sdp == NULL) { 3604bff34e3Sthurlow return (DDI_FAILURE); 3614bff34e3Sthurlow } 3624bff34e3Sthurlow if ((sdp->sd_flags & NSMBFL_OPEN) == 0) { 3634bff34e3Sthurlow return (EBADF); 3644bff34e3Sthurlow } 3654bff34e3Sthurlow 3664bff34e3Sthurlow /* 3674bff34e3Sthurlow * Dont give access if the zone id is not as the same as we 3684bff34e3Sthurlow * set in the nsmb_open or dont belong to the global zone. 3694bff34e3Sthurlow * Check if the user belongs to this zone.. 3704bff34e3Sthurlow */ 3714bff34e3Sthurlow if (sdp->zoneid != getzoneid()) 3724bff34e3Sthurlow return (EIO); 3734bff34e3Sthurlow 374613a2f6bSGordon Ross /* 375613a2f6bSGordon Ross * We have a zone_shutdown call back that kills all the VCs 376613a2f6bSGordon Ross * in a zone that's shutting down. That action will cause 377613a2f6bSGordon Ross * all of these ioctls to fail on such VCs, so no need to 378613a2f6bSGordon Ross * check the zone status here on every ioctl call. 379613a2f6bSGordon Ross */ 3804bff34e3Sthurlow 381613a2f6bSGordon Ross err = 0; 3824bff34e3Sthurlow switch (cmd) { 383613a2f6bSGordon Ross case SMBIOC_GETVERS: 38402d09e03SGordon Ross (void) ddi_copyout(&nsmb_version, (void *)arg, 385613a2f6bSGordon Ross sizeof (nsmb_version), flags); 386613a2f6bSGordon Ross break; 3874bff34e3Sthurlow 388613a2f6bSGordon Ross case SMBIOC_FLAGS2: 389613a2f6bSGordon Ross err = smb_usr_get_flags2(sdp, arg, flags); 390613a2f6bSGordon Ross break; 3914bff34e3Sthurlow 392613a2f6bSGordon Ross case SMBIOC_GETSSNKEY: 393613a2f6bSGordon Ross err = smb_usr_get_ssnkey(sdp, arg, flags); 394613a2f6bSGordon Ross break; 3954bff34e3Sthurlow 396*430b4c46SGordon Ross case SMBIOC_DUP_DEV: 397*430b4c46SGordon Ross err = smb_usr_dup_dev(sdp, arg, flags); 398*430b4c46SGordon Ross break; 399*430b4c46SGordon Ross 400613a2f6bSGordon Ross case SMBIOC_REQUEST: 401613a2f6bSGordon Ross err = smb_usr_simplerq(sdp, arg, flags, cr); 402613a2f6bSGordon Ross break; 4034bff34e3Sthurlow 404613a2f6bSGordon Ross case SMBIOC_T2RQ: 405613a2f6bSGordon Ross err = smb_usr_t2request(sdp, arg, flags, cr); 406613a2f6bSGordon Ross break; 4074bff34e3Sthurlow 408613a2f6bSGordon Ross case SMBIOC_READ: 409613a2f6bSGordon Ross case SMBIOC_WRITE: 410613a2f6bSGordon Ross err = smb_usr_rw(sdp, cmd, arg, flags, cr); 411613a2f6bSGordon Ross break; 4124bff34e3Sthurlow 413*430b4c46SGordon Ross case SMBIOC_NTCREATE: 414*430b4c46SGordon Ross err = smb_usr_ntcreate(sdp, arg, flags, cr); 415*430b4c46SGordon Ross break; 416*430b4c46SGordon Ross 417*430b4c46SGordon Ross case SMBIOC_PRINTJOB: 418*430b4c46SGordon Ross err = smb_usr_printjob(sdp, arg, flags, cr); 419*430b4c46SGordon Ross break; 420*430b4c46SGordon Ross 421*430b4c46SGordon Ross case SMBIOC_CLOSEFH: 422*430b4c46SGordon Ross err = smb_usr_closefh(sdp, cr); 423*430b4c46SGordon Ross break; 424*430b4c46SGordon Ross 425613a2f6bSGordon Ross case SMBIOC_SSN_CREATE: 426613a2f6bSGordon Ross case SMBIOC_SSN_FIND: 427613a2f6bSGordon Ross err = smb_usr_get_ssn(sdp, cmd, arg, flags, cr); 428613a2f6bSGordon Ross break; 4294bff34e3Sthurlow 430613a2f6bSGordon Ross case SMBIOC_SSN_KILL: 431613a2f6bSGordon Ross case SMBIOC_SSN_RELE: 432613a2f6bSGordon Ross err = smb_usr_drop_ssn(sdp, cmd); 433613a2f6bSGordon Ross break; 4344bff34e3Sthurlow 435613a2f6bSGordon Ross case SMBIOC_TREE_CONNECT: 436613a2f6bSGordon Ross case SMBIOC_TREE_FIND: 437613a2f6bSGordon Ross err = smb_usr_get_tree(sdp, cmd, arg, flags, cr); 438613a2f6bSGordon Ross break; 4394bff34e3Sthurlow 440613a2f6bSGordon Ross case SMBIOC_TREE_KILL: 441613a2f6bSGordon Ross case SMBIOC_TREE_RELE: 442613a2f6bSGordon Ross err = smb_usr_drop_tree(sdp, cmd); 443613a2f6bSGordon Ross break; 4444bff34e3Sthurlow 445613a2f6bSGordon Ross case SMBIOC_IOD_WORK: 446613a2f6bSGordon Ross err = smb_usr_iod_work(sdp, arg, flags, cr); 447613a2f6bSGordon Ross break; 4484bff34e3Sthurlow 449613a2f6bSGordon Ross case SMBIOC_IOD_IDLE: 450613a2f6bSGordon Ross case SMBIOC_IOD_RCFAIL: 451613a2f6bSGordon Ross err = smb_usr_iod_ioctl(sdp, cmd, arg, flags); 452613a2f6bSGordon Ross break; 4534bff34e3Sthurlow 454613a2f6bSGordon Ross case SMBIOC_PK_ADD: 455613a2f6bSGordon Ross case SMBIOC_PK_DEL: 456613a2f6bSGordon Ross case SMBIOC_PK_CHK: 457613a2f6bSGordon Ross case SMBIOC_PK_DEL_OWNER: 458613a2f6bSGordon Ross case SMBIOC_PK_DEL_EVERYONE: 459613a2f6bSGordon Ross err = smb_pkey_ioctl(cmd, arg, flags, cr); 460613a2f6bSGordon Ross break; 4614bff34e3Sthurlow 462613a2f6bSGordon Ross default: 463613a2f6bSGordon Ross err = ENOTTY; 464613a2f6bSGordon Ross break; 4654bff34e3Sthurlow } 4664bff34e3Sthurlow 467613a2f6bSGordon Ross return (err); 4684bff34e3Sthurlow } 4694bff34e3Sthurlow 4704bff34e3Sthurlow /*ARGSUSED*/ 4714bff34e3Sthurlow static int 4724bff34e3Sthurlow nsmb_open(dev_t *dev, int flags, int otyp, cred_t *cr) 4734bff34e3Sthurlow { 4744bff34e3Sthurlow major_t new_major; 4754bff34e3Sthurlow smb_dev_t *sdp, *sdv; 4764bff34e3Sthurlow 4774bff34e3Sthurlow mutex_enter(&dev_lck); 4784bff34e3Sthurlow for (; ; ) { 4794bff34e3Sthurlow minor_t start = nsmb_minor; 4804bff34e3Sthurlow do { 4814bff34e3Sthurlow if (nsmb_minor >= MAXMIN32) { 4824bff34e3Sthurlow if (nsmb_major == getmajor(*dev)) 4834bff34e3Sthurlow nsmb_minor = NSMB_MIN_MINOR; 4844bff34e3Sthurlow else 4854bff34e3Sthurlow nsmb_minor = 0; 4864bff34e3Sthurlow } else { 4874bff34e3Sthurlow nsmb_minor++; 4884bff34e3Sthurlow } 4894bff34e3Sthurlow sdv = ddi_get_soft_state(statep, nsmb_minor); 4904bff34e3Sthurlow } while ((sdv != NULL) && (nsmb_minor != start)); 4914bff34e3Sthurlow if (nsmb_minor == start) { 4924bff34e3Sthurlow /* 4934bff34e3Sthurlow * The condition we need to solve here is all the 4944bff34e3Sthurlow * MAXMIN32(~262000) minors numbers are reached. We 4954bff34e3Sthurlow * need to create a new major number. 4964bff34e3Sthurlow * zfs uses getudev() to create a new major number. 4974bff34e3Sthurlow */ 4984bff34e3Sthurlow if ((new_major = getudev()) == (major_t)-1) { 4994bff34e3Sthurlow cmn_err(CE_WARN, 5004bff34e3Sthurlow "nsmb: Can't get unique major " 5014bff34e3Sthurlow "device number."); 5024bff34e3Sthurlow mutex_exit(&dev_lck); 5034bff34e3Sthurlow return (-1); 5044bff34e3Sthurlow } 5054bff34e3Sthurlow nsmb_major = new_major; 5064bff34e3Sthurlow nsmb_minor = 0; 5074bff34e3Sthurlow } else { 5084bff34e3Sthurlow break; 5094bff34e3Sthurlow } 5104bff34e3Sthurlow } 5114bff34e3Sthurlow 5124bff34e3Sthurlow /* 5134bff34e3Sthurlow * This is called by mount or open call. 5144bff34e3Sthurlow * The open() routine is passed a pointer to a device number so 5154bff34e3Sthurlow * that the driver can change the minor number. This allows 5164bff34e3Sthurlow * drivers to dynamically create minor instances of the dev- 5174bff34e3Sthurlow * ice. An example of this might be a pseudo-terminal driver 5184bff34e3Sthurlow * that creates a new pseudo-terminal whenever it is opened. 5194bff34e3Sthurlow * A driver that chooses the minor number dynamically, normally 5204bff34e3Sthurlow * creates only one minor device node in attach(9E) with 5214bff34e3Sthurlow * ddi_create_minor_node(9F) then changes the minor number com- 5224bff34e3Sthurlow * ponent of *devp using makedevice(9F) and getmajor(9F) The 5234bff34e3Sthurlow * driver needs to keep track of available minor numbers inter- 5244bff34e3Sthurlow * nally. 5254bff34e3Sthurlow * Stuff the structure smb_dev. 5264bff34e3Sthurlow * return. 5274bff34e3Sthurlow */ 5284bff34e3Sthurlow 5294bff34e3Sthurlow if (ddi_soft_state_zalloc(statep, nsmb_minor) == DDI_FAILURE) { 5304bff34e3Sthurlow mutex_exit(&dev_lck); 5314bff34e3Sthurlow return (ENXIO); 5324bff34e3Sthurlow } 5334bff34e3Sthurlow if ((sdp = ddi_get_soft_state(statep, nsmb_minor)) == NULL) { 5344bff34e3Sthurlow mutex_exit(&dev_lck); 5354bff34e3Sthurlow return (ENXIO); 5364bff34e3Sthurlow } 5374bff34e3Sthurlow 5384bff34e3Sthurlow sdp->sd_seq = nsmb_minor; 539*430b4c46SGordon Ross sdp->sd_cred = cr; 540*430b4c46SGordon Ross sdp->sd_smbfid = -1; 5414bff34e3Sthurlow sdp->sd_flags |= NSMBFL_OPEN; 5424bff34e3Sthurlow sdp->zoneid = crgetzoneid(cr); 5434bff34e3Sthurlow mutex_exit(&dev_lck); 5444bff34e3Sthurlow 5454bff34e3Sthurlow *dev = makedevice(nsmb_major, nsmb_minor); 5464bff34e3Sthurlow 5474bff34e3Sthurlow return (0); 5484bff34e3Sthurlow } 5494bff34e3Sthurlow 5504bff34e3Sthurlow /*ARGSUSED*/ 5514bff34e3Sthurlow static int 5524bff34e3Sthurlow nsmb_close(dev_t dev, int flags, int otyp, cred_t *cr) 5534bff34e3Sthurlow { 5544bff34e3Sthurlow minor_t inst = getminor(dev); 5554bff34e3Sthurlow smb_dev_t *sdp; 556613a2f6bSGordon Ross int err; 5574bff34e3Sthurlow 5584bff34e3Sthurlow mutex_enter(&dev_lck); 5594bff34e3Sthurlow /* 5604bff34e3Sthurlow * 1. Check the validity of the minor number. 5614bff34e3Sthurlow * 2. Release any shares/vc associated with the connection. 5624bff34e3Sthurlow * 3. Can close the minor number. 5634bff34e3Sthurlow * 4. Deallocate any resources allocated in open() call. 5644bff34e3Sthurlow */ 5654bff34e3Sthurlow 5664bff34e3Sthurlow sdp = ddi_get_soft_state(statep, inst); 567613a2f6bSGordon Ross if (sdp != NULL) 568613a2f6bSGordon Ross err = nsmb_close2(sdp, cr); 569613a2f6bSGordon Ross else 570613a2f6bSGordon Ross err = ENXIO; 5714bff34e3Sthurlow 5724bff34e3Sthurlow /* 573613a2f6bSGordon Ross * Free the instance 5744bff34e3Sthurlow */ 575613a2f6bSGordon Ross ddi_soft_state_free(statep, inst); 576613a2f6bSGordon Ross mutex_exit(&dev_lck); 577613a2f6bSGordon Ross return (err); 578613a2f6bSGordon Ross } 579613a2f6bSGordon Ross 580613a2f6bSGordon Ross static int 581613a2f6bSGordon Ross nsmb_close2(smb_dev_t *sdp, cred_t *cr) 582613a2f6bSGordon Ross { 583613a2f6bSGordon Ross struct smb_vc *vcp; 584613a2f6bSGordon Ross struct smb_share *ssp; 585613a2f6bSGordon Ross 586*430b4c46SGordon Ross if (sdp->sd_smbfid != -1) 587*430b4c46SGordon Ross (void) smb_usr_closefh(sdp, cr); 588*430b4c46SGordon Ross 5894bff34e3Sthurlow ssp = sdp->sd_share; 5904bff34e3Sthurlow if (ssp != NULL) 5914bff34e3Sthurlow smb_share_rele(ssp); 592*430b4c46SGordon Ross 5934bff34e3Sthurlow vcp = sdp->sd_vc; 5944bff34e3Sthurlow if (vcp != NULL) { 5954bff34e3Sthurlow /* 596613a2f6bSGordon Ross * If this dev minor was opened by smbiod, 597613a2f6bSGordon Ross * mark this VC as "dead" because it now 598613a2f6bSGordon Ross * will have no IOD to service it. 5994bff34e3Sthurlow */ 600613a2f6bSGordon Ross if (sdp->sd_flags & NSMBFL_IOD) 6016723e17fSGordon Ross smb_iod_disconnect(vcp); 6024bff34e3Sthurlow smb_vc_rele(vcp); 6034bff34e3Sthurlow } 6044bff34e3Sthurlow 6054bff34e3Sthurlow return (0); 6064bff34e3Sthurlow } 6074bff34e3Sthurlow 608*430b4c46SGordon Ross /* 609*430b4c46SGordon Ross * Helper for SMBIOC_DUP_DEV 610*430b4c46SGordon Ross * Duplicate state from the FD @arg ("from") onto 611*430b4c46SGordon Ross * the FD for this device instance. 612*430b4c46SGordon Ross */ 613*430b4c46SGordon Ross int 614*430b4c46SGordon Ross smb_usr_dup_dev(smb_dev_t *sdp, intptr_t arg, int flags) 615*430b4c46SGordon Ross { 616*430b4c46SGordon Ross file_t *fp = NULL; 617*430b4c46SGordon Ross vnode_t *vp; 618*430b4c46SGordon Ross smb_dev_t *from_sdp; 619*430b4c46SGordon Ross dev_t dev; 620*430b4c46SGordon Ross int32_t ufd; 621*430b4c46SGordon Ross int err; 622*430b4c46SGordon Ross 623*430b4c46SGordon Ross /* Should be no VC */ 624*430b4c46SGordon Ross if (sdp->sd_vc != NULL) 625*430b4c46SGordon Ross return (EISCONN); 626*430b4c46SGordon Ross 627*430b4c46SGordon Ross /* 628*430b4c46SGordon Ross * Get from_sdp (what we will duplicate) 629*430b4c46SGordon Ross */ 630*430b4c46SGordon Ross if (ddi_copyin((void *) arg, &ufd, sizeof (ufd), flags)) 631*430b4c46SGordon Ross return (EFAULT); 632*430b4c46SGordon Ross if ((fp = getf(ufd)) == NULL) 633*430b4c46SGordon Ross return (EBADF); 634*430b4c46SGordon Ross /* rele fp below */ 635*430b4c46SGordon Ross vp = fp->f_vnode; 636*430b4c46SGordon Ross dev = vp->v_rdev; 637*430b4c46SGordon Ross if (dev == 0 || dev == NODEV || 638*430b4c46SGordon Ross getmajor(dev) != nsmb_major) { 639*430b4c46SGordon Ross err = EINVAL; 640*430b4c46SGordon Ross goto out; 641*430b4c46SGordon Ross } 642*430b4c46SGordon Ross from_sdp = ddi_get_soft_state(statep, getminor(dev)); 643*430b4c46SGordon Ross if (from_sdp == NULL) { 644*430b4c46SGordon Ross err = EINVAL; 645*430b4c46SGordon Ross goto out; 646*430b4c46SGordon Ross } 647*430b4c46SGordon Ross 648*430b4c46SGordon Ross /* 649*430b4c46SGordon Ross * Duplicate VC and share references onto this FD. 650*430b4c46SGordon Ross */ 651*430b4c46SGordon Ross if ((sdp->sd_vc = from_sdp->sd_vc) != NULL) 652*430b4c46SGordon Ross smb_vc_hold(sdp->sd_vc); 653*430b4c46SGordon Ross if ((sdp->sd_share = from_sdp->sd_share) != NULL) 654*430b4c46SGordon Ross smb_share_hold(sdp->sd_share); 655*430b4c46SGordon Ross sdp->sd_level = from_sdp->sd_level; 656*430b4c46SGordon Ross err = 0; 657*430b4c46SGordon Ross 658*430b4c46SGordon Ross out: 659*430b4c46SGordon Ross if (fp) 660*430b4c46SGordon Ross releasef(ufd); 661*430b4c46SGordon Ross return (err); 662*430b4c46SGordon Ross } 663*430b4c46SGordon Ross 664*430b4c46SGordon Ross 665*430b4c46SGordon Ross /* 666*430b4c46SGordon Ross * Helper used by smbfs_mount 667*430b4c46SGordon Ross */ 6684bff34e3Sthurlow int 6694bff34e3Sthurlow smb_dev2share(int fd, struct smb_share **sspp) 6704bff34e3Sthurlow { 671613a2f6bSGordon Ross file_t *fp = NULL; 672613a2f6bSGordon Ross vnode_t *vp; 6734bff34e3Sthurlow smb_dev_t *sdp; 674613a2f6bSGordon Ross smb_share_t *ssp; 6754bff34e3Sthurlow dev_t dev; 676613a2f6bSGordon Ross int err; 6774bff34e3Sthurlow 6784bff34e3Sthurlow if ((fp = getf(fd)) == NULL) 679613a2f6bSGordon Ross return (EBADF); 680*430b4c46SGordon Ross /* rele fp below */ 681613a2f6bSGordon Ross 6824bff34e3Sthurlow vp = fp->f_vnode; 6834bff34e3Sthurlow dev = vp->v_rdev; 684613a2f6bSGordon Ross if (dev == 0 || dev == NODEV || 685613a2f6bSGordon Ross getmajor(dev) != nsmb_major) { 686*430b4c46SGordon Ross err = EINVAL; 687613a2f6bSGordon Ross goto out; 6884bff34e3Sthurlow } 689613a2f6bSGordon Ross 6904bff34e3Sthurlow sdp = ddi_get_soft_state(statep, getminor(dev)); 6914bff34e3Sthurlow if (sdp == NULL) { 692613a2f6bSGordon Ross err = EINVAL; 693613a2f6bSGordon Ross goto out; 6944bff34e3Sthurlow } 695613a2f6bSGordon Ross 6964bff34e3Sthurlow ssp = sdp->sd_share; 6974bff34e3Sthurlow if (ssp == NULL) { 698613a2f6bSGordon Ross err = ENOTCONN; 699613a2f6bSGordon Ross goto out; 7004bff34e3Sthurlow } 701613a2f6bSGordon Ross 7024bff34e3Sthurlow /* 703613a2f6bSGordon Ross * Our caller gains a ref. to this share. 7044bff34e3Sthurlow */ 7054bff34e3Sthurlow *sspp = ssp; 706613a2f6bSGordon Ross smb_share_hold(ssp); 707613a2f6bSGordon Ross err = 0; 708613a2f6bSGordon Ross 709613a2f6bSGordon Ross out: 710613a2f6bSGordon Ross if (fp) 711613a2f6bSGordon Ross releasef(fd); 712613a2f6bSGordon Ross return (err); 7134bff34e3Sthurlow } 714