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 /*
34613a2f6bSGordon Ross * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
354bff34e3Sthurlow * Use is subject to license terms.
368329232eSGordon Ross *
3740c0e231SGordon Ross * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
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>
6540c0e231SGordon Ross #include <sys/socket.h>
664bff34e3Sthurlow #include <sys/zone.h>
674bff34e3Sthurlow
684bff34e3Sthurlow #include <netsmb/smb_osdep.h>
694bff34e3Sthurlow #include <netsmb/mchain.h> /* for "htoles()" */
704bff34e3Sthurlow
714bff34e3Sthurlow #include <netsmb/smb.h>
72adee6784SGordon Ross #include <netsmb/smb2.h>
734bff34e3Sthurlow #include <netsmb/smb_conn.h>
744bff34e3Sthurlow #include <netsmb/smb_subr.h>
754bff34e3Sthurlow #include <netsmb/smb_dev.h>
764bff34e3Sthurlow #include <netsmb/smb_pass.h>
774bff34e3Sthurlow
788329232eSGordon Ross #ifndef _KERNEL
798329232eSGordon Ross #include <libfknsmb.h>
808329232eSGordon Ross
818329232eSGordon Ross #define _init(v) nsmb_drv_init(v)
828329232eSGordon Ross #define _fini(v) nsmb_drv_fini(v)
838329232eSGordon Ross
848329232eSGordon Ross #endif /* _KERNEL */
858329232eSGordon Ross
865ab8bad6SGordon Ross #define NSMB_MIN_MINOR 1
875ab8bad6SGordon Ross #define NSMB_MAX_MINOR L_MAXMIN32
885ab8bad6SGordon Ross
894bff34e3Sthurlow /* for version checks */
904bff34e3Sthurlow const uint32_t nsmb_version = NSMB_VERSION;
914bff34e3Sthurlow
9240c0e231SGordon Ross /* for smb_nbst_create() */
9340c0e231SGordon Ross dev_t nsmb_dev_tcp = NODEV;
9440c0e231SGordon Ross dev_t nsmb_dev_tcp6 = NODEV;
9540c0e231SGordon Ross
964bff34e3Sthurlow static void *statep;
974bff34e3Sthurlow static major_t nsmb_major;
985ab8bad6SGordon Ross static minor_t last_minor = NSMB_MIN_MINOR;
994bff34e3Sthurlow static kmutex_t dev_lck;
1004bff34e3Sthurlow
1014bff34e3Sthurlow /*
1024bff34e3Sthurlow * cb_ops device operations.
1034bff34e3Sthurlow */
1044bff34e3Sthurlow static int nsmb_open(dev_t *devp, int flag, int otyp, cred_t *credp);
1054bff34e3Sthurlow static int nsmb_close(dev_t dev, int flag, int otyp, cred_t *credp);
1064bff34e3Sthurlow static int nsmb_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
1074bff34e3Sthurlow cred_t *credp, int *rvalp);
108613a2f6bSGordon Ross static int nsmb_close2(smb_dev_t *sdp, cred_t *cr);
109613a2f6bSGordon Ross
1108329232eSGordon Ross #ifdef _KERNEL
1118329232eSGordon Ross
1128329232eSGordon Ross static dev_info_t *nsmb_dip;
1138329232eSGordon Ross
1148329232eSGordon Ross /* Zone support */
1158329232eSGordon Ross zone_key_t nsmb_zone_key;
1168329232eSGordon Ross extern void nsmb_zone_shutdown(zoneid_t zoneid, void *data);
1178329232eSGordon Ross extern void nsmb_zone_destroy(zoneid_t zoneid, void *data);
1188329232eSGordon 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 */
170613a2f6bSGordon 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
1808329232eSGordon Ross #endif /* _KERNEL */
1818329232eSGordon Ross
1824bff34e3Sthurlow int
_init(void)1834bff34e3Sthurlow _init(void)
1844bff34e3Sthurlow {
1858329232eSGordon Ross #ifdef _KERNEL
1864bff34e3Sthurlow int error;
1878329232eSGordon Ross #endif /* _KERNEL */
1884bff34e3Sthurlow
18902d09e03SGordon Ross (void) ddi_soft_state_init(&statep, sizeof (smb_dev_t), 1);
1904bff34e3Sthurlow
1914bff34e3Sthurlow /* Can initialize some mutexes also. */
1924bff34e3Sthurlow mutex_init(&dev_lck, NULL, MUTEX_DRIVER, NULL);
1934bff34e3Sthurlow
1944bff34e3Sthurlow /* Connection data structures. */
1954bff34e3Sthurlow (void) smb_sm_init();
1964bff34e3Sthurlow
1974bff34e3Sthurlow /* Initialize password Key chain DB. */
1984bff34e3Sthurlow smb_pkey_init();
1994bff34e3Sthurlow
2008329232eSGordon Ross #ifdef _KERNEL
2014bff34e3Sthurlow zone_key_create(&nsmb_zone_key, NULL, nsmb_zone_shutdown,
2024bff34e3Sthurlow nsmb_zone_destroy);
2034bff34e3Sthurlow
2044bff34e3Sthurlow /*
2054bff34e3Sthurlow * Install the module. Do this after other init,
2064bff34e3Sthurlow * to prevent entrances before we're ready.
2074bff34e3Sthurlow */
2084bff34e3Sthurlow if ((error = mod_install((&nsmb_modlinkage))) != 0) {
2094bff34e3Sthurlow
2104bff34e3Sthurlow /* Same as 2nd half of _fini */
2114bff34e3Sthurlow (void) zone_key_delete(nsmb_zone_key);
2124bff34e3Sthurlow smb_pkey_fini();
2134bff34e3Sthurlow smb_sm_done();
2144bff34e3Sthurlow mutex_destroy(&dev_lck);
2154bff34e3Sthurlow ddi_soft_state_fini(&statep);
2164bff34e3Sthurlow
2174bff34e3Sthurlow return (error);
2184bff34e3Sthurlow }
2198329232eSGordon Ross #else /* _KERNEL */
2208329232eSGordon Ross streams_msg_init();
2218329232eSGordon Ross /* No attach, so need to set major. */
2228329232eSGordon Ross nsmb_major = 1;
22340c0e231SGordon Ross /* And these, for smb_nbst_create() */
22440c0e231SGordon Ross nsmb_dev_tcp = AF_INET;
22540c0e231SGordon Ross nsmb_dev_tcp6 = AF_INET6;
2268329232eSGordon Ross #endif /* _KERNEL */
2274bff34e3Sthurlow
2284bff34e3Sthurlow return (0);
2294bff34e3Sthurlow }
2304bff34e3Sthurlow
2314bff34e3Sthurlow int
_fini(void)2324bff34e3Sthurlow _fini(void)
2334bff34e3Sthurlow {
2344bff34e3Sthurlow int status;
2354bff34e3Sthurlow
2364bff34e3Sthurlow /*
2374bff34e3Sthurlow * Prevent unload if we have active VCs
2384bff34e3Sthurlow * or stored passwords
2394bff34e3Sthurlow */
2404bff34e3Sthurlow if ((status = smb_sm_idle()) != 0)
2414bff34e3Sthurlow return (status);
2424bff34e3Sthurlow if ((status = smb_pkey_idle()) != 0)
2434bff34e3Sthurlow return (status);
2444bff34e3Sthurlow
2458329232eSGordon Ross #ifdef _KERNEL
2464bff34e3Sthurlow /*
2474bff34e3Sthurlow * Remove the module. Do this before destroying things,
2484bff34e3Sthurlow * to prevent new entrances while we're destorying.
2494bff34e3Sthurlow */
2504bff34e3Sthurlow if ((status = mod_remove(&nsmb_modlinkage)) != 0) {
2514bff34e3Sthurlow return (status);
2524bff34e3Sthurlow }
2534bff34e3Sthurlow
2544bff34e3Sthurlow (void) zone_key_delete(nsmb_zone_key);
2558329232eSGordon Ross #endif /* _KERNEL */
2564bff34e3Sthurlow
2574bff34e3Sthurlow /* Destroy password Key chain DB. */
2584bff34e3Sthurlow smb_pkey_fini();
2594bff34e3Sthurlow
2604bff34e3Sthurlow smb_sm_done();
2614bff34e3Sthurlow
2624bff34e3Sthurlow mutex_destroy(&dev_lck);
2634bff34e3Sthurlow ddi_soft_state_fini(&statep);
2644bff34e3Sthurlow
2654bff34e3Sthurlow return (status);
2664bff34e3Sthurlow }
2674bff34e3Sthurlow
2688329232eSGordon Ross #ifdef _KERNEL
2698329232eSGordon Ross
2704bff34e3Sthurlow int
_info(struct modinfo * modinfop)2714bff34e3Sthurlow _info(struct modinfo *modinfop)
2724bff34e3Sthurlow {
2734bff34e3Sthurlow return (mod_info(&nsmb_modlinkage, modinfop));
2744bff34e3Sthurlow }
2754bff34e3Sthurlow
2764bff34e3Sthurlow /*ARGSUSED*/
2774bff34e3Sthurlow static int
nsmb_getinfo(dev_info_t * dip,ddi_info_cmd_t cmd,void * arg,void ** result)2784bff34e3Sthurlow nsmb_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
2794bff34e3Sthurlow {
2804bff34e3Sthurlow int ret = DDI_SUCCESS;
2814bff34e3Sthurlow
2824bff34e3Sthurlow switch (cmd) {
2834bff34e3Sthurlow case DDI_INFO_DEVT2DEVINFO:
2845ab8bad6SGordon Ross *result = nsmb_dip;
2854bff34e3Sthurlow break;
2864bff34e3Sthurlow case DDI_INFO_DEVT2INSTANCE:
2875ab8bad6SGordon Ross *result = NULL;
2884bff34e3Sthurlow break;
2894bff34e3Sthurlow default:
2904bff34e3Sthurlow ret = DDI_FAILURE;
2914bff34e3Sthurlow }
2924bff34e3Sthurlow return (ret);
2934bff34e3Sthurlow }
2944bff34e3Sthurlow
2954bff34e3Sthurlow static int
nsmb_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)2964bff34e3Sthurlow nsmb_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
2974bff34e3Sthurlow {
29840c0e231SGordon Ross major_t tmaj;
2994bff34e3Sthurlow
3004bff34e3Sthurlow if (cmd != DDI_ATTACH)
3014bff34e3Sthurlow return (DDI_FAILURE);
3025ab8bad6SGordon Ross
3034bff34e3Sthurlow /*
3045ab8bad6SGordon Ross * We only support only one "instance". Note that
3055ab8bad6SGordon Ross * "instances" are different from minor units.
3065ab8bad6SGordon Ross * We get one (unique) minor unit per open.
3074bff34e3Sthurlow */
3084bff34e3Sthurlow if (ddi_get_instance(dip) > 0)
3094bff34e3Sthurlow return (DDI_FAILURE);
3104bff34e3Sthurlow
3114bff34e3Sthurlow if (ddi_create_minor_node(dip, "nsmb", S_IFCHR, 0, DDI_PSEUDO,
312*25a52949SToomas Soome 0) == DDI_FAILURE) {
3134bff34e3Sthurlow cmn_err(CE_WARN, "nsmb_attach: create minor");
3145ab8bad6SGordon Ross return (DDI_FAILURE);
3154bff34e3Sthurlow }
3164bff34e3Sthurlow
3175ab8bad6SGordon Ross /*
3185ab8bad6SGordon Ross * We need the major number a couple places,
3195ab8bad6SGordon Ross * i.e. in smb_dev2share()
3205ab8bad6SGordon Ross */
3215ab8bad6SGordon Ross nsmb_major = ddi_name_to_major(NSMB_NAME);
3225ab8bad6SGordon Ross
32340c0e231SGordon Ross /*
32440c0e231SGordon Ross * We also need major numbers for t_kopen
32540c0e231SGordon Ross */
32640c0e231SGordon Ross tmaj = ddi_name_to_major("tcp");
32740c0e231SGordon Ross if (tmaj == DDI_MAJOR_T_NONE)
32840c0e231SGordon Ross cmn_err(CE_NOTE, "no tcp major?");
32940c0e231SGordon Ross else
33040c0e231SGordon Ross nsmb_dev_tcp = makedevice(tmaj, 0);
33140c0e231SGordon Ross tmaj = ddi_name_to_major("tcp6");
33240c0e231SGordon Ross if (tmaj == DDI_MAJOR_T_NONE)
33340c0e231SGordon Ross cmn_err(CE_NOTE, "no tcp6 major?");
33440c0e231SGordon Ross else
33540c0e231SGordon Ross nsmb_dev_tcp6 = makedevice(tmaj, 0);
33640c0e231SGordon Ross
3375ab8bad6SGordon Ross nsmb_dip = dip;
3384bff34e3Sthurlow ddi_report_dev(dip);
3394bff34e3Sthurlow return (DDI_SUCCESS);
3404bff34e3Sthurlow }
3414bff34e3Sthurlow
3424bff34e3Sthurlow /*ARGSUSED*/
3434bff34e3Sthurlow static int
nsmb_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)3444bff34e3Sthurlow nsmb_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
3454bff34e3Sthurlow {
3464bff34e3Sthurlow
3474bff34e3Sthurlow if (cmd != DDI_DETACH)
3484bff34e3Sthurlow return (DDI_FAILURE);
3494bff34e3Sthurlow if (ddi_get_instance(dip) > 0)
3504bff34e3Sthurlow return (DDI_FAILURE);
3514bff34e3Sthurlow
3525ab8bad6SGordon Ross nsmb_dip = NULL;
3534bff34e3Sthurlow ddi_remove_minor_node(dip, NULL);
3544bff34e3Sthurlow
3554bff34e3Sthurlow return (DDI_SUCCESS);
3564bff34e3Sthurlow }
3574bff34e3Sthurlow
3588329232eSGordon Ross #else /* _KERNEL */
3598329232eSGordon Ross
3608329232eSGordon Ross /*
3618329232eSGordon Ross * Wrappers for libfknsmb: ioctl, open, close, load
3628329232eSGordon Ross */
3638329232eSGordon Ross
3648329232eSGordon Ross /*ARGSUSED*/
3658329232eSGordon Ross int
nsmb_drv_ioctl(dev32_t dev32,int cmd,intptr_t arg,int flags)3668329232eSGordon Ross nsmb_drv_ioctl(dev32_t dev32, int cmd, intptr_t arg, int flags)
3678329232eSGordon Ross {
3688329232eSGordon Ross dev_t dev = expldev(dev32);
3698329232eSGordon Ross cred_t *cr = CRED();
3708329232eSGordon Ross int err;
3718329232eSGordon Ross
3728329232eSGordon Ross err = nsmb_ioctl(dev, cmd, arg, flags, cr, NULL);
3738329232eSGordon Ross return (err);
3748329232eSGordon Ross }
3758329232eSGordon Ross
3768329232eSGordon Ross /*ARGSUSED*/
3778329232eSGordon Ross int
nsmb_drv_open(dev32_t * dev32p,int flags,int otyp)3788329232eSGordon Ross nsmb_drv_open(dev32_t *dev32p, int flags, int otyp)
3798329232eSGordon Ross {
3808329232eSGordon Ross dev_t dev = expldev(*dev32p);
3818329232eSGordon Ross int err;
3828329232eSGordon Ross
3838329232eSGordon Ross err = nsmb_open(&dev, flags, otyp, CRED());
3848329232eSGordon Ross if (err == 0) {
3858329232eSGordon Ross /*
3868329232eSGordon Ross * We have NSMB_MAX_MINOR == L_MAXMIN32
3878329232eSGordon Ross * therefore cmpldev never fails.
3888329232eSGordon Ross */
3898329232eSGordon Ross VERIFY(cmpldev(dev32p, dev) != 0);
3908329232eSGordon Ross }
3918329232eSGordon Ross return (err);
3928329232eSGordon Ross }
3938329232eSGordon Ross
3948329232eSGordon Ross /*ARGSUSED*/
3958329232eSGordon Ross int
nsmb_drv_close(dev32_t dev32,int flags,int otyp)3968329232eSGordon Ross nsmb_drv_close(dev32_t dev32, int flags, int otyp)
3978329232eSGordon Ross {
3988329232eSGordon Ross dev_t dev = expldev(dev32);
3998329232eSGordon Ross int err;
4008329232eSGordon Ross
4018329232eSGordon Ross err = nsmb_close(dev, flags, otyp, CRED());
4028329232eSGordon Ross return (err);
4038329232eSGordon Ross }
4048329232eSGordon Ross
4058329232eSGordon Ross /*
4068329232eSGordon Ross * This function intentionally does nothing. It's used only to
4078329232eSGordon Ross * force libfknsmb to load at program start so one can set
4088329232eSGordon Ross * breakpoints etc. without debugger "force load" tricks.
4098329232eSGordon Ross */
4108329232eSGordon Ross void
nsmb_drv_load(void)4118329232eSGordon Ross nsmb_drv_load(void)
4128329232eSGordon Ross {
4138329232eSGordon Ross }
4148329232eSGordon Ross
4158329232eSGordon Ross #endif /* _KERNEL */
4168329232eSGordon Ross
4174bff34e3Sthurlow /*ARGSUSED*/
4184bff34e3Sthurlow static int
nsmb_ioctl(dev_t dev,int cmd,intptr_t arg,int flags,cred_t * cr,int * rvalp)419613a2f6bSGordon Ross nsmb_ioctl(dev_t dev, int cmd, intptr_t arg, int flags, /* model.h */
420613a2f6bSGordon Ross cred_t *cr, int *rvalp)
4214bff34e3Sthurlow {
4224bff34e3Sthurlow smb_dev_t *sdp;
423613a2f6bSGordon Ross int err;
4244bff34e3Sthurlow
4254bff34e3Sthurlow sdp = ddi_get_soft_state(statep, getminor(dev));
4264bff34e3Sthurlow if (sdp == NULL) {
4278329232eSGordon Ross return (EBADF);
4284bff34e3Sthurlow }
4294bff34e3Sthurlow if ((sdp->sd_flags & NSMBFL_OPEN) == 0) {
4304bff34e3Sthurlow return (EBADF);
4314bff34e3Sthurlow }
4324bff34e3Sthurlow
4334bff34e3Sthurlow /*
4344bff34e3Sthurlow * Dont give access if the zone id is not as the same as we
4354bff34e3Sthurlow * set in the nsmb_open or dont belong to the global zone.
4364bff34e3Sthurlow * Check if the user belongs to this zone..
4374bff34e3Sthurlow */
4384bff34e3Sthurlow if (sdp->zoneid != getzoneid())
4394bff34e3Sthurlow return (EIO);
4404bff34e3Sthurlow
441613a2f6bSGordon Ross /*
442613a2f6bSGordon Ross * We have a zone_shutdown call back that kills all the VCs
443613a2f6bSGordon Ross * in a zone that's shutting down. That action will cause
444613a2f6bSGordon Ross * all of these ioctls to fail on such VCs, so no need to
445613a2f6bSGordon Ross * check the zone status here on every ioctl call.
446613a2f6bSGordon Ross */
4474bff34e3Sthurlow
44840c0e231SGordon Ross err = smb_usr_ioctl(sdp, cmd, arg, flags, cr);
449216041c4SGordon Ross
450613a2f6bSGordon Ross return (err);
4514bff34e3Sthurlow }
4524bff34e3Sthurlow
4535ab8bad6SGordon Ross /*
4545ab8bad6SGordon Ross * This does "clone" open, meaning it automatically
4555ab8bad6SGordon Ross * assigns an available minor unit for each open.
4565ab8bad6SGordon Ross */
4574bff34e3Sthurlow /*ARGSUSED*/
4584bff34e3Sthurlow static int
nsmb_open(dev_t * dev,int flags,int otyp,cred_t * cr)4594bff34e3Sthurlow nsmb_open(dev_t *dev, int flags, int otyp, cred_t *cr)
4604bff34e3Sthurlow {
4615ab8bad6SGordon Ross smb_dev_t *sdp;
4625ab8bad6SGordon Ross minor_t m;
4634bff34e3Sthurlow
4644bff34e3Sthurlow mutex_enter(&dev_lck);
4655ab8bad6SGordon Ross
4665ab8bad6SGordon Ross for (m = last_minor + 1; m != last_minor; m++) {
4675ab8bad6SGordon Ross if (m > NSMB_MAX_MINOR)
4685ab8bad6SGordon Ross m = NSMB_MIN_MINOR;
4695ab8bad6SGordon Ross
4705ab8bad6SGordon Ross if (ddi_get_soft_state(statep, m) == NULL) {
4715ab8bad6SGordon Ross last_minor = m;
4725ab8bad6SGordon Ross goto found;
4734bff34e3Sthurlow }
4745ab8bad6SGordon Ross }
4755ab8bad6SGordon Ross
4765ab8bad6SGordon Ross /* No available minor units. */
4774bff34e3Sthurlow mutex_exit(&dev_lck);
4785ab8bad6SGordon Ross return (ENXIO);
4794bff34e3Sthurlow
4805ab8bad6SGordon Ross found:
4815ab8bad6SGordon Ross /* NB: dev_lck still held */
4825ab8bad6SGordon Ross if (ddi_soft_state_zalloc(statep, m) == DDI_FAILURE) {
4834bff34e3Sthurlow mutex_exit(&dev_lck);
4844bff34e3Sthurlow return (ENXIO);
4854bff34e3Sthurlow }
4865ab8bad6SGordon Ross if ((sdp = ddi_get_soft_state(statep, m)) == NULL) {
4874bff34e3Sthurlow mutex_exit(&dev_lck);
4884bff34e3Sthurlow return (ENXIO);
4894bff34e3Sthurlow }
4905ab8bad6SGordon Ross *dev = makedevice(nsmb_major, m);
4915ab8bad6SGordon Ross mutex_exit(&dev_lck);
4924bff34e3Sthurlow
4934bff34e3Sthurlow sdp->sd_flags |= NSMBFL_OPEN;
4944bff34e3Sthurlow sdp->zoneid = crgetzoneid(cr);
495216041c4SGordon Ross mutex_init(&sdp->sd_lock, NULL, MUTEX_DRIVER, NULL);
4964bff34e3Sthurlow
4974bff34e3Sthurlow return (0);
4984bff34e3Sthurlow }
4994bff34e3Sthurlow
5004bff34e3Sthurlow /*ARGSUSED*/
5014bff34e3Sthurlow static int
nsmb_close(dev_t dev,int flags,int otyp,cred_t * cr)5024bff34e3Sthurlow nsmb_close(dev_t dev, int flags, int otyp, cred_t *cr)
5034bff34e3Sthurlow {
5044bff34e3Sthurlow minor_t inst = getminor(dev);
5054bff34e3Sthurlow smb_dev_t *sdp;
506613a2f6bSGordon Ross int err;
5074bff34e3Sthurlow
5084bff34e3Sthurlow /*
5094bff34e3Sthurlow * 1. Check the validity of the minor number.
5104bff34e3Sthurlow * 2. Release any shares/vc associated with the connection.
5114bff34e3Sthurlow * 3. Can close the minor number.
5124bff34e3Sthurlow * 4. Deallocate any resources allocated in open() call.
5134bff34e3Sthurlow */
5144bff34e3Sthurlow
5154bff34e3Sthurlow sdp = ddi_get_soft_state(statep, inst);
516613a2f6bSGordon Ross if (sdp != NULL)
517613a2f6bSGordon Ross err = nsmb_close2(sdp, cr);
518613a2f6bSGordon Ross else
519613a2f6bSGordon Ross err = ENXIO;
5204bff34e3Sthurlow
5214bff34e3Sthurlow /*
5224bff34e3Sthurlow * Free the instance
5234bff34e3Sthurlow */
52439f633a0SBayard Bell mutex_enter(&dev_lck);
5254bff34e3Sthurlow ddi_soft_state_free(statep, inst);
5264bff34e3Sthurlow mutex_exit(&dev_lck);
527613a2f6bSGordon Ross return (err);
528613a2f6bSGordon Ross }
529613a2f6bSGordon Ross
530adee6784SGordon Ross /*ARGSUSED*/
531613a2f6bSGordon Ross static int
nsmb_close2(smb_dev_t * sdp,cred_t * cr)532613a2f6bSGordon Ross nsmb_close2(smb_dev_t *sdp, cred_t *cr)
533613a2f6bSGordon Ross {
534613a2f6bSGordon Ross struct smb_vc *vcp;
535613a2f6bSGordon Ross struct smb_share *ssp;
536adee6784SGordon Ross struct smb_fh *fhp;
537613a2f6bSGordon Ross
538adee6784SGordon Ross fhp = sdp->sd_fh;
539adee6784SGordon Ross if (fhp != NULL)
540adee6784SGordon Ross smb_fh_rele(fhp);
541430b4c46SGordon Ross
542613a2f6bSGordon Ross ssp = sdp->sd_share;
543613a2f6bSGordon Ross if (ssp != NULL)
544613a2f6bSGordon Ross smb_share_rele(ssp);
545430b4c46SGordon Ross
546613a2f6bSGordon Ross vcp = sdp->sd_vc;
547613a2f6bSGordon Ross if (vcp != NULL) {
548613a2f6bSGordon Ross /*
549613a2f6bSGordon Ross * If this dev minor was opened by smbiod,
550613a2f6bSGordon Ross * mark this VC as "dead" because it now
551613a2f6bSGordon Ross * will have no IOD to service it.
552613a2f6bSGordon Ross */
553613a2f6bSGordon Ross if (sdp->sd_flags & NSMBFL_IOD)
554613a2f6bSGordon Ross smb_iod_disconnect(vcp);
555613a2f6bSGordon Ross smb_vc_rele(vcp);
556613a2f6bSGordon Ross }
557216041c4SGordon Ross mutex_destroy(&sdp->sd_lock);
558613a2f6bSGordon Ross
5594bff34e3Sthurlow return (0);
5604bff34e3Sthurlow }
5614bff34e3Sthurlow
562430b4c46SGordon Ross /*
563430b4c46SGordon Ross * Helper for SMBIOC_DUP_DEV
564430b4c46SGordon Ross * Duplicate state from the FD @arg ("from") onto
565430b4c46SGordon Ross * the FD for this device instance.
566430b4c46SGordon Ross */
567430b4c46SGordon Ross int
smb_usr_dup_dev(smb_dev_t * sdp,intptr_t arg,int flags)568430b4c46SGordon Ross smb_usr_dup_dev(smb_dev_t *sdp, intptr_t arg, int flags)
569430b4c46SGordon Ross {
5708329232eSGordon Ross #ifdef _KERNEL
571430b4c46SGordon Ross file_t *fp = NULL;
572430b4c46SGordon Ross vnode_t *vp;
5738329232eSGordon Ross #endif /* _KERNEL */
574430b4c46SGordon Ross smb_dev_t *from_sdp;
575430b4c46SGordon Ross dev_t dev;
576430b4c46SGordon Ross int32_t ufd;
577430b4c46SGordon Ross int err;
578430b4c46SGordon Ross
579430b4c46SGordon Ross /* Should be no VC */
580430b4c46SGordon Ross if (sdp->sd_vc != NULL)
581430b4c46SGordon Ross return (EISCONN);
582430b4c46SGordon Ross
583430b4c46SGordon Ross /*
584430b4c46SGordon Ross * Get from_sdp (what we will duplicate)
585430b4c46SGordon Ross */
586430b4c46SGordon Ross if (ddi_copyin((void *) arg, &ufd, sizeof (ufd), flags))
587430b4c46SGordon Ross return (EFAULT);
5888329232eSGordon Ross #ifdef _KERNEL
589430b4c46SGordon Ross if ((fp = getf(ufd)) == NULL)
590430b4c46SGordon Ross return (EBADF);
591430b4c46SGordon Ross /* rele fp below */
592430b4c46SGordon Ross vp = fp->f_vnode;
593430b4c46SGordon Ross dev = vp->v_rdev;
5948329232eSGordon Ross #else /* _KERNEL */
5958329232eSGordon Ross /*
5968329232eSGordon Ross * No getf(ufd) -- ufd is really a dev32_t
5978329232eSGordon Ross */
5988329232eSGordon Ross dev = expldev((dev32_t)ufd);
5998329232eSGordon Ross #endif /* _KERNEL */
600430b4c46SGordon Ross if (dev == 0 || dev == NODEV ||
601430b4c46SGordon Ross getmajor(dev) != nsmb_major) {
602430b4c46SGordon Ross err = EINVAL;
603430b4c46SGordon Ross goto out;
604430b4c46SGordon Ross }
6058329232eSGordon Ross
606430b4c46SGordon Ross from_sdp = ddi_get_soft_state(statep, getminor(dev));
607430b4c46SGordon Ross if (from_sdp == NULL) {
608430b4c46SGordon Ross err = EINVAL;
609430b4c46SGordon Ross goto out;
610430b4c46SGordon Ross }
611430b4c46SGordon Ross
612430b4c46SGordon Ross /*
613430b4c46SGordon Ross * Duplicate VC and share references onto this FD.
614430b4c46SGordon Ross */
615430b4c46SGordon Ross if ((sdp->sd_vc = from_sdp->sd_vc) != NULL)
616430b4c46SGordon Ross smb_vc_hold(sdp->sd_vc);
617430b4c46SGordon Ross if ((sdp->sd_share = from_sdp->sd_share) != NULL)
618430b4c46SGordon Ross smb_share_hold(sdp->sd_share);
619430b4c46SGordon Ross sdp->sd_level = from_sdp->sd_level;
620430b4c46SGordon Ross err = 0;
621430b4c46SGordon Ross
622430b4c46SGordon Ross out:
6238329232eSGordon Ross #ifdef _KERNEL
624430b4c46SGordon Ross if (fp)
625430b4c46SGordon Ross releasef(ufd);
6268329232eSGordon Ross #endif /* _KERNEL */
627430b4c46SGordon Ross return (err);
628430b4c46SGordon Ross }
629430b4c46SGordon Ross
630430b4c46SGordon Ross
631430b4c46SGordon Ross /*
632430b4c46SGordon Ross * Helper used by smbfs_mount
633430b4c46SGordon Ross */
6344bff34e3Sthurlow int
smb_dev2share(int fd,struct smb_share ** sspp)6354bff34e3Sthurlow smb_dev2share(int fd, struct smb_share **sspp)
6364bff34e3Sthurlow {
6378329232eSGordon Ross #ifdef _KERNEL
638613a2f6bSGordon Ross file_t *fp = NULL;
639613a2f6bSGordon Ross vnode_t *vp;
6408329232eSGordon Ross #endif /* _KERNEL */
6414bff34e3Sthurlow smb_dev_t *sdp;
642613a2f6bSGordon Ross smb_share_t *ssp;
6434bff34e3Sthurlow dev_t dev;
644613a2f6bSGordon Ross int err;
6454bff34e3Sthurlow
6468329232eSGordon Ross #ifdef _KERNEL
6474bff34e3Sthurlow if ((fp = getf(fd)) == NULL)
648613a2f6bSGordon Ross return (EBADF);
649430b4c46SGordon Ross /* rele fp below */
6504bff34e3Sthurlow vp = fp->f_vnode;
6514bff34e3Sthurlow dev = vp->v_rdev;
6528329232eSGordon Ross #else /* _KERNEL */
6538329232eSGordon Ross /*
6548329232eSGordon Ross * No getf(ufd) -- fd is really a dev32_t
6558329232eSGordon Ross */
6568329232eSGordon Ross dev = expldev((dev32_t)fd);
6578329232eSGordon Ross #endif /* _KERNEL */
658613a2f6bSGordon Ross if (dev == 0 || dev == NODEV ||
659613a2f6bSGordon Ross getmajor(dev) != nsmb_major) {
660430b4c46SGordon Ross err = EINVAL;
661613a2f6bSGordon Ross goto out;
6624bff34e3Sthurlow }
663613a2f6bSGordon Ross
6644bff34e3Sthurlow sdp = ddi_get_soft_state(statep, getminor(dev));
6654bff34e3Sthurlow if (sdp == NULL) {
666613a2f6bSGordon Ross err = EINVAL;
667613a2f6bSGordon Ross goto out;
6684bff34e3Sthurlow }
669613a2f6bSGordon Ross
6704bff34e3Sthurlow ssp = sdp->sd_share;
6714bff34e3Sthurlow if (ssp == NULL) {
672613a2f6bSGordon Ross err = ENOTCONN;
673613a2f6bSGordon Ross goto out;
6744bff34e3Sthurlow }
675613a2f6bSGordon Ross
6764bff34e3Sthurlow /*
677613a2f6bSGordon Ross * Our caller gains a ref. to this share.
6784bff34e3Sthurlow */
6794bff34e3Sthurlow *sspp = ssp;
680613a2f6bSGordon Ross smb_share_hold(ssp);
681613a2f6bSGordon Ross err = 0;
682613a2f6bSGordon Ross
683613a2f6bSGordon Ross out:
6848329232eSGordon Ross #ifdef _KERNEL
685613a2f6bSGordon Ross if (fp)
686613a2f6bSGordon Ross releasef(fd);
6878329232eSGordon Ross #endif /* _KERNEL */
688613a2f6bSGordon Ross return (err);
6894bff34e3Sthurlow }
690