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