xref: /onnv-gate/usr/src/uts/common/fs/smbsrv/smb_server.c (revision 12890:16985853e3aa)
16139Sjb150015 /*
26139Sjb150015  * CDDL HEADER START
36139Sjb150015  *
46139Sjb150015  * The contents of this file are subject to the terms of the
56139Sjb150015  * Common Development and Distribution License (the "License").
66139Sjb150015  * You may not use this file except in compliance with the License.
76139Sjb150015  *
86139Sjb150015  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
96139Sjb150015  * or http://www.opensolaris.org/os/licensing.
106139Sjb150015  * See the License for the specific language governing permissions
116139Sjb150015  * and limitations under the License.
126139Sjb150015  *
136139Sjb150015  * When distributing Covered Code, include this CDDL HEADER in each
146139Sjb150015  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
156139Sjb150015  * If applicable, add the following below this CDDL HEADER, with the
166139Sjb150015  * fields enclosed by brackets "[]" replaced with your own identifying
176139Sjb150015  * information: Portions Copyright [yyyy] [name of copyright owner]
186139Sjb150015  *
196139Sjb150015  * CDDL HEADER END
206139Sjb150015  */
216139Sjb150015 /*
2212065SKeyur.Desai@Sun.COM  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
236139Sjb150015  */
246139Sjb150015 
256139Sjb150015 /*
266139Sjb150015  * General Structures Layout
276139Sjb150015  * -------------------------
286139Sjb150015  *
296139Sjb150015  * This is a simplified diagram showing the relationship between most of the
306139Sjb150015  * main structures.
316139Sjb150015  *
326139Sjb150015  * +-------------------+
336139Sjb150015  * |     SMB_SERVER    |
346139Sjb150015  * +-------------------+
356139Sjb150015  *          |
366139Sjb150015  *          |
376139Sjb150015  *          v
386139Sjb150015  * +-------------------+       +-------------------+      +-------------------+
396139Sjb150015  * |     SESSION       |<----->|     SESSION       |......|      SESSION      |
406139Sjb150015  * +-------------------+       +-------------------+      +-------------------+
416139Sjb150015  *          |
426139Sjb150015  *          |
436139Sjb150015  *          v
446139Sjb150015  * +-------------------+       +-------------------+      +-------------------+
456139Sjb150015  * |       USER        |<----->|       USER        |......|       USER        |
466139Sjb150015  * +-------------------+       +-------------------+      +-------------------+
476139Sjb150015  *          |
486139Sjb150015  *          |
496139Sjb150015  *          v
506139Sjb150015  * +-------------------+       +-------------------+      +-------------------+
516139Sjb150015  * |       TREE        |<----->|       TREE        |......|       TREE        |
526139Sjb150015  * +-------------------+       +-------------------+      +-------------------+
536139Sjb150015  *      |         |
546139Sjb150015  *      |         |
556139Sjb150015  *      |         v
566139Sjb150015  *      |     +-------+       +-------+      +-------+
576139Sjb150015  *      |     | OFILE |<----->| OFILE |......| OFILE |
586139Sjb150015  *      |     +-------+       +-------+      +-------+
596139Sjb150015  *      |
606139Sjb150015  *      |
616139Sjb150015  *      v
626139Sjb150015  *  +-------+       +------+      +------+
636139Sjb150015  *  | ODIR  |<----->| ODIR |......| ODIR |
646139Sjb150015  *  +-------+       +------+      +------+
656139Sjb150015  *
666139Sjb150015  *
676139Sjb150015  * Module Interface Overview
686139Sjb150015  * -------------------------
696139Sjb150015  *
706139Sjb150015  *
716139Sjb150015  *	    +===================================+
726139Sjb150015  *	    |		 smbd daemon		|
736139Sjb150015  *	    +===================================+
746139Sjb150015  *	      |		     |		      ^
756139Sjb150015  *	      |		     |		      |
766139Sjb150015  * User	      |		     |		      |
776139Sjb150015  * -----------|--------------|----------------|--------------------------------
786139Sjb150015  * Kernel     |		     |		      |
796139Sjb150015  *            |		     |		      |
806139Sjb150015  *	      |		     |		      |
816139Sjb150015  *  +=========|==============|================|=================+
826139Sjb150015  *  |	      v		     v		      |			|
836139Sjb150015  *  | +-----------+ +--------------------+ +------------------+ |
846139Sjb150015  *  | |     IO    | | Kernel Door Server | | User Door Servers|	|
856139Sjb150015  *  | | Interface | |     Interface      | |   Interface      | |
866139Sjb150015  *  | +-----------+ +--------------------+ +------------------+ |
876139Sjb150015  *  |		|	     |		      ^		^	|
886139Sjb150015  *  |		v	     v		      |		|	|    +=========+
896139Sjb150015  *  |	     +-----------------------------------+	|	|    |	       |
906139Sjb150015  *  |	     + SMB Server Management (this file) |<------------------|	 ZFS   |
916139Sjb150015  *  |	     +-----------------------------------+	|	|    |	       |
926139Sjb150015  *  |							|	|    |  Module |
936139Sjb150015  *  |	     +-----------------------------------+	|	|    |	       |
946139Sjb150015  *  |	     +     SMB Server Internal Layers    |------+	|    +=========+
956139Sjb150015  *  |	     +-----------------------------------+		|
966139Sjb150015  *  |								|
976139Sjb150015  *  |								|
986139Sjb150015  *  +===========================================================+
996139Sjb150015  *
1006139Sjb150015  *
1016139Sjb150015  * Server State Machine
1026139Sjb150015  * --------------------
1036139Sjb150015  *                                  |
1046139Sjb150015  *                                  | T0
1056139Sjb150015  *                                  |
1066139Sjb150015  *                                  v
1076139Sjb150015  *                    +-----------------------------+
1086139Sjb150015  *		      |   SMB_SERVER_STATE_CREATED  |
1096139Sjb150015  *		      +-----------------------------+
1106139Sjb150015  *				    |
1116139Sjb150015  *				    | T1
1126139Sjb150015  *				    |
1136139Sjb150015  *				    v
1146139Sjb150015  *		      +-----------------------------+
1156139Sjb150015  *		      | SMB_SERVER_STATE_CONFIGURED |
1166139Sjb150015  *		      +-----------------------------+
1176139Sjb150015  *				    |
1186139Sjb150015  *				    | T2
1196139Sjb150015  *				    |
1206139Sjb150015  *				    v
1216139Sjb150015  *		      +-----------------------------+
12211963SAfshin.Ardakani@Sun.COM  *		      |  SMB_SERVER_STATE_RUNNING / |
12311963SAfshin.Ardakani@Sun.COM  *		      |  SMB_SERVER_STATE_STOPPING  |
1246139Sjb150015  *		      +-----------------------------+
1256139Sjb150015  *				    |
1266139Sjb150015  *				    | T3
1276139Sjb150015  *				    |
1286139Sjb150015  *				    v
1296139Sjb150015  *		      +-----------------------------+
1306139Sjb150015  *		      |  SMB_SERVER_STATE_DELETING  |
1316139Sjb150015  *                    +-----------------------------+
1326139Sjb150015  *				    |
1336139Sjb150015  *				    |
1346139Sjb150015  *				    |
1356139Sjb150015  *				    v
1366139Sjb150015  *
1376139Sjb150015  * States
1386139Sjb150015  * ------
1396139Sjb150015  *
1406139Sjb150015  * SMB_SERVER_STATE_CREATED
1416139Sjb150015  *
1426139Sjb150015  *    This is the state of the server just after creation.
1436139Sjb150015  *
1446139Sjb150015  * SMB_SERVER_STATE_CONFIGURED
1456139Sjb150015  *
1466139Sjb150015  *    The server has been configured.
1476139Sjb150015  *
1486139Sjb150015  * SMB_SERVER_STATE_RUNNING
1496139Sjb150015  *
1506139Sjb150015  *    The server has been started. While in this state the threads listening on
1516139Sjb150015  *    the sockets car be started. The smbd daemon does so through an Ioctl:
1526139Sjb150015  *
1536139Sjb150015  *	smb_drv_ioctl(SMB_IOC_NBT_LISTEN) --> smb_server_nbt_listen()
1546139Sjb150015  *	smb_drv_ioctl(SMB_IOC_TCP_LISTEN) --> smb_server_nbt_listen()
1556139Sjb150015  *
1566139Sjb150015  *    When a client establishes a connection the thread listening leaves
1576139Sjb150015  *    temporarily the kernel. While in user space it creates a thread for the
1586139Sjb150015  *    new session. It then returns to kernel with the result of the thread
1596139Sjb150015  *    creation. If the creation failed the new session context is destroyed
1606139Sjb150015  *    before returning listening.
1616139Sjb150015  *
1626139Sjb150015  *    The new created thread enters the kernel though an Ioctl:
1636139Sjb150015  *
1646139Sjb150015  *	smb_drv_ioctl(SMB_IOC_NBT_RECEIVE) --> smb_server_nbt_receive()
1656139Sjb150015  *	smb_drv_ioctl(SMB_IOC_TCP_RECEIVE) --> smb_server_tcp_receive()
1666139Sjb150015  *
1676139Sjb150015  * SMB_SERVER_STATE_STOPPING
1686139Sjb150015  *
1696139Sjb150015  *    The threads listening on the NBT and TCP sockets are being terminated.
1706139Sjb150015  *
1716139Sjb150015  *
1726139Sjb150015  * Transitions
1736139Sjb150015  * -----------
1746139Sjb150015  *
1756139Sjb150015  * Transition T0
1766139Sjb150015  *
1776139Sjb150015  *    The daemon smbd triggers its creation by opening the smbsrv device. If
1786139Sjb150015  *    the zone where the daemon lives doesn't have an smb server yet it is
1796139Sjb150015  *    created.
1806139Sjb150015  *
1816139Sjb150015  *		smb_drv_open() --> smb_server_create()
1826139Sjb150015  *
1836139Sjb150015  * Transition T1
1846139Sjb150015  *
1856139Sjb150015  *    This transition occurs in smb_server_configure(). It is triggered by the
1866139Sjb150015  *    daemon through an Ioctl.
1876139Sjb150015  *
1886139Sjb150015  *	smb_drv_ioctl(SMB_IOC_CONFIG) --> smb_server_configure()
1896139Sjb150015  *
1906139Sjb150015  * Transition T2
1916139Sjb150015  *
1926139Sjb150015  *    This transition occurs in smb_server_start(). It is triggered by the
1936139Sjb150015  *    daemon through an Ioctl.
1946139Sjb150015  *
1956139Sjb150015  *	smb_drv_ioctl(SMB_IOC_START) --> smb_server_start()
1966139Sjb150015  *
1976139Sjb150015  * Transition T3
1986139Sjb150015  *
1996139Sjb150015  *    This transition occurs in smb_server_delete(). It is triggered by the
2006139Sjb150015  *    daemon when closing the smbsrv device
2016139Sjb150015  *
2026139Sjb150015  *		smb_drv_close() --> smb_server_delete()
2036139Sjb150015  *
2046139Sjb150015  * Comments
2056139Sjb150015  * --------
2066139Sjb150015  *
2076139Sjb150015  * This files assumes that there will one SMB server per zone. For now the
2086139Sjb150015  * smb server works only in global zone. There's nothing in this file preventing
2096139Sjb150015  * an smb server from being created in a non global zone. That limitation is
2106139Sjb150015  * enforced in user space.
2116139Sjb150015  */
2126139Sjb150015 
2136139Sjb150015 #include <sys/strsubr.h>
2146139Sjb150015 #include <sys/cmn_err.h>
2156139Sjb150015 #include <sys/priv.h>
2166139Sjb150015 #include <sys/socketvar.h>
2176139Sjb150015 #include <sys/zone.h>
21810966SJordan.Brown@Sun.COM #include <netinet/in.h>
21910966SJordan.Brown@Sun.COM #include <netinet/in_systm.h>
22010966SJordan.Brown@Sun.COM #include <netinet/ip.h>
22110966SJordan.Brown@Sun.COM #include <netinet/ip_icmp.h>
22210966SJordan.Brown@Sun.COM #include <netinet/ip_var.h>
22310966SJordan.Brown@Sun.COM #include <netinet/tcp.h>
2246139Sjb150015 #include <smbsrv/smb_kproto.h>
22510966SJordan.Brown@Sun.COM #include <smbsrv/string.h>
2266139Sjb150015 #include <smbsrv/netbios.h>
2276139Sjb150015 #include <smbsrv/smb_fsops.h>
2287052Samw #include <smbsrv/smb_share.h>
22911963SAfshin.Ardakani@Sun.COM #include <smbsrv/smb_door.h>
2306432Sas200622 #include <smbsrv/smb_kstat.h>
2316139Sjb150015 
2326139Sjb150015 extern void smb_reply_notify_change_request(smb_request_t *);
2336139Sjb150015 
23412508Samw@Sun.COM static void smb_server_kstat_init(smb_server_t *);
2356139Sjb150015 static void smb_server_kstat_fini(smb_server_t *);
2366139Sjb150015 static void smb_server_timers(smb_thread_t *, void *);
2376139Sjb150015 static int smb_server_listen(smb_server_t *, smb_listener_daemon_t *,
2388670SJose.Borrego@Sun.COM     in_port_t, int, int);
23911963SAfshin.Ardakani@Sun.COM static void smb_server_listen_fini(smb_listener_daemon_t *);
24011963SAfshin.Ardakani@Sun.COM static kt_did_t smb_server_listener_tid(smb_listener_daemon_t *);
2416139Sjb150015 static int smb_server_lookup(smb_server_t **);
2426139Sjb150015 static void smb_server_release(smb_server_t *);
2439832Samw@Sun.COM static void smb_server_store_cfg(smb_server_t *, smb_ioc_cfg_t *);
24411963SAfshin.Ardakani@Sun.COM static void smb_server_shutdown(smb_server_t *);
2456139Sjb150015 static int smb_server_fsop_start(smb_server_t *);
2466139Sjb150015 static void smb_server_fsop_stop(smb_server_t *);
24711963SAfshin.Ardakani@Sun.COM static void smb_server_signal_listeners(smb_server_t *);
24811963SAfshin.Ardakani@Sun.COM static void smb_event_cancel(smb_server_t *, uint32_t);
24911963SAfshin.Ardakani@Sun.COM static uint32_t smb_event_alloc_txid(void);
2506139Sjb150015 
25111963SAfshin.Ardakani@Sun.COM static void smb_server_disconnect_share(smb_session_list_t *, const char *);
25210122SJordan.Brown@Sun.COM static void smb_server_enum_private(smb_session_list_t *, smb_svcenum_t *);
25310122SJordan.Brown@Sun.COM static int smb_server_sesion_disconnect(smb_session_list_t *, const char *,
25410122SJordan.Brown@Sun.COM     const char *);
25510122SJordan.Brown@Sun.COM static int smb_server_fclose(smb_session_list_t *, uint32_t);
25612508Samw@Sun.COM static int smb_server_kstat_update(kstat_t *, int);
257*12890SJoyce.McIntosh@Sun.COM static int smb_server_legacy_kstat_update(kstat_t *, int);
25810122SJordan.Brown@Sun.COM 
25911963SAfshin.Ardakani@Sun.COM int smb_event_debug = 0;
26011963SAfshin.Ardakani@Sun.COM 
2616139Sjb150015 static smb_llist_t	smb_servers;
2626139Sjb150015 
2636139Sjb150015 /*
2646139Sjb150015  * *****************************************************************************
2656139Sjb150015  * **************** Functions called from the device interface *****************
2666139Sjb150015  * *****************************************************************************
2676139Sjb150015  *
26810122SJordan.Brown@Sun.COM  * These functions typically have to determine the relevant smb server
26910122SJordan.Brown@Sun.COM  * to which the call applies.
2706139Sjb150015  */
2716139Sjb150015 
2726139Sjb150015 /*
2736139Sjb150015  * smb_server_svc_init
2746139Sjb150015  *
2757348SJose.Borrego@Sun.COM  * This function must be called from smb_drv_attach().
2766139Sjb150015  */
2776139Sjb150015 int
2786139Sjb150015 smb_server_svc_init(void)
2796139Sjb150015 {
2806139Sjb150015 	int	rc = 0;
2816139Sjb150015 
2826139Sjb150015 	while (rc == 0) {
2838934SJose.Borrego@Sun.COM 		if (rc = smb_mbc_init())
2848934SJose.Borrego@Sun.COM 			continue;
2856139Sjb150015 		if (rc = smb_vop_init())
2866139Sjb150015 			continue;
2876139Sjb150015 		if (rc = smb_node_init())
2886496Sjb150015 			continue;
289*12890SJoyce.McIntosh@Sun.COM 		if (rc = smb_oplock_init())
290*12890SJoyce.McIntosh@Sun.COM 			continue;
2916139Sjb150015 		if (rc = smb_fem_init())
2926496Sjb150015 			continue;
2936139Sjb150015 		if (rc = smb_notify_init())
2946496Sjb150015 			continue;
2956496Sjb150015 		if (rc = smb_net_init())
2966496Sjb150015 			continue;
29711963SAfshin.Ardakani@Sun.COM 		smb_llist_init();
2986139Sjb150015 		smb_llist_constructor(&smb_servers, sizeof (smb_server_t),
2996139Sjb150015 		    offsetof(smb_server_t, sv_lnd));
3006139Sjb150015 		return (0);
3016139Sjb150015 	}
30211963SAfshin.Ardakani@Sun.COM 
30311963SAfshin.Ardakani@Sun.COM 	smb_llist_fini();
3046496Sjb150015 	smb_net_fini();
3056139Sjb150015 	smb_notify_fini();
3066139Sjb150015 	smb_fem_fini();
3076139Sjb150015 	smb_node_fini();
3086139Sjb150015 	smb_vop_fini();
3098934SJose.Borrego@Sun.COM 	smb_mbc_fini();
3106139Sjb150015 	return (rc);
3116139Sjb150015 }
3126139Sjb150015 
3136139Sjb150015 /*
3146139Sjb150015  * smb_server_svc_fini
3156139Sjb150015  *
3166139Sjb150015  * This function must called from smb_drv_detach(). It will fail if servers
3176139Sjb150015  * still exist.
3186139Sjb150015  */
3196139Sjb150015 int
3206139Sjb150015 smb_server_svc_fini(void)
3216139Sjb150015 {
3226139Sjb150015 	int	rc = EBUSY;
3236139Sjb150015 
3246139Sjb150015 	if (smb_llist_get_count(&smb_servers) == 0) {
32511963SAfshin.Ardakani@Sun.COM 		smb_llist_fini();
3266496Sjb150015 		smb_net_fini();
3276139Sjb150015 		smb_notify_fini();
3286139Sjb150015 		smb_fem_fini();
3296139Sjb150015 		smb_node_fini();
330*12890SJoyce.McIntosh@Sun.COM 		smb_oplock_fini();
3316139Sjb150015 		smb_vop_fini();
3328934SJose.Borrego@Sun.COM 		smb_mbc_fini();
3336139Sjb150015 		smb_llist_destructor(&smb_servers);
3346139Sjb150015 		rc = 0;
3356139Sjb150015 	}
3366139Sjb150015 	return (rc);
3376139Sjb150015 }
3386139Sjb150015 
3396139Sjb150015 /*
3406139Sjb150015  * smb_server_create
3416139Sjb150015  *
3426139Sjb150015  * This function will fail if there's already a server associated with the
3436139Sjb150015  * caller's zone.
3446139Sjb150015  */
3456139Sjb150015 int
3466139Sjb150015 smb_server_create(void)
3476139Sjb150015 {
3486139Sjb150015 	zoneid_t	zid;
3496139Sjb150015 	smb_server_t	*sv;
3506139Sjb150015 
3516139Sjb150015 	zid = getzoneid();
3526139Sjb150015 
3536139Sjb150015 	smb_llist_enter(&smb_servers, RW_WRITER);
3546139Sjb150015 	sv = smb_llist_head(&smb_servers);
3556139Sjb150015 	while (sv) {
35611963SAfshin.Ardakani@Sun.COM 		SMB_SERVER_VALID(sv);
3576139Sjb150015 		if (sv->sv_zid == zid) {
3586139Sjb150015 			smb_llist_exit(&smb_servers);
3598167Samw@Sun.COM 			return (EPERM);
3606139Sjb150015 		}
3616139Sjb150015 		sv = smb_llist_next(&smb_servers, sv);
3626139Sjb150015 	}
3636139Sjb150015 
3646139Sjb150015 	sv = kmem_zalloc(sizeof (smb_server_t), KM_NOSLEEP);
3656139Sjb150015 	if (sv == NULL) {
3666139Sjb150015 		smb_llist_exit(&smb_servers);
3676139Sjb150015 		return (ENOMEM);
3686139Sjb150015 	}
3696139Sjb150015 
37011963SAfshin.Ardakani@Sun.COM 	smb_llist_constructor(&sv->sv_opipe_list, sizeof (smb_opipe_t),
37111963SAfshin.Ardakani@Sun.COM 	    offsetof(smb_opipe_t, p_lnd));
37211963SAfshin.Ardakani@Sun.COM 
37311963SAfshin.Ardakani@Sun.COM 	smb_llist_constructor(&sv->sv_event_list, sizeof (smb_event_t),
37411963SAfshin.Ardakani@Sun.COM 	    offsetof(smb_event_t, se_lnd));
37511963SAfshin.Ardakani@Sun.COM 
376*12890SJoyce.McIntosh@Sun.COM 	smb_llist_constructor(&sv->sp_info.sp_list, sizeof (smb_kspooldoc_t),
377*12890SJoyce.McIntosh@Sun.COM 	    offsetof(smb_kspooldoc_t, sd_lnd));
378*12890SJoyce.McIntosh@Sun.COM 
379*12890SJoyce.McIntosh@Sun.COM 	smb_llist_constructor(&sv->sp_info.sp_fidlist,
380*12890SJoyce.McIntosh@Sun.COM 	    sizeof (smb_spoolfid_t), offsetof(smb_spoolfid_t, sf_lnd));
381*12890SJoyce.McIntosh@Sun.COM 
3826139Sjb150015 	smb_session_list_constructor(&sv->sv_nbt_daemon.ld_session_list);
3836139Sjb150015 	smb_session_list_constructor(&sv->sv_tcp_daemon.ld_session_list);
3846139Sjb150015 
3856139Sjb150015 	sv->si_cache_request = kmem_cache_create("smb_request_cache",
3866139Sjb150015 	    sizeof (smb_request_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
3876139Sjb150015 	sv->si_cache_session = kmem_cache_create("smb_session_cache",
3886139Sjb150015 	    sizeof (smb_session_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
3896139Sjb150015 	sv->si_cache_user = kmem_cache_create("smb_user_cache",
3906139Sjb150015 	    sizeof (smb_user_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
3916139Sjb150015 	sv->si_cache_tree = kmem_cache_create("smb_tree_cache",
3926139Sjb150015 	    sizeof (smb_tree_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
3936139Sjb150015 	sv->si_cache_ofile = kmem_cache_create("smb_ofile_cache",
3946139Sjb150015 	    sizeof (smb_ofile_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
3956139Sjb150015 	sv->si_cache_odir = kmem_cache_create("smb_odir_cache",
3966139Sjb150015 	    sizeof (smb_odir_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
39711963SAfshin.Ardakani@Sun.COM 	sv->si_cache_opipe = kmem_cache_create("smb_opipe_cache",
39811963SAfshin.Ardakani@Sun.COM 	    sizeof (smb_opipe_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
39911963SAfshin.Ardakani@Sun.COM 	sv->si_cache_event = kmem_cache_create("smb_event_cache",
40011963SAfshin.Ardakani@Sun.COM 	    sizeof (smb_event_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
4016139Sjb150015 
4026139Sjb150015 	smb_thread_init(&sv->si_thread_timers,
4036139Sjb150015 	    "smb_timers", smb_server_timers, sv,
4046139Sjb150015 	    NULL, NULL);
4056139Sjb150015 
4066432Sas200622 	sv->sv_pid = curproc->p_pid;
40712508Samw@Sun.COM 	smb_srqueue_init(&sv->sv_srqueue);
4086139Sjb150015 
40911963SAfshin.Ardakani@Sun.COM 	smb_kdoor_init();
4107052Samw 	smb_opipe_door_init();
41112508Samw@Sun.COM 	smb_server_kstat_init(sv);
4126139Sjb150015 
4136139Sjb150015 	mutex_init(&sv->sv_mutex, NULL, MUTEX_DEFAULT, NULL);
414*12890SJoyce.McIntosh@Sun.COM 	mutex_init(&sv->sp_info.sp_mutex, NULL, MUTEX_DEFAULT, NULL);
4156139Sjb150015 	cv_init(&sv->sv_cv, NULL, CV_DEFAULT, NULL);
416*12890SJoyce.McIntosh@Sun.COM 	cv_init(&sv->sp_info.sp_cv, NULL, CV_DEFAULT, NULL);
417*12890SJoyce.McIntosh@Sun.COM 
4186139Sjb150015 	sv->sv_state = SMB_SERVER_STATE_CREATED;
4196139Sjb150015 	sv->sv_magic = SMB_SERVER_MAGIC;
4206139Sjb150015 	sv->sv_zid = zid;
4216139Sjb150015 
4226139Sjb150015 	smb_llist_insert_tail(&smb_servers, sv);
4236139Sjb150015 	smb_llist_exit(&smb_servers);
424*12890SJoyce.McIntosh@Sun.COM 
425*12890SJoyce.McIntosh@Sun.COM 	smb_threshold_init(&sv->sv_ssetup_ct, SMB_SSETUP_CMD,
426*12890SJoyce.McIntosh@Sun.COM 	    smb_ssetup_threshold, smb_ssetup_timeout);
427*12890SJoyce.McIntosh@Sun.COM 	smb_threshold_init(&sv->sv_tcon_ct, SMB_TCON_CMD, smb_tcon_threshold,
428*12890SJoyce.McIntosh@Sun.COM 	    smb_tcon_timeout);
429*12890SJoyce.McIntosh@Sun.COM 	smb_threshold_init(&sv->sv_opipe_ct, SMB_OPIPE_CMD, smb_opipe_threshold,
430*12890SJoyce.McIntosh@Sun.COM 	    smb_opipe_timeout);
431*12890SJoyce.McIntosh@Sun.COM 
4326139Sjb150015 	return (0);
4336139Sjb150015 }
4346139Sjb150015 
4356139Sjb150015 /*
4366139Sjb150015  * smb_server_delete
4376139Sjb150015  *
4386139Sjb150015  * This function will delete the server passed in. It will make sure that all
4396139Sjb150015  * activity associated that server has ceased before destroying it.
4406139Sjb150015  */
4416139Sjb150015 int
4426139Sjb150015 smb_server_delete(void)
4436139Sjb150015 {
4446139Sjb150015 	smb_server_t	*sv;
44511963SAfshin.Ardakani@Sun.COM 	kt_did_t	nbt_tid;
44611963SAfshin.Ardakani@Sun.COM 	kt_did_t	tcp_tid;
4476139Sjb150015 	int		rc;
4486139Sjb150015 
4496139Sjb150015 	rc = smb_server_lookup(&sv);
4506139Sjb150015 	if (rc != 0)
4516139Sjb150015 		return (rc);
4526139Sjb150015 
453*12890SJoyce.McIntosh@Sun.COM 	smb_threshold_fini(&sv->sv_ssetup_ct);
454*12890SJoyce.McIntosh@Sun.COM 	smb_threshold_fini(&sv->sv_tcon_ct);
455*12890SJoyce.McIntosh@Sun.COM 	smb_threshold_fini(&sv->sv_opipe_ct);
456*12890SJoyce.McIntosh@Sun.COM 
4576139Sjb150015 	mutex_enter(&sv->sv_mutex);
4586139Sjb150015 	switch (sv->sv_state) {
4596139Sjb150015 	case SMB_SERVER_STATE_RUNNING:
46011963SAfshin.Ardakani@Sun.COM 	case SMB_SERVER_STATE_STOPPING:
46111963SAfshin.Ardakani@Sun.COM 		sv->sv_state = SMB_SERVER_STATE_STOPPING;
46211963SAfshin.Ardakani@Sun.COM 		smb_server_signal_listeners(sv);
46311963SAfshin.Ardakani@Sun.COM 		nbt_tid = smb_server_listener_tid(&sv->sv_nbt_daemon);
46411963SAfshin.Ardakani@Sun.COM 		tcp_tid = smb_server_listener_tid(&sv->sv_tcp_daemon);
465*12890SJoyce.McIntosh@Sun.COM 		cv_broadcast(&sv->sp_info.sp_cv);
4666139Sjb150015 
4676139Sjb150015 		sv->sv_state = SMB_SERVER_STATE_DELETING;
4686139Sjb150015 		mutex_exit(&sv->sv_mutex);
46911963SAfshin.Ardakani@Sun.COM 
47011963SAfshin.Ardakani@Sun.COM 		if (nbt_tid != 0)
47111963SAfshin.Ardakani@Sun.COM 			thread_join(nbt_tid);
47211963SAfshin.Ardakani@Sun.COM 		if (tcp_tid != 0)
47311963SAfshin.Ardakani@Sun.COM 			thread_join(tcp_tid);
47411963SAfshin.Ardakani@Sun.COM 
47511963SAfshin.Ardakani@Sun.COM 		smb_server_listen_fini(&sv->sv_nbt_daemon);
47611963SAfshin.Ardakani@Sun.COM 		smb_server_listen_fini(&sv->sv_tcp_daemon);
4776139Sjb150015 		mutex_enter(&sv->sv_mutex);
4786139Sjb150015 		break;
4796139Sjb150015 	case SMB_SERVER_STATE_CONFIGURED:
4806139Sjb150015 	case SMB_SERVER_STATE_CREATED:
4816139Sjb150015 		sv->sv_state = SMB_SERVER_STATE_DELETING;
4826139Sjb150015 		break;
4836139Sjb150015 	default:
48411963SAfshin.Ardakani@Sun.COM 		SMB_SERVER_STATE_VALID(sv->sv_state);
4856139Sjb150015 		mutex_exit(&sv->sv_mutex);
4866139Sjb150015 		smb_server_release(sv);
4876139Sjb150015 		return (ENOTTY);
4886139Sjb150015 	}
4896139Sjb150015 
4906139Sjb150015 	ASSERT(sv->sv_state == SMB_SERVER_STATE_DELETING);
4916139Sjb150015 
4926139Sjb150015 	sv->sv_refcnt--;
4936139Sjb150015 	while (sv->sv_refcnt)
4946139Sjb150015 		cv_wait(&sv->sv_cv, &sv->sv_mutex);
4956139Sjb150015 
4966139Sjb150015 	mutex_exit(&sv->sv_mutex);
4976139Sjb150015 
4986139Sjb150015 	smb_llist_enter(&smb_servers, RW_WRITER);
4996139Sjb150015 	smb_llist_remove(&smb_servers, sv);
5006139Sjb150015 	smb_llist_exit(&smb_servers);
5016139Sjb150015 
50211963SAfshin.Ardakani@Sun.COM 	smb_server_shutdown(sv);
5036139Sjb150015 	rw_destroy(&sv->sv_cfg_lock);
5047052Samw 	smb_opipe_door_fini();
50511963SAfshin.Ardakani@Sun.COM 	smb_kdoor_fini();
5066139Sjb150015 	smb_server_kstat_fini(sv);
50711963SAfshin.Ardakani@Sun.COM 	smb_llist_destructor(&sv->sv_opipe_list);
50811963SAfshin.Ardakani@Sun.COM 	smb_llist_destructor(&sv->sv_event_list);
5097619SJose.Borrego@Sun.COM 
5106139Sjb150015 	kmem_cache_destroy(sv->si_cache_request);
5116139Sjb150015 	kmem_cache_destroy(sv->si_cache_session);
5126139Sjb150015 	kmem_cache_destroy(sv->si_cache_user);
5136139Sjb150015 	kmem_cache_destroy(sv->si_cache_tree);
5146139Sjb150015 	kmem_cache_destroy(sv->si_cache_ofile);
5156139Sjb150015 	kmem_cache_destroy(sv->si_cache_odir);
51611963SAfshin.Ardakani@Sun.COM 	kmem_cache_destroy(sv->si_cache_opipe);
51711963SAfshin.Ardakani@Sun.COM 	kmem_cache_destroy(sv->si_cache_event);
5186139Sjb150015 
51912508Samw@Sun.COM 	smb_srqueue_destroy(&sv->sv_srqueue);
52012508Samw@Sun.COM 
5216139Sjb150015 	smb_thread_destroy(&sv->si_thread_timers);
5226139Sjb150015 	mutex_destroy(&sv->sv_mutex);
5236139Sjb150015 	cv_destroy(&sv->sv_cv);
5246139Sjb150015 	sv->sv_magic = 0;
5256139Sjb150015 	kmem_free(sv, sizeof (smb_server_t));
5266139Sjb150015 
5276139Sjb150015 	return (0);
5286139Sjb150015 }
5296139Sjb150015 
5306139Sjb150015 /*
5316139Sjb150015  * smb_server_configure
5326139Sjb150015  */
5336139Sjb150015 int
5349832Samw@Sun.COM smb_server_configure(smb_ioc_cfg_t *ioc)
5356139Sjb150015 {
5366139Sjb150015 	int		rc = 0;
5376139Sjb150015 	smb_server_t	*sv;
5386139Sjb150015 
5396139Sjb150015 	rc = smb_server_lookup(&sv);
5406139Sjb150015 	if (rc)
5416139Sjb150015 		return (rc);
5426139Sjb150015 
5436139Sjb150015 	mutex_enter(&sv->sv_mutex);
5446139Sjb150015 	switch (sv->sv_state) {
5456139Sjb150015 	case SMB_SERVER_STATE_CREATED:
5469832Samw@Sun.COM 		smb_server_store_cfg(sv, ioc);
5476139Sjb150015 		sv->sv_state = SMB_SERVER_STATE_CONFIGURED;
5486139Sjb150015 		break;
5496139Sjb150015 
5506139Sjb150015 	case SMB_SERVER_STATE_CONFIGURED:
5519832Samw@Sun.COM 		smb_server_store_cfg(sv, ioc);
5526139Sjb150015 		break;
5536139Sjb150015 
5546139Sjb150015 	case SMB_SERVER_STATE_RUNNING:
55511963SAfshin.Ardakani@Sun.COM 	case SMB_SERVER_STATE_STOPPING:
5566139Sjb150015 		rw_enter(&sv->sv_cfg_lock, RW_WRITER);
5579832Samw@Sun.COM 		smb_server_store_cfg(sv, ioc);
5586139Sjb150015 		rw_exit(&sv->sv_cfg_lock);
5596139Sjb150015 		break;
5606139Sjb150015 
5616139Sjb150015 	default:
56211963SAfshin.Ardakani@Sun.COM 		SMB_SERVER_STATE_VALID(sv->sv_state);
5636139Sjb150015 		rc = EFAULT;
5646139Sjb150015 		break;
5656139Sjb150015 	}
5666139Sjb150015 	mutex_exit(&sv->sv_mutex);
5676139Sjb150015 
5686139Sjb150015 	smb_server_release(sv);
5696139Sjb150015 
5706139Sjb150015 	return (rc);
5716139Sjb150015 }
5726139Sjb150015 
5736139Sjb150015 /*
5746139Sjb150015  * smb_server_start
5756139Sjb150015  */
5766139Sjb150015 int
5779832Samw@Sun.COM smb_server_start(smb_ioc_start_t *ioc)
5786139Sjb150015 {
5796139Sjb150015 	int		rc = 0;
5806139Sjb150015 	smb_server_t	*sv;
5816139Sjb150015 
5826139Sjb150015 	rc = smb_server_lookup(&sv);
5836139Sjb150015 	if (rc)
5846139Sjb150015 		return (rc);
5856139Sjb150015 
5866139Sjb150015 	mutex_enter(&sv->sv_mutex);
5876139Sjb150015 	switch (sv->sv_state) {
5886139Sjb150015 	case SMB_SERVER_STATE_CONFIGURED:
58910966SJordan.Brown@Sun.COM 		smb_codepage_init();
5906139Sjb150015 
5916139Sjb150015 		sv->sv_thread_pool = taskq_create("smb_workers",
5926139Sjb150015 		    sv->sv_cfg.skc_maxworkers, SMB_WORKER_PRIORITY,
5936139Sjb150015 		    sv->sv_cfg.skc_maxworkers, INT_MAX,
5946139Sjb150015 		    TASKQ_DYNAMIC|TASKQ_PREPOPULATE);
5956139Sjb150015 
5968670SJose.Borrego@Sun.COM 		sv->sv_session = smb_session_create(NULL, 0, sv, 0);
5977588Samw@Sun.COM 
5987588Samw@Sun.COM 		if (sv->sv_thread_pool == NULL || sv->sv_session == NULL) {
5996139Sjb150015 			rc = ENOMEM;
6006139Sjb150015 			break;
6016139Sjb150015 		}
6026139Sjb150015 
6036139Sjb150015 		if (rc = smb_server_fsop_start(sv))
6046139Sjb150015 			break;
6056139Sjb150015 		ASSERT(sv->sv_lmshrd == NULL);
60612508Samw@Sun.COM 		sv->sv_lmshrd = smb_kshare_door_init(ioc->lmshrd);
6076139Sjb150015 		if (sv->sv_lmshrd == NULL)
6086139Sjb150015 			break;
60911963SAfshin.Ardakani@Sun.COM 		if (rc = smb_kdoor_open(ioc->udoor)) {
61011963SAfshin.Ardakani@Sun.COM 			cmn_err(CE_WARN, "Cannot open smbd door");
6116139Sjb150015 			break;
61211963SAfshin.Ardakani@Sun.COM 		}
61311963SAfshin.Ardakani@Sun.COM 		if (rc = smb_opipe_door_open(ioc->opipe)) {
61411963SAfshin.Ardakani@Sun.COM 			cmn_err(CE_WARN, "Cannot open opipe door");
61511963SAfshin.Ardakani@Sun.COM 			break;
61611963SAfshin.Ardakani@Sun.COM 		}
6176139Sjb150015 		if (rc = smb_thread_start(&sv->si_thread_timers))
6186139Sjb150015 			break;
6196139Sjb150015 		sv->sv_state = SMB_SERVER_STATE_RUNNING;
62012508Samw@Sun.COM 		sv->sv_start_time = gethrtime();
6216139Sjb150015 		mutex_exit(&sv->sv_mutex);
6226139Sjb150015 		smb_server_release(sv);
62312508Samw@Sun.COM 
62412508Samw@Sun.COM 		smb_export_start();
6256139Sjb150015 		return (0);
6266139Sjb150015 	default:
62711963SAfshin.Ardakani@Sun.COM 		SMB_SERVER_STATE_VALID(sv->sv_state);
6286139Sjb150015 		mutex_exit(&sv->sv_mutex);
6296139Sjb150015 		smb_server_release(sv);
6306139Sjb150015 		return (ENOTTY);
6316139Sjb150015 	}
6326139Sjb150015 
63311963SAfshin.Ardakani@Sun.COM 	smb_server_shutdown(sv);
6346139Sjb150015 	mutex_exit(&sv->sv_mutex);
6356139Sjb150015 	smb_server_release(sv);
6366139Sjb150015 	return (rc);
6376139Sjb150015 }
6386139Sjb150015 
6396139Sjb150015 /*
64011963SAfshin.Ardakani@Sun.COM  * An smbd is shutting down.
64111963SAfshin.Ardakani@Sun.COM  */
64211963SAfshin.Ardakani@Sun.COM int
64311963SAfshin.Ardakani@Sun.COM smb_server_stop(void)
64411963SAfshin.Ardakani@Sun.COM {
64511963SAfshin.Ardakani@Sun.COM 	smb_server_t	*sv;
64611963SAfshin.Ardakani@Sun.COM 	int		rc;
64711963SAfshin.Ardakani@Sun.COM 
64811963SAfshin.Ardakani@Sun.COM 	if ((rc = smb_server_lookup(&sv)) != 0)
64911963SAfshin.Ardakani@Sun.COM 		return (rc);
65011963SAfshin.Ardakani@Sun.COM 
65111963SAfshin.Ardakani@Sun.COM 	mutex_enter(&sv->sv_mutex);
65211963SAfshin.Ardakani@Sun.COM 	switch (sv->sv_state) {
65311963SAfshin.Ardakani@Sun.COM 	case SMB_SERVER_STATE_RUNNING:
65411963SAfshin.Ardakani@Sun.COM 		sv->sv_state = SMB_SERVER_STATE_STOPPING;
65511963SAfshin.Ardakani@Sun.COM 		smb_server_signal_listeners(sv);
656*12890SJoyce.McIntosh@Sun.COM 		cv_broadcast(&sv->sp_info.sp_cv);
65711963SAfshin.Ardakani@Sun.COM 		break;
65811963SAfshin.Ardakani@Sun.COM 	default:
65911963SAfshin.Ardakani@Sun.COM 		SMB_SERVER_STATE_VALID(sv->sv_state);
66011963SAfshin.Ardakani@Sun.COM 		break;
66111963SAfshin.Ardakani@Sun.COM 	}
66211963SAfshin.Ardakani@Sun.COM 	mutex_exit(&sv->sv_mutex);
66311963SAfshin.Ardakani@Sun.COM 
66411963SAfshin.Ardakani@Sun.COM 	smb_server_release(sv);
66511963SAfshin.Ardakani@Sun.COM 	return (0);
66611963SAfshin.Ardakani@Sun.COM }
66711963SAfshin.Ardakani@Sun.COM 
66811963SAfshin.Ardakani@Sun.COM boolean_t
66911963SAfshin.Ardakani@Sun.COM smb_server_is_stopping(void)
67011963SAfshin.Ardakani@Sun.COM {
67112508Samw@Sun.COM 	smb_server_t    *sv;
67211963SAfshin.Ardakani@Sun.COM 	boolean_t	status;
67311963SAfshin.Ardakani@Sun.COM 
67411963SAfshin.Ardakani@Sun.COM 	if (smb_server_lookup(&sv) != 0)
67511963SAfshin.Ardakani@Sun.COM 		return (B_TRUE);
67611963SAfshin.Ardakani@Sun.COM 
67711963SAfshin.Ardakani@Sun.COM 	SMB_SERVER_VALID(sv);
67811963SAfshin.Ardakani@Sun.COM 
67911963SAfshin.Ardakani@Sun.COM 	mutex_enter(&sv->sv_mutex);
68011963SAfshin.Ardakani@Sun.COM 
68111963SAfshin.Ardakani@Sun.COM 	switch (sv->sv_state) {
68211963SAfshin.Ardakani@Sun.COM 	case SMB_SERVER_STATE_STOPPING:
68311963SAfshin.Ardakani@Sun.COM 	case SMB_SERVER_STATE_DELETING:
68411963SAfshin.Ardakani@Sun.COM 		status = B_TRUE;
68511963SAfshin.Ardakani@Sun.COM 		break;
68611963SAfshin.Ardakani@Sun.COM 	default:
68711963SAfshin.Ardakani@Sun.COM 		status = B_FALSE;
68811963SAfshin.Ardakani@Sun.COM 		break;
68911963SAfshin.Ardakani@Sun.COM 	}
69011963SAfshin.Ardakani@Sun.COM 
69111963SAfshin.Ardakani@Sun.COM 	mutex_exit(&sv->sv_mutex);
69211963SAfshin.Ardakani@Sun.COM 	smb_server_release(sv);
69311963SAfshin.Ardakani@Sun.COM 	return (status);
69411963SAfshin.Ardakani@Sun.COM }
69511963SAfshin.Ardakani@Sun.COM 
69611963SAfshin.Ardakani@Sun.COM int
69711963SAfshin.Ardakani@Sun.COM smb_server_cancel_event(uint32_t txid)
69811963SAfshin.Ardakani@Sun.COM {
69911963SAfshin.Ardakani@Sun.COM 	smb_server_t	*sv;
70011963SAfshin.Ardakani@Sun.COM 	int		rc;
70111963SAfshin.Ardakani@Sun.COM 
70211963SAfshin.Ardakani@Sun.COM 	if ((rc = smb_server_lookup(&sv)) == 0) {
70311963SAfshin.Ardakani@Sun.COM 		smb_event_cancel(sv, txid);
70411963SAfshin.Ardakani@Sun.COM 		smb_server_release(sv);
70511963SAfshin.Ardakani@Sun.COM 	}
70611963SAfshin.Ardakani@Sun.COM 
70711963SAfshin.Ardakani@Sun.COM 	return (rc);
70811963SAfshin.Ardakani@Sun.COM }
70911963SAfshin.Ardakani@Sun.COM 
71011963SAfshin.Ardakani@Sun.COM int
71111963SAfshin.Ardakani@Sun.COM smb_server_notify_event(smb_ioc_event_t *ioc)
71211963SAfshin.Ardakani@Sun.COM {
71311963SAfshin.Ardakani@Sun.COM 	smb_server_t	*sv;
71411963SAfshin.Ardakani@Sun.COM 	int		rc;
71511963SAfshin.Ardakani@Sun.COM 
71611963SAfshin.Ardakani@Sun.COM 	if ((rc = smb_server_lookup(&sv)) == 0) {
71711963SAfshin.Ardakani@Sun.COM 		smb_event_notify(sv, ioc->txid);
71811963SAfshin.Ardakani@Sun.COM 		smb_server_release(sv);
71911963SAfshin.Ardakani@Sun.COM 	}
72011963SAfshin.Ardakani@Sun.COM 
72111963SAfshin.Ardakani@Sun.COM 	return (rc);
72211963SAfshin.Ardakani@Sun.COM }
72311963SAfshin.Ardakani@Sun.COM 
72411963SAfshin.Ardakani@Sun.COM /*
72511963SAfshin.Ardakani@Sun.COM  * SMB-over-NetBIOS (port 139)
7266139Sjb150015  *
72711963SAfshin.Ardakani@Sun.COM  * Traditional SMB service over NetBIOS, which requires that a NetBIOS
72811963SAfshin.Ardakani@Sun.COM  * session be established.
7296139Sjb150015  */
7306139Sjb150015 int
7319832Samw@Sun.COM smb_server_nbt_listen(smb_ioc_listen_t *ioc)
7326139Sjb150015 {
7336139Sjb150015 	smb_server_t	*sv;
7346139Sjb150015 	int		rc;
7356139Sjb150015 
7366139Sjb150015 	rc = smb_server_lookup(&sv);
7376139Sjb150015 	if (rc)
7386139Sjb150015 		return (rc);
7396139Sjb150015 
7406139Sjb150015 	mutex_enter(&sv->sv_mutex);
7416139Sjb150015 	switch (sv->sv_state) {
7426139Sjb150015 	case SMB_SERVER_STATE_RUNNING:
7436139Sjb150015 		if ((sv->sv_nbt_daemon.ld_kth != NULL) &&
7446139Sjb150015 		    (sv->sv_nbt_daemon.ld_kth != curthread)) {
7456139Sjb150015 			mutex_exit(&sv->sv_mutex);
7469422SAfshin.Ardakani@Sun.COM 			smb_server_release(sv);
7476139Sjb150015 			return (EACCES);
7486139Sjb150015 		} else {
7496139Sjb150015 			sv->sv_nbt_daemon.ld_kth = curthread;
7506139Sjb150015 			sv->sv_nbt_daemon.ld_ktdid = curthread->t_did;
7516139Sjb150015 		}
7526139Sjb150015 		break;
75311963SAfshin.Ardakani@Sun.COM 	case SMB_SERVER_STATE_STOPPING:
75411963SAfshin.Ardakani@Sun.COM 		mutex_exit(&sv->sv_mutex);
75511963SAfshin.Ardakani@Sun.COM 		smb_server_release(sv);
75611963SAfshin.Ardakani@Sun.COM 		return (ECANCELED);
7576139Sjb150015 	default:
75811963SAfshin.Ardakani@Sun.COM 		SMB_SERVER_STATE_VALID(sv->sv_state);
7596139Sjb150015 		mutex_exit(&sv->sv_mutex);
7606139Sjb150015 		smb_server_release(sv);
7616139Sjb150015 		return (EFAULT);
7626139Sjb150015 	}
7636139Sjb150015 	mutex_exit(&sv->sv_mutex);
7646139Sjb150015 
7658670SJose.Borrego@Sun.COM 	/*
7668670SJose.Borrego@Sun.COM 	 * netbios must be ipv4
7678670SJose.Borrego@Sun.COM 	 */
76810717Samw@Sun.COM 	rc = smb_server_listen(sv, &sv->sv_nbt_daemon, IPPORT_NETBIOS_SSN,
7699832Samw@Sun.COM 	    AF_INET, ioc->error);
7706139Sjb150015 
77111963SAfshin.Ardakani@Sun.COM 	mutex_enter(&sv->sv_mutex);
77211963SAfshin.Ardakani@Sun.COM 	sv->sv_nbt_daemon.ld_kth = NULL;
77311963SAfshin.Ardakani@Sun.COM 	mutex_exit(&sv->sv_mutex);
7746139Sjb150015 
7756139Sjb150015 	smb_server_release(sv);
7766139Sjb150015 	return (rc);
7776139Sjb150015 }
7786139Sjb150015 
77911963SAfshin.Ardakani@Sun.COM /*
78011963SAfshin.Ardakani@Sun.COM  *  SMB-over-TCP (port 445)
78111963SAfshin.Ardakani@Sun.COM  */
7826139Sjb150015 int
7839832Samw@Sun.COM smb_server_tcp_listen(smb_ioc_listen_t *ioc)
7846139Sjb150015 {
7856139Sjb150015 	smb_server_t	*sv;
7866139Sjb150015 	int		rc;
7876139Sjb150015 
7886139Sjb150015 	rc = smb_server_lookup(&sv);
7896139Sjb150015 	if (rc)
7906139Sjb150015 		return (rc);
7916139Sjb150015 
7926139Sjb150015 	mutex_enter(&sv->sv_mutex);
7936139Sjb150015 	switch (sv->sv_state) {
7946139Sjb150015 	case SMB_SERVER_STATE_RUNNING:
79511963SAfshin.Ardakani@Sun.COM 		if ((sv->sv_tcp_daemon.ld_kth != NULL) &&
7966139Sjb150015 		    (sv->sv_tcp_daemon.ld_kth != curthread)) {
7976139Sjb150015 			mutex_exit(&sv->sv_mutex);
7989422SAfshin.Ardakani@Sun.COM 			smb_server_release(sv);
7996139Sjb150015 			return (EACCES);
8006139Sjb150015 		} else {
8016139Sjb150015 			sv->sv_tcp_daemon.ld_kth = curthread;
8026139Sjb150015 			sv->sv_tcp_daemon.ld_ktdid = curthread->t_did;
8036139Sjb150015 		}
8046139Sjb150015 		break;
80511963SAfshin.Ardakani@Sun.COM 	case SMB_SERVER_STATE_STOPPING:
80611963SAfshin.Ardakani@Sun.COM 		mutex_exit(&sv->sv_mutex);
80711963SAfshin.Ardakani@Sun.COM 		smb_server_release(sv);
80811963SAfshin.Ardakani@Sun.COM 		return (ECANCELED);
8096139Sjb150015 	default:
81011963SAfshin.Ardakani@Sun.COM 		SMB_SERVER_STATE_VALID(sv->sv_state);
8116139Sjb150015 		mutex_exit(&sv->sv_mutex);
8129422SAfshin.Ardakani@Sun.COM 		smb_server_release(sv);
8136139Sjb150015 		return (EFAULT);
8146139Sjb150015 	}
8156139Sjb150015 	mutex_exit(&sv->sv_mutex);
8166139Sjb150015 
8178670SJose.Borrego@Sun.COM 	if (sv->sv_cfg.skc_ipv6_enable)
8188670SJose.Borrego@Sun.COM 		rc = smb_server_listen(sv, &sv->sv_tcp_daemon,
81910717Samw@Sun.COM 		    IPPORT_SMB, AF_INET6, ioc->error);
8208670SJose.Borrego@Sun.COM 	else
8218670SJose.Borrego@Sun.COM 		rc = smb_server_listen(sv, &sv->sv_tcp_daemon,
82210717Samw@Sun.COM 		    IPPORT_SMB, AF_INET, ioc->error);
82311963SAfshin.Ardakani@Sun.COM 
82411963SAfshin.Ardakani@Sun.COM 	mutex_enter(&sv->sv_mutex);
82511963SAfshin.Ardakani@Sun.COM 	sv->sv_tcp_daemon.ld_kth = NULL;
82611963SAfshin.Ardakani@Sun.COM 	mutex_exit(&sv->sv_mutex);
8276139Sjb150015 
8286139Sjb150015 	smb_server_release(sv);
8296139Sjb150015 	return (rc);
8306139Sjb150015 }
8316139Sjb150015 
8326139Sjb150015 /*
8336139Sjb150015  * smb_server_nbt_receive
8346139Sjb150015  */
8356139Sjb150015 int
8366139Sjb150015 smb_server_nbt_receive(void)
8376139Sjb150015 {
8386139Sjb150015 	int		rc;
8396139Sjb150015 	smb_server_t	*sv;
8406139Sjb150015 
8419422SAfshin.Ardakani@Sun.COM 	if ((rc = smb_server_lookup(&sv)) == 0) {
8429422SAfshin.Ardakani@Sun.COM 		rc = smb_session_daemon(&sv->sv_nbt_daemon.ld_session_list);
8439422SAfshin.Ardakani@Sun.COM 		smb_server_release(sv);
8449422SAfshin.Ardakani@Sun.COM 	}
8456139Sjb150015 
8466139Sjb150015 	return (rc);
8476139Sjb150015 }
8486139Sjb150015 
8496139Sjb150015 /*
8506139Sjb150015  * smb_server_tcp_receive
8516139Sjb150015  */
8526139Sjb150015 int
8536139Sjb150015 smb_server_tcp_receive(void)
8546139Sjb150015 {
8556139Sjb150015 	int		rc;
8566139Sjb150015 	smb_server_t	*sv;
8576139Sjb150015 
8589422SAfshin.Ardakani@Sun.COM 	if ((rc = smb_server_lookup(&sv)) == 0) {
8599422SAfshin.Ardakani@Sun.COM 		rc = smb_session_daemon(&sv->sv_tcp_daemon.ld_session_list);
8609422SAfshin.Ardakani@Sun.COM 		smb_server_release(sv);
8619422SAfshin.Ardakani@Sun.COM 	}
8626139Sjb150015 
8636139Sjb150015 	return (rc);
8646139Sjb150015 }
8656139Sjb150015 
866*12890SJoyce.McIntosh@Sun.COM /*
867*12890SJoyce.McIntosh@Sun.COM  * smb_server_spooldoc
868*12890SJoyce.McIntosh@Sun.COM  *
869*12890SJoyce.McIntosh@Sun.COM  * Waits for print file close broadcast.
870*12890SJoyce.McIntosh@Sun.COM  * Gets the head of the fid list,
871*12890SJoyce.McIntosh@Sun.COM  * then searches the spooldoc list and returns
872*12890SJoyce.McIntosh@Sun.COM  * this info via the ioctl to user land.
873*12890SJoyce.McIntosh@Sun.COM  *
874*12890SJoyce.McIntosh@Sun.COM  * rc - 0 success
875*12890SJoyce.McIntosh@Sun.COM  */
876*12890SJoyce.McIntosh@Sun.COM 
877*12890SJoyce.McIntosh@Sun.COM int
878*12890SJoyce.McIntosh@Sun.COM smb_server_spooldoc(smb_ioc_spooldoc_t *ioc)
879*12890SJoyce.McIntosh@Sun.COM {
880*12890SJoyce.McIntosh@Sun.COM 	smb_server_t	*sv;
881*12890SJoyce.McIntosh@Sun.COM 	int		rc;
882*12890SJoyce.McIntosh@Sun.COM 	smb_kspooldoc_t *spdoc;
883*12890SJoyce.McIntosh@Sun.COM 	uint16_t	fid;
884*12890SJoyce.McIntosh@Sun.COM 
885*12890SJoyce.McIntosh@Sun.COM 	if ((rc = smb_server_lookup(&sv)) == 0) {
886*12890SJoyce.McIntosh@Sun.COM 		if (sv->sv_state != SMB_SERVER_STATE_RUNNING) {
887*12890SJoyce.McIntosh@Sun.COM 			smb_server_release(sv);
888*12890SJoyce.McIntosh@Sun.COM 			return (ECANCELED);
889*12890SJoyce.McIntosh@Sun.COM 		}
890*12890SJoyce.McIntosh@Sun.COM 		mutex_enter(&sv->sp_info.sp_mutex);
891*12890SJoyce.McIntosh@Sun.COM 		spdoc = kmem_zalloc(sizeof (smb_kspooldoc_t), KM_SLEEP);
892*12890SJoyce.McIntosh@Sun.COM 		cv_wait(&sv->sp_info.sp_cv, &sv->sp_info.sp_mutex);
893*12890SJoyce.McIntosh@Sun.COM 		if (sv->sv_state != SMB_SERVER_STATE_RUNNING)
894*12890SJoyce.McIntosh@Sun.COM 			rc = ECANCELED;
895*12890SJoyce.McIntosh@Sun.COM 		else {
896*12890SJoyce.McIntosh@Sun.COM 			fid = smb_spool_get_fid();
897*12890SJoyce.McIntosh@Sun.COM 			atomic_inc_32(&sv->sp_info.sp_cnt);
898*12890SJoyce.McIntosh@Sun.COM 			if (smb_spool_lookup_doc_byfid(fid, spdoc)) {
899*12890SJoyce.McIntosh@Sun.COM 				ioc->spool_num = spdoc->sd_spool_num;
900*12890SJoyce.McIntosh@Sun.COM 				ioc->ipaddr = spdoc->sd_ipaddr;
901*12890SJoyce.McIntosh@Sun.COM 				(void) strlcpy(ioc->path, spdoc->sd_path,
902*12890SJoyce.McIntosh@Sun.COM 				    MAXPATHLEN);
903*12890SJoyce.McIntosh@Sun.COM 				(void) strlcpy(ioc->username,
904*12890SJoyce.McIntosh@Sun.COM 				    spdoc->sd_username, MAXNAMELEN);
905*12890SJoyce.McIntosh@Sun.COM 			}
906*12890SJoyce.McIntosh@Sun.COM 		}
907*12890SJoyce.McIntosh@Sun.COM 		kmem_free(spdoc, sizeof (smb_kspooldoc_t));
908*12890SJoyce.McIntosh@Sun.COM 		mutex_exit(&sv->sp_info.sp_mutex);
909*12890SJoyce.McIntosh@Sun.COM 		smb_server_release(sv);
910*12890SJoyce.McIntosh@Sun.COM 	}
911*12890SJoyce.McIntosh@Sun.COM 	return (rc);
912*12890SJoyce.McIntosh@Sun.COM }
913*12890SJoyce.McIntosh@Sun.COM 
9146139Sjb150015 int
9159832Samw@Sun.COM smb_server_set_gmtoff(smb_ioc_gmt_t *ioc)
9166139Sjb150015 {
9176139Sjb150015 	int		rc;
9186139Sjb150015 	smb_server_t	*sv;
9196139Sjb150015 
9209422SAfshin.Ardakani@Sun.COM 	if ((rc = smb_server_lookup(&sv)) == 0) {
9219832Samw@Sun.COM 		sv->si_gmtoff = ioc->offset;
9229422SAfshin.Ardakani@Sun.COM 		smb_server_release(sv);
9239422SAfshin.Ardakani@Sun.COM 	}
9246139Sjb150015 
9256139Sjb150015 	return (rc);
9266139Sjb150015 }
9276139Sjb150015 
9289832Samw@Sun.COM int
92910122SJordan.Brown@Sun.COM smb_server_numopen(smb_ioc_opennum_t *ioc)
9309832Samw@Sun.COM {
9319832Samw@Sun.COM 	smb_server_t	*sv;
9329832Samw@Sun.COM 	int		rc;
9339832Samw@Sun.COM 
9349832Samw@Sun.COM 	if ((rc = smb_server_lookup(&sv)) == 0) {
93512508Samw@Sun.COM 		ioc->open_users = sv->sv_users;
93612508Samw@Sun.COM 		ioc->open_trees = sv->sv_trees;
93712508Samw@Sun.COM 		ioc->open_files = sv->sv_files + sv->sv_pipes;
9389832Samw@Sun.COM 		smb_server_release(sv);
9399832Samw@Sun.COM 	}
9409832Samw@Sun.COM 	return (rc);
9419832Samw@Sun.COM }
9429832Samw@Sun.COM 
9436139Sjb150015 /*
94410122SJordan.Brown@Sun.COM  * Enumerate objects within the server.  The svcenum provides the
94510122SJordan.Brown@Sun.COM  * enumeration context, i.e. what the caller want to get back.
94610122SJordan.Brown@Sun.COM  */
94710122SJordan.Brown@Sun.COM int
94810122SJordan.Brown@Sun.COM smb_server_enum(smb_ioc_svcenum_t *ioc)
94910122SJordan.Brown@Sun.COM {
95010122SJordan.Brown@Sun.COM 	smb_svcenum_t		*svcenum = &ioc->svcenum;
95110122SJordan.Brown@Sun.COM 	smb_server_t		*sv;
95210122SJordan.Brown@Sun.COM 	smb_session_list_t	*se;
95310122SJordan.Brown@Sun.COM 	int			rc;
95410122SJordan.Brown@Sun.COM 
95510122SJordan.Brown@Sun.COM 	switch (svcenum->se_type) {
95610122SJordan.Brown@Sun.COM 	case SMB_SVCENUM_TYPE_USER:
95710122SJordan.Brown@Sun.COM 	case SMB_SVCENUM_TYPE_TREE:
95810122SJordan.Brown@Sun.COM 	case SMB_SVCENUM_TYPE_FILE:
95910122SJordan.Brown@Sun.COM 		break;
96010122SJordan.Brown@Sun.COM 	default:
96110122SJordan.Brown@Sun.COM 		return (EINVAL);
96210122SJordan.Brown@Sun.COM 	}
96310122SJordan.Brown@Sun.COM 
96410122SJordan.Brown@Sun.COM 	if ((rc = smb_server_lookup(&sv)) != 0)
96510122SJordan.Brown@Sun.COM 		return (rc);
96610122SJordan.Brown@Sun.COM 
96710122SJordan.Brown@Sun.COM 	svcenum->se_bavail = svcenum->se_buflen;
96810122SJordan.Brown@Sun.COM 	svcenum->se_bused = 0;
96910122SJordan.Brown@Sun.COM 	svcenum->se_nitems = 0;
97010122SJordan.Brown@Sun.COM 
97110122SJordan.Brown@Sun.COM 	se = &sv->sv_nbt_daemon.ld_session_list;
97210122SJordan.Brown@Sun.COM 	smb_server_enum_private(se, svcenum);
97310122SJordan.Brown@Sun.COM 
97410122SJordan.Brown@Sun.COM 	se = &sv->sv_tcp_daemon.ld_session_list;
97510122SJordan.Brown@Sun.COM 	smb_server_enum_private(se, svcenum);
97610122SJordan.Brown@Sun.COM 
97710122SJordan.Brown@Sun.COM 	smb_server_release(sv);
97810122SJordan.Brown@Sun.COM 	return (0);
97910122SJordan.Brown@Sun.COM }
98010122SJordan.Brown@Sun.COM 
98110122SJordan.Brown@Sun.COM /*
98210122SJordan.Brown@Sun.COM  * Look for sessions to disconnect by client and user name.
98310122SJordan.Brown@Sun.COM  */
98410122SJordan.Brown@Sun.COM int
98510122SJordan.Brown@Sun.COM smb_server_session_close(smb_ioc_session_t *ioc)
98610122SJordan.Brown@Sun.COM {
98710122SJordan.Brown@Sun.COM 	smb_session_list_t	*se;
98810122SJordan.Brown@Sun.COM 	smb_server_t		*sv;
98910122SJordan.Brown@Sun.COM 	int			nbt_cnt;
99010122SJordan.Brown@Sun.COM 	int			tcp_cnt;
99110122SJordan.Brown@Sun.COM 	int			rc;
99210122SJordan.Brown@Sun.COM 
99310122SJordan.Brown@Sun.COM 	if ((rc = smb_server_lookup(&sv)) != 0)
99410122SJordan.Brown@Sun.COM 		return (rc);
99510122SJordan.Brown@Sun.COM 
99610122SJordan.Brown@Sun.COM 	se = &sv->sv_nbt_daemon.ld_session_list;
99710122SJordan.Brown@Sun.COM 	nbt_cnt = smb_server_sesion_disconnect(se, ioc->client, ioc->username);
99810122SJordan.Brown@Sun.COM 
99910122SJordan.Brown@Sun.COM 	se = &sv->sv_tcp_daemon.ld_session_list;
100010122SJordan.Brown@Sun.COM 	tcp_cnt = smb_server_sesion_disconnect(se, ioc->client, ioc->username);
100110122SJordan.Brown@Sun.COM 
100210122SJordan.Brown@Sun.COM 	smb_server_release(sv);
100310122SJordan.Brown@Sun.COM 
100410122SJordan.Brown@Sun.COM 	if ((nbt_cnt == 0) && (tcp_cnt == 0))
100510122SJordan.Brown@Sun.COM 		return (ENOENT);
100610122SJordan.Brown@Sun.COM 	return (0);
100710122SJordan.Brown@Sun.COM }
100810122SJordan.Brown@Sun.COM 
100910122SJordan.Brown@Sun.COM /*
101010122SJordan.Brown@Sun.COM  * Close a file by uniqid.
101110122SJordan.Brown@Sun.COM  */
101210122SJordan.Brown@Sun.COM int
101310122SJordan.Brown@Sun.COM smb_server_file_close(smb_ioc_fileid_t *ioc)
101410122SJordan.Brown@Sun.COM {
101510122SJordan.Brown@Sun.COM 	uint32_t		uniqid = ioc->uniqid;
101610122SJordan.Brown@Sun.COM 	smb_session_list_t	*se;
101710122SJordan.Brown@Sun.COM 	smb_server_t		*sv;
101810122SJordan.Brown@Sun.COM 	int			rc;
101910122SJordan.Brown@Sun.COM 
102010122SJordan.Brown@Sun.COM 	if ((rc = smb_server_lookup(&sv)) != 0)
102110122SJordan.Brown@Sun.COM 		return (rc);
102210122SJordan.Brown@Sun.COM 
102310122SJordan.Brown@Sun.COM 	se = &sv->sv_nbt_daemon.ld_session_list;
102410122SJordan.Brown@Sun.COM 	rc = smb_server_fclose(se, uniqid);
102510122SJordan.Brown@Sun.COM 
102610122SJordan.Brown@Sun.COM 	if (rc == ENOENT) {
102710122SJordan.Brown@Sun.COM 		se = &sv->sv_tcp_daemon.ld_session_list;
102810122SJordan.Brown@Sun.COM 		rc = smb_server_fclose(se, uniqid);
102910122SJordan.Brown@Sun.COM 	}
103010122SJordan.Brown@Sun.COM 
103110122SJordan.Brown@Sun.COM 	smb_server_release(sv);
103210122SJordan.Brown@Sun.COM 	return (rc);
103310122SJordan.Brown@Sun.COM }
103410122SJordan.Brown@Sun.COM 
103510122SJordan.Brown@Sun.COM /*
10366139Sjb150015  * These functions determine the relevant smb server to which the call apply.
10376139Sjb150015  */
10386139Sjb150015 
10396139Sjb150015 uint32_t
10406139Sjb150015 smb_server_get_session_count(void)
10416139Sjb150015 {
10426139Sjb150015 	smb_server_t	*sv;
10436139Sjb150015 	uint32_t	counter = 0;
10446139Sjb150015 
10456139Sjb150015 	if (smb_server_lookup(&sv))
10466139Sjb150015 		return (0);
10476139Sjb150015 
10486139Sjb150015 	rw_enter(&sv->sv_nbt_daemon.ld_session_list.se_lock, RW_READER);
10496139Sjb150015 	counter = sv->sv_nbt_daemon.ld_session_list.se_act.count;
10506139Sjb150015 	rw_exit(&sv->sv_nbt_daemon.ld_session_list.se_lock);
10516139Sjb150015 	rw_enter(&sv->sv_tcp_daemon.ld_session_list.se_lock, RW_READER);
10526139Sjb150015 	counter += sv->sv_tcp_daemon.ld_session_list.se_act.count;
10536139Sjb150015 	rw_exit(&sv->sv_tcp_daemon.ld_session_list.se_lock);
10546139Sjb150015 
10556139Sjb150015 	smb_server_release(sv);
10566139Sjb150015 
10576139Sjb150015 	return (counter);
10586139Sjb150015 }
10596139Sjb150015 
10606139Sjb150015 /*
106112508Samw@Sun.COM  * Gets the vnode of the specified share path.
106212508Samw@Sun.COM  *
106312508Samw@Sun.COM  * A hold on the returned vnode pointer is taken so the caller
106412508Samw@Sun.COM  * must call VN_RELE.
106512508Samw@Sun.COM  */
106612508Samw@Sun.COM int
106712508Samw@Sun.COM smb_server_sharevp(const char *shr_path, vnode_t **vp)
106812508Samw@Sun.COM {
106912508Samw@Sun.COM 	smb_server_t	*sv;
107012508Samw@Sun.COM 	smb_request_t	*sr;
107112508Samw@Sun.COM 	smb_node_t	*fnode = NULL;
107212508Samw@Sun.COM 	smb_node_t	*dnode;
107312508Samw@Sun.COM 	char		last_comp[MAXNAMELEN];
107412508Samw@Sun.COM 	int		rc = 0;
107512508Samw@Sun.COM 
107612508Samw@Sun.COM 	ASSERT(shr_path);
107712508Samw@Sun.COM 
107812508Samw@Sun.COM 	if ((rc = smb_server_lookup(&sv)))
107912508Samw@Sun.COM 		return (rc);
108012508Samw@Sun.COM 
108112508Samw@Sun.COM 	mutex_enter(&sv->sv_mutex);
108212508Samw@Sun.COM 	switch (sv->sv_state) {
108312508Samw@Sun.COM 	case SMB_SERVER_STATE_RUNNING:
108412508Samw@Sun.COM 		break;
108512508Samw@Sun.COM 	default:
108612508Samw@Sun.COM 		mutex_exit(&sv->sv_mutex);
108712508Samw@Sun.COM 		smb_server_release(sv);
108812508Samw@Sun.COM 		return (ENOTACTIVE);
108912508Samw@Sun.COM 	}
109012508Samw@Sun.COM 	mutex_exit(&sv->sv_mutex);
109112508Samw@Sun.COM 
109212508Samw@Sun.COM 	if ((sr = smb_request_alloc(sv->sv_session, 0)) == NULL) {
109312508Samw@Sun.COM 		smb_server_release(sv);
109412508Samw@Sun.COM 		return (ENOMEM);
109512508Samw@Sun.COM 	}
109612508Samw@Sun.COM 	sr->user_cr = kcred;
109712508Samw@Sun.COM 
109812508Samw@Sun.COM 	rc = smb_pathname_reduce(sr, sr->user_cr, shr_path,
109912508Samw@Sun.COM 	    NULL, NULL, &dnode, last_comp);
110012508Samw@Sun.COM 
110112508Samw@Sun.COM 	if (rc == 0) {
110212508Samw@Sun.COM 		rc = smb_fsop_lookup(sr, sr->user_cr, SMB_FOLLOW_LINKS,
110312508Samw@Sun.COM 		    sv->si_root_smb_node, dnode, last_comp, &fnode);
110412508Samw@Sun.COM 		smb_node_release(dnode);
110512508Samw@Sun.COM 	}
110612508Samw@Sun.COM 
110712508Samw@Sun.COM 	smb_request_free(sr);
110812508Samw@Sun.COM 	smb_server_release(sv);
110912508Samw@Sun.COM 
111012508Samw@Sun.COM 	if (rc != 0)
111112508Samw@Sun.COM 		return (rc);
111212508Samw@Sun.COM 
111312508Samw@Sun.COM 	ASSERT(fnode->vp && fnode->vp->v_vfsp);
111412508Samw@Sun.COM 
111512508Samw@Sun.COM 	VN_HOLD(fnode->vp);
111612508Samw@Sun.COM 	*vp = fnode->vp;
111712508Samw@Sun.COM 
111812508Samw@Sun.COM 	smb_node_release(fnode);
111912508Samw@Sun.COM 
112012508Samw@Sun.COM 	return (0);
112112508Samw@Sun.COM }
112212508Samw@Sun.COM 
112312508Samw@Sun.COM 
112412508Samw@Sun.COM /*
112512508Samw@Sun.COM  * This is a special interface that will be utilized by ZFS to cause a share to
112612508Samw@Sun.COM  * be added/removed.
112712508Samw@Sun.COM  *
112812508Samw@Sun.COM  * arg is either a lmshare_info_t or share_name from userspace.
112912508Samw@Sun.COM  * It will need to be copied into the kernel.   It is lmshare_info_t
113012508Samw@Sun.COM  * for add operations and share_name for delete operations.
113112508Samw@Sun.COM  */
113212508Samw@Sun.COM int
113312508Samw@Sun.COM smb_server_share(void *arg, boolean_t add_share)
113412508Samw@Sun.COM {
113512508Samw@Sun.COM 	smb_server_t	*sv;
113612508Samw@Sun.COM 	int		rc;
113712508Samw@Sun.COM 
113812508Samw@Sun.COM 	if ((rc = smb_server_lookup(&sv)) == 0) {
113912508Samw@Sun.COM 		mutex_enter(&sv->sv_mutex);
114012508Samw@Sun.COM 		switch (sv->sv_state) {
114112508Samw@Sun.COM 		case SMB_SERVER_STATE_RUNNING:
114212508Samw@Sun.COM 			mutex_exit(&sv->sv_mutex);
114312508Samw@Sun.COM 			(void) smb_kshare_upcall(sv->sv_lmshrd, arg, add_share);
114412508Samw@Sun.COM 			break;
114512508Samw@Sun.COM 		default:
114612508Samw@Sun.COM 			mutex_exit(&sv->sv_mutex);
114712508Samw@Sun.COM 			break;
114812508Samw@Sun.COM 		}
114912508Samw@Sun.COM 		smb_server_release(sv);
115012508Samw@Sun.COM 	}
115112508Samw@Sun.COM 
115212508Samw@Sun.COM 	return (rc);
115312508Samw@Sun.COM }
115412508Samw@Sun.COM 
115512508Samw@Sun.COM int
115612508Samw@Sun.COM smb_server_unshare(const char *sharename)
115712508Samw@Sun.COM {
115812508Samw@Sun.COM 	smb_server_t		*sv;
115912508Samw@Sun.COM 	smb_session_list_t	*slist;
116012508Samw@Sun.COM 	int			rc;
116112508Samw@Sun.COM 
116212508Samw@Sun.COM 	if ((rc = smb_server_lookup(&sv)))
116312508Samw@Sun.COM 		return (rc);
116412508Samw@Sun.COM 
116512508Samw@Sun.COM 	mutex_enter(&sv->sv_mutex);
116612508Samw@Sun.COM 	switch (sv->sv_state) {
116712508Samw@Sun.COM 	case SMB_SERVER_STATE_RUNNING:
116812508Samw@Sun.COM 	case SMB_SERVER_STATE_STOPPING:
116912508Samw@Sun.COM 		break;
117012508Samw@Sun.COM 	default:
117112508Samw@Sun.COM 		mutex_exit(&sv->sv_mutex);
117212508Samw@Sun.COM 		smb_server_release(sv);
117312508Samw@Sun.COM 		return (ENOTACTIVE);
117412508Samw@Sun.COM 	}
117512508Samw@Sun.COM 	mutex_exit(&sv->sv_mutex);
117612508Samw@Sun.COM 
117712508Samw@Sun.COM 	slist = &sv->sv_nbt_daemon.ld_session_list;
117812508Samw@Sun.COM 	smb_server_disconnect_share(slist, sharename);
117912508Samw@Sun.COM 
118012508Samw@Sun.COM 	slist = &sv->sv_tcp_daemon.ld_session_list;
118112508Samw@Sun.COM 	smb_server_disconnect_share(slist, sharename);
118212508Samw@Sun.COM 
118312508Samw@Sun.COM 	smb_server_release(sv);
118412508Samw@Sun.COM 	return (0);
118512508Samw@Sun.COM }
118612508Samw@Sun.COM 
118712508Samw@Sun.COM /*
118811963SAfshin.Ardakani@Sun.COM  * Disconnect the specified share.
118911963SAfshin.Ardakani@Sun.COM  * Typically called when a share has been removed.
11906139Sjb150015  */
11917619SJose.Borrego@Sun.COM static void
119211963SAfshin.Ardakani@Sun.COM smb_server_disconnect_share(smb_session_list_t *slist, const char *sharename)
11936139Sjb150015 {
119411963SAfshin.Ardakani@Sun.COM 	smb_session_t		*session;
119511963SAfshin.Ardakani@Sun.COM 
119611963SAfshin.Ardakani@Sun.COM 	rw_enter(&slist->se_lock, RW_READER);
119711963SAfshin.Ardakani@Sun.COM 
119811963SAfshin.Ardakani@Sun.COM 	session = list_head(&slist->se_act.lst);
119911963SAfshin.Ardakani@Sun.COM 	while (session) {
120011963SAfshin.Ardakani@Sun.COM 		ASSERT(session->s_magic == SMB_SESSION_MAGIC);
120111963SAfshin.Ardakani@Sun.COM 		smb_rwx_rwenter(&session->s_lock, RW_READER);
120211963SAfshin.Ardakani@Sun.COM 		switch (session->s_state) {
120311963SAfshin.Ardakani@Sun.COM 		case SMB_SESSION_STATE_NEGOTIATED:
120411963SAfshin.Ardakani@Sun.COM 		case SMB_SESSION_STATE_OPLOCK_BREAKING:
120511963SAfshin.Ardakani@Sun.COM 		case SMB_SESSION_STATE_WRITE_RAW_ACTIVE:
120611963SAfshin.Ardakani@Sun.COM 			smb_session_disconnect_share(session, sharename);
120711963SAfshin.Ardakani@Sun.COM 			break;
120811963SAfshin.Ardakani@Sun.COM 		default:
120911963SAfshin.Ardakani@Sun.COM 			break;
121011963SAfshin.Ardakani@Sun.COM 		}
121111963SAfshin.Ardakani@Sun.COM 		smb_rwx_rwexit(&session->s_lock);
121211963SAfshin.Ardakani@Sun.COM 		session = list_next(&slist->se_act.lst, session);
121311963SAfshin.Ardakani@Sun.COM 	}
121411963SAfshin.Ardakani@Sun.COM 
121511963SAfshin.Ardakani@Sun.COM 	rw_exit(&slist->se_lock);
12166139Sjb150015 }
12176139Sjb150015 
12186139Sjb150015 /*
12196139Sjb150015  * *****************************************************************************
12206139Sjb150015  * **************** Functions called from the internal layers ******************
12216139Sjb150015  * *****************************************************************************
12226139Sjb150015  *
12236139Sjb150015  * These functions are provided the relevant smb server by the caller.
12246139Sjb150015  */
12256139Sjb150015 
12266139Sjb150015 void
12276139Sjb150015 smb_server_reconnection_check(smb_server_t *sv, smb_session_t *session)
12286139Sjb150015 {
12296139Sjb150015 	ASSERT(sv == session->s_server);
12306139Sjb150015 
12316139Sjb150015 	smb_session_reconnection_check(&sv->sv_nbt_daemon.ld_session_list,
12326139Sjb150015 	    session);
12336139Sjb150015 	smb_session_reconnection_check(&sv->sv_tcp_daemon.ld_session_list,
12346139Sjb150015 	    session);
12356139Sjb150015 }
12366139Sjb150015 
12376139Sjb150015 void
12386139Sjb150015 smb_server_get_cfg(smb_server_t *sv, smb_kmod_cfg_t *cfg)
12396139Sjb150015 {
12406139Sjb150015 	rw_enter(&sv->sv_cfg_lock, RW_READER);
12416139Sjb150015 	bcopy(&sv->sv_cfg, cfg, sizeof (*cfg));
12426139Sjb150015 	rw_exit(&sv->sv_cfg_lock);
12436139Sjb150015 }
12446139Sjb150015 
12456139Sjb150015 /*
124612508Samw@Sun.COM  *
124712508Samw@Sun.COM  */
124812508Samw@Sun.COM void
124912508Samw@Sun.COM smb_server_inc_nbt_sess(smb_server_t *sv)
125012508Samw@Sun.COM {
125112508Samw@Sun.COM 	SMB_SERVER_VALID(sv);
125212508Samw@Sun.COM 	atomic_inc_32(&sv->sv_nbt_sess);
125312508Samw@Sun.COM }
125412508Samw@Sun.COM 
125512508Samw@Sun.COM void
125612508Samw@Sun.COM smb_server_dec_nbt_sess(smb_server_t *sv)
125712508Samw@Sun.COM {
125812508Samw@Sun.COM 	SMB_SERVER_VALID(sv);
125912508Samw@Sun.COM 	atomic_dec_32(&sv->sv_nbt_sess);
126012508Samw@Sun.COM }
126112508Samw@Sun.COM 
126212508Samw@Sun.COM void
126312508Samw@Sun.COM smb_server_inc_tcp_sess(smb_server_t *sv)
126412508Samw@Sun.COM {
126512508Samw@Sun.COM 	SMB_SERVER_VALID(sv);
126612508Samw@Sun.COM 	atomic_inc_32(&sv->sv_tcp_sess);
126712508Samw@Sun.COM }
126812508Samw@Sun.COM 
126912508Samw@Sun.COM void
127012508Samw@Sun.COM smb_server_dec_tcp_sess(smb_server_t *sv)
127112508Samw@Sun.COM {
127212508Samw@Sun.COM 	SMB_SERVER_VALID(sv);
127312508Samw@Sun.COM 	atomic_dec_32(&sv->sv_tcp_sess);
127412508Samw@Sun.COM }
127512508Samw@Sun.COM 
127612508Samw@Sun.COM void
127712508Samw@Sun.COM smb_server_inc_users(smb_server_t *sv)
127812508Samw@Sun.COM {
127912508Samw@Sun.COM 	SMB_SERVER_VALID(sv);
128012508Samw@Sun.COM 	atomic_inc_32(&sv->sv_users);
128112508Samw@Sun.COM }
128212508Samw@Sun.COM 
128312508Samw@Sun.COM void
128412508Samw@Sun.COM smb_server_dec_users(smb_server_t *sv)
128512508Samw@Sun.COM {
128612508Samw@Sun.COM 	SMB_SERVER_VALID(sv);
128712508Samw@Sun.COM 	atomic_dec_32(&sv->sv_users);
128812508Samw@Sun.COM }
128912508Samw@Sun.COM 
129012508Samw@Sun.COM void
129112508Samw@Sun.COM smb_server_inc_trees(smb_server_t *sv)
129212508Samw@Sun.COM {
129312508Samw@Sun.COM 	SMB_SERVER_VALID(sv);
129412508Samw@Sun.COM 	atomic_inc_32(&sv->sv_trees);
129512508Samw@Sun.COM }
129612508Samw@Sun.COM 
129712508Samw@Sun.COM void
129812508Samw@Sun.COM smb_server_dec_trees(smb_server_t *sv)
129912508Samw@Sun.COM {
130012508Samw@Sun.COM 	SMB_SERVER_VALID(sv);
130112508Samw@Sun.COM 	atomic_dec_32(&sv->sv_trees);
130212508Samw@Sun.COM }
130312508Samw@Sun.COM 
130412508Samw@Sun.COM void
130512508Samw@Sun.COM smb_server_inc_files(smb_server_t *sv)
130612508Samw@Sun.COM {
130712508Samw@Sun.COM 	SMB_SERVER_VALID(sv);
130812508Samw@Sun.COM 	atomic_inc_32(&sv->sv_files);
130912508Samw@Sun.COM }
131012508Samw@Sun.COM 
131112508Samw@Sun.COM void
131212508Samw@Sun.COM smb_server_dec_files(smb_server_t *sv)
131312508Samw@Sun.COM {
131412508Samw@Sun.COM 	SMB_SERVER_VALID(sv);
131512508Samw@Sun.COM 	atomic_dec_32(&sv->sv_files);
131612508Samw@Sun.COM }
131712508Samw@Sun.COM 
131812508Samw@Sun.COM void
131912508Samw@Sun.COM smb_server_inc_pipes(smb_server_t *sv)
132012508Samw@Sun.COM {
132112508Samw@Sun.COM 	SMB_SERVER_VALID(sv);
132212508Samw@Sun.COM 	atomic_inc_32(&sv->sv_pipes);
132312508Samw@Sun.COM }
132412508Samw@Sun.COM 
132512508Samw@Sun.COM void
132612508Samw@Sun.COM smb_server_dec_pipes(smb_server_t *sv)
132712508Samw@Sun.COM {
132812508Samw@Sun.COM 	SMB_SERVER_VALID(sv);
132912508Samw@Sun.COM 	atomic_dec_32(&sv->sv_pipes);
133012508Samw@Sun.COM }
133112508Samw@Sun.COM 
133212508Samw@Sun.COM void
133312508Samw@Sun.COM smb_server_add_rxb(smb_server_t *sv, int64_t value)
133412508Samw@Sun.COM {
133512508Samw@Sun.COM 	SMB_SERVER_VALID(sv);
133612508Samw@Sun.COM 	atomic_add_64(&sv->sv_rxb, value);
133712508Samw@Sun.COM }
133812508Samw@Sun.COM 
133912508Samw@Sun.COM void
134012508Samw@Sun.COM smb_server_add_txb(smb_server_t *sv, int64_t value)
134112508Samw@Sun.COM {
134212508Samw@Sun.COM 	SMB_SERVER_VALID(sv);
134312508Samw@Sun.COM 	atomic_add_64(&sv->sv_txb, value);
134412508Samw@Sun.COM }
134512508Samw@Sun.COM 
134612508Samw@Sun.COM void
134712508Samw@Sun.COM smb_server_inc_req(smb_server_t *sv)
134812508Samw@Sun.COM {
134912508Samw@Sun.COM 	SMB_SERVER_VALID(sv);
135012508Samw@Sun.COM 	atomic_inc_64(&sv->sv_nreq);
135112508Samw@Sun.COM }
135212508Samw@Sun.COM 
135312508Samw@Sun.COM /*
13546139Sjb150015  * *****************************************************************************
13556139Sjb150015  * *************************** Static Functions ********************************
13566139Sjb150015  * *****************************************************************************
13576139Sjb150015  */
13586139Sjb150015 
13596139Sjb150015 static void
13606139Sjb150015 smb_server_timers(smb_thread_t *thread, void *arg)
13616139Sjb150015 {
13626139Sjb150015 	smb_server_t	*sv = (smb_server_t *)arg;
13636139Sjb150015 
13646139Sjb150015 	ASSERT(sv != NULL);
13656139Sjb150015 
13666139Sjb150015 	while (smb_thread_continue_timedwait(thread, 1 /* Seconds */)) {
13676139Sjb150015 		smb_session_timers(&sv->sv_nbt_daemon.ld_session_list);
13686139Sjb150015 		smb_session_timers(&sv->sv_tcp_daemon.ld_session_list);
13696139Sjb150015 	}
13706139Sjb150015 }
13716139Sjb150015 
13726139Sjb150015 /*
13736139Sjb150015  * smb_server_kstat_init
13746139Sjb150015  */
137512508Samw@Sun.COM static void
13766139Sjb150015 smb_server_kstat_init(smb_server_t *sv)
13776139Sjb150015 {
1378*12890SJoyce.McIntosh@Sun.COM 	char	name[KSTAT_STRLEN];
1379*12890SJoyce.McIntosh@Sun.COM 
138012508Samw@Sun.COM 	sv->sv_ksp = kstat_create_zone(SMBSRV_KSTAT_MODULE, sv->sv_zid,
138112508Samw@Sun.COM 	    SMBSRV_KSTAT_STATISTICS, SMBSRV_KSTAT_CLASS, KSTAT_TYPE_RAW,
138212508Samw@Sun.COM 	    sizeof (smbsrv_kstats_t), 0, sv->sv_zid);
13836139Sjb150015 
138412508Samw@Sun.COM 	if (sv->sv_ksp != NULL) {
138512508Samw@Sun.COM 		sv->sv_ksp->ks_update = smb_server_kstat_update;
138612508Samw@Sun.COM 		sv->sv_ksp->ks_private = sv;
138712508Samw@Sun.COM 		((smbsrv_kstats_t *)sv->sv_ksp->ks_data)->ks_start_time =
138812508Samw@Sun.COM 		    sv->sv_start_time;
138912508Samw@Sun.COM 		smb_dispatch_stats_init(
139012508Samw@Sun.COM 		    ((smbsrv_kstats_t *)sv->sv_ksp->ks_data)->ks_reqs);
13916139Sjb150015 		kstat_install(sv->sv_ksp);
139212508Samw@Sun.COM 	} else {
139312508Samw@Sun.COM 		cmn_err(CE_WARN, "SMB Server: Statistics unavailable");
13946139Sjb150015 	}
1395*12890SJoyce.McIntosh@Sun.COM 
1396*12890SJoyce.McIntosh@Sun.COM 	(void) snprintf(name, sizeof (name), "%s%d",
1397*12890SJoyce.McIntosh@Sun.COM 	    SMBSRV_KSTAT_NAME, sv->sv_zid);
1398*12890SJoyce.McIntosh@Sun.COM 
1399*12890SJoyce.McIntosh@Sun.COM 	sv->sv_legacy_ksp = kstat_create(SMBSRV_KSTAT_MODULE, sv->sv_zid,
1400*12890SJoyce.McIntosh@Sun.COM 	    name, SMBSRV_KSTAT_CLASS, KSTAT_TYPE_NAMED,
1401*12890SJoyce.McIntosh@Sun.COM 	    sizeof (smb_server_legacy_kstat_t) / sizeof (kstat_named_t), 0);
1402*12890SJoyce.McIntosh@Sun.COM 
1403*12890SJoyce.McIntosh@Sun.COM 	if (sv->sv_legacy_ksp != NULL) {
1404*12890SJoyce.McIntosh@Sun.COM 		smb_server_legacy_kstat_t *ksd;
1405*12890SJoyce.McIntosh@Sun.COM 
1406*12890SJoyce.McIntosh@Sun.COM 		ksd = sv->sv_legacy_ksp->ks_data;
1407*12890SJoyce.McIntosh@Sun.COM 
1408*12890SJoyce.McIntosh@Sun.COM 		(void) strlcpy(ksd->ls_files.name, "open_files",
1409*12890SJoyce.McIntosh@Sun.COM 		    sizeof (ksd->ls_files.name));
1410*12890SJoyce.McIntosh@Sun.COM 		ksd->ls_files.data_type = KSTAT_DATA_UINT32;
1411*12890SJoyce.McIntosh@Sun.COM 
1412*12890SJoyce.McIntosh@Sun.COM 		(void) strlcpy(ksd->ls_trees.name, "connections",
1413*12890SJoyce.McIntosh@Sun.COM 		    sizeof (ksd->ls_trees.name));
1414*12890SJoyce.McIntosh@Sun.COM 		ksd->ls_trees.data_type = KSTAT_DATA_UINT32;
1415*12890SJoyce.McIntosh@Sun.COM 
1416*12890SJoyce.McIntosh@Sun.COM 		(void) strlcpy(ksd->ls_users.name, "connections",
1417*12890SJoyce.McIntosh@Sun.COM 		    sizeof (ksd->ls_users.name));
1418*12890SJoyce.McIntosh@Sun.COM 		ksd->ls_users.data_type = KSTAT_DATA_UINT32;
1419*12890SJoyce.McIntosh@Sun.COM 
1420*12890SJoyce.McIntosh@Sun.COM 		mutex_init(&sv->sv_legacy_ksmtx, NULL, MUTEX_DEFAULT, NULL);
1421*12890SJoyce.McIntosh@Sun.COM 		sv->sv_legacy_ksp->ks_lock = &sv->sv_legacy_ksmtx;
1422*12890SJoyce.McIntosh@Sun.COM 		sv->sv_legacy_ksp->ks_update = smb_server_legacy_kstat_update;
1423*12890SJoyce.McIntosh@Sun.COM 		kstat_install(sv->sv_legacy_ksp);
1424*12890SJoyce.McIntosh@Sun.COM 	}
14256139Sjb150015 }
14266139Sjb150015 
14276139Sjb150015 /*
14286139Sjb150015  * smb_server_kstat_fini
14296139Sjb150015  */
14306139Sjb150015 static void
14316139Sjb150015 smb_server_kstat_fini(smb_server_t *sv)
14326139Sjb150015 {
1433*12890SJoyce.McIntosh@Sun.COM 	if (sv->sv_legacy_ksp != NULL) {
1434*12890SJoyce.McIntosh@Sun.COM 		kstat_delete(sv->sv_legacy_ksp);
1435*12890SJoyce.McIntosh@Sun.COM 		mutex_destroy(&sv->sv_legacy_ksmtx);
1436*12890SJoyce.McIntosh@Sun.COM 		sv->sv_legacy_ksp = NULL;
1437*12890SJoyce.McIntosh@Sun.COM 	}
1438*12890SJoyce.McIntosh@Sun.COM 
143912508Samw@Sun.COM 	if (sv->sv_ksp != NULL) {
14406139Sjb150015 		kstat_delete(sv->sv_ksp);
14416139Sjb150015 		sv->sv_ksp = NULL;
144212508Samw@Sun.COM 		smb_dispatch_stats_fini();
14436139Sjb150015 	}
14446139Sjb150015 }
14456139Sjb150015 
144612508Samw@Sun.COM /*
144712508Samw@Sun.COM  * smb_server_kstat_update
144812508Samw@Sun.COM  */
14496139Sjb150015 static int
145012508Samw@Sun.COM smb_server_kstat_update(kstat_t *ksp, int rw)
14516139Sjb150015 {
14526139Sjb150015 	smb_server_t	*sv;
145312508Samw@Sun.COM 	smbsrv_kstats_t	*ksd;
14546139Sjb150015 
145512508Samw@Sun.COM 	if (rw == KSTAT_READ) {
145612508Samw@Sun.COM 		sv = ksp->ks_private;
145711963SAfshin.Ardakani@Sun.COM 		SMB_SERVER_VALID(sv);
145812508Samw@Sun.COM 		ksd = (smbsrv_kstats_t *)ksp->ks_data;
145912508Samw@Sun.COM 		/*
146012508Samw@Sun.COM 		 * Counters
146112508Samw@Sun.COM 		 */
146212508Samw@Sun.COM 		ksd->ks_nbt_sess = sv->sv_nbt_sess;
146312508Samw@Sun.COM 		ksd->ks_tcp_sess = sv->sv_tcp_sess;
146412508Samw@Sun.COM 		ksd->ks_users = sv->sv_users;
146512508Samw@Sun.COM 		ksd->ks_trees = sv->sv_trees;
146612508Samw@Sun.COM 		ksd->ks_files = sv->sv_files;
146712508Samw@Sun.COM 		ksd->ks_pipes = sv->sv_pipes;
146812508Samw@Sun.COM 		/*
146912508Samw@Sun.COM 		 * Throughput
147012508Samw@Sun.COM 		 */
147112508Samw@Sun.COM 		ksd->ks_txb = sv->sv_txb;
147212508Samw@Sun.COM 		ksd->ks_rxb = sv->sv_rxb;
147312508Samw@Sun.COM 		ksd->ks_nreq = sv->sv_nreq;
147412508Samw@Sun.COM 		/*
147512508Samw@Sun.COM 		 * Busyness
147612508Samw@Sun.COM 		 */
147712508Samw@Sun.COM 		ksd->ks_maxreqs = sv->sv_cfg.skc_maxworkers;
147812508Samw@Sun.COM 		smb_srqueue_update(&sv->sv_srqueue,
147912508Samw@Sun.COM 		    &ksd->ks_utilization);
148012508Samw@Sun.COM 		/*
148112508Samw@Sun.COM 		 * Latency & Throughput of the requests
148212508Samw@Sun.COM 		 */
148312508Samw@Sun.COM 		smb_dispatch_stats_update(ksd->ks_reqs, 0, SMB_COM_NUM);
148412508Samw@Sun.COM 		return (0);
148512508Samw@Sun.COM 	}
148612508Samw@Sun.COM 	if (rw == KSTAT_WRITE)
148712508Samw@Sun.COM 		return (EACCES);
14886139Sjb150015 
148912508Samw@Sun.COM 	return (EIO);
14906139Sjb150015 }
14916139Sjb150015 
1492*12890SJoyce.McIntosh@Sun.COM static int
1493*12890SJoyce.McIntosh@Sun.COM smb_server_legacy_kstat_update(kstat_t *ksp, int rw)
1494*12890SJoyce.McIntosh@Sun.COM {
1495*12890SJoyce.McIntosh@Sun.COM 	smb_server_t			*sv;
1496*12890SJoyce.McIntosh@Sun.COM 	smb_server_legacy_kstat_t	*ksd;
1497*12890SJoyce.McIntosh@Sun.COM 	int				rc;
1498*12890SJoyce.McIntosh@Sun.COM 
1499*12890SJoyce.McIntosh@Sun.COM 	switch (rw) {
1500*12890SJoyce.McIntosh@Sun.COM 	case KSTAT_WRITE:
1501*12890SJoyce.McIntosh@Sun.COM 		rc = EACCES;
1502*12890SJoyce.McIntosh@Sun.COM 		break;
1503*12890SJoyce.McIntosh@Sun.COM 	case KSTAT_READ:
1504*12890SJoyce.McIntosh@Sun.COM 		if (!smb_server_lookup(&sv)) {
1505*12890SJoyce.McIntosh@Sun.COM 			ASSERT(MUTEX_HELD(ksp->ks_lock));
1506*12890SJoyce.McIntosh@Sun.COM 			ASSERT(sv->sv_legacy_ksp == ksp);
1507*12890SJoyce.McIntosh@Sun.COM 			ksd = (smb_server_legacy_kstat_t *)ksp->ks_data;
1508*12890SJoyce.McIntosh@Sun.COM 			ksd->ls_files.value.ui32 = sv->sv_files + sv->sv_pipes;
1509*12890SJoyce.McIntosh@Sun.COM 			ksd->ls_trees.value.ui32 = sv->sv_trees;
1510*12890SJoyce.McIntosh@Sun.COM 			ksd->ls_users.value.ui32 = sv->sv_users;
1511*12890SJoyce.McIntosh@Sun.COM 			smb_server_release(sv);
1512*12890SJoyce.McIntosh@Sun.COM 			rc = 0;
1513*12890SJoyce.McIntosh@Sun.COM 			break;
1514*12890SJoyce.McIntosh@Sun.COM 		}
1515*12890SJoyce.McIntosh@Sun.COM 		_NOTE(FALLTHRU)
1516*12890SJoyce.McIntosh@Sun.COM 	default:
1517*12890SJoyce.McIntosh@Sun.COM 		rc = EIO;
1518*12890SJoyce.McIntosh@Sun.COM 		break;
1519*12890SJoyce.McIntosh@Sun.COM 	}
1520*12890SJoyce.McIntosh@Sun.COM 	return (rc);
1521*12890SJoyce.McIntosh@Sun.COM 
1522*12890SJoyce.McIntosh@Sun.COM }
1523*12890SJoyce.McIntosh@Sun.COM 
15246139Sjb150015 /*
15256139Sjb150015  * The mutex of the server must have been entered before calling this function.
15266139Sjb150015  */
15276139Sjb150015 static void
152811963SAfshin.Ardakani@Sun.COM smb_server_shutdown(smb_server_t *sv)
15296139Sjb150015 {
153011963SAfshin.Ardakani@Sun.COM 	SMB_SERVER_VALID(sv);
15316139Sjb150015 
15327052Samw 	smb_opipe_door_close();
15336139Sjb150015 	smb_thread_stop(&sv->si_thread_timers);
153411963SAfshin.Ardakani@Sun.COM 	smb_kdoor_close();
153512508Samw@Sun.COM 	smb_kshare_door_fini(sv->sv_lmshrd);
15366849Sjb150015 	sv->sv_lmshrd = NULL;
153712508Samw@Sun.COM 	smb_export_stop();
15386139Sjb150015 	smb_server_fsop_stop(sv);
15397588Samw@Sun.COM 
15406139Sjb150015 	if (sv->sv_session) {
15416139Sjb150015 		smb_session_delete(sv->sv_session);
15426139Sjb150015 		sv->sv_session = NULL;
15436139Sjb150015 	}
15447588Samw@Sun.COM 
15457588Samw@Sun.COM 	if (sv->sv_thread_pool) {
15467588Samw@Sun.COM 		taskq_destroy(sv->sv_thread_pool);
15477588Samw@Sun.COM 		sv->sv_thread_pool = NULL;
15487588Samw@Sun.COM 	}
15496139Sjb150015 }
15506139Sjb150015 
15516139Sjb150015 static int
15526139Sjb150015 smb_server_listen(
15536139Sjb150015     smb_server_t		*sv,
15546139Sjb150015     smb_listener_daemon_t	*ld,
15556139Sjb150015     in_port_t			port,
15568670SJose.Borrego@Sun.COM     int				family,
15576139Sjb150015     int				pthread_create_error)
15586139Sjb150015 {
155911963SAfshin.Ardakani@Sun.COM 	int			rc = 0;
15608348SEric.Yu@Sun.COM 	ksocket_t		s_so;
156111963SAfshin.Ardakani@Sun.COM 	uint32_t		on;
156211963SAfshin.Ardakani@Sun.COM 	uint32_t		off;
156311963SAfshin.Ardakani@Sun.COM 	uint32_t		txbuf_size;
15646139Sjb150015 	smb_session_t		*session;
15656139Sjb150015 
15666139Sjb150015 	if (pthread_create_error) {
15676139Sjb150015 		/*
15686139Sjb150015 		 * Delete the last session created. The user space thread
15696139Sjb150015 		 * creation failed.
15706139Sjb150015 		 */
15716139Sjb150015 		smb_session_list_delete_tail(&ld->ld_session_list);
15726139Sjb150015 	}
15736139Sjb150015 
15746139Sjb150015 	if (ld->ld_so == NULL) {
15756139Sjb150015 		/* First time listener */
15768670SJose.Borrego@Sun.COM 		if (family == AF_INET) {
15778670SJose.Borrego@Sun.COM 			ld->ld_sin.sin_family = (uint32_t)family;
15788670SJose.Borrego@Sun.COM 			ld->ld_sin.sin_port = htons(port);
15798670SJose.Borrego@Sun.COM 			ld->ld_sin.sin_addr.s_addr = htonl(INADDR_ANY);
15808670SJose.Borrego@Sun.COM 		} else {
15818670SJose.Borrego@Sun.COM 			ld->ld_sin6.sin6_family = (uint32_t)family;
15828670SJose.Borrego@Sun.COM 			ld->ld_sin6.sin6_port = htons(port);
15838670SJose.Borrego@Sun.COM 			(void) memset(&ld->ld_sin6.sin6_addr.s6_addr, 0,
15848670SJose.Borrego@Sun.COM 			    sizeof (ld->ld_sin6.sin6_addr.s6_addr));
15858670SJose.Borrego@Sun.COM 		}
158611963SAfshin.Ardakani@Sun.COM 
15878670SJose.Borrego@Sun.COM 		ld->ld_so = smb_socreate(family, SOCK_STREAM, 0);
158811963SAfshin.Ardakani@Sun.COM 		if (ld->ld_so == NULL) {
158911963SAfshin.Ardakani@Sun.COM 			cmn_err(CE_WARN, "port %d: socket create failed", port);
159011963SAfshin.Ardakani@Sun.COM 			return (ENOMEM);
159111963SAfshin.Ardakani@Sun.COM 		}
15926139Sjb150015 
159311963SAfshin.Ardakani@Sun.COM 		off = 0;
159411963SAfshin.Ardakani@Sun.COM 		(void) ksocket_setsockopt(ld->ld_so, SOL_SOCKET,
159511963SAfshin.Ardakani@Sun.COM 		    SO_MAC_EXEMPT, &off, sizeof (off), CRED());
159611963SAfshin.Ardakani@Sun.COM 
159711963SAfshin.Ardakani@Sun.COM 		on = 1;
159811963SAfshin.Ardakani@Sun.COM 		(void) ksocket_setsockopt(ld->ld_so, SOL_SOCKET,
159911963SAfshin.Ardakani@Sun.COM 		    SO_REUSEADDR, &on, sizeof (on), CRED());
16009021Samw@Sun.COM 
160111963SAfshin.Ardakani@Sun.COM 		if (family == AF_INET) {
160211963SAfshin.Ardakani@Sun.COM 			rc = ksocket_bind(ld->ld_so,
160311963SAfshin.Ardakani@Sun.COM 			    (struct sockaddr *)&ld->ld_sin,
160411963SAfshin.Ardakani@Sun.COM 			    sizeof (ld->ld_sin), CRED());
16056139Sjb150015 		} else {
160611963SAfshin.Ardakani@Sun.COM 			rc = ksocket_bind(ld->ld_so,
160711963SAfshin.Ardakani@Sun.COM 			    (struct sockaddr *)&ld->ld_sin6,
160811963SAfshin.Ardakani@Sun.COM 			    sizeof (ld->ld_sin6), CRED());
160911963SAfshin.Ardakani@Sun.COM 		}
161011963SAfshin.Ardakani@Sun.COM 
161111963SAfshin.Ardakani@Sun.COM 		if (rc != 0) {
161211963SAfshin.Ardakani@Sun.COM 			cmn_err(CE_WARN, "port %d: bind failed (%d)", port, rc);
161311963SAfshin.Ardakani@Sun.COM 			smb_server_listen_fini(ld);
161411963SAfshin.Ardakani@Sun.COM 			return (rc);
161511963SAfshin.Ardakani@Sun.COM 		}
161611963SAfshin.Ardakani@Sun.COM 
161711963SAfshin.Ardakani@Sun.COM 		rc =  ksocket_listen(ld->ld_so, 20, CRED());
161811963SAfshin.Ardakani@Sun.COM 		if (rc < 0) {
161911963SAfshin.Ardakani@Sun.COM 			cmn_err(CE_WARN, "port %d: listen failed", port);
162011963SAfshin.Ardakani@Sun.COM 			smb_server_listen_fini(ld);
162111963SAfshin.Ardakani@Sun.COM 			return (rc);
16226139Sjb150015 		}
16236139Sjb150015 	}
16246139Sjb150015 
16256139Sjb150015 	DTRACE_PROBE1(so__wait__accept, struct sonode *, ld->ld_so);
16266139Sjb150015 
16276139Sjb150015 	for (;;) {
162811963SAfshin.Ardakani@Sun.COM 		if (smb_server_is_stopping()) {
162911963SAfshin.Ardakani@Sun.COM 			rc = ECANCELED;
163011963SAfshin.Ardakani@Sun.COM 			break;
163111963SAfshin.Ardakani@Sun.COM 		}
163211963SAfshin.Ardakani@Sun.COM 
16338348SEric.Yu@Sun.COM 		rc = ksocket_accept(ld->ld_so, NULL, NULL, &s_so, CRED());
163411963SAfshin.Ardakani@Sun.COM 		if (rc != 0)
163511963SAfshin.Ardakani@Sun.COM 			break;
163611963SAfshin.Ardakani@Sun.COM 
163711963SAfshin.Ardakani@Sun.COM 		if (smb_server_is_stopping()) {
163811963SAfshin.Ardakani@Sun.COM 			smb_soshutdown(s_so);
163911963SAfshin.Ardakani@Sun.COM 			smb_sodestroy(s_so);
164011963SAfshin.Ardakani@Sun.COM 			rc = ECANCELED;
164111963SAfshin.Ardakani@Sun.COM 			break;
164211963SAfshin.Ardakani@Sun.COM 		}
16436139Sjb150015 
164411963SAfshin.Ardakani@Sun.COM 		DTRACE_PROBE1(so__accept, struct sonode *, s_so);
164511963SAfshin.Ardakani@Sun.COM 
164611963SAfshin.Ardakani@Sun.COM 		on = 1;
164711963SAfshin.Ardakani@Sun.COM 		(void) ksocket_setsockopt(s_so, IPPROTO_TCP, TCP_NODELAY,
164811963SAfshin.Ardakani@Sun.COM 		    &on, sizeof (on), CRED());
164911963SAfshin.Ardakani@Sun.COM 
165011963SAfshin.Ardakani@Sun.COM 		on = 1;
165111963SAfshin.Ardakani@Sun.COM 		(void) ksocket_setsockopt(s_so, SOL_SOCKET, SO_KEEPALIVE,
165211963SAfshin.Ardakani@Sun.COM 		    &on, sizeof (on), CRED());
16536139Sjb150015 
165411963SAfshin.Ardakani@Sun.COM 		txbuf_size = 128*1024;
165511963SAfshin.Ardakani@Sun.COM 		(void) ksocket_setsockopt(s_so, SOL_SOCKET, SO_SNDBUF,
165611963SAfshin.Ardakani@Sun.COM 		    (const void *)&txbuf_size, sizeof (txbuf_size), CRED());
165711963SAfshin.Ardakani@Sun.COM 
165811963SAfshin.Ardakani@Sun.COM 		/*
165911963SAfshin.Ardakani@Sun.COM 		 * Create a session for this connection.
166011963SAfshin.Ardakani@Sun.COM 		 */
166111963SAfshin.Ardakani@Sun.COM 		session = smb_session_create(s_so, port, sv, family);
166211963SAfshin.Ardakani@Sun.COM 		if (session) {
166311963SAfshin.Ardakani@Sun.COM 			smb_session_list_append(&ld->ld_session_list, session);
166411963SAfshin.Ardakani@Sun.COM 			rc = 0;
166511963SAfshin.Ardakani@Sun.COM 			break;
166611963SAfshin.Ardakani@Sun.COM 		} else {
166711963SAfshin.Ardakani@Sun.COM 			smb_soshutdown(s_so);
166811963SAfshin.Ardakani@Sun.COM 			smb_sodestroy(s_so);
16696139Sjb150015 		}
167011963SAfshin.Ardakani@Sun.COM 	}
167111963SAfshin.Ardakani@Sun.COM 
167211963SAfshin.Ardakani@Sun.COM 	if (rc != 0)
167311963SAfshin.Ardakani@Sun.COM 		smb_server_listen_fini(ld);
167411963SAfshin.Ardakani@Sun.COM 
167511963SAfshin.Ardakani@Sun.COM 	return (rc);
167611963SAfshin.Ardakani@Sun.COM }
167711963SAfshin.Ardakani@Sun.COM 
167811963SAfshin.Ardakani@Sun.COM static void
167911963SAfshin.Ardakani@Sun.COM smb_server_listen_fini(smb_listener_daemon_t *ld)
168011963SAfshin.Ardakani@Sun.COM {
168111963SAfshin.Ardakani@Sun.COM 	if (ld->ld_so != NULL) {
16826139Sjb150015 		smb_session_list_signal(&ld->ld_session_list);
16836139Sjb150015 		smb_soshutdown(ld->ld_so);
16846139Sjb150015 		smb_sodestroy(ld->ld_so);
16856139Sjb150015 		ld->ld_so = NULL;
168611963SAfshin.Ardakani@Sun.COM 	}
168711963SAfshin.Ardakani@Sun.COM }
168811963SAfshin.Ardakani@Sun.COM 
168911963SAfshin.Ardakani@Sun.COM static kt_did_t
169011963SAfshin.Ardakani@Sun.COM smb_server_listener_tid(smb_listener_daemon_t *ld)
169111963SAfshin.Ardakani@Sun.COM {
1692*12890SJoyce.McIntosh@Sun.COM 	kt_did_t	tid = 0;
169311963SAfshin.Ardakani@Sun.COM 
169411963SAfshin.Ardakani@Sun.COM 	if (ld->ld_ktdid != 0) {
169511963SAfshin.Ardakani@Sun.COM 		tid = ld->ld_ktdid;
169611963SAfshin.Ardakani@Sun.COM 		ld->ld_ktdid = 0;
16976139Sjb150015 	}
16986139Sjb150015 
169911963SAfshin.Ardakani@Sun.COM 	return (tid);
17006139Sjb150015 }
17016139Sjb150015 
17026139Sjb150015 /*
17036139Sjb150015  * smb_server_lookup
17046139Sjb150015  *
17056139Sjb150015  * This function tries to find the server associated with the zone of the
17066139Sjb150015  * caller.
17076139Sjb150015  */
17086139Sjb150015 static int
17096139Sjb150015 smb_server_lookup(smb_server_t **psv)
17106139Sjb150015 {
17116139Sjb150015 	zoneid_t	zid;
17126139Sjb150015 	smb_server_t	*sv;
17136139Sjb150015 
17146139Sjb150015 	zid = getzoneid();
17156139Sjb150015 
17166139Sjb150015 	smb_llist_enter(&smb_servers, RW_READER);
17176139Sjb150015 	sv = smb_llist_head(&smb_servers);
17186139Sjb150015 	while (sv) {
171911963SAfshin.Ardakani@Sun.COM 		SMB_SERVER_VALID(sv);
17206139Sjb150015 		if (sv->sv_zid == zid) {
17216139Sjb150015 			mutex_enter(&sv->sv_mutex);
17226139Sjb150015 			if (sv->sv_state != SMB_SERVER_STATE_DELETING) {
17236139Sjb150015 				sv->sv_refcnt++;
17246139Sjb150015 				mutex_exit(&sv->sv_mutex);
17256139Sjb150015 				smb_llist_exit(&smb_servers);
17266139Sjb150015 				*psv = sv;
17276139Sjb150015 				return (0);
17286139Sjb150015 			}
17296139Sjb150015 			mutex_exit(&sv->sv_mutex);
17306139Sjb150015 			break;
17316139Sjb150015 		}
17326139Sjb150015 		sv = smb_llist_next(&smb_servers, sv);
17336139Sjb150015 	}
17346139Sjb150015 	smb_llist_exit(&smb_servers);
17356139Sjb150015 	return (EPERM);
17366139Sjb150015 }
17376139Sjb150015 
17386139Sjb150015 /*
17396139Sjb150015  * smb_server_release
17406139Sjb150015  *
17416139Sjb150015  * This function decrements the reference count of the server and signals its
17426139Sjb150015  * condition variable if the state of the server is SMB_SERVER_STATE_DELETING.
17436139Sjb150015  */
17446139Sjb150015 static void
17456139Sjb150015 smb_server_release(smb_server_t *sv)
17466139Sjb150015 {
174711963SAfshin.Ardakani@Sun.COM 	SMB_SERVER_VALID(sv);
17486139Sjb150015 
17496139Sjb150015 	mutex_enter(&sv->sv_mutex);
17506139Sjb150015 	ASSERT(sv->sv_refcnt);
17516139Sjb150015 	sv->sv_refcnt--;
17526139Sjb150015 	if ((sv->sv_refcnt == 0) && (sv->sv_state == SMB_SERVER_STATE_DELETING))
17536139Sjb150015 		cv_signal(&sv->sv_cv);
17546139Sjb150015 	mutex_exit(&sv->sv_mutex);
17556139Sjb150015 }
17566139Sjb150015 
175710122SJordan.Brown@Sun.COM /*
175810122SJordan.Brown@Sun.COM  * Enumerate the users associated with a session list.
175910122SJordan.Brown@Sun.COM  */
176010122SJordan.Brown@Sun.COM static void
176110122SJordan.Brown@Sun.COM smb_server_enum_private(smb_session_list_t *se, smb_svcenum_t *svcenum)
17626139Sjb150015 {
176310122SJordan.Brown@Sun.COM 	smb_session_t	*sn;
176410122SJordan.Brown@Sun.COM 	smb_llist_t	*ulist;
176510122SJordan.Brown@Sun.COM 	smb_user_t	*user;
176610122SJordan.Brown@Sun.COM 	int		rc = 0;
17676139Sjb150015 
17686139Sjb150015 	rw_enter(&se->se_lock, RW_READER);
17696139Sjb150015 	sn = list_head(&se->se_act.lst);
177010122SJordan.Brown@Sun.COM 
177110122SJordan.Brown@Sun.COM 	while (sn != NULL) {
17726139Sjb150015 		ASSERT(sn->s_magic == SMB_SESSION_MAGIC);
17736139Sjb150015 		ulist = &sn->s_user_list;
17746139Sjb150015 		smb_llist_enter(ulist, RW_READER);
17756139Sjb150015 		user = smb_llist_head(ulist);
177610122SJordan.Brown@Sun.COM 
177710122SJordan.Brown@Sun.COM 		while (user != NULL) {
177810122SJordan.Brown@Sun.COM 			if (smb_user_hold(user)) {
177910122SJordan.Brown@Sun.COM 				rc = smb_user_enum(user, svcenum);
178010122SJordan.Brown@Sun.COM 				smb_user_release(user);
178110122SJordan.Brown@Sun.COM 			}
178210122SJordan.Brown@Sun.COM 
178310122SJordan.Brown@Sun.COM 			user = smb_llist_next(ulist, user);
178410122SJordan.Brown@Sun.COM 		}
178510122SJordan.Brown@Sun.COM 
178610122SJordan.Brown@Sun.COM 		smb_llist_exit(ulist);
178710122SJordan.Brown@Sun.COM 
178810122SJordan.Brown@Sun.COM 		if (rc != 0)
178910122SJordan.Brown@Sun.COM 			break;
179010122SJordan.Brown@Sun.COM 
179110122SJordan.Brown@Sun.COM 		sn = list_next(&se->se_act.lst, sn);
179210122SJordan.Brown@Sun.COM 	}
179310122SJordan.Brown@Sun.COM 
179410122SJordan.Brown@Sun.COM 	rw_exit(&se->se_lock);
179510122SJordan.Brown@Sun.COM }
179610122SJordan.Brown@Sun.COM 
179710122SJordan.Brown@Sun.COM /*
179810122SJordan.Brown@Sun.COM  * Disconnect sessions associated with the specified client and username.
179910122SJordan.Brown@Sun.COM  * Empty strings are treated as wildcards.
180010122SJordan.Brown@Sun.COM  */
180110122SJordan.Brown@Sun.COM static int
180210122SJordan.Brown@Sun.COM smb_server_sesion_disconnect(smb_session_list_t *se,
180310122SJordan.Brown@Sun.COM     const char *client, const char *name)
180410122SJordan.Brown@Sun.COM {
180510122SJordan.Brown@Sun.COM 	smb_session_t	*sn;
180610122SJordan.Brown@Sun.COM 	smb_llist_t	*ulist;
180710122SJordan.Brown@Sun.COM 	smb_user_t	*user;
180810122SJordan.Brown@Sun.COM 	boolean_t	match;
180910122SJordan.Brown@Sun.COM 	int		count = 0;
181010122SJordan.Brown@Sun.COM 
181110122SJordan.Brown@Sun.COM 	rw_enter(&se->se_lock, RW_READER);
181210122SJordan.Brown@Sun.COM 	sn = list_head(&se->se_act.lst);
181310122SJordan.Brown@Sun.COM 
181410122SJordan.Brown@Sun.COM 	while (sn != NULL) {
181510122SJordan.Brown@Sun.COM 		ASSERT(sn->s_magic == SMB_SESSION_MAGIC);
181610122SJordan.Brown@Sun.COM 
181710122SJordan.Brown@Sun.COM 		if ((*client != '\0') && (!smb_session_isclient(sn, client))) {
181810122SJordan.Brown@Sun.COM 			sn = list_next(&se->se_act.lst, sn);
181910122SJordan.Brown@Sun.COM 			continue;
182010122SJordan.Brown@Sun.COM 		}
182110122SJordan.Brown@Sun.COM 
182210122SJordan.Brown@Sun.COM 		ulist = &sn->s_user_list;
182310122SJordan.Brown@Sun.COM 		smb_llist_enter(ulist, RW_READER);
182410122SJordan.Brown@Sun.COM 		user = smb_llist_head(ulist);
182510122SJordan.Brown@Sun.COM 
182610122SJordan.Brown@Sun.COM 		while (user != NULL) {
182710122SJordan.Brown@Sun.COM 			if (smb_user_hold(user)) {
182810122SJordan.Brown@Sun.COM 				match = (*name == '\0');
182910122SJordan.Brown@Sun.COM 				if (!match)
183010122SJordan.Brown@Sun.COM 					match = smb_user_namecmp(user, name);
183110122SJordan.Brown@Sun.COM 
183210122SJordan.Brown@Sun.COM 				if (match) {
183310122SJordan.Brown@Sun.COM 					smb_llist_exit(ulist);
183410122SJordan.Brown@Sun.COM 					smb_user_logoff(user);
183510122SJordan.Brown@Sun.COM 					++count;
183610122SJordan.Brown@Sun.COM 					smb_user_release(user);
183710122SJordan.Brown@Sun.COM 					smb_llist_enter(ulist, RW_READER);
183810122SJordan.Brown@Sun.COM 					user = smb_llist_head(ulist);
183910122SJordan.Brown@Sun.COM 					continue;
18406139Sjb150015 				}
184110122SJordan.Brown@Sun.COM 
184210122SJordan.Brown@Sun.COM 				smb_user_release(user);
18436139Sjb150015 			}
184410122SJordan.Brown@Sun.COM 
18456139Sjb150015 			user = smb_llist_next(ulist, user);
18466139Sjb150015 		}
184710122SJordan.Brown@Sun.COM 
18486139Sjb150015 		smb_llist_exit(ulist);
18497961SNatalie.Li@Sun.COM 		sn = list_next(&se->se_act.lst, sn);
18506139Sjb150015 	}
185110122SJordan.Brown@Sun.COM 
18526139Sjb150015 	rw_exit(&se->se_lock);
185310122SJordan.Brown@Sun.COM 	return (count);
185410122SJordan.Brown@Sun.COM }
185510122SJordan.Brown@Sun.COM 
185610122SJordan.Brown@Sun.COM /*
185710122SJordan.Brown@Sun.COM  * Close a file by its unique id.
185810122SJordan.Brown@Sun.COM  */
185910122SJordan.Brown@Sun.COM static int
186010122SJordan.Brown@Sun.COM smb_server_fclose(smb_session_list_t *se, uint32_t uniqid)
186110122SJordan.Brown@Sun.COM {
186210122SJordan.Brown@Sun.COM 	smb_session_t	*sn;
186310122SJordan.Brown@Sun.COM 	smb_llist_t	*ulist;
186410122SJordan.Brown@Sun.COM 	smb_user_t	*user;
186510122SJordan.Brown@Sun.COM 	int		rc = ENOENT;
186610122SJordan.Brown@Sun.COM 
186710122SJordan.Brown@Sun.COM 	rw_enter(&se->se_lock, RW_READER);
186810122SJordan.Brown@Sun.COM 	sn = list_head(&se->se_act.lst);
186910122SJordan.Brown@Sun.COM 
187010122SJordan.Brown@Sun.COM 	while ((sn != NULL) && (rc == ENOENT)) {
187110122SJordan.Brown@Sun.COM 		ASSERT(sn->s_magic == SMB_SESSION_MAGIC);
187210122SJordan.Brown@Sun.COM 		ulist = &sn->s_user_list;
187310122SJordan.Brown@Sun.COM 		smb_llist_enter(ulist, RW_READER);
187410122SJordan.Brown@Sun.COM 		user = smb_llist_head(ulist);
187510122SJordan.Brown@Sun.COM 
187610122SJordan.Brown@Sun.COM 		while ((user != NULL) && (rc == ENOENT)) {
187710122SJordan.Brown@Sun.COM 			if (smb_user_hold(user)) {
187810122SJordan.Brown@Sun.COM 				rc = smb_user_fclose(user, uniqid);
187910122SJordan.Brown@Sun.COM 				smb_user_release(user);
188010122SJordan.Brown@Sun.COM 			}
188110122SJordan.Brown@Sun.COM 
188210122SJordan.Brown@Sun.COM 			user = smb_llist_next(ulist, user);
188310122SJordan.Brown@Sun.COM 		}
188410122SJordan.Brown@Sun.COM 
188510122SJordan.Brown@Sun.COM 		smb_llist_exit(ulist);
188610122SJordan.Brown@Sun.COM 		sn = list_next(&se->se_act.lst, sn);
188710122SJordan.Brown@Sun.COM 	}
188810122SJordan.Brown@Sun.COM 
188910122SJordan.Brown@Sun.COM 	rw_exit(&se->se_lock);
189010122SJordan.Brown@Sun.COM 	return (rc);
18916139Sjb150015 }
18926139Sjb150015 
18936139Sjb150015 static void
18949832Samw@Sun.COM smb_server_store_cfg(smb_server_t *sv, smb_ioc_cfg_t *ioc)
18956139Sjb150015 {
18969832Samw@Sun.COM 	if (ioc->maxconnections == 0)
18979832Samw@Sun.COM 		ioc->maxconnections = 0xFFFFFFFF;
18986139Sjb150015 
18996139Sjb150015 	smb_session_correct_keep_alive_values(
19009832Samw@Sun.COM 	    &sv->sv_nbt_daemon.ld_session_list, ioc->keepalive);
19016139Sjb150015 	smb_session_correct_keep_alive_values(
19029832Samw@Sun.COM 	    &sv->sv_tcp_daemon.ld_session_list, ioc->keepalive);
19036139Sjb150015 
19049832Samw@Sun.COM 	sv->sv_cfg.skc_maxworkers = ioc->maxworkers;
19059832Samw@Sun.COM 	sv->sv_cfg.skc_maxconnections = ioc->maxconnections;
19069832Samw@Sun.COM 	sv->sv_cfg.skc_keepalive = ioc->keepalive;
19079832Samw@Sun.COM 	sv->sv_cfg.skc_restrict_anon = ioc->restrict_anon;
19089832Samw@Sun.COM 	sv->sv_cfg.skc_signing_enable = ioc->signing_enable;
19099832Samw@Sun.COM 	sv->sv_cfg.skc_signing_required = ioc->signing_required;
19109832Samw@Sun.COM 	sv->sv_cfg.skc_oplock_enable = ioc->oplock_enable;
19119832Samw@Sun.COM 	sv->sv_cfg.skc_sync_enable = ioc->sync_enable;
19129832Samw@Sun.COM 	sv->sv_cfg.skc_secmode = ioc->secmode;
19139832Samw@Sun.COM 	sv->sv_cfg.skc_ipv6_enable = ioc->ipv6_enable;
1914*12890SJoyce.McIntosh@Sun.COM 	sv->sv_cfg.skc_print_enable = ioc->print_enable;
191512508Samw@Sun.COM 	sv->sv_cfg.skc_execflags = ioc->exec_flags;
191612508Samw@Sun.COM 	sv->sv_cfg.skc_version = ioc->version;
19179832Samw@Sun.COM 	(void) strlcpy(sv->sv_cfg.skc_nbdomain, ioc->nbdomain,
19189832Samw@Sun.COM 	    sizeof (sv->sv_cfg.skc_nbdomain));
19199832Samw@Sun.COM 	(void) strlcpy(sv->sv_cfg.skc_fqdn, ioc->fqdn,
19209832Samw@Sun.COM 	    sizeof (sv->sv_cfg.skc_fqdn));
19219832Samw@Sun.COM 	(void) strlcpy(sv->sv_cfg.skc_hostname, ioc->hostname,
19229832Samw@Sun.COM 	    sizeof (sv->sv_cfg.skc_hostname));
19239832Samw@Sun.COM 	(void) strlcpy(sv->sv_cfg.skc_system_comment, ioc->system_comment,
19249832Samw@Sun.COM 	    sizeof (sv->sv_cfg.skc_system_comment));
19256139Sjb150015 }
19266139Sjb150015 
19276139Sjb150015 static int
19286139Sjb150015 smb_server_fsop_start(smb_server_t *sv)
19296139Sjb150015 {
19306139Sjb150015 	int	error;
19316139Sjb150015 
19326139Sjb150015 	error = smb_node_root_init(rootdir, sv, &sv->si_root_smb_node);
19336139Sjb150015 	if (error != 0)
19346139Sjb150015 		sv->si_root_smb_node = NULL;
19356139Sjb150015 
19366139Sjb150015 	return (error);
19376139Sjb150015 }
19386139Sjb150015 
19396139Sjb150015 static void
19406139Sjb150015 smb_server_fsop_stop(smb_server_t *sv)
19416139Sjb150015 {
19426139Sjb150015 	if (sv->si_root_smb_node != NULL) {
19436139Sjb150015 		smb_node_release(sv->si_root_smb_node);
19446139Sjb150015 		sv->si_root_smb_node = NULL;
19456139Sjb150015 	}
19466139Sjb150015 }
194711963SAfshin.Ardakani@Sun.COM 
194811963SAfshin.Ardakani@Sun.COM static void
194911963SAfshin.Ardakani@Sun.COM smb_server_signal_listeners(smb_server_t *sv)
195011963SAfshin.Ardakani@Sun.COM {
195111963SAfshin.Ardakani@Sun.COM 	SMB_SERVER_VALID(sv);
195211963SAfshin.Ardakani@Sun.COM 	ASSERT(sv->sv_state == SMB_SERVER_STATE_STOPPING);
195311963SAfshin.Ardakani@Sun.COM 	ASSERT(MUTEX_HELD(&sv->sv_mutex));
195411963SAfshin.Ardakani@Sun.COM 
195511963SAfshin.Ardakani@Sun.COM 	smb_event_cancel(sv, 0);
195611963SAfshin.Ardakani@Sun.COM 
195711963SAfshin.Ardakani@Sun.COM 	if (sv->sv_nbt_daemon.ld_kth != NULL) {
195811963SAfshin.Ardakani@Sun.COM 		tsignal(sv->sv_nbt_daemon.ld_kth, SIGINT);
195911963SAfshin.Ardakani@Sun.COM 		sv->sv_nbt_daemon.ld_kth = NULL;
196011963SAfshin.Ardakani@Sun.COM 	}
196111963SAfshin.Ardakani@Sun.COM 
196211963SAfshin.Ardakani@Sun.COM 	if (sv->sv_tcp_daemon.ld_kth != NULL) {
196311963SAfshin.Ardakani@Sun.COM 		tsignal(sv->sv_tcp_daemon.ld_kth, SIGINT);
196411963SAfshin.Ardakani@Sun.COM 		sv->sv_tcp_daemon.ld_kth = NULL;
196511963SAfshin.Ardakani@Sun.COM 	}
196611963SAfshin.Ardakani@Sun.COM }
196711963SAfshin.Ardakani@Sun.COM 
196811963SAfshin.Ardakani@Sun.COM smb_event_t *
1969*12890SJoyce.McIntosh@Sun.COM smb_event_create(int timeout)
197011963SAfshin.Ardakani@Sun.COM {
197111963SAfshin.Ardakani@Sun.COM 	smb_server_t	*sv;
197211963SAfshin.Ardakani@Sun.COM 	smb_event_t	*event;
197311963SAfshin.Ardakani@Sun.COM 
197411963SAfshin.Ardakani@Sun.COM 	if (smb_server_is_stopping())
197511963SAfshin.Ardakani@Sun.COM 		return (NULL);
197611963SAfshin.Ardakani@Sun.COM 
197711963SAfshin.Ardakani@Sun.COM 	if (smb_server_lookup(&sv) != 0) {
197811963SAfshin.Ardakani@Sun.COM 		cmn_err(CE_NOTE, "smb_event_create failed");
197911963SAfshin.Ardakani@Sun.COM 		return (NULL);
198011963SAfshin.Ardakani@Sun.COM 	}
198111963SAfshin.Ardakani@Sun.COM 
198211963SAfshin.Ardakani@Sun.COM 	event = kmem_cache_alloc(sv->si_cache_event, KM_SLEEP);
198311963SAfshin.Ardakani@Sun.COM 
198411963SAfshin.Ardakani@Sun.COM 	bzero(event, sizeof (smb_event_t));
198511963SAfshin.Ardakani@Sun.COM 	mutex_init(&event->se_mutex, NULL, MUTEX_DEFAULT, NULL);
198611963SAfshin.Ardakani@Sun.COM 	cv_init(&event->se_cv, NULL, CV_DEFAULT, NULL);
198711963SAfshin.Ardakani@Sun.COM 	event->se_magic = SMB_EVENT_MAGIC;
198811963SAfshin.Ardakani@Sun.COM 	event->se_txid = smb_event_alloc_txid();
198911963SAfshin.Ardakani@Sun.COM 	event->se_server = sv;
1990*12890SJoyce.McIntosh@Sun.COM 	event->se_timeout = timeout;
199111963SAfshin.Ardakani@Sun.COM 
199211963SAfshin.Ardakani@Sun.COM 	smb_llist_enter(&sv->sv_event_list, RW_WRITER);
199311963SAfshin.Ardakani@Sun.COM 	smb_llist_insert_tail(&sv->sv_event_list, event);
199411963SAfshin.Ardakani@Sun.COM 	smb_llist_exit(&sv->sv_event_list);
199511963SAfshin.Ardakani@Sun.COM 
199611963SAfshin.Ardakani@Sun.COM 	smb_server_release(sv);
199711963SAfshin.Ardakani@Sun.COM 	return (event);
199811963SAfshin.Ardakani@Sun.COM }
199911963SAfshin.Ardakani@Sun.COM 
200011963SAfshin.Ardakani@Sun.COM void
200111963SAfshin.Ardakani@Sun.COM smb_event_destroy(smb_event_t *event)
200211963SAfshin.Ardakani@Sun.COM {
200311963SAfshin.Ardakani@Sun.COM 	smb_server_t	*sv;
200411963SAfshin.Ardakani@Sun.COM 
200511963SAfshin.Ardakani@Sun.COM 	if (event == NULL)
200611963SAfshin.Ardakani@Sun.COM 		return;
200711963SAfshin.Ardakani@Sun.COM 
200811963SAfshin.Ardakani@Sun.COM 	SMB_EVENT_VALID(event);
200911963SAfshin.Ardakani@Sun.COM 	ASSERT(event->se_waittime == 0);
201011963SAfshin.Ardakani@Sun.COM 
201111963SAfshin.Ardakani@Sun.COM 	if (smb_server_lookup(&sv) != 0)
201211963SAfshin.Ardakani@Sun.COM 		return;
201311963SAfshin.Ardakani@Sun.COM 
201411963SAfshin.Ardakani@Sun.COM 	smb_llist_enter(&sv->sv_event_list, RW_WRITER);
201511963SAfshin.Ardakani@Sun.COM 	smb_llist_remove(&sv->sv_event_list, event);
201611963SAfshin.Ardakani@Sun.COM 	smb_llist_exit(&sv->sv_event_list);
201711963SAfshin.Ardakani@Sun.COM 
201811963SAfshin.Ardakani@Sun.COM 	event->se_magic = (uint32_t)~SMB_EVENT_MAGIC;
201911963SAfshin.Ardakani@Sun.COM 	cv_destroy(&event->se_cv);
202011963SAfshin.Ardakani@Sun.COM 	mutex_destroy(&event->se_mutex);
202111963SAfshin.Ardakani@Sun.COM 
202211963SAfshin.Ardakani@Sun.COM 	kmem_cache_free(sv->si_cache_event, event);
202311963SAfshin.Ardakani@Sun.COM 	smb_server_release(sv);
202411963SAfshin.Ardakani@Sun.COM }
202511963SAfshin.Ardakani@Sun.COM 
202611963SAfshin.Ardakani@Sun.COM /*
202711963SAfshin.Ardakani@Sun.COM  * Get the txid for the specified event.
202811963SAfshin.Ardakani@Sun.COM  */
202911963SAfshin.Ardakani@Sun.COM uint32_t
203011963SAfshin.Ardakani@Sun.COM smb_event_txid(smb_event_t *event)
203111963SAfshin.Ardakani@Sun.COM {
203211963SAfshin.Ardakani@Sun.COM 	if (event != NULL) {
203311963SAfshin.Ardakani@Sun.COM 		SMB_EVENT_VALID(event);
203411963SAfshin.Ardakani@Sun.COM 		return (event->se_txid);
203511963SAfshin.Ardakani@Sun.COM 	}
203611963SAfshin.Ardakani@Sun.COM 
203711963SAfshin.Ardakani@Sun.COM 	cmn_err(CE_NOTE, "smb_event_txid failed");
203811963SAfshin.Ardakani@Sun.COM 	return ((uint32_t)-1);
203911963SAfshin.Ardakani@Sun.COM }
204011963SAfshin.Ardakani@Sun.COM 
204111963SAfshin.Ardakani@Sun.COM /*
204211963SAfshin.Ardakani@Sun.COM  * Wait for event notification.
204311963SAfshin.Ardakani@Sun.COM  */
204411963SAfshin.Ardakani@Sun.COM int
204511963SAfshin.Ardakani@Sun.COM smb_event_wait(smb_event_t *event)
204611963SAfshin.Ardakani@Sun.COM {
204711963SAfshin.Ardakani@Sun.COM 	int	seconds = 1;
204811963SAfshin.Ardakani@Sun.COM 	int	ticks;
204911963SAfshin.Ardakani@Sun.COM 
205011963SAfshin.Ardakani@Sun.COM 	if (event == NULL)
205111963SAfshin.Ardakani@Sun.COM 		return (EINVAL);
205211963SAfshin.Ardakani@Sun.COM 
205311963SAfshin.Ardakani@Sun.COM 	SMB_EVENT_VALID(event);
205411963SAfshin.Ardakani@Sun.COM 
205511963SAfshin.Ardakani@Sun.COM 	mutex_enter(&event->se_mutex);
205611963SAfshin.Ardakani@Sun.COM 	event->se_waittime = 1;
205711963SAfshin.Ardakani@Sun.COM 	event->se_errno = 0;
205811963SAfshin.Ardakani@Sun.COM 
205911963SAfshin.Ardakani@Sun.COM 	while (!(event->se_notified)) {
206012065SKeyur.Desai@Sun.COM 		if (smb_event_debug && ((event->se_waittime % 30) == 0))
206111963SAfshin.Ardakani@Sun.COM 			cmn_err(CE_NOTE, "smb_event_wait[%d] (%d sec)",
206211963SAfshin.Ardakani@Sun.COM 			    event->se_txid, event->se_waittime);
206311963SAfshin.Ardakani@Sun.COM 
206411963SAfshin.Ardakani@Sun.COM 		if (event->se_errno != 0)
206511963SAfshin.Ardakani@Sun.COM 			break;
206611963SAfshin.Ardakani@Sun.COM 
2067*12890SJoyce.McIntosh@Sun.COM 		if (event->se_waittime > event->se_timeout) {
206811963SAfshin.Ardakani@Sun.COM 			event->se_errno = ETIME;
206911963SAfshin.Ardakani@Sun.COM 			break;
207011963SAfshin.Ardakani@Sun.COM 		}
207111963SAfshin.Ardakani@Sun.COM 
207211963SAfshin.Ardakani@Sun.COM 		ticks = SEC_TO_TICK(seconds);
207311963SAfshin.Ardakani@Sun.COM 		(void) cv_reltimedwait(&event->se_cv,
207411963SAfshin.Ardakani@Sun.COM 		    &event->se_mutex, (clock_t)ticks, TR_CLOCK_TICK);
207511963SAfshin.Ardakani@Sun.COM 		++event->se_waittime;
207611963SAfshin.Ardakani@Sun.COM 	}
207711963SAfshin.Ardakani@Sun.COM 
207811963SAfshin.Ardakani@Sun.COM 	event->se_waittime = 0;
207911963SAfshin.Ardakani@Sun.COM 	event->se_notified = B_FALSE;
208011963SAfshin.Ardakani@Sun.COM 	cv_signal(&event->se_cv);
208111963SAfshin.Ardakani@Sun.COM 	mutex_exit(&event->se_mutex);
208211963SAfshin.Ardakani@Sun.COM 	return (event->se_errno);
208311963SAfshin.Ardakani@Sun.COM }
208411963SAfshin.Ardakani@Sun.COM 
208511963SAfshin.Ardakani@Sun.COM /*
208611963SAfshin.Ardakani@Sun.COM  * If txid is non-zero, cancel the specified event.
208711963SAfshin.Ardakani@Sun.COM  * Otherwise, cancel all events.
208811963SAfshin.Ardakani@Sun.COM  */
208911963SAfshin.Ardakani@Sun.COM static void
209011963SAfshin.Ardakani@Sun.COM smb_event_cancel(smb_server_t *sv, uint32_t txid)
209111963SAfshin.Ardakani@Sun.COM {
209211963SAfshin.Ardakani@Sun.COM 	smb_event_t	*event;
209311963SAfshin.Ardakani@Sun.COM 	smb_llist_t	*event_list;
209411963SAfshin.Ardakani@Sun.COM 
209511963SAfshin.Ardakani@Sun.COM 	SMB_SERVER_VALID(sv);
209611963SAfshin.Ardakani@Sun.COM 
209711963SAfshin.Ardakani@Sun.COM 	event_list = &sv->sv_event_list;
209811963SAfshin.Ardakani@Sun.COM 	smb_llist_enter(event_list, RW_WRITER);
209911963SAfshin.Ardakani@Sun.COM 
210011963SAfshin.Ardakani@Sun.COM 	event = smb_llist_head(event_list);
210111963SAfshin.Ardakani@Sun.COM 	while (event) {
210211963SAfshin.Ardakani@Sun.COM 		SMB_EVENT_VALID(event);
210311963SAfshin.Ardakani@Sun.COM 
210411963SAfshin.Ardakani@Sun.COM 		if (txid == 0 || event->se_txid == txid) {
210511963SAfshin.Ardakani@Sun.COM 			mutex_enter(&event->se_mutex);
210611963SAfshin.Ardakani@Sun.COM 			event->se_errno = ECANCELED;
210711963SAfshin.Ardakani@Sun.COM 			event->se_notified = B_TRUE;
210811963SAfshin.Ardakani@Sun.COM 			cv_signal(&event->se_cv);
210911963SAfshin.Ardakani@Sun.COM 			mutex_exit(&event->se_mutex);
211011963SAfshin.Ardakani@Sun.COM 
211111963SAfshin.Ardakani@Sun.COM 			if (txid != 0)
211211963SAfshin.Ardakani@Sun.COM 				break;
211311963SAfshin.Ardakani@Sun.COM 		}
211411963SAfshin.Ardakani@Sun.COM 
211511963SAfshin.Ardakani@Sun.COM 		event = smb_llist_next(event_list, event);
211611963SAfshin.Ardakani@Sun.COM 	}
211711963SAfshin.Ardakani@Sun.COM 
211811963SAfshin.Ardakani@Sun.COM 	smb_llist_exit(event_list);
211911963SAfshin.Ardakani@Sun.COM }
212011963SAfshin.Ardakani@Sun.COM 
212111963SAfshin.Ardakani@Sun.COM /*
212211963SAfshin.Ardakani@Sun.COM  * If txid is non-zero, notify the specified event.
212311963SAfshin.Ardakani@Sun.COM  * Otherwise, notify all events.
212411963SAfshin.Ardakani@Sun.COM  */
2125*12890SJoyce.McIntosh@Sun.COM void
212611963SAfshin.Ardakani@Sun.COM smb_event_notify(smb_server_t *sv, uint32_t txid)
212711963SAfshin.Ardakani@Sun.COM {
212811963SAfshin.Ardakani@Sun.COM 	smb_event_t	*event;
212911963SAfshin.Ardakani@Sun.COM 	smb_llist_t	*event_list;
213011963SAfshin.Ardakani@Sun.COM 
213111963SAfshin.Ardakani@Sun.COM 	SMB_SERVER_VALID(sv);
213211963SAfshin.Ardakani@Sun.COM 
213311963SAfshin.Ardakani@Sun.COM 	event_list = &sv->sv_event_list;
213411963SAfshin.Ardakani@Sun.COM 	smb_llist_enter(event_list, RW_READER);
213511963SAfshin.Ardakani@Sun.COM 
213611963SAfshin.Ardakani@Sun.COM 	event = smb_llist_head(event_list);
213711963SAfshin.Ardakani@Sun.COM 	while (event) {
213811963SAfshin.Ardakani@Sun.COM 		SMB_EVENT_VALID(event);
213911963SAfshin.Ardakani@Sun.COM 
214011963SAfshin.Ardakani@Sun.COM 		if (txid == 0 || event->se_txid == txid) {
214111963SAfshin.Ardakani@Sun.COM 			mutex_enter(&event->se_mutex);
214211963SAfshin.Ardakani@Sun.COM 			event->se_notified = B_TRUE;
214311963SAfshin.Ardakani@Sun.COM 			cv_signal(&event->se_cv);
214411963SAfshin.Ardakani@Sun.COM 			mutex_exit(&event->se_mutex);
214511963SAfshin.Ardakani@Sun.COM 
214611963SAfshin.Ardakani@Sun.COM 			if (txid != 0)
214711963SAfshin.Ardakani@Sun.COM 				break;
214811963SAfshin.Ardakani@Sun.COM 		}
214911963SAfshin.Ardakani@Sun.COM 
215011963SAfshin.Ardakani@Sun.COM 		event = smb_llist_next(event_list, event);
215111963SAfshin.Ardakani@Sun.COM 	}
215211963SAfshin.Ardakani@Sun.COM 
215311963SAfshin.Ardakani@Sun.COM 	smb_llist_exit(event_list);
215411963SAfshin.Ardakani@Sun.COM }
215511963SAfshin.Ardakani@Sun.COM 
215611963SAfshin.Ardakani@Sun.COM /*
215711963SAfshin.Ardakani@Sun.COM  * Allocate a new transaction id (txid).
215811963SAfshin.Ardakani@Sun.COM  *
215911963SAfshin.Ardakani@Sun.COM  * 0 or -1 are not assigned because they are used to detect invalid
216011963SAfshin.Ardakani@Sun.COM  * conditions or to indicate all open id's.
216111963SAfshin.Ardakani@Sun.COM  */
216211963SAfshin.Ardakani@Sun.COM static uint32_t
216311963SAfshin.Ardakani@Sun.COM smb_event_alloc_txid(void)
216411963SAfshin.Ardakani@Sun.COM {
216511963SAfshin.Ardakani@Sun.COM 	static kmutex_t	txmutex;
216611963SAfshin.Ardakani@Sun.COM 	static uint32_t	txid;
216711963SAfshin.Ardakani@Sun.COM 	uint32_t	txid_ret;
216811963SAfshin.Ardakani@Sun.COM 
216911963SAfshin.Ardakani@Sun.COM 	mutex_enter(&txmutex);
217011963SAfshin.Ardakani@Sun.COM 
217111963SAfshin.Ardakani@Sun.COM 	if (txid == 0)
217211963SAfshin.Ardakani@Sun.COM 		txid = ddi_get_lbolt() << 11;
217311963SAfshin.Ardakani@Sun.COM 
217411963SAfshin.Ardakani@Sun.COM 	do {
217511963SAfshin.Ardakani@Sun.COM 		++txid;
217611963SAfshin.Ardakani@Sun.COM 	} while (txid == 0 || txid == (uint32_t)-1);
217711963SAfshin.Ardakani@Sun.COM 
217811963SAfshin.Ardakani@Sun.COM 	txid_ret = txid;
217911963SAfshin.Ardakani@Sun.COM 	mutex_exit(&txmutex);
218011963SAfshin.Ardakani@Sun.COM 
218111963SAfshin.Ardakani@Sun.COM 	return (txid_ret);
218211963SAfshin.Ardakani@Sun.COM }
2183*12890SJoyce.McIntosh@Sun.COM 
2184*12890SJoyce.McIntosh@Sun.COM /*
2185*12890SJoyce.McIntosh@Sun.COM  * Called by the ioctl to find the corresponding
2186*12890SJoyce.McIntosh@Sun.COM  * spooldoc node.  removes node on success
2187*12890SJoyce.McIntosh@Sun.COM  *
2188*12890SJoyce.McIntosh@Sun.COM  * Return values
2189*12890SJoyce.McIntosh@Sun.COM  * rc
2190*12890SJoyce.McIntosh@Sun.COM  * B_FALSE - not found
2191*12890SJoyce.McIntosh@Sun.COM  * B_TRUE  - found
2192*12890SJoyce.McIntosh@Sun.COM  *
2193*12890SJoyce.McIntosh@Sun.COM  */
2194*12890SJoyce.McIntosh@Sun.COM 
2195*12890SJoyce.McIntosh@Sun.COM boolean_t
2196*12890SJoyce.McIntosh@Sun.COM smb_spool_lookup_doc_byfid(uint16_t fid, smb_kspooldoc_t *spdoc)
2197*12890SJoyce.McIntosh@Sun.COM {
2198*12890SJoyce.McIntosh@Sun.COM 	smb_kspooldoc_t *sp;
2199*12890SJoyce.McIntosh@Sun.COM 	smb_llist_t	*splist;
2200*12890SJoyce.McIntosh@Sun.COM 	smb_server_t	*sv;
2201*12890SJoyce.McIntosh@Sun.COM 	int		rc;
2202*12890SJoyce.McIntosh@Sun.COM 
2203*12890SJoyce.McIntosh@Sun.COM 	rc = smb_server_lookup(&sv);
2204*12890SJoyce.McIntosh@Sun.COM 	if (rc)
2205*12890SJoyce.McIntosh@Sun.COM 		return (B_FALSE);
2206*12890SJoyce.McIntosh@Sun.COM 
2207*12890SJoyce.McIntosh@Sun.COM 	splist = &sv->sp_info.sp_list;
2208*12890SJoyce.McIntosh@Sun.COM 	smb_llist_enter(splist, RW_WRITER);
2209*12890SJoyce.McIntosh@Sun.COM 	sp = smb_llist_head(splist);
2210*12890SJoyce.McIntosh@Sun.COM 	while (sp != NULL) {
2211*12890SJoyce.McIntosh@Sun.COM 		/*
2212*12890SJoyce.McIntosh@Sun.COM 		 * check for a matching fid
2213*12890SJoyce.McIntosh@Sun.COM 		 */
2214*12890SJoyce.McIntosh@Sun.COM 		if (sp->sd_fid == fid) {
2215*12890SJoyce.McIntosh@Sun.COM 			*spdoc = *sp;
2216*12890SJoyce.McIntosh@Sun.COM 			smb_llist_remove(splist, sp);
2217*12890SJoyce.McIntosh@Sun.COM 			smb_llist_exit(splist);
2218*12890SJoyce.McIntosh@Sun.COM 			kmem_free(sp, sizeof (smb_kspooldoc_t));
2219*12890SJoyce.McIntosh@Sun.COM 			smb_server_release(sv);
2220*12890SJoyce.McIntosh@Sun.COM 			return (B_TRUE);
2221*12890SJoyce.McIntosh@Sun.COM 		}
2222*12890SJoyce.McIntosh@Sun.COM 		sp = smb_llist_next(splist, sp);
2223*12890SJoyce.McIntosh@Sun.COM 	}
2224*12890SJoyce.McIntosh@Sun.COM 	cmn_err(CE_WARN, "smb_spool_lookup_user_byfid: no fid:%d", fid);
2225*12890SJoyce.McIntosh@Sun.COM 	smb_llist_exit(splist);
2226*12890SJoyce.McIntosh@Sun.COM 	smb_server_release(sv);
2227*12890SJoyce.McIntosh@Sun.COM 	return (B_FALSE);
2228*12890SJoyce.McIntosh@Sun.COM }
2229*12890SJoyce.McIntosh@Sun.COM 
2230*12890SJoyce.McIntosh@Sun.COM /*
2231*12890SJoyce.McIntosh@Sun.COM  * Adds the spool fid to a linked list to be used
2232*12890SJoyce.McIntosh@Sun.COM  * as a search key in the spooldoc queue
2233*12890SJoyce.McIntosh@Sun.COM  *
2234*12890SJoyce.McIntosh@Sun.COM  * Return values
2235*12890SJoyce.McIntosh@Sun.COM  *      rc non-zero error
2236*12890SJoyce.McIntosh@Sun.COM  *	rc zero success
2237*12890SJoyce.McIntosh@Sun.COM  *
2238*12890SJoyce.McIntosh@Sun.COM  */
2239*12890SJoyce.McIntosh@Sun.COM 
2240*12890SJoyce.McIntosh@Sun.COM int
2241*12890SJoyce.McIntosh@Sun.COM smb_spool_add_fid(uint16_t fid)
2242*12890SJoyce.McIntosh@Sun.COM {
2243*12890SJoyce.McIntosh@Sun.COM 	smb_llist_t	*fidlist;
2244*12890SJoyce.McIntosh@Sun.COM 	smb_server_t	*sv;
2245*12890SJoyce.McIntosh@Sun.COM 	smb_spoolfid_t  *sf;
2246*12890SJoyce.McIntosh@Sun.COM 	int rc = 0;
2247*12890SJoyce.McIntosh@Sun.COM 
2248*12890SJoyce.McIntosh@Sun.COM 	rc = smb_server_lookup(&sv);
2249*12890SJoyce.McIntosh@Sun.COM 	if (rc)
2250*12890SJoyce.McIntosh@Sun.COM 		return (rc);
2251*12890SJoyce.McIntosh@Sun.COM 
2252*12890SJoyce.McIntosh@Sun.COM 	sf = kmem_zalloc(sizeof (smb_spoolfid_t), KM_SLEEP);
2253*12890SJoyce.McIntosh@Sun.COM 	fidlist = &sv->sp_info.sp_fidlist;
2254*12890SJoyce.McIntosh@Sun.COM 	smb_llist_enter(fidlist, RW_WRITER);
2255*12890SJoyce.McIntosh@Sun.COM 	sf->sf_fid = fid;
2256*12890SJoyce.McIntosh@Sun.COM 	smb_llist_insert_tail(fidlist, sf);
2257*12890SJoyce.McIntosh@Sun.COM 	smb_llist_exit(fidlist);
2258*12890SJoyce.McIntosh@Sun.COM 	smb_server_release(sv);
2259*12890SJoyce.McIntosh@Sun.COM 	return (rc);
2260*12890SJoyce.McIntosh@Sun.COM }
2261*12890SJoyce.McIntosh@Sun.COM 
2262*12890SJoyce.McIntosh@Sun.COM /*
2263*12890SJoyce.McIntosh@Sun.COM  * Called by the ioctl to get and remove the head of the fid list
2264*12890SJoyce.McIntosh@Sun.COM  *
2265*12890SJoyce.McIntosh@Sun.COM  * Return values
2266*12890SJoyce.McIntosh@Sun.COM  * int fd
2267*12890SJoyce.McIntosh@Sun.COM  * greater than 0 success
2268*12890SJoyce.McIntosh@Sun.COM  * 0 - error
2269*12890SJoyce.McIntosh@Sun.COM  *
2270*12890SJoyce.McIntosh@Sun.COM  */
2271*12890SJoyce.McIntosh@Sun.COM 
2272*12890SJoyce.McIntosh@Sun.COM uint16_t
2273*12890SJoyce.McIntosh@Sun.COM smb_spool_get_fid()
2274*12890SJoyce.McIntosh@Sun.COM {
2275*12890SJoyce.McIntosh@Sun.COM 	smb_spoolfid_t	*spfid;
2276*12890SJoyce.McIntosh@Sun.COM 	smb_llist_t	*splist;
2277*12890SJoyce.McIntosh@Sun.COM 	smb_server_t	*sv;
2278*12890SJoyce.McIntosh@Sun.COM 	int 		rc = 0;
2279*12890SJoyce.McIntosh@Sun.COM 	uint16_t	fid;
2280*12890SJoyce.McIntosh@Sun.COM 
2281*12890SJoyce.McIntosh@Sun.COM 	rc = smb_server_lookup(&sv);
2282*12890SJoyce.McIntosh@Sun.COM 	if (rc)
2283*12890SJoyce.McIntosh@Sun.COM 		return (0);
2284*12890SJoyce.McIntosh@Sun.COM 
2285*12890SJoyce.McIntosh@Sun.COM 	splist = &sv->sp_info.sp_fidlist;
2286*12890SJoyce.McIntosh@Sun.COM 	smb_llist_enter(splist, RW_WRITER);
2287*12890SJoyce.McIntosh@Sun.COM 	spfid = smb_llist_head(splist);
2288*12890SJoyce.McIntosh@Sun.COM 	if (spfid != NULL) {
2289*12890SJoyce.McIntosh@Sun.COM 		fid = spfid->sf_fid;
2290*12890SJoyce.McIntosh@Sun.COM 		smb_llist_remove(&sv->sp_info.sp_fidlist, spfid);
2291*12890SJoyce.McIntosh@Sun.COM 		kmem_free(spfid, sizeof (smb_spoolfid_t));
2292*12890SJoyce.McIntosh@Sun.COM 	} else {
2293*12890SJoyce.McIntosh@Sun.COM 		fid = 0;
2294*12890SJoyce.McIntosh@Sun.COM 	}
2295*12890SJoyce.McIntosh@Sun.COM 	smb_llist_exit(splist);
2296*12890SJoyce.McIntosh@Sun.COM 	smb_server_release(sv);
2297*12890SJoyce.McIntosh@Sun.COM 	return (fid);
2298*12890SJoyce.McIntosh@Sun.COM }
2299*12890SJoyce.McIntosh@Sun.COM 
2300*12890SJoyce.McIntosh@Sun.COM /*
2301*12890SJoyce.McIntosh@Sun.COM  * Adds the spooldoc to the tail of the spooldoc list
2302*12890SJoyce.McIntosh@Sun.COM  *
2303*12890SJoyce.McIntosh@Sun.COM  * Return values
2304*12890SJoyce.McIntosh@Sun.COM  *      rc non-zero error
2305*12890SJoyce.McIntosh@Sun.COM  *	rc zero success
2306*12890SJoyce.McIntosh@Sun.COM  */
2307*12890SJoyce.McIntosh@Sun.COM int
2308*12890SJoyce.McIntosh@Sun.COM smb_spool_add_doc(smb_kspooldoc_t *sp)
2309*12890SJoyce.McIntosh@Sun.COM {
2310*12890SJoyce.McIntosh@Sun.COM 	smb_llist_t	*splist;
2311*12890SJoyce.McIntosh@Sun.COM 	smb_server_t	*sv;
2312*12890SJoyce.McIntosh@Sun.COM 	int rc = 0;
2313*12890SJoyce.McIntosh@Sun.COM 
2314*12890SJoyce.McIntosh@Sun.COM 	rc = smb_server_lookup(&sv);
2315*12890SJoyce.McIntosh@Sun.COM 	if (rc)
2316*12890SJoyce.McIntosh@Sun.COM 		return (rc);
2317*12890SJoyce.McIntosh@Sun.COM 
2318*12890SJoyce.McIntosh@Sun.COM 	splist = &sv->sp_info.sp_list;
2319*12890SJoyce.McIntosh@Sun.COM 	smb_llist_enter(splist, RW_WRITER);
2320*12890SJoyce.McIntosh@Sun.COM 	sp->sd_spool_num = sv->sp_info.sp_cnt;
2321*12890SJoyce.McIntosh@Sun.COM 	smb_llist_insert_tail(splist, sp);
2322*12890SJoyce.McIntosh@Sun.COM 	smb_llist_exit(splist);
2323*12890SJoyce.McIntosh@Sun.COM 	smb_server_release(sv);
2324*12890SJoyce.McIntosh@Sun.COM 	return (rc);
2325*12890SJoyce.McIntosh@Sun.COM }
2326