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*613a2f6bSGordon Ross * Copyright 2009 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); 117*613a2f6bSGordon Ross static int nsmb_close2(smb_dev_t *sdp, cred_t *cr); 118*613a2f6bSGordon Ross 1194bff34e3Sthurlow /* smbfs cb_ops */ 1204bff34e3Sthurlow static struct cb_ops nsmb_cbops = { 1214bff34e3Sthurlow nsmb_open, /* open */ 1224bff34e3Sthurlow nsmb_close, /* close */ 1234bff34e3Sthurlow nodev, /* strategy */ 1244bff34e3Sthurlow nodev, /* print */ 1254bff34e3Sthurlow nodev, /* dump */ 1264bff34e3Sthurlow nodev, /* read */ 1274bff34e3Sthurlow nodev, /* write */ 1284bff34e3Sthurlow nsmb_ioctl, /* ioctl */ 1294bff34e3Sthurlow nodev, /* devmap */ 1304bff34e3Sthurlow nodev, /* mmap */ 1314bff34e3Sthurlow nodev, /* segmap */ 1324bff34e3Sthurlow nochpoll, /* poll */ 1334bff34e3Sthurlow ddi_prop_op, /* prop_op */ 1344bff34e3Sthurlow NULL, /* stream */ 1354bff34e3Sthurlow D_MP, /* cb_flag */ 1364bff34e3Sthurlow CB_REV, /* rev */ 1374bff34e3Sthurlow nodev, /* int (*cb_aread)() */ 1384bff34e3Sthurlow nodev /* int (*cb_awrite)() */ 1394bff34e3Sthurlow }; 1404bff34e3Sthurlow 1414bff34e3Sthurlow /* 1424bff34e3Sthurlow * Device options 1434bff34e3Sthurlow */ 1444bff34e3Sthurlow static int nsmb_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); 1454bff34e3Sthurlow static int nsmb_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); 1464bff34e3Sthurlow static int nsmb_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, 1474bff34e3Sthurlow void *arg, void **result); 1484bff34e3Sthurlow 1494bff34e3Sthurlow static struct dev_ops nsmb_ops = { 1504bff34e3Sthurlow DEVO_REV, /* devo_rev, */ 1514bff34e3Sthurlow 0, /* refcnt */ 1524bff34e3Sthurlow nsmb_getinfo, /* info */ 1534bff34e3Sthurlow nulldev, /* identify */ 1544bff34e3Sthurlow nulldev, /* probe */ 1554bff34e3Sthurlow nsmb_attach, /* attach */ 1564bff34e3Sthurlow nsmb_detach, /* detach */ 1574bff34e3Sthurlow nodev, /* reset */ 1584bff34e3Sthurlow &nsmb_cbops, /* driver ops - devctl interfaces */ 1594bff34e3Sthurlow NULL, /* bus operations */ 16019397407SSherry Moore NULL, /* power */ 16119397407SSherry Moore ddi_quiesce_not_needed, /* quiesce */ 1624bff34e3Sthurlow }; 1634bff34e3Sthurlow 1644bff34e3Sthurlow /* 1654bff34e3Sthurlow * Module linkage information. 1664bff34e3Sthurlow */ 1674bff34e3Sthurlow 1684bff34e3Sthurlow static struct modldrv nsmb_modldrv = { 1694bff34e3Sthurlow &mod_driverops, /* Driver module */ 170*613a2f6bSGordon Ross "SMBFS network driver", 1714bff34e3Sthurlow &nsmb_ops /* Driver ops */ 1724bff34e3Sthurlow }; 1734bff34e3Sthurlow 1744bff34e3Sthurlow static struct modlinkage nsmb_modlinkage = { 1754bff34e3Sthurlow MODREV_1, 1764bff34e3Sthurlow (void *)&nsmb_modldrv, 1774bff34e3Sthurlow NULL 1784bff34e3Sthurlow }; 1794bff34e3Sthurlow 1804bff34e3Sthurlow int 1814bff34e3Sthurlow _init(void) 1824bff34e3Sthurlow { 1834bff34e3Sthurlow int error; 1844bff34e3Sthurlow 1854bff34e3Sthurlow ddi_soft_state_init(&statep, sizeof (smb_dev_t), 1); 1864bff34e3Sthurlow 1874bff34e3Sthurlow /* Can initialize some mutexes also. */ 1884bff34e3Sthurlow mutex_init(&dev_lck, NULL, MUTEX_DRIVER, NULL); 1894bff34e3Sthurlow /* 1904bff34e3Sthurlow * Create a major name and number. 1914bff34e3Sthurlow */ 1924bff34e3Sthurlow nsmb_major = ddi_name_to_major(NSMB_NAME); 1934bff34e3Sthurlow nsmb_minor = 0; 1944bff34e3Sthurlow 1954bff34e3Sthurlow /* Connection data structures. */ 1964bff34e3Sthurlow (void) smb_sm_init(); 1974bff34e3Sthurlow 1984bff34e3Sthurlow /* Initialize password Key chain DB. */ 1994bff34e3Sthurlow smb_pkey_init(); 2004bff34e3Sthurlow 2019c9af259SGordon Ross /* Initialize crypto mechanisms. */ 2029c9af259SGordon Ross smb_crypto_mech_init(); 2039c9af259SGordon Ross 2044bff34e3Sthurlow zone_key_create(&nsmb_zone_key, NULL, nsmb_zone_shutdown, 2054bff34e3Sthurlow nsmb_zone_destroy); 2064bff34e3Sthurlow 2074bff34e3Sthurlow /* 2084bff34e3Sthurlow * Install the module. Do this after other init, 2094bff34e3Sthurlow * to prevent entrances before we're ready. 2104bff34e3Sthurlow */ 2114bff34e3Sthurlow if ((error = mod_install((&nsmb_modlinkage))) != 0) { 2124bff34e3Sthurlow 2134bff34e3Sthurlow /* Same as 2nd half of _fini */ 2144bff34e3Sthurlow (void) zone_key_delete(nsmb_zone_key); 2154bff34e3Sthurlow smb_pkey_fini(); 2164bff34e3Sthurlow smb_sm_done(); 2174bff34e3Sthurlow mutex_destroy(&dev_lck); 2184bff34e3Sthurlow ddi_soft_state_fini(&statep); 2194bff34e3Sthurlow 2204bff34e3Sthurlow return (error); 2214bff34e3Sthurlow } 2224bff34e3Sthurlow 2234bff34e3Sthurlow return (0); 2244bff34e3Sthurlow } 2254bff34e3Sthurlow 2264bff34e3Sthurlow int 2274bff34e3Sthurlow _fini(void) 2284bff34e3Sthurlow { 2294bff34e3Sthurlow int status; 2304bff34e3Sthurlow 2314bff34e3Sthurlow /* 2324bff34e3Sthurlow * Prevent unload if we have active VCs 2334bff34e3Sthurlow * or stored passwords 2344bff34e3Sthurlow */ 2354bff34e3Sthurlow if ((status = smb_sm_idle()) != 0) 2364bff34e3Sthurlow return (status); 2374bff34e3Sthurlow if ((status = smb_pkey_idle()) != 0) 2384bff34e3Sthurlow return (status); 2394bff34e3Sthurlow 2404bff34e3Sthurlow /* 2414bff34e3Sthurlow * Remove the module. Do this before destroying things, 2424bff34e3Sthurlow * to prevent new entrances while we're destorying. 2434bff34e3Sthurlow */ 2444bff34e3Sthurlow if ((status = mod_remove(&nsmb_modlinkage)) != 0) { 2454bff34e3Sthurlow return (status); 2464bff34e3Sthurlow } 2474bff34e3Sthurlow 2484bff34e3Sthurlow (void) zone_key_delete(nsmb_zone_key); 2494bff34e3Sthurlow 2504bff34e3Sthurlow /* Destroy password Key chain DB. */ 2514bff34e3Sthurlow smb_pkey_fini(); 2524bff34e3Sthurlow 2534bff34e3Sthurlow smb_sm_done(); 2544bff34e3Sthurlow 2554bff34e3Sthurlow mutex_destroy(&dev_lck); 2564bff34e3Sthurlow ddi_soft_state_fini(&statep); 2574bff34e3Sthurlow 2584bff34e3Sthurlow return (status); 2594bff34e3Sthurlow } 2604bff34e3Sthurlow 2614bff34e3Sthurlow int 2624bff34e3Sthurlow _info(struct modinfo *modinfop) 2634bff34e3Sthurlow { 2644bff34e3Sthurlow return (mod_info(&nsmb_modlinkage, modinfop)); 2654bff34e3Sthurlow } 2664bff34e3Sthurlow 2674bff34e3Sthurlow /*ARGSUSED*/ 2684bff34e3Sthurlow static int 2694bff34e3Sthurlow nsmb_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) 2704bff34e3Sthurlow { 2714bff34e3Sthurlow int ret = DDI_SUCCESS; 2724bff34e3Sthurlow 2734bff34e3Sthurlow switch (cmd) { 2744bff34e3Sthurlow case DDI_INFO_DEVT2DEVINFO: 2754bff34e3Sthurlow *result = 0; 2764bff34e3Sthurlow break; 2774bff34e3Sthurlow case DDI_INFO_DEVT2INSTANCE: 2784bff34e3Sthurlow *result = 0; 2794bff34e3Sthurlow break; 2804bff34e3Sthurlow default: 2814bff34e3Sthurlow ret = DDI_FAILURE; 2824bff34e3Sthurlow } 2834bff34e3Sthurlow return (ret); 2844bff34e3Sthurlow } 2854bff34e3Sthurlow 2864bff34e3Sthurlow static int 2874bff34e3Sthurlow nsmb_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 2884bff34e3Sthurlow { 2894bff34e3Sthurlow smb_dev_t *sdp; 2904bff34e3Sthurlow 2914bff34e3Sthurlow if (cmd != DDI_ATTACH) 2924bff34e3Sthurlow return (DDI_FAILURE); 2934bff34e3Sthurlow /* 2944bff34e3Sthurlow * only one instance - but we clone using the open routine 2954bff34e3Sthurlow */ 2964bff34e3Sthurlow if (ddi_get_instance(dip) > 0) 2974bff34e3Sthurlow return (DDI_FAILURE); 2984bff34e3Sthurlow 2994bff34e3Sthurlow mutex_enter(&dev_lck); 3004bff34e3Sthurlow 3014bff34e3Sthurlow /* 3024bff34e3Sthurlow * This is the Zero'th minor device which is created. 3034bff34e3Sthurlow */ 3044bff34e3Sthurlow if (ddi_soft_state_zalloc(statep, 0) == DDI_FAILURE) { 3054bff34e3Sthurlow cmn_err(CE_WARN, "nsmb_attach: soft state alloc"); 3064bff34e3Sthurlow goto attach_failed; 3074bff34e3Sthurlow } 3084bff34e3Sthurlow if (ddi_create_minor_node(dip, "nsmb", S_IFCHR, 0, DDI_PSEUDO, 3094bff34e3Sthurlow NULL) == DDI_FAILURE) { 3104bff34e3Sthurlow cmn_err(CE_WARN, "nsmb_attach: create minor"); 3114bff34e3Sthurlow goto attach_failed; 3124bff34e3Sthurlow } 3134bff34e3Sthurlow if ((sdp = ddi_get_soft_state(statep, 0)) == NULL) { 3144bff34e3Sthurlow cmn_err(CE_WARN, "nsmb_attach: get soft state"); 3154bff34e3Sthurlow ddi_remove_minor_node(dip, NULL); 3164bff34e3Sthurlow goto attach_failed; 3174bff34e3Sthurlow } 3184bff34e3Sthurlow 3194bff34e3Sthurlow /* 3204bff34e3Sthurlow * Need to see if this field is required. 3214bff34e3Sthurlow * REVISIT 3224bff34e3Sthurlow */ 3234bff34e3Sthurlow sdp->smb_dip = dip; 3244bff34e3Sthurlow sdp->sd_seq = 0; 3254bff34e3Sthurlow sdp->sd_opened = 1; 3264bff34e3Sthurlow 3274bff34e3Sthurlow mutex_exit(&dev_lck); 3284bff34e3Sthurlow ddi_report_dev(dip); 3294bff34e3Sthurlow return (DDI_SUCCESS); 3304bff34e3Sthurlow 3314bff34e3Sthurlow attach_failed: 3324bff34e3Sthurlow ddi_soft_state_free(statep, 0); 3334bff34e3Sthurlow mutex_exit(&dev_lck); 3344bff34e3Sthurlow return (DDI_FAILURE); 3354bff34e3Sthurlow } 3364bff34e3Sthurlow 3374bff34e3Sthurlow /*ARGSUSED*/ 3384bff34e3Sthurlow static int 3394bff34e3Sthurlow nsmb_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 3404bff34e3Sthurlow { 3414bff34e3Sthurlow 3424bff34e3Sthurlow if (cmd != DDI_DETACH) 3434bff34e3Sthurlow return (DDI_FAILURE); 3444bff34e3Sthurlow if (ddi_get_instance(dip) > 0) 3454bff34e3Sthurlow return (DDI_FAILURE); 3464bff34e3Sthurlow 3474bff34e3Sthurlow ddi_soft_state_free(statep, 0); 3484bff34e3Sthurlow ddi_remove_minor_node(dip, NULL); 3494bff34e3Sthurlow 3504bff34e3Sthurlow return (DDI_SUCCESS); 3514bff34e3Sthurlow } 3524bff34e3Sthurlow 3534bff34e3Sthurlow /*ARGSUSED*/ 3544bff34e3Sthurlow static int 355*613a2f6bSGordon Ross nsmb_ioctl(dev_t dev, int cmd, intptr_t arg, int flags, /* model.h */ 356*613a2f6bSGordon Ross cred_t *cr, int *rvalp) 3574bff34e3Sthurlow { 3584bff34e3Sthurlow smb_dev_t *sdp; 359*613a2f6bSGordon Ross int err; 3604bff34e3Sthurlow 3614bff34e3Sthurlow sdp = ddi_get_soft_state(statep, getminor(dev)); 3624bff34e3Sthurlow if (sdp == NULL) { 3634bff34e3Sthurlow return (DDI_FAILURE); 3644bff34e3Sthurlow } 3654bff34e3Sthurlow if ((sdp->sd_flags & NSMBFL_OPEN) == 0) { 3664bff34e3Sthurlow return (EBADF); 3674bff34e3Sthurlow } 3684bff34e3Sthurlow 3694bff34e3Sthurlow /* 3704bff34e3Sthurlow * Dont give access if the zone id is not as the same as we 3714bff34e3Sthurlow * set in the nsmb_open or dont belong to the global zone. 3724bff34e3Sthurlow * Check if the user belongs to this zone.. 3734bff34e3Sthurlow */ 3744bff34e3Sthurlow if (sdp->zoneid != getzoneid()) 3754bff34e3Sthurlow return (EIO); 3764bff34e3Sthurlow 377*613a2f6bSGordon Ross /* 378*613a2f6bSGordon Ross * We have a zone_shutdown call back that kills all the VCs 379*613a2f6bSGordon Ross * in a zone that's shutting down. That action will cause 380*613a2f6bSGordon Ross * all of these ioctls to fail on such VCs, so no need to 381*613a2f6bSGordon Ross * check the zone status here on every ioctl call. 382*613a2f6bSGordon Ross */ 3834bff34e3Sthurlow 384*613a2f6bSGordon Ross err = 0; 3854bff34e3Sthurlow switch (cmd) { 386*613a2f6bSGordon Ross case SMBIOC_GETVERS: 387*613a2f6bSGordon Ross ddi_copyout(&nsmb_version, (void *)arg, 388*613a2f6bSGordon Ross sizeof (nsmb_version), flags); 389*613a2f6bSGordon Ross break; 3904bff34e3Sthurlow 391*613a2f6bSGordon Ross case SMBIOC_FLAGS2: 392*613a2f6bSGordon Ross err = smb_usr_get_flags2(sdp, arg, flags); 393*613a2f6bSGordon Ross break; 3944bff34e3Sthurlow 395*613a2f6bSGordon Ross case SMBIOC_GETSSNKEY: 396*613a2f6bSGordon Ross err = smb_usr_get_ssnkey(sdp, arg, flags); 397*613a2f6bSGordon Ross break; 3984bff34e3Sthurlow 399*613a2f6bSGordon Ross case SMBIOC_REQUEST: 400*613a2f6bSGordon Ross err = smb_usr_simplerq(sdp, arg, flags, cr); 401*613a2f6bSGordon Ross break; 4024bff34e3Sthurlow 403*613a2f6bSGordon Ross case SMBIOC_T2RQ: 404*613a2f6bSGordon Ross err = smb_usr_t2request(sdp, arg, flags, cr); 405*613a2f6bSGordon Ross break; 4064bff34e3Sthurlow 407*613a2f6bSGordon Ross case SMBIOC_READ: 408*613a2f6bSGordon Ross case SMBIOC_WRITE: 409*613a2f6bSGordon Ross err = smb_usr_rw(sdp, cmd, arg, flags, cr); 410*613a2f6bSGordon Ross break; 4114bff34e3Sthurlow 412*613a2f6bSGordon Ross case SMBIOC_SSN_CREATE: 413*613a2f6bSGordon Ross case SMBIOC_SSN_FIND: 414*613a2f6bSGordon Ross err = smb_usr_get_ssn(sdp, cmd, arg, flags, cr); 415*613a2f6bSGordon Ross break; 4164bff34e3Sthurlow 417*613a2f6bSGordon Ross case SMBIOC_SSN_KILL: 418*613a2f6bSGordon Ross case SMBIOC_SSN_RELE: 419*613a2f6bSGordon Ross err = smb_usr_drop_ssn(sdp, cmd); 420*613a2f6bSGordon Ross break; 4214bff34e3Sthurlow 422*613a2f6bSGordon Ross case SMBIOC_TREE_CONNECT: 423*613a2f6bSGordon Ross case SMBIOC_TREE_FIND: 424*613a2f6bSGordon Ross err = smb_usr_get_tree(sdp, cmd, arg, flags, cr); 425*613a2f6bSGordon Ross break; 4264bff34e3Sthurlow 427*613a2f6bSGordon Ross case SMBIOC_TREE_KILL: 428*613a2f6bSGordon Ross case SMBIOC_TREE_RELE: 429*613a2f6bSGordon Ross err = smb_usr_drop_tree(sdp, cmd); 430*613a2f6bSGordon Ross break; 4314bff34e3Sthurlow 432*613a2f6bSGordon Ross case SMBIOC_IOD_WORK: 433*613a2f6bSGordon Ross err = smb_usr_iod_work(sdp, arg, flags, cr); 434*613a2f6bSGordon Ross break; 4354bff34e3Sthurlow 436*613a2f6bSGordon Ross case SMBIOC_IOD_IDLE: 437*613a2f6bSGordon Ross case SMBIOC_IOD_RCFAIL: 438*613a2f6bSGordon Ross err = smb_usr_iod_ioctl(sdp, cmd, arg, flags); 439*613a2f6bSGordon Ross break; 4404bff34e3Sthurlow 441*613a2f6bSGordon Ross case SMBIOC_PK_ADD: 442*613a2f6bSGordon Ross case SMBIOC_PK_DEL: 443*613a2f6bSGordon Ross case SMBIOC_PK_CHK: 444*613a2f6bSGordon Ross case SMBIOC_PK_DEL_OWNER: 445*613a2f6bSGordon Ross case SMBIOC_PK_DEL_EVERYONE: 446*613a2f6bSGordon Ross err = smb_pkey_ioctl(cmd, arg, flags, cr); 447*613a2f6bSGordon Ross break; 4484bff34e3Sthurlow 449*613a2f6bSGordon Ross default: 450*613a2f6bSGordon Ross err = ENOTTY; 451*613a2f6bSGordon Ross break; 4524bff34e3Sthurlow } 4534bff34e3Sthurlow 454*613a2f6bSGordon Ross return (err); 4554bff34e3Sthurlow } 4564bff34e3Sthurlow 4574bff34e3Sthurlow /*ARGSUSED*/ 4584bff34e3Sthurlow static int 4594bff34e3Sthurlow nsmb_open(dev_t *dev, int flags, int otyp, cred_t *cr) 4604bff34e3Sthurlow { 4614bff34e3Sthurlow major_t new_major; 4624bff34e3Sthurlow smb_dev_t *sdp, *sdv; 4634bff34e3Sthurlow 4644bff34e3Sthurlow mutex_enter(&dev_lck); 4654bff34e3Sthurlow for (; ; ) { 4664bff34e3Sthurlow minor_t start = nsmb_minor; 4674bff34e3Sthurlow do { 4684bff34e3Sthurlow if (nsmb_minor >= MAXMIN32) { 4694bff34e3Sthurlow if (nsmb_major == getmajor(*dev)) 4704bff34e3Sthurlow nsmb_minor = NSMB_MIN_MINOR; 4714bff34e3Sthurlow else 4724bff34e3Sthurlow nsmb_minor = 0; 4734bff34e3Sthurlow } else { 4744bff34e3Sthurlow nsmb_minor++; 4754bff34e3Sthurlow } 4764bff34e3Sthurlow sdv = ddi_get_soft_state(statep, nsmb_minor); 4774bff34e3Sthurlow } while ((sdv != NULL) && (nsmb_minor != start)); 4784bff34e3Sthurlow if (nsmb_minor == start) { 4794bff34e3Sthurlow /* 4804bff34e3Sthurlow * The condition we need to solve here is all the 4814bff34e3Sthurlow * MAXMIN32(~262000) minors numbers are reached. We 4824bff34e3Sthurlow * need to create a new major number. 4834bff34e3Sthurlow * zfs uses getudev() to create a new major number. 4844bff34e3Sthurlow */ 4854bff34e3Sthurlow if ((new_major = getudev()) == (major_t)-1) { 4864bff34e3Sthurlow cmn_err(CE_WARN, 4874bff34e3Sthurlow "nsmb: Can't get unique major " 4884bff34e3Sthurlow "device number."); 4894bff34e3Sthurlow mutex_exit(&dev_lck); 4904bff34e3Sthurlow return (-1); 4914bff34e3Sthurlow } 4924bff34e3Sthurlow nsmb_major = new_major; 4934bff34e3Sthurlow nsmb_minor = 0; 4944bff34e3Sthurlow } else { 4954bff34e3Sthurlow break; 4964bff34e3Sthurlow } 4974bff34e3Sthurlow } 4984bff34e3Sthurlow 4994bff34e3Sthurlow /* 5004bff34e3Sthurlow * This is called by mount or open call. 5014bff34e3Sthurlow * The open() routine is passed a pointer to a device number so 5024bff34e3Sthurlow * that the driver can change the minor number. This allows 5034bff34e3Sthurlow * drivers to dynamically create minor instances of the dev- 5044bff34e3Sthurlow * ice. An example of this might be a pseudo-terminal driver 5054bff34e3Sthurlow * that creates a new pseudo-terminal whenever it is opened. 5064bff34e3Sthurlow * A driver that chooses the minor number dynamically, normally 5074bff34e3Sthurlow * creates only one minor device node in attach(9E) with 5084bff34e3Sthurlow * ddi_create_minor_node(9F) then changes the minor number com- 5094bff34e3Sthurlow * ponent of *devp using makedevice(9F) and getmajor(9F) The 5104bff34e3Sthurlow * driver needs to keep track of available minor numbers inter- 5114bff34e3Sthurlow * nally. 5124bff34e3Sthurlow * Stuff the structure smb_dev. 5134bff34e3Sthurlow * return. 5144bff34e3Sthurlow */ 5154bff34e3Sthurlow 5164bff34e3Sthurlow if (ddi_soft_state_zalloc(statep, nsmb_minor) == DDI_FAILURE) { 5174bff34e3Sthurlow mutex_exit(&dev_lck); 5184bff34e3Sthurlow return (ENXIO); 5194bff34e3Sthurlow } 5204bff34e3Sthurlow if ((sdp = ddi_get_soft_state(statep, nsmb_minor)) == NULL) { 5214bff34e3Sthurlow mutex_exit(&dev_lck); 5224bff34e3Sthurlow return (ENXIO); 5234bff34e3Sthurlow } 5244bff34e3Sthurlow 5254bff34e3Sthurlow sdp->sd_opened = 1; 5264bff34e3Sthurlow sdp->sd_seq = nsmb_minor; 5274bff34e3Sthurlow sdp->smb_cred = cr; 5284bff34e3Sthurlow sdp->sd_flags |= NSMBFL_OPEN; 5294bff34e3Sthurlow sdp->zoneid = crgetzoneid(cr); 5304bff34e3Sthurlow mutex_exit(&dev_lck); 5314bff34e3Sthurlow 5324bff34e3Sthurlow *dev = makedevice(nsmb_major, nsmb_minor); 5334bff34e3Sthurlow 5344bff34e3Sthurlow return (0); 5354bff34e3Sthurlow } 5364bff34e3Sthurlow 5374bff34e3Sthurlow /*ARGSUSED*/ 5384bff34e3Sthurlow static int 5394bff34e3Sthurlow nsmb_close(dev_t dev, int flags, int otyp, cred_t *cr) 5404bff34e3Sthurlow { 5414bff34e3Sthurlow minor_t inst = getminor(dev); 5424bff34e3Sthurlow smb_dev_t *sdp; 543*613a2f6bSGordon Ross int err; 5444bff34e3Sthurlow 5454bff34e3Sthurlow mutex_enter(&dev_lck); 5464bff34e3Sthurlow /* 5474bff34e3Sthurlow * 1. Check the validity of the minor number. 5484bff34e3Sthurlow * 2. Release any shares/vc associated with the connection. 5494bff34e3Sthurlow * 3. Can close the minor number. 5504bff34e3Sthurlow * 4. Deallocate any resources allocated in open() call. 5514bff34e3Sthurlow */ 5524bff34e3Sthurlow 5534bff34e3Sthurlow sdp = ddi_get_soft_state(statep, inst); 554*613a2f6bSGordon Ross if (sdp != NULL) 555*613a2f6bSGordon Ross err = nsmb_close2(sdp, cr); 556*613a2f6bSGordon Ross else 557*613a2f6bSGordon Ross err = ENXIO; 5584bff34e3Sthurlow 5594bff34e3Sthurlow /* 560*613a2f6bSGordon Ross * Free the instance 5614bff34e3Sthurlow */ 562*613a2f6bSGordon Ross ddi_soft_state_free(statep, inst); 563*613a2f6bSGordon Ross mutex_exit(&dev_lck); 564*613a2f6bSGordon Ross return (err); 565*613a2f6bSGordon Ross } 566*613a2f6bSGordon Ross 567*613a2f6bSGordon Ross static int 568*613a2f6bSGordon Ross nsmb_close2(smb_dev_t *sdp, cred_t *cr) 569*613a2f6bSGordon Ross { 570*613a2f6bSGordon Ross struct smb_vc *vcp; 571*613a2f6bSGordon Ross struct smb_share *ssp; 572*613a2f6bSGordon Ross struct smb_cred scred; 573*613a2f6bSGordon Ross 574*613a2f6bSGordon Ross smb_credinit(&scred, cr); 5754bff34e3Sthurlow ssp = sdp->sd_share; 5764bff34e3Sthurlow if (ssp != NULL) 5774bff34e3Sthurlow smb_share_rele(ssp); 5784bff34e3Sthurlow vcp = sdp->sd_vc; 5794bff34e3Sthurlow if (vcp != NULL) { 5804bff34e3Sthurlow /* 581*613a2f6bSGordon Ross * If this dev minor was opened by smbiod, 582*613a2f6bSGordon Ross * mark this VC as "dead" because it now 583*613a2f6bSGordon Ross * will have no IOD to service it. 5844bff34e3Sthurlow */ 585*613a2f6bSGordon Ross if (sdp->sd_flags & NSMBFL_IOD) 5866723e17fSGordon Ross smb_iod_disconnect(vcp); 5874bff34e3Sthurlow smb_vc_rele(vcp); 5884bff34e3Sthurlow } 5894bff34e3Sthurlow 590*613a2f6bSGordon Ross smb_credrele(&scred); 5914bff34e3Sthurlow return (0); 5924bff34e3Sthurlow } 5934bff34e3Sthurlow 5944bff34e3Sthurlow int 5954bff34e3Sthurlow smb_dev2share(int fd, struct smb_share **sspp) 5964bff34e3Sthurlow { 597*613a2f6bSGordon Ross file_t *fp = NULL; 598*613a2f6bSGordon Ross vnode_t *vp; 5994bff34e3Sthurlow smb_dev_t *sdp; 600*613a2f6bSGordon Ross smb_share_t *ssp; 6014bff34e3Sthurlow dev_t dev; 602*613a2f6bSGordon Ross int err; 6034bff34e3Sthurlow 6044bff34e3Sthurlow if ((fp = getf(fd)) == NULL) 605*613a2f6bSGordon Ross return (EBADF); 606*613a2f6bSGordon Ross 6074bff34e3Sthurlow vp = fp->f_vnode; 6084bff34e3Sthurlow dev = vp->v_rdev; 609*613a2f6bSGordon Ross if (dev == 0 || dev == NODEV || 610*613a2f6bSGordon Ross getmajor(dev) != nsmb_major) { 611*613a2f6bSGordon Ross err = EBADF; 612*613a2f6bSGordon Ross goto out; 6134bff34e3Sthurlow } 614*613a2f6bSGordon Ross 6154bff34e3Sthurlow sdp = ddi_get_soft_state(statep, getminor(dev)); 6164bff34e3Sthurlow if (sdp == NULL) { 617*613a2f6bSGordon Ross err = EINVAL; 618*613a2f6bSGordon Ross goto out; 6194bff34e3Sthurlow } 620*613a2f6bSGordon Ross 6214bff34e3Sthurlow ssp = sdp->sd_share; 6224bff34e3Sthurlow if (ssp == NULL) { 623*613a2f6bSGordon Ross err = ENOTCONN; 624*613a2f6bSGordon Ross goto out; 6254bff34e3Sthurlow } 626*613a2f6bSGordon Ross 6274bff34e3Sthurlow /* 628*613a2f6bSGordon Ross * Our caller gains a ref. to this share. 6294bff34e3Sthurlow */ 6304bff34e3Sthurlow *sspp = ssp; 631*613a2f6bSGordon Ross smb_share_hold(ssp); 632*613a2f6bSGordon Ross err = 0; 633*613a2f6bSGordon Ross 634*613a2f6bSGordon Ross out: 635*613a2f6bSGordon Ross if (fp) 636*613a2f6bSGordon Ross releasef(fd); 637*613a2f6bSGordon Ross return (err); 6384bff34e3Sthurlow } 639