xref: /onnv-gate/usr/src/uts/common/fs/smbclnt/netsmb/smb_dev.c (revision 11332:ed3411181494)
16007Sthurlow /*
26007Sthurlow  * Copyright (c) 2000-2001 Boris Popov
36007Sthurlow  * All rights reserved.
46007Sthurlow  *
56007Sthurlow  * Redistribution and use in source and binary forms, with or without
66007Sthurlow  * modification, are permitted provided that the following conditions
76007Sthurlow  * are met:
86007Sthurlow  * 1. Redistributions of source code must retain the above copyright
96007Sthurlow  *    notice, this list of conditions and the following disclaimer.
106007Sthurlow  * 2. Redistributions in binary form must reproduce the above copyright
116007Sthurlow  *    notice, this list of conditions and the following disclaimer in the
126007Sthurlow  *    documentation and/or other materials provided with the distribution.
136007Sthurlow  * 3. All advertising materials mentioning features or use of this software
146007Sthurlow  *    must display the following acknowledgement:
156007Sthurlow  *    This product includes software developed by Boris Popov.
166007Sthurlow  * 4. Neither the name of the author nor the names of any co-contributors
176007Sthurlow  *    may be used to endorse or promote products derived from this software
186007Sthurlow  *    without specific prior written permission.
196007Sthurlow  *
206007Sthurlow  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
216007Sthurlow  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
226007Sthurlow  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
236007Sthurlow  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
246007Sthurlow  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
256007Sthurlow  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
266007Sthurlow  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
276007Sthurlow  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
286007Sthurlow  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
296007Sthurlow  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
306007Sthurlow  * SUCH DAMAGE.
316007Sthurlow  *
326007Sthurlow  * $Id: smb_dev.c,v 1.21 2004/12/13 00:25:18 lindak Exp $
336007Sthurlow  */
346007Sthurlow 
356007Sthurlow /*
3610023SGordon.Ross@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
376007Sthurlow  * Use is subject to license terms.
386007Sthurlow  */
396007Sthurlow 
406007Sthurlow #include <sys/types.h>
416007Sthurlow #include <sys/param.h>
426007Sthurlow #include <sys/errno.h>
436007Sthurlow #include <sys/sysmacros.h>
446007Sthurlow #include <sys/uio.h>
456007Sthurlow #include <sys/buf.h>
466007Sthurlow #include <sys/modctl.h>
476007Sthurlow #include <sys/open.h>
486007Sthurlow #include <sys/file.h>
496007Sthurlow #include <sys/kmem.h>
506007Sthurlow #include <sys/conf.h>
516007Sthurlow #include <sys/cmn_err.h>
526007Sthurlow #include <sys/stat.h>
536007Sthurlow #include <sys/ddi.h>
546007Sthurlow #include <sys/sunddi.h>
556007Sthurlow #include <sys/sunldi.h>
566007Sthurlow #include <sys/policy.h>
576007Sthurlow #include <sys/zone.h>
586007Sthurlow #include <sys/pathname.h>
596007Sthurlow #include <sys/mount.h>
606007Sthurlow #include <sys/sdt.h>
616007Sthurlow #include <fs/fs_subr.h>
626007Sthurlow #include <sys/modctl.h>
636007Sthurlow #include <sys/devops.h>
646007Sthurlow #include <sys/thread.h>
656007Sthurlow #include <sys/mkdev.h>
666007Sthurlow #include <sys/types.h>
676007Sthurlow #include <sys/zone.h>
686007Sthurlow 
696007Sthurlow #include <netsmb/smb_osdep.h>
706007Sthurlow #include <netsmb/mchain.h>		/* for "htoles()" */
716007Sthurlow 
726007Sthurlow #include <netsmb/smb.h>
736007Sthurlow #include <netsmb/smb_conn.h>
746007Sthurlow #include <netsmb/smb_subr.h>
756007Sthurlow #include <netsmb/smb_dev.h>
766007Sthurlow #include <netsmb/smb_pass.h>
776007Sthurlow 
786007Sthurlow /* for version checks */
796007Sthurlow const uint32_t nsmb_version = NSMB_VERSION;
806007Sthurlow 
816007Sthurlow /*
826007Sthurlow  * Userland code loops through minor #s 0 to 1023, looking for one which opens.
836007Sthurlow  * Intially we create minor 0 and leave it for anyone.  Minor zero will never
846007Sthurlow  * actually get used - opening triggers creation of another (but private) minor,
856007Sthurlow  * which userland code will get to and mark busy.
866007Sthurlow  */
876007Sthurlow #define	SMBMINORS 1024
886007Sthurlow static void *statep;
896007Sthurlow static major_t nsmb_major;
906007Sthurlow static minor_t nsmb_minor = 1;
916007Sthurlow 
926007Sthurlow #define	NSMB_MAX_MINOR  (1 << 8)
936007Sthurlow #define	NSMB_MIN_MINOR   (NSMB_MAX_MINOR + 1)
946007Sthurlow 
956007Sthurlow #define	ILP32	1
966007Sthurlow #define	LP64	2
976007Sthurlow 
986007Sthurlow static kmutex_t  dev_lck;
996007Sthurlow 
1006007Sthurlow /* Zone support */
1016007Sthurlow zone_key_t nsmb_zone_key;
1026007Sthurlow extern void nsmb_zone_shutdown(zoneid_t zoneid, void *data);
1036007Sthurlow extern void nsmb_zone_destroy(zoneid_t zoneid, void *data);
1046007Sthurlow 
1056007Sthurlow /*
1066007Sthurlow  * cb_ops device operations.
1076007Sthurlow  */
1086007Sthurlow static int nsmb_open(dev_t *devp, int flag, int otyp, cred_t *credp);
1096007Sthurlow static int nsmb_close(dev_t dev, int flag, int otyp, cred_t *credp);
1106007Sthurlow static int nsmb_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
1116007Sthurlow 				cred_t *credp, int *rvalp);
11210023SGordon.Ross@Sun.COM static int nsmb_close2(smb_dev_t *sdp, cred_t *cr);
11310023SGordon.Ross@Sun.COM 
1146007Sthurlow /* smbfs cb_ops */
1156007Sthurlow static struct cb_ops nsmb_cbops = {
1166007Sthurlow 	nsmb_open,	/* open */
1176007Sthurlow 	nsmb_close,	/* close */
1186007Sthurlow 	nodev,		/* strategy */
1196007Sthurlow 	nodev,		/* print */
1206007Sthurlow 	nodev,		/* dump */
1216007Sthurlow 	nodev,		/* read */
1226007Sthurlow 	nodev,		/* write */
1236007Sthurlow 	nsmb_ioctl,	/* ioctl */
1246007Sthurlow 	nodev,		/* devmap */
1256007Sthurlow 	nodev,		/* mmap */
1266007Sthurlow 	nodev,		/* segmap */
1276007Sthurlow 	nochpoll,	/* poll */
1286007Sthurlow 	ddi_prop_op,	/* prop_op */
1296007Sthurlow 	NULL,		/* stream */
1306007Sthurlow 	D_MP,		/* cb_flag */
1316007Sthurlow 	CB_REV,		/* rev */
1326007Sthurlow 	nodev,		/* int (*cb_aread)() */
1336007Sthurlow 	nodev		/* int (*cb_awrite)() */
1346007Sthurlow };
1356007Sthurlow 
1366007Sthurlow /*
1376007Sthurlow  * Device options
1386007Sthurlow  */
1396007Sthurlow static int nsmb_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
1406007Sthurlow static int nsmb_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
1416007Sthurlow static int nsmb_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd,
1426007Sthurlow 	void *arg, void **result);
1436007Sthurlow 
1446007Sthurlow static struct dev_ops nsmb_ops = {
1456007Sthurlow 	DEVO_REV,	/* devo_rev, */
1466007Sthurlow 	0,		/* refcnt  */
1476007Sthurlow 	nsmb_getinfo,	/* info */
1486007Sthurlow 	nulldev,	/* identify */
1496007Sthurlow 	nulldev,	/* probe */
1506007Sthurlow 	nsmb_attach,	/* attach */
1516007Sthurlow 	nsmb_detach,	/* detach */
1526007Sthurlow 	nodev,		/* reset */
1536007Sthurlow 	&nsmb_cbops,	/* driver ops - devctl interfaces */
1546007Sthurlow 	NULL,		/* bus operations */
1557656SSherry.Moore@Sun.COM 	NULL,		/* power */
1567656SSherry.Moore@Sun.COM 	ddi_quiesce_not_needed,	/* quiesce */
1576007Sthurlow };
1586007Sthurlow 
1596007Sthurlow /*
1606007Sthurlow  * Module linkage information.
1616007Sthurlow  */
1626007Sthurlow 
1636007Sthurlow static struct modldrv nsmb_modldrv = {
1646007Sthurlow 	&mod_driverops,				/* Driver module */
16510023SGordon.Ross@Sun.COM 	"SMBFS network driver",
1666007Sthurlow 	&nsmb_ops				/* Driver ops */
1676007Sthurlow };
1686007Sthurlow 
1696007Sthurlow static struct modlinkage nsmb_modlinkage = {
1706007Sthurlow 	MODREV_1,
1716007Sthurlow 	(void *)&nsmb_modldrv,
1726007Sthurlow 	NULL
1736007Sthurlow };
1746007Sthurlow 
1756007Sthurlow int
_init(void)1766007Sthurlow _init(void)
1776007Sthurlow {
1786007Sthurlow 	int error;
1796007Sthurlow 
180*11332SGordon.Ross@Sun.COM 	(void) ddi_soft_state_init(&statep, sizeof (smb_dev_t), 1);
1816007Sthurlow 
1826007Sthurlow 	/* Can initialize some mutexes also. */
1836007Sthurlow 	mutex_init(&dev_lck, NULL, MUTEX_DRIVER, NULL);
1846007Sthurlow 	/*
1856007Sthurlow 	 * Create a major name and number.
1866007Sthurlow 	 */
1876007Sthurlow 	nsmb_major = ddi_name_to_major(NSMB_NAME);
1886007Sthurlow 	nsmb_minor = 0;
1896007Sthurlow 
1906007Sthurlow 	/* Connection data structures. */
1916007Sthurlow 	(void) smb_sm_init();
1926007Sthurlow 
1936007Sthurlow 	/* Initialize password Key chain DB. */
1946007Sthurlow 	smb_pkey_init();
1956007Sthurlow 
196*11332SGordon.Ross@Sun.COM 	/* Time conversion stuff. */
197*11332SGordon.Ross@Sun.COM 	smb_time_init();
198*11332SGordon.Ross@Sun.COM 
1998271SGordon.Ross@Sun.COM 	/* Initialize crypto mechanisms. */
2008271SGordon.Ross@Sun.COM 	smb_crypto_mech_init();
2018271SGordon.Ross@Sun.COM 
2026007Sthurlow 	zone_key_create(&nsmb_zone_key, NULL, nsmb_zone_shutdown,
2036007Sthurlow 	    nsmb_zone_destroy);
2046007Sthurlow 
2056007Sthurlow 	/*
2066007Sthurlow 	 * Install the module.  Do this after other init,
2076007Sthurlow 	 * to prevent entrances before we're ready.
2086007Sthurlow 	 */
2096007Sthurlow 	if ((error = mod_install((&nsmb_modlinkage))) != 0) {
2106007Sthurlow 
2116007Sthurlow 		/* Same as 2nd half of _fini */
2126007Sthurlow 		(void) zone_key_delete(nsmb_zone_key);
2136007Sthurlow 		smb_pkey_fini();
2146007Sthurlow 		smb_sm_done();
2156007Sthurlow 		mutex_destroy(&dev_lck);
2166007Sthurlow 		ddi_soft_state_fini(&statep);
2176007Sthurlow 
2186007Sthurlow 		return (error);
2196007Sthurlow 	}
2206007Sthurlow 
2216007Sthurlow 	return (0);
2226007Sthurlow }
2236007Sthurlow 
2246007Sthurlow int
_fini(void)2256007Sthurlow _fini(void)
2266007Sthurlow {
2276007Sthurlow 	int status;
2286007Sthurlow 
2296007Sthurlow 	/*
2306007Sthurlow 	 * Prevent unload if we have active VCs
2316007Sthurlow 	 * or stored passwords
2326007Sthurlow 	 */
2336007Sthurlow 	if ((status = smb_sm_idle()) != 0)
2346007Sthurlow 		return (status);
2356007Sthurlow 	if ((status = smb_pkey_idle()) != 0)
2366007Sthurlow 		return (status);
2376007Sthurlow 
2386007Sthurlow 	/*
2396007Sthurlow 	 * Remove the module.  Do this before destroying things,
2406007Sthurlow 	 * to prevent new entrances while we're destorying.
2416007Sthurlow 	 */
2426007Sthurlow 	if ((status = mod_remove(&nsmb_modlinkage)) != 0) {
2436007Sthurlow 		return (status);
2446007Sthurlow 	}
2456007Sthurlow 
2466007Sthurlow 	(void) zone_key_delete(nsmb_zone_key);
2476007Sthurlow 
248*11332SGordon.Ross@Sun.COM 	/* Time conversion stuff. */
249*11332SGordon.Ross@Sun.COM 	smb_time_fini();
250*11332SGordon.Ross@Sun.COM 
2516007Sthurlow 	/* Destroy password Key chain DB. */
2526007Sthurlow 	smb_pkey_fini();
2536007Sthurlow 
2546007Sthurlow 	smb_sm_done();
2556007Sthurlow 
2566007Sthurlow 	mutex_destroy(&dev_lck);
2576007Sthurlow 	ddi_soft_state_fini(&statep);
2586007Sthurlow 
2596007Sthurlow 	return (status);
2606007Sthurlow }
2616007Sthurlow 
2626007Sthurlow int
_info(struct modinfo * modinfop)2636007Sthurlow _info(struct modinfo *modinfop)
2646007Sthurlow {
2656007Sthurlow 	return (mod_info(&nsmb_modlinkage, modinfop));
2666007Sthurlow }
2676007Sthurlow 
2686007Sthurlow /*ARGSUSED*/
2696007Sthurlow static int
nsmb_getinfo(dev_info_t * dip,ddi_info_cmd_t cmd,void * arg,void ** result)2706007Sthurlow nsmb_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
2716007Sthurlow {
2726007Sthurlow 	int ret = DDI_SUCCESS;
2736007Sthurlow 
2746007Sthurlow 	switch (cmd) {
2756007Sthurlow 	case DDI_INFO_DEVT2DEVINFO:
2766007Sthurlow 		*result = 0;
2776007Sthurlow 		break;
2786007Sthurlow 	case DDI_INFO_DEVT2INSTANCE:
2796007Sthurlow 		*result = 0;
2806007Sthurlow 		break;
2816007Sthurlow 	default:
2826007Sthurlow 		ret = DDI_FAILURE;
2836007Sthurlow 	}
2846007Sthurlow 	return (ret);
2856007Sthurlow }
2866007Sthurlow 
2876007Sthurlow static int
nsmb_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)2886007Sthurlow nsmb_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
2896007Sthurlow {
2906007Sthurlow 	smb_dev_t *sdp;
2916007Sthurlow 
2926007Sthurlow 	if (cmd != DDI_ATTACH)
2936007Sthurlow 		return (DDI_FAILURE);
2946007Sthurlow 	/*
2956007Sthurlow 	 * only one instance - but we clone using the open routine
2966007Sthurlow 	 */
2976007Sthurlow 	if (ddi_get_instance(dip) > 0)
2986007Sthurlow 		return (DDI_FAILURE);
2996007Sthurlow 
3006007Sthurlow 	mutex_enter(&dev_lck);
3016007Sthurlow 
3026007Sthurlow 	/*
3036007Sthurlow 	 * This is the Zero'th minor device which is created.
3046007Sthurlow 	 */
3056007Sthurlow 	if (ddi_soft_state_zalloc(statep, 0) == DDI_FAILURE) {
3066007Sthurlow 		cmn_err(CE_WARN, "nsmb_attach: soft state alloc");
3076007Sthurlow 		goto attach_failed;
3086007Sthurlow 	}
3096007Sthurlow 	if (ddi_create_minor_node(dip, "nsmb", S_IFCHR, 0, DDI_PSEUDO,
3106007Sthurlow 	    NULL) == DDI_FAILURE) {
3116007Sthurlow 		cmn_err(CE_WARN, "nsmb_attach: create minor");
3126007Sthurlow 		goto attach_failed;
3136007Sthurlow 	}
3146007Sthurlow 	if ((sdp = ddi_get_soft_state(statep, 0)) == NULL) {
3156007Sthurlow 		cmn_err(CE_WARN, "nsmb_attach: get soft state");
3166007Sthurlow 		ddi_remove_minor_node(dip, NULL);
3176007Sthurlow 		goto attach_failed;
3186007Sthurlow 	}
3196007Sthurlow 
3206007Sthurlow 	/*
3216007Sthurlow 	 * Need to see if this field is required.
3226007Sthurlow 	 * REVISIT
3236007Sthurlow 	 */
3246007Sthurlow 	sdp->smb_dip = dip;
3256007Sthurlow 	sdp->sd_seq = 0;
3266007Sthurlow 	sdp->sd_opened = 1;
3276007Sthurlow 
3286007Sthurlow 	mutex_exit(&dev_lck);
3296007Sthurlow 	ddi_report_dev(dip);
3306007Sthurlow 	return (DDI_SUCCESS);
3316007Sthurlow 
3326007Sthurlow attach_failed:
3336007Sthurlow 	ddi_soft_state_free(statep, 0);
3346007Sthurlow 	mutex_exit(&dev_lck);
3356007Sthurlow 	return (DDI_FAILURE);
3366007Sthurlow }
3376007Sthurlow 
3386007Sthurlow /*ARGSUSED*/
3396007Sthurlow static int
nsmb_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)3406007Sthurlow nsmb_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
3416007Sthurlow {
3426007Sthurlow 
3436007Sthurlow 	if (cmd != DDI_DETACH)
3446007Sthurlow 		return (DDI_FAILURE);
3456007Sthurlow 	if (ddi_get_instance(dip) > 0)
3466007Sthurlow 		return (DDI_FAILURE);
3476007Sthurlow 
3486007Sthurlow 	ddi_soft_state_free(statep, 0);
3496007Sthurlow 	ddi_remove_minor_node(dip, NULL);
3506007Sthurlow 
3516007Sthurlow 	return (DDI_SUCCESS);
3526007Sthurlow }
3536007Sthurlow 
3546007Sthurlow /*ARGSUSED*/
3556007Sthurlow static int
nsmb_ioctl(dev_t dev,int cmd,intptr_t arg,int flags,cred_t * cr,int * rvalp)35610023SGordon.Ross@Sun.COM nsmb_ioctl(dev_t dev, int cmd, intptr_t arg, int flags,	/* model.h */
35710023SGordon.Ross@Sun.COM 	cred_t *cr, int *rvalp)
3586007Sthurlow {
3596007Sthurlow 	smb_dev_t *sdp;
36010023SGordon.Ross@Sun.COM 	int err;
3616007Sthurlow 
3626007Sthurlow 	sdp = ddi_get_soft_state(statep, getminor(dev));
3636007Sthurlow 	if (sdp == NULL) {
3646007Sthurlow 		return (DDI_FAILURE);
3656007Sthurlow 	}
3666007Sthurlow 	if ((sdp->sd_flags & NSMBFL_OPEN) == 0) {
3676007Sthurlow 		return (EBADF);
3686007Sthurlow 	}
3696007Sthurlow 
3706007Sthurlow 	/*
3716007Sthurlow 	 * Dont give access if the zone id is not as the same as we
3726007Sthurlow 	 * set in the nsmb_open or dont belong to the global zone.
3736007Sthurlow 	 * Check if the user belongs to this zone..
3746007Sthurlow 	 */
3756007Sthurlow 	if (sdp->zoneid != getzoneid())
3766007Sthurlow 		return (EIO);
3776007Sthurlow 
37810023SGordon.Ross@Sun.COM 	/*
37910023SGordon.Ross@Sun.COM 	 * We have a zone_shutdown call back that kills all the VCs
38010023SGordon.Ross@Sun.COM 	 * in a zone that's shutting down.  That action will cause
38110023SGordon.Ross@Sun.COM 	 * all of these ioctls to fail on such VCs, so no need to
38210023SGordon.Ross@Sun.COM 	 * check the zone status here on every ioctl call.
38310023SGordon.Ross@Sun.COM 	 */
3846007Sthurlow 
38510023SGordon.Ross@Sun.COM 	err = 0;
38610023SGordon.Ross@Sun.COM 	switch (cmd) {
38710023SGordon.Ross@Sun.COM 	case SMBIOC_GETVERS:
388*11332SGordon.Ross@Sun.COM 		(void) ddi_copyout(&nsmb_version, (void *)arg,
38910023SGordon.Ross@Sun.COM 		    sizeof (nsmb_version), flags);
39010023SGordon.Ross@Sun.COM 		break;
3916007Sthurlow 
39210023SGordon.Ross@Sun.COM 	case SMBIOC_FLAGS2:
39310023SGordon.Ross@Sun.COM 		err = smb_usr_get_flags2(sdp, arg, flags);
39410023SGordon.Ross@Sun.COM 		break;
39510023SGordon.Ross@Sun.COM 
39610023SGordon.Ross@Sun.COM 	case SMBIOC_GETSSNKEY:
39710023SGordon.Ross@Sun.COM 		err = smb_usr_get_ssnkey(sdp, arg, flags);
39810023SGordon.Ross@Sun.COM 		break;
3996007Sthurlow 
40010023SGordon.Ross@Sun.COM 	case SMBIOC_REQUEST:
40110023SGordon.Ross@Sun.COM 		err = smb_usr_simplerq(sdp, arg, flags, cr);
40210023SGordon.Ross@Sun.COM 		break;
4036294Sbs135383 
40410023SGordon.Ross@Sun.COM 	case SMBIOC_T2RQ:
40510023SGordon.Ross@Sun.COM 		err = smb_usr_t2request(sdp, arg, flags, cr);
40610023SGordon.Ross@Sun.COM 		break;
40710023SGordon.Ross@Sun.COM 
40810023SGordon.Ross@Sun.COM 	case SMBIOC_READ:
40910023SGordon.Ross@Sun.COM 	case SMBIOC_WRITE:
41010023SGordon.Ross@Sun.COM 		err = smb_usr_rw(sdp, cmd, arg, flags, cr);
41110023SGordon.Ross@Sun.COM 		break;
4126007Sthurlow 
41310023SGordon.Ross@Sun.COM 	case SMBIOC_SSN_CREATE:
41410023SGordon.Ross@Sun.COM 	case SMBIOC_SSN_FIND:
41510023SGordon.Ross@Sun.COM 		err = smb_usr_get_ssn(sdp, cmd, arg, flags, cr);
41610023SGordon.Ross@Sun.COM 		break;
41710023SGordon.Ross@Sun.COM 
41810023SGordon.Ross@Sun.COM 	case SMBIOC_SSN_KILL:
41910023SGordon.Ross@Sun.COM 	case SMBIOC_SSN_RELE:
42010023SGordon.Ross@Sun.COM 		err = smb_usr_drop_ssn(sdp, cmd);
42110023SGordon.Ross@Sun.COM 		break;
42210023SGordon.Ross@Sun.COM 
42310023SGordon.Ross@Sun.COM 	case SMBIOC_TREE_CONNECT:
42410023SGordon.Ross@Sun.COM 	case SMBIOC_TREE_FIND:
42510023SGordon.Ross@Sun.COM 		err = smb_usr_get_tree(sdp, cmd, arg, flags, cr);
42610023SGordon.Ross@Sun.COM 		break;
42710023SGordon.Ross@Sun.COM 
42810023SGordon.Ross@Sun.COM 	case SMBIOC_TREE_KILL:
42910023SGordon.Ross@Sun.COM 	case SMBIOC_TREE_RELE:
43010023SGordon.Ross@Sun.COM 		err = smb_usr_drop_tree(sdp, cmd);
43110023SGordon.Ross@Sun.COM 		break;
4326007Sthurlow 
43310023SGordon.Ross@Sun.COM 	case SMBIOC_IOD_WORK:
43410023SGordon.Ross@Sun.COM 		err = smb_usr_iod_work(sdp, arg, flags, cr);
43510023SGordon.Ross@Sun.COM 		break;
43610023SGordon.Ross@Sun.COM 
43710023SGordon.Ross@Sun.COM 	case SMBIOC_IOD_IDLE:
43810023SGordon.Ross@Sun.COM 	case SMBIOC_IOD_RCFAIL:
43910023SGordon.Ross@Sun.COM 		err = smb_usr_iod_ioctl(sdp, cmd, arg, flags);
44010023SGordon.Ross@Sun.COM 		break;
4416007Sthurlow 
44210023SGordon.Ross@Sun.COM 	case SMBIOC_PK_ADD:
44310023SGordon.Ross@Sun.COM 	case SMBIOC_PK_DEL:
44410023SGordon.Ross@Sun.COM 	case SMBIOC_PK_CHK:
44510023SGordon.Ross@Sun.COM 	case SMBIOC_PK_DEL_OWNER:
44610023SGordon.Ross@Sun.COM 	case SMBIOC_PK_DEL_EVERYONE:
44710023SGordon.Ross@Sun.COM 		err = smb_pkey_ioctl(cmd, arg, flags, cr);
44810023SGordon.Ross@Sun.COM 		break;
4496007Sthurlow 
45010023SGordon.Ross@Sun.COM 	default:
45110023SGordon.Ross@Sun.COM 		err = ENOTTY;
45210023SGordon.Ross@Sun.COM 		break;
4536007Sthurlow 	}
4546007Sthurlow 
45510023SGordon.Ross@Sun.COM 	return (err);
4566007Sthurlow }
4576007Sthurlow 
4586007Sthurlow /*ARGSUSED*/
4596007Sthurlow static int
nsmb_open(dev_t * dev,int flags,int otyp,cred_t * cr)4606007Sthurlow nsmb_open(dev_t *dev, int flags, int otyp, cred_t *cr)
4616007Sthurlow {
4626007Sthurlow 	major_t new_major;
4636007Sthurlow 	smb_dev_t *sdp, *sdv;
4646007Sthurlow 
4656007Sthurlow 	mutex_enter(&dev_lck);
4666007Sthurlow 	for (; ; ) {
4676007Sthurlow 		minor_t start = nsmb_minor;
4686007Sthurlow 		do {
4696007Sthurlow 			if (nsmb_minor >= MAXMIN32) {
4706007Sthurlow 				if (nsmb_major == getmajor(*dev))
4716007Sthurlow 					nsmb_minor = NSMB_MIN_MINOR;
4726007Sthurlow 				else
4736007Sthurlow 					nsmb_minor = 0;
4746007Sthurlow 			} else {
4756007Sthurlow 				nsmb_minor++;
4766007Sthurlow 			}
4776007Sthurlow 			sdv = ddi_get_soft_state(statep, nsmb_minor);
4786007Sthurlow 		} while ((sdv != NULL) && (nsmb_minor != start));
4796007Sthurlow 		if (nsmb_minor == start) {
4806007Sthurlow 			/*
4816007Sthurlow 			 * The condition we need to solve here is  all the
4826007Sthurlow 			 * MAXMIN32(~262000) minors numbers are reached. We
4836007Sthurlow 			 * need to create a new major number.
4846007Sthurlow 			 * zfs uses getudev() to create a new major number.
4856007Sthurlow 			 */
4866007Sthurlow 			if ((new_major = getudev()) == (major_t)-1) {
4876007Sthurlow 				cmn_err(CE_WARN,
4886007Sthurlow 				    "nsmb: Can't get unique major "
4896007Sthurlow 				    "device number.");
4906007Sthurlow 				mutex_exit(&dev_lck);
4916007Sthurlow 				return (-1);
4926007Sthurlow 			}
4936007Sthurlow 			nsmb_major = new_major;
4946007Sthurlow 			nsmb_minor = 0;
4956007Sthurlow 		} else {
4966007Sthurlow 			break;
4976007Sthurlow 		}
4986007Sthurlow 	}
4996007Sthurlow 
5006007Sthurlow 	/*
5016007Sthurlow 	 * This is called by mount or open call.
5026007Sthurlow 	 * The open() routine is passed a pointer to a device number so
5036007Sthurlow 	 * that  the  driver  can  change the minor number. This allows
5046007Sthurlow 	 * drivers to dynamically  create minor instances of  the  dev-
5056007Sthurlow 	 * ice.  An  example of this might be a  pseudo-terminal driver
5066007Sthurlow 	 * that creates a new pseudo-terminal whenever it   is  opened.
5076007Sthurlow 	 * A driver that chooses the minor number dynamically, normally
5086007Sthurlow 	 * creates only one  minor  device  node  in   attach(9E)  with
5096007Sthurlow 	 * ddi_create_minor_node(9F) then changes the minor number com-
5106007Sthurlow 	 * ponent of *devp using makedevice(9F)  and  getmajor(9F)  The
5116007Sthurlow 	 * driver needs to keep track of available minor numbers inter-
5126007Sthurlow 	 * nally.
5136007Sthurlow 	 * Stuff the structure smb_dev.
5146007Sthurlow 	 * return.
5156007Sthurlow 	 */
5166007Sthurlow 
5176007Sthurlow 	if (ddi_soft_state_zalloc(statep, nsmb_minor) == DDI_FAILURE) {
5186007Sthurlow 		mutex_exit(&dev_lck);
5196007Sthurlow 		return (ENXIO);
5206007Sthurlow 	}
5216007Sthurlow 	if ((sdp = ddi_get_soft_state(statep, nsmb_minor)) == NULL) {
5226007Sthurlow 		mutex_exit(&dev_lck);
5236007Sthurlow 		return (ENXIO);
5246007Sthurlow 	}
5256007Sthurlow 
5266007Sthurlow 	sdp->sd_opened = 1;
5276007Sthurlow 	sdp->sd_seq = nsmb_minor;
5286007Sthurlow 	sdp->smb_cred = cr;
5296007Sthurlow 	sdp->sd_flags |= NSMBFL_OPEN;
5306007Sthurlow 	sdp->zoneid = crgetzoneid(cr);
5316007Sthurlow 	mutex_exit(&dev_lck);
5326007Sthurlow 
5336007Sthurlow 	*dev = makedevice(nsmb_major, nsmb_minor);
5346007Sthurlow 
5356007Sthurlow 	return (0);
5366007Sthurlow }
5376007Sthurlow 
5386007Sthurlow /*ARGSUSED*/
5396007Sthurlow static int
nsmb_close(dev_t dev,int flags,int otyp,cred_t * cr)5406007Sthurlow nsmb_close(dev_t dev, int flags, int otyp, cred_t *cr)
5416007Sthurlow {
5426007Sthurlow 	minor_t inst = getminor(dev);
5436007Sthurlow 	smb_dev_t *sdp;
54410023SGordon.Ross@Sun.COM 	int err;
5456007Sthurlow 
5466007Sthurlow 	mutex_enter(&dev_lck);
5476007Sthurlow 	/*
5486007Sthurlow 	 * 1. Check the validity of the minor number.
5496007Sthurlow 	 * 2. Release any shares/vc associated  with the connection.
5506007Sthurlow 	 * 3. Can close the minor number.
5516007Sthurlow 	 * 4. Deallocate any resources allocated in open() call.
5526007Sthurlow 	 */
5536007Sthurlow 
5546007Sthurlow 	sdp = ddi_get_soft_state(statep, inst);
55510023SGordon.Ross@Sun.COM 	if (sdp != NULL)
55610023SGordon.Ross@Sun.COM 		err = nsmb_close2(sdp, cr);
55710023SGordon.Ross@Sun.COM 	else
55810023SGordon.Ross@Sun.COM 		err = ENXIO;
5596007Sthurlow 
5606007Sthurlow 	/*
56110023SGordon.Ross@Sun.COM 	 * Free the instance
5626007Sthurlow 	 */
56310023SGordon.Ross@Sun.COM 	ddi_soft_state_free(statep, inst);
56410023SGordon.Ross@Sun.COM 	mutex_exit(&dev_lck);
56510023SGordon.Ross@Sun.COM 	return (err);
56610023SGordon.Ross@Sun.COM }
56710023SGordon.Ross@Sun.COM 
56810023SGordon.Ross@Sun.COM static int
nsmb_close2(smb_dev_t * sdp,cred_t * cr)56910023SGordon.Ross@Sun.COM nsmb_close2(smb_dev_t *sdp, cred_t *cr)
57010023SGordon.Ross@Sun.COM {
57110023SGordon.Ross@Sun.COM 	struct smb_vc *vcp;
57210023SGordon.Ross@Sun.COM 	struct smb_share *ssp;
57310023SGordon.Ross@Sun.COM 	struct smb_cred scred;
57410023SGordon.Ross@Sun.COM 
57510023SGordon.Ross@Sun.COM 	smb_credinit(&scred, cr);
5766007Sthurlow 	ssp = sdp->sd_share;
5776007Sthurlow 	if (ssp != NULL)
5786007Sthurlow 		smb_share_rele(ssp);
5796007Sthurlow 	vcp = sdp->sd_vc;
5806007Sthurlow 	if (vcp != NULL) {
5816007Sthurlow 		/*
58210023SGordon.Ross@Sun.COM 		 * If this dev minor was opened by smbiod,
58310023SGordon.Ross@Sun.COM 		 * mark this VC as "dead" because it now
58410023SGordon.Ross@Sun.COM 		 * will have no IOD to service it.
5856007Sthurlow 		 */
58610023SGordon.Ross@Sun.COM 		if (sdp->sd_flags & NSMBFL_IOD)
5877431SGordon.Ross@Sun.COM 			smb_iod_disconnect(vcp);
5886007Sthurlow 		smb_vc_rele(vcp);
5896007Sthurlow 	}
59010023SGordon.Ross@Sun.COM 
5916007Sthurlow 	smb_credrele(&scred);
5926007Sthurlow 	return (0);
5936007Sthurlow }
5946007Sthurlow 
5956007Sthurlow int
smb_dev2share(int fd,struct smb_share ** sspp)5966007Sthurlow smb_dev2share(int fd, struct smb_share **sspp)
5976007Sthurlow {
59810023SGordon.Ross@Sun.COM 	file_t *fp = NULL;
59910023SGordon.Ross@Sun.COM 	vnode_t *vp;
6006007Sthurlow 	smb_dev_t *sdp;
60110023SGordon.Ross@Sun.COM 	smb_share_t *ssp;
6026007Sthurlow 	dev_t dev;
60310023SGordon.Ross@Sun.COM 	int err;
6046007Sthurlow 
6056007Sthurlow 	if ((fp = getf(fd)) == NULL)
60610023SGordon.Ross@Sun.COM 		return (EBADF);
60710023SGordon.Ross@Sun.COM 
6086007Sthurlow 	vp = fp->f_vnode;
6096007Sthurlow 	dev = vp->v_rdev;
61010023SGordon.Ross@Sun.COM 	if (dev == 0 || dev == NODEV ||
61110023SGordon.Ross@Sun.COM 	    getmajor(dev) != nsmb_major) {
61210023SGordon.Ross@Sun.COM 		err = EBADF;
61310023SGordon.Ross@Sun.COM 		goto out;
6146007Sthurlow 	}
61510023SGordon.Ross@Sun.COM 
6166007Sthurlow 	sdp = ddi_get_soft_state(statep, getminor(dev));
6176007Sthurlow 	if (sdp == NULL) {
61810023SGordon.Ross@Sun.COM 		err = EINVAL;
61910023SGordon.Ross@Sun.COM 		goto out;
6206007Sthurlow 	}
62110023SGordon.Ross@Sun.COM 
6226007Sthurlow 	ssp = sdp->sd_share;
6236007Sthurlow 	if (ssp == NULL) {
62410023SGordon.Ross@Sun.COM 		err = ENOTCONN;
62510023SGordon.Ross@Sun.COM 		goto out;
6266007Sthurlow 	}
62710023SGordon.Ross@Sun.COM 
6286007Sthurlow 	/*
62910023SGordon.Ross@Sun.COM 	 * Our caller gains a ref. to this share.
6306007Sthurlow 	 */
6316007Sthurlow 	*sspp = ssp;
63210023SGordon.Ross@Sun.COM 	smb_share_hold(ssp);
63310023SGordon.Ross@Sun.COM 	err = 0;
63410023SGordon.Ross@Sun.COM 
63510023SGordon.Ross@Sun.COM out:
63610023SGordon.Ross@Sun.COM 	if (fp)
63710023SGordon.Ross@Sun.COM 		releasef(fd);
63810023SGordon.Ross@Sun.COM 	return (err);
6396007Sthurlow }
640