xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_server.c (revision 8d94f651a44d41a7147253bb5dad1a53941e8f50)
1faa1795aSjb150015 /*
2faa1795aSjb150015  * CDDL HEADER START
3faa1795aSjb150015  *
4faa1795aSjb150015  * The contents of this file are subject to the terms of the
5faa1795aSjb150015  * Common Development and Distribution License (the "License").
6faa1795aSjb150015  * You may not use this file except in compliance with the License.
7faa1795aSjb150015  *
8faa1795aSjb150015  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9faa1795aSjb150015  * or http://www.opensolaris.org/os/licensing.
10faa1795aSjb150015  * See the License for the specific language governing permissions
11faa1795aSjb150015  * and limitations under the License.
12faa1795aSjb150015  *
13faa1795aSjb150015  * When distributing Covered Code, include this CDDL HEADER in each
14faa1795aSjb150015  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15faa1795aSjb150015  * If applicable, add the following below this CDDL HEADER, with the
16faa1795aSjb150015  * fields enclosed by brackets "[]" replaced with your own identifying
17faa1795aSjb150015  * information: Portions Copyright [yyyy] [name of copyright owner]
18faa1795aSjb150015  *
19faa1795aSjb150015  * CDDL HEADER END
20faa1795aSjb150015  */
21faa1795aSjb150015 /*
22c5866007SKeyur Desai  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
23adc68ba9SPavel Zakharov  * Copyright (c) 2017 by Delphix. All rights reserved.
24*8d94f651SGordon Ross  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
25faa1795aSjb150015  */
26faa1795aSjb150015 
27faa1795aSjb150015 /*
28faa1795aSjb150015  * General Structures Layout
29faa1795aSjb150015  * -------------------------
30faa1795aSjb150015  *
31faa1795aSjb150015  * This is a simplified diagram showing the relationship between most of the
32faa1795aSjb150015  * main structures.
33faa1795aSjb150015  *
34faa1795aSjb150015  * +-------------------+
35faa1795aSjb150015  * |     SMB_SERVER    |
36faa1795aSjb150015  * +-------------------+
37faa1795aSjb150015  *          |
38faa1795aSjb150015  *          |
39faa1795aSjb150015  *          v
40faa1795aSjb150015  * +-------------------+       +-------------------+      +-------------------+
41faa1795aSjb150015  * |     SESSION       |<----->|     SESSION       |......|      SESSION      |
42faa1795aSjb150015  * +-------------------+       +-------------------+      +-------------------+
43faa1795aSjb150015  *          |
44faa1795aSjb150015  *          |
45faa1795aSjb150015  *          v
46faa1795aSjb150015  * +-------------------+       +-------------------+      +-------------------+
47faa1795aSjb150015  * |       USER        |<----->|       USER        |......|       USER        |
48faa1795aSjb150015  * +-------------------+       +-------------------+      +-------------------+
49faa1795aSjb150015  *          |
50faa1795aSjb150015  *          |
51faa1795aSjb150015  *          v
52faa1795aSjb150015  * +-------------------+       +-------------------+      +-------------------+
53faa1795aSjb150015  * |       TREE        |<----->|       TREE        |......|       TREE        |
54faa1795aSjb150015  * +-------------------+       +-------------------+      +-------------------+
55faa1795aSjb150015  *      |         |
56faa1795aSjb150015  *      |         |
57faa1795aSjb150015  *      |         v
58faa1795aSjb150015  *      |     +-------+       +-------+      +-------+
59faa1795aSjb150015  *      |     | OFILE |<----->| OFILE |......| OFILE |
60faa1795aSjb150015  *      |     +-------+       +-------+      +-------+
61faa1795aSjb150015  *      |
62faa1795aSjb150015  *      |
63faa1795aSjb150015  *      v
64faa1795aSjb150015  *  +-------+       +------+      +------+
65faa1795aSjb150015  *  | ODIR  |<----->| ODIR |......| ODIR |
66faa1795aSjb150015  *  +-------+       +------+      +------+
67faa1795aSjb150015  *
68faa1795aSjb150015  *
69faa1795aSjb150015  * Module Interface Overview
70faa1795aSjb150015  * -------------------------
71faa1795aSjb150015  *
72faa1795aSjb150015  *
73faa1795aSjb150015  *	    +===================================+
74faa1795aSjb150015  *	    |		 smbd daemon		|
75faa1795aSjb150015  *	    +===================================+
76faa1795aSjb150015  *	      |		     |		      ^
77faa1795aSjb150015  *	      |		     |		      |
78faa1795aSjb150015  * User	      |		     |		      |
79faa1795aSjb150015  * -----------|--------------|----------------|--------------------------------
80faa1795aSjb150015  * Kernel     |		     |		      |
81faa1795aSjb150015  *            |		     |		      |
82faa1795aSjb150015  *	      |		     |		      |
83faa1795aSjb150015  *  +=========|==============|================|=================+
84faa1795aSjb150015  *  |	      v		     v		      |			|
85faa1795aSjb150015  *  | +-----------+ +--------------------+ +------------------+ |
86faa1795aSjb150015  *  | |     IO    | | Kernel Door Server | | User Door Servers|	|
87faa1795aSjb150015  *  | | Interface | |     Interface      | |   Interface      | |
88faa1795aSjb150015  *  | +-----------+ +--------------------+ +------------------+ |
89faa1795aSjb150015  *  |		|	     |		      ^		^	|
90faa1795aSjb150015  *  |		v	     v		      |		|	|    +=========+
91faa1795aSjb150015  *  |	     +-----------------------------------+	|	|    |	       |
92faa1795aSjb150015  *  |	     + SMB Server Management (this file) |<------------------|	 ZFS   |
93faa1795aSjb150015  *  |	     +-----------------------------------+	|	|    |	       |
94faa1795aSjb150015  *  |							|	|    |  Module |
95faa1795aSjb150015  *  |	     +-----------------------------------+	|	|    |	       |
96faa1795aSjb150015  *  |	     +     SMB Server Internal Layers    |------+	|    +=========+
97faa1795aSjb150015  *  |	     +-----------------------------------+		|
98faa1795aSjb150015  *  |								|
99faa1795aSjb150015  *  |								|
100faa1795aSjb150015  *  +===========================================================+
101faa1795aSjb150015  *
102faa1795aSjb150015  *
103faa1795aSjb150015  * Server State Machine
104faa1795aSjb150015  * --------------------
105faa1795aSjb150015  *                                  |
106faa1795aSjb150015  *                                  | T0
107faa1795aSjb150015  *                                  |
108faa1795aSjb150015  *                                  v
109faa1795aSjb150015  *                    +-----------------------------+
110faa1795aSjb150015  *		      |   SMB_SERVER_STATE_CREATED  |
111faa1795aSjb150015  *		      +-----------------------------+
112faa1795aSjb150015  *				    |
113faa1795aSjb150015  *				    | T1
114faa1795aSjb150015  *				    |
115faa1795aSjb150015  *				    v
116faa1795aSjb150015  *		      +-----------------------------+
117faa1795aSjb150015  *		      | SMB_SERVER_STATE_CONFIGURED |
118faa1795aSjb150015  *		      +-----------------------------+
119faa1795aSjb150015  *				    |
120faa1795aSjb150015  *				    | T2
121faa1795aSjb150015  *				    |
122faa1795aSjb150015  *				    v
123faa1795aSjb150015  *		      +-----------------------------+
1249fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  *		      |  SMB_SERVER_STATE_RUNNING / |
1259fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  *		      |  SMB_SERVER_STATE_STOPPING  |
126faa1795aSjb150015  *		      +-----------------------------+
127faa1795aSjb150015  *				    |
128faa1795aSjb150015  *				    | T3
129faa1795aSjb150015  *				    |
130faa1795aSjb150015  *				    v
131faa1795aSjb150015  *		      +-----------------------------+
132faa1795aSjb150015  *		      |  SMB_SERVER_STATE_DELETING  |
133faa1795aSjb150015  *                    +-----------------------------+
134faa1795aSjb150015  *				    |
135faa1795aSjb150015  *				    |
136faa1795aSjb150015  *				    |
137faa1795aSjb150015  *				    v
138faa1795aSjb150015  *
139faa1795aSjb150015  * States
140faa1795aSjb150015  * ------
141faa1795aSjb150015  *
142faa1795aSjb150015  * SMB_SERVER_STATE_CREATED
143faa1795aSjb150015  *
144faa1795aSjb150015  *    This is the state of the server just after creation.
145faa1795aSjb150015  *
146faa1795aSjb150015  * SMB_SERVER_STATE_CONFIGURED
147faa1795aSjb150015  *
148faa1795aSjb150015  *    The server has been configured.
149faa1795aSjb150015  *
150faa1795aSjb150015  * SMB_SERVER_STATE_RUNNING
151faa1795aSjb150015  *
152faa1795aSjb150015  *    The server has been started. While in this state the threads listening on
1534163af6aSjose borrego  *    the sockets are started.
154faa1795aSjb150015  *
1554163af6aSjose borrego  *    When a client establishes a connection the thread listening dispatches
1564163af6aSjose borrego  *    a task with the new session as an argument. If the dispatch fails the new
1574163af6aSjose borrego  *    session context is destroyed.
158faa1795aSjb150015  *
159faa1795aSjb150015  * SMB_SERVER_STATE_STOPPING
160faa1795aSjb150015  *
161faa1795aSjb150015  *    The threads listening on the NBT and TCP sockets are being terminated.
162faa1795aSjb150015  *
163faa1795aSjb150015  *
164faa1795aSjb150015  * Transitions
165faa1795aSjb150015  * -----------
166faa1795aSjb150015  *
167faa1795aSjb150015  * Transition T0
168faa1795aSjb150015  *
169faa1795aSjb150015  *    The daemon smbd triggers its creation by opening the smbsrv device. If
170faa1795aSjb150015  *    the zone where the daemon lives doesn't have an smb server yet it is
171faa1795aSjb150015  *    created.
172faa1795aSjb150015  *
173faa1795aSjb150015  *		smb_drv_open() --> smb_server_create()
174faa1795aSjb150015  *
175faa1795aSjb150015  * Transition T1
176faa1795aSjb150015  *
177faa1795aSjb150015  *    This transition occurs in smb_server_configure(). It is triggered by the
178faa1795aSjb150015  *    daemon through an Ioctl.
179faa1795aSjb150015  *
180faa1795aSjb150015  *	smb_drv_ioctl(SMB_IOC_CONFIG) --> smb_server_configure()
181faa1795aSjb150015  *
182faa1795aSjb150015  * Transition T2
183faa1795aSjb150015  *
184faa1795aSjb150015  *    This transition occurs in smb_server_start(). It is triggered by the
185faa1795aSjb150015  *    daemon through an Ioctl.
186faa1795aSjb150015  *
187faa1795aSjb150015  *	smb_drv_ioctl(SMB_IOC_START) --> smb_server_start()
188faa1795aSjb150015  *
189faa1795aSjb150015  * Transition T3
190faa1795aSjb150015  *
191faa1795aSjb150015  *    This transition occurs in smb_server_delete(). It is triggered by the
192faa1795aSjb150015  *    daemon when closing the smbsrv device
193faa1795aSjb150015  *
194faa1795aSjb150015  *		smb_drv_close() --> smb_server_delete()
195faa1795aSjb150015  *
196faa1795aSjb150015  * Comments
197faa1795aSjb150015  * --------
198faa1795aSjb150015  *
199faa1795aSjb150015  * This files assumes that there will one SMB server per zone. For now the
200faa1795aSjb150015  * smb server works only in global zone. There's nothing in this file preventing
201faa1795aSjb150015  * an smb server from being created in a non global zone. That limitation is
202faa1795aSjb150015  * enforced in user space.
203faa1795aSjb150015  */
204faa1795aSjb150015 
205faa1795aSjb150015 #include <sys/cmn_err.h>
206faa1795aSjb150015 #include <sys/priv.h>
207faa1795aSjb150015 #include <sys/zone.h>
208bbf6f00cSJordan Brown #include <netinet/in.h>
209bbf6f00cSJordan Brown #include <netinet/in_systm.h>
210bbf6f00cSJordan Brown #include <netinet/ip.h>
211bbf6f00cSJordan Brown #include <netinet/ip_icmp.h>
212bbf6f00cSJordan Brown #include <netinet/ip_var.h>
213bbf6f00cSJordan Brown #include <netinet/tcp.h>
214a90cf9f2SGordon Ross #include <smbsrv/smb2_kproto.h>
215bbf6f00cSJordan Brown #include <smbsrv/string.h>
216faa1795aSjb150015 #include <smbsrv/netbios.h>
217faa1795aSjb150015 #include <smbsrv/smb_fsops.h>
2183db3f65cSamw #include <smbsrv/smb_share.h>
2199fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States #include <smbsrv/smb_door.h>
2206537f381Sas200622 #include <smbsrv/smb_kstat.h>
221faa1795aSjb150015 
222148c5f43SAlan Wright static void smb_server_kstat_init(smb_server_t *);
223faa1795aSjb150015 static void smb_server_kstat_fini(smb_server_t *);
224faa1795aSjb150015 static void smb_server_timers(smb_thread_t *, void *);
22529bd2886SAlan Wright static void smb_server_store_cfg(smb_server_t *, smb_ioc_cfg_t *);
2269fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void smb_server_shutdown(smb_server_t *);
227faa1795aSjb150015 static int smb_server_fsop_start(smb_server_t *);
228faa1795aSjb150015 static void smb_server_fsop_stop(smb_server_t *);
2299fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void smb_event_cancel(smb_server_t *, uint32_t);
2309fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static uint32_t smb_event_alloc_txid(void);
231faa1795aSjb150015 
232*8d94f651SGordon Ross static void smb_server_disconnect_share(smb_server_t *, const char *);
233*8d94f651SGordon Ross static void smb_server_enum_users(smb_server_t *, smb_svcenum_t *);
234*8d94f651SGordon Ross static void smb_server_enum_trees(smb_server_t *, smb_svcenum_t *);
235*8d94f651SGordon Ross static int smb_server_session_disconnect(smb_server_t *, const char *,
2361fcced4cSJordan Brown     const char *);
237*8d94f651SGordon Ross static int smb_server_fclose(smb_server_t *, uint32_t);
238148c5f43SAlan Wright static int smb_server_kstat_update(kstat_t *, int);
239cb174861Sjoyce mcintosh static int smb_server_legacy_kstat_update(kstat_t *, int);
2404163af6aSjose borrego static void smb_server_listener_init(smb_server_t *, smb_listener_daemon_t *,
2414163af6aSjose borrego     char *, in_port_t, int);
2424163af6aSjose borrego static void smb_server_listener_destroy(smb_listener_daemon_t *);
2434163af6aSjose borrego static int smb_server_listener_start(smb_listener_daemon_t *);
2444163af6aSjose borrego static void smb_server_listener_stop(smb_listener_daemon_t *);
2454163af6aSjose borrego static void smb_server_listener(smb_thread_t *, void *);
2464163af6aSjose borrego static void smb_server_receiver(void *);
2474163af6aSjose borrego static void smb_server_create_session(smb_listener_daemon_t *, ksocket_t);
248811599a4SMatt Barden static void smb_server_destroy_session(smb_session_t *);
24923a9c295SGordon Ross static uint16_t smb_spool_get_fid(smb_server_t *);
25023a9c295SGordon Ross static boolean_t smb_spool_lookup_doc_byfid(smb_server_t *, uint16_t,
25123a9c295SGordon Ross     smb_kspooldoc_t *);
2521fcced4cSJordan Brown 
253811599a4SMatt Barden /*
254811599a4SMatt Barden  * How many "buckets" should our hash tables use?  On a "real" server,
255811599a4SMatt Barden  * make them much larger than the number of CPUs we're likely to have.
256811599a4SMatt Barden  * On "fksmbd" make it smaller so dtrace logs are shorter.
257811599a4SMatt Barden  * These must be powers of two.
258811599a4SMatt Barden  */
259811599a4SMatt Barden #ifdef	_KERNEL
260811599a4SMatt Barden #define	DEFAULT_HASH_NBUCKETS	256	/* real server */
261811599a4SMatt Barden #else
262811599a4SMatt Barden #define	DEFAULT_HASH_NBUCKETS	16	/* for "fksmbd" */
263811599a4SMatt Barden #endif
264811599a4SMatt Barden uint32_t SMB_OFILE_HASH_NBUCKETS = DEFAULT_HASH_NBUCKETS;
265811599a4SMatt Barden uint32_t SMB_LEASE_HASH_NBUCKETS = DEFAULT_HASH_NBUCKETS;
266811599a4SMatt Barden 
2679fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States int smb_event_debug = 0;
2689fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
269faa1795aSjb150015 static smb_llist_t	smb_servers;
270faa1795aSjb150015 
2718622ec45SGordon Ross kmem_cache_t		*smb_cache_request;
2728622ec45SGordon Ross kmem_cache_t		*smb_cache_session;
2738622ec45SGordon Ross kmem_cache_t		*smb_cache_user;
2748622ec45SGordon Ross kmem_cache_t		*smb_cache_tree;
2758622ec45SGordon Ross kmem_cache_t		*smb_cache_ofile;
2768622ec45SGordon Ross kmem_cache_t		*smb_cache_odir;
2778622ec45SGordon Ross kmem_cache_t		*smb_cache_opipe;
2788622ec45SGordon Ross kmem_cache_t		*smb_cache_event;
2790897f7fbSGordon Ross kmem_cache_t		*smb_cache_lock;
2808622ec45SGordon Ross 
281faa1795aSjb150015 /*
282faa1795aSjb150015  * *****************************************************************************
283faa1795aSjb150015  * **************** Functions called from the device interface *****************
284faa1795aSjb150015  * *****************************************************************************
285faa1795aSjb150015  *
2861fcced4cSJordan Brown  * These functions typically have to determine the relevant smb server
2871fcced4cSJordan Brown  * to which the call applies.
288faa1795aSjb150015  */
289faa1795aSjb150015 
290faa1795aSjb150015 /*
291a90cf9f2SGordon Ross  * How many zones have an SMB server active?
292a90cf9f2SGordon Ross  */
293a90cf9f2SGordon Ross int
294a90cf9f2SGordon Ross smb_server_get_count(void)
295a90cf9f2SGordon Ross {
296a90cf9f2SGordon Ross 	return (smb_llist_get_count(&smb_servers));
297a90cf9f2SGordon Ross }
298a90cf9f2SGordon Ross 
299a90cf9f2SGordon Ross /*
3008622ec45SGordon Ross  * smb_server_g_init
301faa1795aSjb150015  *
302c8ec8eeaSjose borrego  * This function must be called from smb_drv_attach().
303faa1795aSjb150015  */
304faa1795aSjb150015 int
3058622ec45SGordon Ross smb_server_g_init(void)
306faa1795aSjb150015 {
3078622ec45SGordon Ross 	int rc;
308faa1795aSjb150015 
3098622ec45SGordon Ross 	if ((rc = smb_vop_init()) != 0)
3108622ec45SGordon Ross 		goto errout;
3118622ec45SGordon Ross 	if ((rc = smb_fem_init()) != 0)
3128622ec45SGordon Ross 		goto errout;
3138622ec45SGordon Ross 
3148622ec45SGordon Ross 	smb_kshare_g_init();
3158622ec45SGordon Ross 	smb_codepage_init();
3168622ec45SGordon Ross 	smb_mbc_init();		/* smb_mbc_cache */
3178622ec45SGordon Ross 	smb_node_init();	/* smb_node_cache, lists */
31894047d49SGordon Ross 	smb2_lease_init();
3198622ec45SGordon Ross 
3208622ec45SGordon Ross 	smb_cache_request = kmem_cache_create("smb_request_cache",
3218622ec45SGordon Ross 	    sizeof (smb_request_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
3228622ec45SGordon Ross 	smb_cache_session = kmem_cache_create("smb_session_cache",
3238622ec45SGordon Ross 	    sizeof (smb_session_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
3248622ec45SGordon Ross 	smb_cache_user = kmem_cache_create("smb_user_cache",
3258622ec45SGordon Ross 	    sizeof (smb_user_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
3268622ec45SGordon Ross 	smb_cache_tree = kmem_cache_create("smb_tree_cache",
3278622ec45SGordon Ross 	    sizeof (smb_tree_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
3288622ec45SGordon Ross 	smb_cache_ofile = kmem_cache_create("smb_ofile_cache",
3298622ec45SGordon Ross 	    sizeof (smb_ofile_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
3308622ec45SGordon Ross 	smb_cache_odir = kmem_cache_create("smb_odir_cache",
3318622ec45SGordon Ross 	    sizeof (smb_odir_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
3328622ec45SGordon Ross 	smb_cache_opipe = kmem_cache_create("smb_opipe_cache",
3338622ec45SGordon Ross 	    sizeof (smb_opipe_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
3348622ec45SGordon Ross 	smb_cache_event = kmem_cache_create("smb_event_cache",
3358622ec45SGordon Ross 	    sizeof (smb_event_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
3360897f7fbSGordon Ross 	smb_cache_lock = kmem_cache_create("smb_lock_cache",
3370897f7fbSGordon Ross 	    sizeof (smb_lock_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
3388622ec45SGordon Ross 
3399fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_init();
340faa1795aSjb150015 	smb_llist_constructor(&smb_servers, sizeof (smb_server_t),
341faa1795aSjb150015 	    offsetof(smb_server_t, sv_lnd));
3429fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
3438622ec45SGordon Ross 	return (0);
3448622ec45SGordon Ross 
3458622ec45SGordon Ross errout:
346faa1795aSjb150015 	smb_fem_fini();
347faa1795aSjb150015 	smb_vop_fini();
348faa1795aSjb150015 	return (rc);
349faa1795aSjb150015 }
350faa1795aSjb150015 
351faa1795aSjb150015 /*
3528622ec45SGordon Ross  * smb_server_g_fini
353faa1795aSjb150015  *
354faa1795aSjb150015  * This function must called from smb_drv_detach(). It will fail if servers
355faa1795aSjb150015  * still exist.
356faa1795aSjb150015  */
357a90cf9f2SGordon Ross void
3588622ec45SGordon Ross smb_server_g_fini(void)
359faa1795aSjb150015 {
360faa1795aSjb150015 
361a90cf9f2SGordon Ross 	ASSERT(smb_llist_get_count(&smb_servers) == 0);
362a90cf9f2SGordon Ross 
3639fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_fini();
3648622ec45SGordon Ross 
3658622ec45SGordon Ross 	kmem_cache_destroy(smb_cache_request);
3668622ec45SGordon Ross 	kmem_cache_destroy(smb_cache_session);
3678622ec45SGordon Ross 	kmem_cache_destroy(smb_cache_user);
3688622ec45SGordon Ross 	kmem_cache_destroy(smb_cache_tree);
3698622ec45SGordon Ross 	kmem_cache_destroy(smb_cache_ofile);
3708622ec45SGordon Ross 	kmem_cache_destroy(smb_cache_odir);
3718622ec45SGordon Ross 	kmem_cache_destroy(smb_cache_opipe);
3728622ec45SGordon Ross 	kmem_cache_destroy(smb_cache_event);
3730897f7fbSGordon Ross 	kmem_cache_destroy(smb_cache_lock);
3748622ec45SGordon Ross 
37594047d49SGordon Ross 	smb2_lease_fini();
376faa1795aSjb150015 	smb_node_fini();
3772c2961f8Sjose borrego 	smb_mbc_fini();
378adc68ba9SPavel Zakharov 	smb_codepage_fini();
3798622ec45SGordon Ross 	smb_kshare_g_fini();
3808622ec45SGordon Ross 
3818622ec45SGordon Ross 	smb_fem_fini();
3828622ec45SGordon Ross 	smb_vop_fini();
3838622ec45SGordon Ross 
384faa1795aSjb150015 	smb_llist_destructor(&smb_servers);
385faa1795aSjb150015 }
386faa1795aSjb150015 
387faa1795aSjb150015 /*
388faa1795aSjb150015  * smb_server_create
389faa1795aSjb150015  *
390faa1795aSjb150015  * This function will fail if there's already a server associated with the
391faa1795aSjb150015  * caller's zone.
392faa1795aSjb150015  */
393faa1795aSjb150015 int
394faa1795aSjb150015 smb_server_create(void)
395faa1795aSjb150015 {
396faa1795aSjb150015 	zoneid_t	zid;
397faa1795aSjb150015 	smb_server_t	*sv;
398faa1795aSjb150015 
399faa1795aSjb150015 	zid = getzoneid();
400faa1795aSjb150015 
401faa1795aSjb150015 	smb_llist_enter(&smb_servers, RW_WRITER);
402faa1795aSjb150015 	sv = smb_llist_head(&smb_servers);
403faa1795aSjb150015 	while (sv) {
4049fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_SERVER_VALID(sv);
405faa1795aSjb150015 		if (sv->sv_zid == zid) {
406faa1795aSjb150015 			smb_llist_exit(&smb_servers);
40794fff790SAlan Wright 			return (EPERM);
408faa1795aSjb150015 		}
409faa1795aSjb150015 		sv = smb_llist_next(&smb_servers, sv);
410faa1795aSjb150015 	}
411faa1795aSjb150015 
4128622ec45SGordon Ross 	sv = kmem_zalloc(sizeof (smb_server_t), KM_SLEEP);
4138622ec45SGordon Ross 
4148622ec45SGordon Ross 	sv->sv_magic = SMB_SERVER_MAGIC;
4158622ec45SGordon Ross 	sv->sv_state = SMB_SERVER_STATE_CREATED;
4168622ec45SGordon Ross 	sv->sv_zid = zid;
417b819cea2SGordon Ross 	sv->sv_pid = ddi_get_pid();
4188622ec45SGordon Ross 
4198622ec45SGordon Ross 	mutex_init(&sv->sv_mutex, NULL, MUTEX_DEFAULT, NULL);
4208622ec45SGordon Ross 	cv_init(&sv->sv_cv, NULL, CV_DEFAULT, NULL);
4218622ec45SGordon Ross 	cv_init(&sv->sp_info.sp_cv, NULL, CV_DEFAULT, NULL);
422faa1795aSjb150015 
423811599a4SMatt Barden 	sv->sv_persistid_ht = smb_hash_create(sizeof (smb_ofile_t),
424811599a4SMatt Barden 	    offsetof(smb_ofile_t, f_dh_lnd), SMB_OFILE_HASH_NBUCKETS);
425811599a4SMatt Barden 
42694047d49SGordon Ross 	sv->sv_lease_ht = smb_hash_create(sizeof (smb_lease_t),
42794047d49SGordon Ross 	    offsetof(smb_lease_t, ls_lnd), SMB_LEASE_HASH_NBUCKETS);
42894047d49SGordon Ross 
429811599a4SMatt Barden 	smb_llist_constructor(&sv->sv_session_list, sizeof (smb_session_t),
430811599a4SMatt Barden 	    offsetof(smb_session_t, s_lnd));
431811599a4SMatt Barden 
4329fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_constructor(&sv->sv_event_list, sizeof (smb_event_t),
4339fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	    offsetof(smb_event_t, se_lnd));
4349fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
435cb174861Sjoyce mcintosh 	smb_llist_constructor(&sv->sp_info.sp_list, sizeof (smb_kspooldoc_t),
436cb174861Sjoyce mcintosh 	    offsetof(smb_kspooldoc_t, sd_lnd));
437cb174861Sjoyce mcintosh 
438cb174861Sjoyce mcintosh 	smb_llist_constructor(&sv->sp_info.sp_fidlist,
439cb174861Sjoyce mcintosh 	    sizeof (smb_spoolfid_t), offsetof(smb_spoolfid_t, sf_lnd));
440cb174861Sjoyce mcintosh 
441a90cf9f2SGordon Ross 	sv->sv_disp_stats1 = kmem_zalloc(SMB_COM_NUM *
442a90cf9f2SGordon Ross 	    sizeof (smb_disp_stats_t), KM_SLEEP);
443a90cf9f2SGordon Ross 
444a90cf9f2SGordon Ross 	sv->sv_disp_stats2 = kmem_zalloc(SMB2__NCMDS *
4458622ec45SGordon Ross 	    sizeof (smb_disp_stats_t), KM_SLEEP);
446faa1795aSjb150015 
44708344b29SGordon Ross 	smb_thread_init(&sv->si_thread_timers, "smb_timers",
44808344b29SGordon Ross 	    smb_server_timers, sv, smbsrv_timer_pri);
449faa1795aSjb150015 
450148c5f43SAlan Wright 	smb_srqueue_init(&sv->sv_srqueue);
451faa1795aSjb150015 
4528622ec45SGordon Ross 	smb_kdoor_init(sv);
4538622ec45SGordon Ross 	smb_kshare_init(sv);
454148c5f43SAlan Wright 	smb_server_kstat_init(sv);
455faa1795aSjb150015 
456856399cfSGordon Ross 	smb_threshold_init(&sv->sv_ssetup_ct, SMB_SSETUP_CMD,
457856399cfSGordon Ross 	    smb_ssetup_threshold, smb_ssetup_timeout);
458856399cfSGordon Ross 	smb_threshold_init(&sv->sv_tcon_ct, SMB_TCON_CMD,
459856399cfSGordon Ross 	    smb_tcon_threshold, smb_tcon_timeout);
460856399cfSGordon Ross 	smb_threshold_init(&sv->sv_opipe_ct, SMB_OPIPE_CMD,
461856399cfSGordon Ross 	    smb_opipe_threshold, smb_opipe_timeout);
462856399cfSGordon Ross 
463faa1795aSjb150015 	smb_llist_insert_tail(&smb_servers, sv);
464faa1795aSjb150015 	smb_llist_exit(&smb_servers);
465cb174861Sjoyce mcintosh 
466faa1795aSjb150015 	return (0);
467faa1795aSjb150015 }
468faa1795aSjb150015 
469faa1795aSjb150015 /*
470faa1795aSjb150015  * smb_server_delete
471faa1795aSjb150015  *
472faa1795aSjb150015  * This function will delete the server passed in. It will make sure that all
473faa1795aSjb150015  * activity associated that server has ceased before destroying it.
474faa1795aSjb150015  */
475faa1795aSjb150015 int
476*8d94f651SGordon Ross smb_server_delete(smb_server_t	*sv)
477faa1795aSjb150015 {
478faa1795aSjb150015 
479faa1795aSjb150015 	mutex_enter(&sv->sv_mutex);
480faa1795aSjb150015 	switch (sv->sv_state) {
481faa1795aSjb150015 	case SMB_SERVER_STATE_RUNNING:
4829fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		sv->sv_state = SMB_SERVER_STATE_STOPPING;
483faa1795aSjb150015 		mutex_exit(&sv->sv_mutex);
4844163af6aSjose borrego 		smb_server_shutdown(sv);
485faa1795aSjb150015 		mutex_enter(&sv->sv_mutex);
4864163af6aSjose borrego 		cv_broadcast(&sv->sp_info.sp_cv);
4874163af6aSjose borrego 		sv->sv_state = SMB_SERVER_STATE_DELETING;
4884163af6aSjose borrego 		break;
4894163af6aSjose borrego 	case SMB_SERVER_STATE_STOPPING:
4904163af6aSjose borrego 		sv->sv_state = SMB_SERVER_STATE_DELETING;
491faa1795aSjb150015 		break;
492faa1795aSjb150015 	case SMB_SERVER_STATE_CONFIGURED:
493faa1795aSjb150015 	case SMB_SERVER_STATE_CREATED:
494faa1795aSjb150015 		sv->sv_state = SMB_SERVER_STATE_DELETING;
495faa1795aSjb150015 		break;
496faa1795aSjb150015 	default:
4979fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_SERVER_STATE_VALID(sv->sv_state);
498faa1795aSjb150015 		mutex_exit(&sv->sv_mutex);
499faa1795aSjb150015 		smb_server_release(sv);
500faa1795aSjb150015 		return (ENOTTY);
501faa1795aSjb150015 	}
502faa1795aSjb150015 
503faa1795aSjb150015 	ASSERT(sv->sv_state == SMB_SERVER_STATE_DELETING);
504faa1795aSjb150015 
505faa1795aSjb150015 	sv->sv_refcnt--;
506faa1795aSjb150015 	while (sv->sv_refcnt)
507faa1795aSjb150015 		cv_wait(&sv->sv_cv, &sv->sv_mutex);
508faa1795aSjb150015 
509faa1795aSjb150015 	mutex_exit(&sv->sv_mutex);
510faa1795aSjb150015 
511faa1795aSjb150015 	smb_llist_enter(&smb_servers, RW_WRITER);
512faa1795aSjb150015 	smb_llist_remove(&smb_servers, sv);
513faa1795aSjb150015 	smb_llist_exit(&smb_servers);
514faa1795aSjb150015 
515856399cfSGordon Ross 	smb_threshold_fini(&sv->sv_ssetup_ct);
516856399cfSGordon Ross 	smb_threshold_fini(&sv->sv_tcon_ct);
517856399cfSGordon Ross 	smb_threshold_fini(&sv->sv_opipe_ct);
518856399cfSGordon Ross 
5194163af6aSjose borrego 	smb_server_listener_destroy(&sv->sv_nbt_daemon);
5204163af6aSjose borrego 	smb_server_listener_destroy(&sv->sv_tcp_daemon);
521faa1795aSjb150015 	rw_destroy(&sv->sv_cfg_lock);
522faa1795aSjb150015 	smb_server_kstat_fini(sv);
5238622ec45SGordon Ross 	smb_kshare_fini(sv);
5248622ec45SGordon Ross 	smb_kdoor_fini(sv);
5259fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_destructor(&sv->sv_event_list);
526811599a4SMatt Barden 	smb_llist_destructor(&sv->sv_session_list);
5272c1b14e5Sjose borrego 
528a90cf9f2SGordon Ross 	kmem_free(sv->sv_disp_stats1,
5298622ec45SGordon Ross 	    SMB_COM_NUM * sizeof (smb_disp_stats_t));
530faa1795aSjb150015 
531a90cf9f2SGordon Ross 	kmem_free(sv->sv_disp_stats2,
532a90cf9f2SGordon Ross 	    SMB2__NCMDS * sizeof (smb_disp_stats_t));
533a90cf9f2SGordon Ross 
534148c5f43SAlan Wright 	smb_srqueue_destroy(&sv->sv_srqueue);
535faa1795aSjb150015 	smb_thread_destroy(&sv->si_thread_timers);
5368622ec45SGordon Ross 
537faa1795aSjb150015 	mutex_destroy(&sv->sv_mutex);
53894047d49SGordon Ross 	smb_hash_destroy(sv->sv_lease_ht);
539811599a4SMatt Barden 	smb_hash_destroy(sv->sv_persistid_ht);
540faa1795aSjb150015 	cv_destroy(&sv->sv_cv);
541faa1795aSjb150015 	sv->sv_magic = 0;
542faa1795aSjb150015 	kmem_free(sv, sizeof (smb_server_t));
543faa1795aSjb150015 
544faa1795aSjb150015 	return (0);
545faa1795aSjb150015 }
546faa1795aSjb150015 
547faa1795aSjb150015 /*
548faa1795aSjb150015  * smb_server_configure
549faa1795aSjb150015  */
550faa1795aSjb150015 int
55129bd2886SAlan Wright smb_server_configure(smb_ioc_cfg_t *ioc)
552faa1795aSjb150015 {
553faa1795aSjb150015 	int		rc = 0;
554faa1795aSjb150015 	smb_server_t	*sv;
555faa1795aSjb150015 
5561d443a93SDan McDonald 	/*
5571d443a93SDan McDonald 	 * Reality check negotiation token length vs. #define'd maximum.
5581d443a93SDan McDonald 	 */
5591d443a93SDan McDonald 	if (ioc->negtok_len > SMB_PI_MAX_NEGTOK)
5601d443a93SDan McDonald 		return (EINVAL);
5611d443a93SDan McDonald 
562faa1795aSjb150015 	rc = smb_server_lookup(&sv);
563faa1795aSjb150015 	if (rc)
564faa1795aSjb150015 		return (rc);
565faa1795aSjb150015 
566faa1795aSjb150015 	mutex_enter(&sv->sv_mutex);
567faa1795aSjb150015 	switch (sv->sv_state) {
568faa1795aSjb150015 	case SMB_SERVER_STATE_CREATED:
56929bd2886SAlan Wright 		smb_server_store_cfg(sv, ioc);
570faa1795aSjb150015 		sv->sv_state = SMB_SERVER_STATE_CONFIGURED;
571faa1795aSjb150015 		break;
572faa1795aSjb150015 
573faa1795aSjb150015 	case SMB_SERVER_STATE_CONFIGURED:
57429bd2886SAlan Wright 		smb_server_store_cfg(sv, ioc);
575faa1795aSjb150015 		break;
576faa1795aSjb150015 
577faa1795aSjb150015 	case SMB_SERVER_STATE_RUNNING:
5789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	case SMB_SERVER_STATE_STOPPING:
579faa1795aSjb150015 		rw_enter(&sv->sv_cfg_lock, RW_WRITER);
58029bd2886SAlan Wright 		smb_server_store_cfg(sv, ioc);
581faa1795aSjb150015 		rw_exit(&sv->sv_cfg_lock);
582faa1795aSjb150015 		break;
583faa1795aSjb150015 
584faa1795aSjb150015 	default:
5859fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_SERVER_STATE_VALID(sv->sv_state);
586faa1795aSjb150015 		rc = EFAULT;
587faa1795aSjb150015 		break;
588faa1795aSjb150015 	}
589faa1795aSjb150015 	mutex_exit(&sv->sv_mutex);
590faa1795aSjb150015 
591faa1795aSjb150015 	smb_server_release(sv);
592faa1795aSjb150015 
593faa1795aSjb150015 	return (rc);
594faa1795aSjb150015 }
595faa1795aSjb150015 
596faa1795aSjb150015 /*
597faa1795aSjb150015  * smb_server_start
598faa1795aSjb150015  */
599faa1795aSjb150015 int
60029bd2886SAlan Wright smb_server_start(smb_ioc_start_t *ioc)
601faa1795aSjb150015 {
602faa1795aSjb150015 	int		rc = 0;
6034163af6aSjose borrego 	int		family;
604faa1795aSjb150015 	smb_server_t	*sv;
605*8d94f651SGordon Ross 	cred_t		*ucr;
606faa1795aSjb150015 
607faa1795aSjb150015 	rc = smb_server_lookup(&sv);
608faa1795aSjb150015 	if (rc)
609faa1795aSjb150015 		return (rc);
610faa1795aSjb150015 
611faa1795aSjb150015 	mutex_enter(&sv->sv_mutex);
612faa1795aSjb150015 	switch (sv->sv_state) {
613faa1795aSjb150015 	case SMB_SERVER_STATE_CONFIGURED:
614faa1795aSjb150015 
6158622ec45SGordon Ross 		if ((rc = smb_server_fsop_start(sv)) != 0)
6168622ec45SGordon Ross 			break;
6178622ec45SGordon Ross 
618*8d94f651SGordon Ross 		/*
619*8d94f651SGordon Ross 		 * Note: smb_kshare_start needs sv_session.
620*8d94f651SGordon Ross 		 */
621*8d94f651SGordon Ross 		sv->sv_session = smb_session_create(NULL, 0, sv, 0);
622*8d94f651SGordon Ross 		if (sv->sv_session == NULL) {
623*8d94f651SGordon Ross 			rc = ENOMEM;
624*8d94f651SGordon Ross 			break;
625*8d94f651SGordon Ross 		}
626*8d94f651SGordon Ross 
627*8d94f651SGordon Ross 		/*
628*8d94f651SGordon Ross 		 * Create a logon on the server session,
629*8d94f651SGordon Ross 		 * used when importing CA shares.
630*8d94f651SGordon Ross 		 */
631*8d94f651SGordon Ross 		sv->sv_rootuser = smb_user_new(sv->sv_session);
632*8d94f651SGordon Ross 		ucr = smb_kcred_create();
633*8d94f651SGordon Ross 		rc = smb_user_logon(sv->sv_rootuser, ucr, "", "root",
634*8d94f651SGordon Ross 		    SMB_USER_FLAG_ADMIN, 0, 0);
635*8d94f651SGordon Ross 		crfree(ucr);
636*8d94f651SGordon Ross 		ucr = NULL;
637*8d94f651SGordon Ross 		if (rc != 0) {
638*8d94f651SGordon Ross 			cmn_err(CE_NOTE, "smb_server_start: "
639*8d94f651SGordon Ross 			    "failed to create root user");
640*8d94f651SGordon Ross 			break;
641*8d94f651SGordon Ross 		}
642*8d94f651SGordon Ross 
6438622ec45SGordon Ross 		if ((rc = smb_kshare_start(sv)) != 0)
6448622ec45SGordon Ross 			break;
6458622ec45SGordon Ross 
646b819cea2SGordon Ross 		/*
647b819cea2SGordon Ross 		 * NB: the proc passed here has to be a "system" one.
648b819cea2SGordon Ross 		 * Normally that's p0, or the NGZ eqivalent.
649b819cea2SGordon Ross 		 */
6508622ec45SGordon Ross 		sv->sv_worker_pool = taskq_create_proc("smb_workers",
65108344b29SGordon Ross 		    sv->sv_cfg.skc_maxworkers, smbsrv_worker_pri,
652faa1795aSjb150015 		    sv->sv_cfg.skc_maxworkers, INT_MAX,
6538622ec45SGordon Ross 		    curzone->zone_zsched, TASKQ_DYNAMIC);
654faa1795aSjb150015 
6558622ec45SGordon Ross 		sv->sv_receiver_pool = taskq_create_proc("smb_receivers",
65608344b29SGordon Ross 		    sv->sv_cfg.skc_maxconnections, smbsrv_receive_pri,
6574163af6aSjose borrego 		    sv->sv_cfg.skc_maxconnections, INT_MAX,
6588622ec45SGordon Ross 		    curzone->zone_zsched, TASKQ_DYNAMIC);
6594163af6aSjose borrego 
660*8d94f651SGordon Ross 		if (sv->sv_worker_pool == NULL ||
661*8d94f651SGordon Ross 		    sv->sv_receiver_pool == NULL) {
662faa1795aSjb150015 			rc = ENOMEM;
663faa1795aSjb150015 			break;
664faa1795aSjb150015 		}
665faa1795aSjb150015 
666b819cea2SGordon Ross #ifdef	_KERNEL
667faa1795aSjb150015 		ASSERT(sv->sv_lmshrd == NULL);
668148c5f43SAlan Wright 		sv->sv_lmshrd = smb_kshare_door_init(ioc->lmshrd);
669faa1795aSjb150015 		if (sv->sv_lmshrd == NULL)
670faa1795aSjb150015 			break;
67154026d5aSGordon Ross 		if ((rc = smb_kdoor_open(sv, ioc->udoor)) != 0) {
6729fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			cmn_err(CE_WARN, "Cannot open smbd door");
673faa1795aSjb150015 			break;
6749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		}
675b819cea2SGordon Ross #else	/* _KERNEL */
676b819cea2SGordon Ross 		/* Fake kernel does not use the kshare_door */
677b819cea2SGordon Ross 		fksmb_kdoor_open(sv, ioc->udoor_func);
678b819cea2SGordon Ross #endif	/* _KERNEL */
679b819cea2SGordon Ross 
68054026d5aSGordon Ross 		if ((rc = smb_thread_start(&sv->si_thread_timers)) != 0)
6819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			break;
6824163af6aSjose borrego 
6834163af6aSjose borrego 		family = AF_INET;
6844163af6aSjose borrego 		smb_server_listener_init(sv, &sv->sv_nbt_daemon,
6854163af6aSjose borrego 		    "smb_nbt_listener", IPPORT_NETBIOS_SSN, family);
6864163af6aSjose borrego 		if (sv->sv_cfg.skc_ipv6_enable)
6874163af6aSjose borrego 			family = AF_INET6;
6884163af6aSjose borrego 		smb_server_listener_init(sv, &sv->sv_tcp_daemon,
6894163af6aSjose borrego 		    "smb_tcp_listener", IPPORT_SMB, family);
6904163af6aSjose borrego 		rc = smb_server_listener_start(&sv->sv_tcp_daemon);
6914163af6aSjose borrego 		if (rc != 0)
6924163af6aSjose borrego 			break;
69383d2dfe6SGordon Ross 		if (sv->sv_cfg.skc_netbios_enable)
69483d2dfe6SGordon Ross 			(void) smb_server_listener_start(&sv->sv_nbt_daemon);
6954163af6aSjose borrego 
696faa1795aSjb150015 		sv->sv_state = SMB_SERVER_STATE_RUNNING;
697148c5f43SAlan Wright 		sv->sv_start_time = gethrtime();
698faa1795aSjb150015 		mutex_exit(&sv->sv_mutex);
699faa1795aSjb150015 		smb_server_release(sv);
7008622ec45SGordon Ross 		smb_export_start(sv);
701faa1795aSjb150015 		return (0);
702faa1795aSjb150015 	default:
7039fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_SERVER_STATE_VALID(sv->sv_state);
704faa1795aSjb150015 		mutex_exit(&sv->sv_mutex);
705faa1795aSjb150015 		smb_server_release(sv);
706faa1795aSjb150015 		return (ENOTTY);
707faa1795aSjb150015 	}
708faa1795aSjb150015 
709faa1795aSjb150015 	mutex_exit(&sv->sv_mutex);
7104163af6aSjose borrego 	smb_server_shutdown(sv);
711faa1795aSjb150015 	smb_server_release(sv);
712faa1795aSjb150015 	return (rc);
713faa1795aSjb150015 }
714faa1795aSjb150015 
715faa1795aSjb150015 /*
7169fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * An smbd is shutting down.
7179fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  */
7189fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States int
7199fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_server_stop(void)
7209fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
7219fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_server_t	*sv;
7229fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	int		rc;
7239fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7249fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if ((rc = smb_server_lookup(&sv)) != 0)
7259fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (rc);
7269fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7279fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_enter(&sv->sv_mutex);
7289fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	switch (sv->sv_state) {
7299fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	case SMB_SERVER_STATE_RUNNING:
7309fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		sv->sv_state = SMB_SERVER_STATE_STOPPING;
7314163af6aSjose borrego 		mutex_exit(&sv->sv_mutex);
7324163af6aSjose borrego 		smb_server_shutdown(sv);
7334163af6aSjose borrego 		mutex_enter(&sv->sv_mutex);
734cb174861Sjoyce mcintosh 		cv_broadcast(&sv->sp_info.sp_cv);
7359fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		break;
7369fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	default:
7379fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_SERVER_STATE_VALID(sv->sv_state);
7389fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		break;
7399fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
7409fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_exit(&sv->sv_mutex);
7419fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7429fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_server_release(sv);
7439fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	return (0);
7449fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
7459fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7469fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States boolean_t
7478622ec45SGordon Ross smb_server_is_stopping(smb_server_t *sv)
7489fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
7499fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	boolean_t	status;
7509fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7519fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	SMB_SERVER_VALID(sv);
7529fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7539fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_enter(&sv->sv_mutex);
7549fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7559fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	switch (sv->sv_state) {
7569fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	case SMB_SERVER_STATE_STOPPING:
7579fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	case SMB_SERVER_STATE_DELETING:
7589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		status = B_TRUE;
7599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		break;
7609fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	default:
7619fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		status = B_FALSE;
7629fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		break;
7639fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
7649fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7659fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_exit(&sv->sv_mutex);
7669fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	return (status);
7679fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
7689fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7698622ec45SGordon Ross void
7708622ec45SGordon Ross smb_server_cancel_event(smb_server_t *sv, uint32_t txid)
7719fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
7729fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_event_cancel(sv, txid);
7739fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
7749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7759fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States int
7769fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_server_notify_event(smb_ioc_event_t *ioc)
7779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
7789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_server_t	*sv;
7799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	int		rc;
7809fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if ((rc = smb_server_lookup(&sv)) == 0) {
7829fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		smb_event_notify(sv, ioc->txid);
7839fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		smb_server_release(sv);
7849fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
7859fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7869fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	return (rc);
7879fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
7889fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7899fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
790cb174861Sjoyce mcintosh  * smb_server_spooldoc
791cb174861Sjoyce mcintosh  *
792cb174861Sjoyce mcintosh  * Waits for print file close broadcast.
793cb174861Sjoyce mcintosh  * Gets the head of the fid list,
794cb174861Sjoyce mcintosh  * then searches the spooldoc list and returns
795cb174861Sjoyce mcintosh  * this info via the ioctl to user land.
796cb174861Sjoyce mcintosh  *
797cb174861Sjoyce mcintosh  * rc - 0 success
798cb174861Sjoyce mcintosh  */
799cb174861Sjoyce mcintosh 
800cb174861Sjoyce mcintosh int
801cb174861Sjoyce mcintosh smb_server_spooldoc(smb_ioc_spooldoc_t *ioc)
802cb174861Sjoyce mcintosh {
803cb174861Sjoyce mcintosh 	smb_server_t	*sv;
804cb174861Sjoyce mcintosh 	int		rc;
805cb174861Sjoyce mcintosh 	smb_kspooldoc_t *spdoc;
806cb174861Sjoyce mcintosh 	uint16_t	fid;
807cb174861Sjoyce mcintosh 
80823a9c295SGordon Ross 	if ((rc = smb_server_lookup(&sv)) != 0)
80923a9c295SGordon Ross 		return (rc);
81023a9c295SGordon Ross 
811b7301bf5SGordon Ross 	if (sv->sv_cfg.skc_print_enable == 0) {
812b7301bf5SGordon Ross 		rc = ENOTTY;
813b7301bf5SGordon Ross 		goto out;
814b7301bf5SGordon Ross 	}
815b7301bf5SGordon Ross 
81623a9c295SGordon Ross 	mutex_enter(&sv->sv_mutex);
81723a9c295SGordon Ross 	for (;;) {
818cb174861Sjoyce mcintosh 		if (sv->sv_state != SMB_SERVER_STATE_RUNNING) {
819cb174861Sjoyce mcintosh 			rc = ECANCELED;
82023a9c295SGordon Ross 			break;
82123a9c295SGordon Ross 		}
82223a9c295SGordon Ross 		if ((fid = smb_spool_get_fid(sv)) != 0) {
82323a9c295SGordon Ross 			rc = 0;
82423a9c295SGordon Ross 			break;
82523a9c295SGordon Ross 		}
82623a9c295SGordon Ross 		if (cv_wait_sig(&sv->sp_info.sp_cv, &sv->sv_mutex) == 0) {
82723a9c295SGordon Ross 			rc = EINTR;
82823a9c295SGordon Ross 			break;
82923a9c295SGordon Ross 		}
83023a9c295SGordon Ross 	}
83123a9c295SGordon Ross 	mutex_exit(&sv->sv_mutex);
832b7301bf5SGordon Ross 	if (rc != 0)
833b7301bf5SGordon Ross 		goto out;
834b7301bf5SGordon Ross 
83523a9c295SGordon Ross 	spdoc = kmem_zalloc(sizeof (*spdoc), KM_SLEEP);
83623a9c295SGordon Ross 	if (smb_spool_lookup_doc_byfid(sv, fid, spdoc)) {
837cb174861Sjoyce mcintosh 		ioc->spool_num = spdoc->sd_spool_num;
838cb174861Sjoyce mcintosh 		ioc->ipaddr = spdoc->sd_ipaddr;
839cb174861Sjoyce mcintosh 		(void) strlcpy(ioc->path, spdoc->sd_path,
840cb174861Sjoyce mcintosh 		    MAXPATHLEN);
841cb174861Sjoyce mcintosh 		(void) strlcpy(ioc->username,
842cb174861Sjoyce mcintosh 		    spdoc->sd_username, MAXNAMELEN);
84323a9c295SGordon Ross 	} else {
84423a9c295SGordon Ross 		/* Did not find that print job. */
84523a9c295SGordon Ross 		rc = EAGAIN;
846cb174861Sjoyce mcintosh 	}
84723a9c295SGordon Ross 	kmem_free(spdoc, sizeof (*spdoc));
84823a9c295SGordon Ross 
849b7301bf5SGordon Ross out:
850cb174861Sjoyce mcintosh 	smb_server_release(sv);
851cb174861Sjoyce mcintosh 	return (rc);
852cb174861Sjoyce mcintosh }
853cb174861Sjoyce mcintosh 
854faa1795aSjb150015 int
85529bd2886SAlan Wright smb_server_set_gmtoff(smb_ioc_gmt_t *ioc)
856faa1795aSjb150015 {
857faa1795aSjb150015 	int		rc;
858faa1795aSjb150015 	smb_server_t	*sv;
859faa1795aSjb150015 
86008f0d8daSafshin salek ardakani - Sun Microsystems - Irvine United States 	if ((rc = smb_server_lookup(&sv)) == 0) {
86129bd2886SAlan Wright 		sv->si_gmtoff = ioc->offset;
862faa1795aSjb150015 		smb_server_release(sv);
86308f0d8daSafshin salek ardakani - Sun Microsystems - Irvine United States 	}
864faa1795aSjb150015 
865faa1795aSjb150015 	return (rc);
866faa1795aSjb150015 }
867faa1795aSjb150015 
86829bd2886SAlan Wright int
8691fcced4cSJordan Brown smb_server_numopen(smb_ioc_opennum_t *ioc)
87029bd2886SAlan Wright {
87129bd2886SAlan Wright 	smb_server_t	*sv;
87229bd2886SAlan Wright 	int		rc;
87329bd2886SAlan Wright 
87429bd2886SAlan Wright 	if ((rc = smb_server_lookup(&sv)) == 0) {
875148c5f43SAlan Wright 		ioc->open_users = sv->sv_users;
876148c5f43SAlan Wright 		ioc->open_trees = sv->sv_trees;
877148c5f43SAlan Wright 		ioc->open_files = sv->sv_files + sv->sv_pipes;
87829bd2886SAlan Wright 		smb_server_release(sv);
87929bd2886SAlan Wright 	}
88029bd2886SAlan Wright 	return (rc);
88129bd2886SAlan Wright }
88229bd2886SAlan Wright 
883faa1795aSjb150015 /*
8841fcced4cSJordan Brown  * Enumerate objects within the server.  The svcenum provides the
8851fcced4cSJordan Brown  * enumeration context, i.e. what the caller want to get back.
8861fcced4cSJordan Brown  */
8871fcced4cSJordan Brown int
8881fcced4cSJordan Brown smb_server_enum(smb_ioc_svcenum_t *ioc)
8891fcced4cSJordan Brown {
8901fcced4cSJordan Brown 	smb_svcenum_t	*svcenum = &ioc->svcenum;
8911fcced4cSJordan Brown 	smb_server_t	*sv;
8921fcced4cSJordan Brown 	int		rc;
8931fcced4cSJordan Brown 
8941d443a93SDan McDonald 	/*
8951d443a93SDan McDonald 	 * Reality check that the buffer-length insize the enum doesn't
8961d443a93SDan McDonald 	 * overrun the ioctl's total length.
8971d443a93SDan McDonald 	 */
8981d443a93SDan McDonald 	if (svcenum->se_buflen + sizeof (*ioc) > ioc->hdr.len)
8991d443a93SDan McDonald 		return (EINVAL);
9001d443a93SDan McDonald 
9011fcced4cSJordan Brown 	if ((rc = smb_server_lookup(&sv)) != 0)
9021fcced4cSJordan Brown 		return (rc);
9031fcced4cSJordan Brown 
9041fcced4cSJordan Brown 	svcenum->se_bavail = svcenum->se_buflen;
9051fcced4cSJordan Brown 	svcenum->se_bused = 0;
9061fcced4cSJordan Brown 	svcenum->se_nitems = 0;
9071fcced4cSJordan Brown 
9083b13a1efSThomas Keiser 	switch (svcenum->se_type) {
9093b13a1efSThomas Keiser 	case SMB_SVCENUM_TYPE_USER:
910*8d94f651SGordon Ross 		smb_server_enum_users(sv, svcenum);
9113b13a1efSThomas Keiser 		break;
9123b13a1efSThomas Keiser 	case SMB_SVCENUM_TYPE_TREE:
9133b13a1efSThomas Keiser 	case SMB_SVCENUM_TYPE_FILE:
914*8d94f651SGordon Ross 		smb_server_enum_trees(sv, svcenum);
9153b13a1efSThomas Keiser 		break;
9163b13a1efSThomas Keiser 	default:
9173b13a1efSThomas Keiser 		rc = EINVAL;
9183b13a1efSThomas Keiser 	}
9191fcced4cSJordan Brown 
9201fcced4cSJordan Brown 	smb_server_release(sv);
9213b13a1efSThomas Keiser 	return (rc);
9221fcced4cSJordan Brown }
9231fcced4cSJordan Brown 
9241fcced4cSJordan Brown /*
9251fcced4cSJordan Brown  * Look for sessions to disconnect by client and user name.
9261fcced4cSJordan Brown  */
9271fcced4cSJordan Brown int
9281fcced4cSJordan Brown smb_server_session_close(smb_ioc_session_t *ioc)
9291fcced4cSJordan Brown {
9301fcced4cSJordan Brown 	smb_server_t	*sv;
931811599a4SMatt Barden 	int		cnt;
9321fcced4cSJordan Brown 	int		rc;
9331fcced4cSJordan Brown 
9341fcced4cSJordan Brown 	if ((rc = smb_server_lookup(&sv)) != 0)
9351fcced4cSJordan Brown 		return (rc);
9361fcced4cSJordan Brown 
937*8d94f651SGordon Ross 	cnt = smb_server_session_disconnect(sv, ioc->client, ioc->username);
9381fcced4cSJordan Brown 
9391fcced4cSJordan Brown 	smb_server_release(sv);
9401fcced4cSJordan Brown 
941811599a4SMatt Barden 	if (cnt == 0)
9421fcced4cSJordan Brown 		return (ENOENT);
9431fcced4cSJordan Brown 	return (0);
9441fcced4cSJordan Brown }
9451fcced4cSJordan Brown 
9461fcced4cSJordan Brown /*
9471fcced4cSJordan Brown  * Close a file by uniqid.
9481fcced4cSJordan Brown  */
9491fcced4cSJordan Brown int
9501fcced4cSJordan Brown smb_server_file_close(smb_ioc_fileid_t *ioc)
9511fcced4cSJordan Brown {
9521fcced4cSJordan Brown 	uint32_t	uniqid = ioc->uniqid;
9531fcced4cSJordan Brown 	smb_server_t	*sv;
9541fcced4cSJordan Brown 	int		rc;
9551fcced4cSJordan Brown 
9561fcced4cSJordan Brown 	if ((rc = smb_server_lookup(&sv)) != 0)
9571fcced4cSJordan Brown 		return (rc);
9581fcced4cSJordan Brown 
959*8d94f651SGordon Ross 	rc = smb_server_fclose(sv, uniqid);
9601fcced4cSJordan Brown 
9611fcced4cSJordan Brown 	smb_server_release(sv);
9621fcced4cSJordan Brown 	return (rc);
9631fcced4cSJordan Brown }
9641fcced4cSJordan Brown 
9651fcced4cSJordan Brown /*
966faa1795aSjb150015  * These functions determine the relevant smb server to which the call apply.
967faa1795aSjb150015  */
968faa1795aSjb150015 
969faa1795aSjb150015 uint32_t
9708622ec45SGordon Ross smb_server_get_session_count(smb_server_t *sv)
971faa1795aSjb150015 {
972faa1795aSjb150015 	uint32_t	counter = 0;
973faa1795aSjb150015 
974811599a4SMatt Barden 	counter = smb_llist_get_count(&sv->sv_session_list);
975faa1795aSjb150015 
976faa1795aSjb150015 	return (counter);
977faa1795aSjb150015 }
978faa1795aSjb150015 
979faa1795aSjb150015 /*
980*8d94f651SGordon Ross  * Gets the smb_node of the specified share path.
981*8d94f651SGordon Ross  * Node is returned held (caller must rele.)
982148c5f43SAlan Wright  */
983148c5f43SAlan Wright int
984*8d94f651SGordon Ross smb_server_share_lookup(smb_server_t *sv, const char *shr_path,
985*8d94f651SGordon Ross     smb_node_t **nodepp)
986148c5f43SAlan Wright {
987148c5f43SAlan Wright 	smb_request_t	*sr;
988148c5f43SAlan Wright 	smb_node_t	*fnode = NULL;
989*8d94f651SGordon Ross 	smb_node_t	*dnode = NULL;
990148c5f43SAlan Wright 	char		last_comp[MAXNAMELEN];
991148c5f43SAlan Wright 	int		rc = 0;
992148c5f43SAlan Wright 
993148c5f43SAlan Wright 	ASSERT(shr_path);
994148c5f43SAlan Wright 
995148c5f43SAlan Wright 	mutex_enter(&sv->sv_mutex);
996148c5f43SAlan Wright 	switch (sv->sv_state) {
997148c5f43SAlan Wright 	case SMB_SERVER_STATE_RUNNING:
998148c5f43SAlan Wright 		break;
999148c5f43SAlan Wright 	default:
1000148c5f43SAlan Wright 		mutex_exit(&sv->sv_mutex);
1001148c5f43SAlan Wright 		return (ENOTACTIVE);
1002148c5f43SAlan Wright 	}
1003148c5f43SAlan Wright 	mutex_exit(&sv->sv_mutex);
1004148c5f43SAlan Wright 
1005148c5f43SAlan Wright 	if ((sr = smb_request_alloc(sv->sv_session, 0)) == NULL) {
1006811599a4SMatt Barden 		return (ENOTCONN);
1007148c5f43SAlan Wright 	}
10088622ec45SGordon Ross 	sr->user_cr = zone_kcred();
1009148c5f43SAlan Wright 
1010148c5f43SAlan Wright 	rc = smb_pathname_reduce(sr, sr->user_cr, shr_path,
1011148c5f43SAlan Wright 	    NULL, NULL, &dnode, last_comp);
1012148c5f43SAlan Wright 
1013148c5f43SAlan Wright 	if (rc == 0) {
1014148c5f43SAlan Wright 		rc = smb_fsop_lookup(sr, sr->user_cr, SMB_FOLLOW_LINKS,
1015148c5f43SAlan Wright 		    sv->si_root_smb_node, dnode, last_comp, &fnode);
1016148c5f43SAlan Wright 		smb_node_release(dnode);
1017148c5f43SAlan Wright 	}
1018148c5f43SAlan Wright 
1019148c5f43SAlan Wright 	smb_request_free(sr);
1020148c5f43SAlan Wright 
1021148c5f43SAlan Wright 	if (rc != 0)
1022148c5f43SAlan Wright 		return (rc);
1023148c5f43SAlan Wright 
1024148c5f43SAlan Wright 	ASSERT(fnode->vp && fnode->vp->v_vfsp);
1025148c5f43SAlan Wright 
1026*8d94f651SGordon Ross 	*nodepp = fnode;
1027148c5f43SAlan Wright 
1028148c5f43SAlan Wright 	return (0);
1029148c5f43SAlan Wright }
1030148c5f43SAlan Wright 
1031b819cea2SGordon Ross #ifdef	_KERNEL
1032148c5f43SAlan Wright /*
1033148c5f43SAlan Wright  * This is a special interface that will be utilized by ZFS to cause a share to
1034148c5f43SAlan Wright  * be added/removed.
1035148c5f43SAlan Wright  *
1036148c5f43SAlan Wright  * arg is either a lmshare_info_t or share_name from userspace.
1037148c5f43SAlan Wright  * It will need to be copied into the kernel.   It is lmshare_info_t
1038148c5f43SAlan Wright  * for add operations and share_name for delete operations.
1039148c5f43SAlan Wright  */
1040148c5f43SAlan Wright int
1041148c5f43SAlan Wright smb_server_share(void *arg, boolean_t add_share)
1042148c5f43SAlan Wright {
1043148c5f43SAlan Wright 	smb_server_t	*sv;
1044148c5f43SAlan Wright 	int		rc;
1045148c5f43SAlan Wright 
1046148c5f43SAlan Wright 	if ((rc = smb_server_lookup(&sv)) == 0) {
1047148c5f43SAlan Wright 		mutex_enter(&sv->sv_mutex);
1048148c5f43SAlan Wright 		switch (sv->sv_state) {
1049148c5f43SAlan Wright 		case SMB_SERVER_STATE_RUNNING:
1050148c5f43SAlan Wright 			mutex_exit(&sv->sv_mutex);
1051148c5f43SAlan Wright 			(void) smb_kshare_upcall(sv->sv_lmshrd, arg, add_share);
1052148c5f43SAlan Wright 			break;
1053148c5f43SAlan Wright 		default:
1054148c5f43SAlan Wright 			mutex_exit(&sv->sv_mutex);
1055148c5f43SAlan Wright 			break;
1056148c5f43SAlan Wright 		}
1057148c5f43SAlan Wright 		smb_server_release(sv);
1058148c5f43SAlan Wright 	}
1059148c5f43SAlan Wright 
1060148c5f43SAlan Wright 	return (rc);
1061148c5f43SAlan Wright }
1062b819cea2SGordon Ross #endif	/* _KERNEL */
1063148c5f43SAlan Wright 
1064148c5f43SAlan Wright int
1065148c5f43SAlan Wright smb_server_unshare(const char *sharename)
1066148c5f43SAlan Wright {
1067148c5f43SAlan Wright 	smb_server_t	*sv;
1068148c5f43SAlan Wright 	int		rc;
1069148c5f43SAlan Wright 
1070148c5f43SAlan Wright 	if ((rc = smb_server_lookup(&sv)))
1071148c5f43SAlan Wright 		return (rc);
1072148c5f43SAlan Wright 
1073148c5f43SAlan Wright 	mutex_enter(&sv->sv_mutex);
1074148c5f43SAlan Wright 	switch (sv->sv_state) {
1075148c5f43SAlan Wright 	case SMB_SERVER_STATE_RUNNING:
1076148c5f43SAlan Wright 	case SMB_SERVER_STATE_STOPPING:
1077148c5f43SAlan Wright 		break;
1078148c5f43SAlan Wright 	default:
1079148c5f43SAlan Wright 		mutex_exit(&sv->sv_mutex);
1080148c5f43SAlan Wright 		smb_server_release(sv);
1081148c5f43SAlan Wright 		return (ENOTACTIVE);
1082148c5f43SAlan Wright 	}
1083148c5f43SAlan Wright 	mutex_exit(&sv->sv_mutex);
1084148c5f43SAlan Wright 
1085*8d94f651SGordon Ross 	smb_server_disconnect_share(sv, sharename);
1086148c5f43SAlan Wright 
1087148c5f43SAlan Wright 	smb_server_release(sv);
1088148c5f43SAlan Wright 	return (0);
1089148c5f43SAlan Wright }
1090148c5f43SAlan Wright 
1091148c5f43SAlan Wright /*
10929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Disconnect the specified share.
10939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Typically called when a share has been removed.
1094faa1795aSjb150015  */
10952c1b14e5Sjose borrego static void
1096*8d94f651SGordon Ross smb_server_disconnect_share(smb_server_t *sv, const char *sharename)
1097faa1795aSjb150015 {
1098*8d94f651SGordon Ross 	smb_llist_t	*ll;
10999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_session_t	*session;
11009fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
1101*8d94f651SGordon Ross 	ll = &sv->sv_session_list;
11024163af6aSjose borrego 	smb_llist_enter(ll, RW_READER);
11039fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
11044163af6aSjose borrego 	session = smb_llist_head(ll);
11059fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	while (session) {
11064163af6aSjose borrego 		SMB_SESSION_VALID(session);
11079fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		smb_rwx_rwenter(&session->s_lock, RW_READER);
11089fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		switch (session->s_state) {
11099fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		case SMB_SESSION_STATE_NEGOTIATED:
1110811599a4SMatt Barden 			smb_rwx_rwexit(&session->s_lock);
11119fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			smb_session_disconnect_share(session, sharename);
11129fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			break;
11139fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		default:
1114811599a4SMatt Barden 			smb_rwx_rwexit(&session->s_lock);
11159fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			break;
11169fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		}
11174163af6aSjose borrego 		session = smb_llist_next(ll, session);
11189fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
11199fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
11204163af6aSjose borrego 	smb_llist_exit(ll);
1121faa1795aSjb150015 }
1122faa1795aSjb150015 
1123faa1795aSjb150015 /*
1124faa1795aSjb150015  * *****************************************************************************
1125faa1795aSjb150015  * **************** Functions called from the internal layers ******************
1126faa1795aSjb150015  * *****************************************************************************
1127faa1795aSjb150015  *
1128faa1795aSjb150015  * These functions are provided the relevant smb server by the caller.
1129faa1795aSjb150015  */
1130faa1795aSjb150015 
1131faa1795aSjb150015 void
1132faa1795aSjb150015 smb_server_get_cfg(smb_server_t *sv, smb_kmod_cfg_t *cfg)
1133faa1795aSjb150015 {
1134faa1795aSjb150015 	rw_enter(&sv->sv_cfg_lock, RW_READER);
1135faa1795aSjb150015 	bcopy(&sv->sv_cfg, cfg, sizeof (*cfg));
1136faa1795aSjb150015 	rw_exit(&sv->sv_cfg_lock);
1137faa1795aSjb150015 }
1138faa1795aSjb150015 
1139faa1795aSjb150015 /*
1140148c5f43SAlan Wright  *
1141148c5f43SAlan Wright  */
1142148c5f43SAlan Wright void
1143148c5f43SAlan Wright smb_server_inc_nbt_sess(smb_server_t *sv)
1144148c5f43SAlan Wright {
1145148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1146148c5f43SAlan Wright 	atomic_inc_32(&sv->sv_nbt_sess);
1147148c5f43SAlan Wright }
1148148c5f43SAlan Wright 
1149148c5f43SAlan Wright void
1150148c5f43SAlan Wright smb_server_dec_nbt_sess(smb_server_t *sv)
1151148c5f43SAlan Wright {
1152148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1153148c5f43SAlan Wright 	atomic_dec_32(&sv->sv_nbt_sess);
1154148c5f43SAlan Wright }
1155148c5f43SAlan Wright 
1156148c5f43SAlan Wright void
1157148c5f43SAlan Wright smb_server_inc_tcp_sess(smb_server_t *sv)
1158148c5f43SAlan Wright {
1159148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1160148c5f43SAlan Wright 	atomic_inc_32(&sv->sv_tcp_sess);
1161148c5f43SAlan Wright }
1162148c5f43SAlan Wright 
1163148c5f43SAlan Wright void
1164148c5f43SAlan Wright smb_server_dec_tcp_sess(smb_server_t *sv)
1165148c5f43SAlan Wright {
1166148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1167148c5f43SAlan Wright 	atomic_dec_32(&sv->sv_tcp_sess);
1168148c5f43SAlan Wright }
1169148c5f43SAlan Wright 
1170148c5f43SAlan Wright void
1171148c5f43SAlan Wright smb_server_inc_users(smb_server_t *sv)
1172148c5f43SAlan Wright {
1173148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1174148c5f43SAlan Wright 	atomic_inc_32(&sv->sv_users);
1175148c5f43SAlan Wright }
1176148c5f43SAlan Wright 
1177148c5f43SAlan Wright void
1178148c5f43SAlan Wright smb_server_dec_users(smb_server_t *sv)
1179148c5f43SAlan Wright {
1180148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1181148c5f43SAlan Wright 	atomic_dec_32(&sv->sv_users);
1182148c5f43SAlan Wright }
1183148c5f43SAlan Wright 
1184148c5f43SAlan Wright void
1185148c5f43SAlan Wright smb_server_inc_trees(smb_server_t *sv)
1186148c5f43SAlan Wright {
1187148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1188148c5f43SAlan Wright 	atomic_inc_32(&sv->sv_trees);
1189148c5f43SAlan Wright }
1190148c5f43SAlan Wright 
1191148c5f43SAlan Wright void
1192148c5f43SAlan Wright smb_server_dec_trees(smb_server_t *sv)
1193148c5f43SAlan Wright {
1194148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1195148c5f43SAlan Wright 	atomic_dec_32(&sv->sv_trees);
1196148c5f43SAlan Wright }
1197148c5f43SAlan Wright 
1198148c5f43SAlan Wright void
1199148c5f43SAlan Wright smb_server_inc_files(smb_server_t *sv)
1200148c5f43SAlan Wright {
1201148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1202148c5f43SAlan Wright 	atomic_inc_32(&sv->sv_files);
1203148c5f43SAlan Wright }
1204148c5f43SAlan Wright 
1205148c5f43SAlan Wright void
1206148c5f43SAlan Wright smb_server_dec_files(smb_server_t *sv)
1207148c5f43SAlan Wright {
1208148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1209148c5f43SAlan Wright 	atomic_dec_32(&sv->sv_files);
1210148c5f43SAlan Wright }
1211148c5f43SAlan Wright 
1212148c5f43SAlan Wright void
1213148c5f43SAlan Wright smb_server_inc_pipes(smb_server_t *sv)
1214148c5f43SAlan Wright {
1215148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1216148c5f43SAlan Wright 	atomic_inc_32(&sv->sv_pipes);
1217148c5f43SAlan Wright }
1218148c5f43SAlan Wright 
1219148c5f43SAlan Wright void
1220148c5f43SAlan Wright smb_server_dec_pipes(smb_server_t *sv)
1221148c5f43SAlan Wright {
1222148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1223148c5f43SAlan Wright 	atomic_dec_32(&sv->sv_pipes);
1224148c5f43SAlan Wright }
1225148c5f43SAlan Wright 
1226148c5f43SAlan Wright void
1227148c5f43SAlan Wright smb_server_add_rxb(smb_server_t *sv, int64_t value)
1228148c5f43SAlan Wright {
1229148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1230148c5f43SAlan Wright 	atomic_add_64(&sv->sv_rxb, value);
1231148c5f43SAlan Wright }
1232148c5f43SAlan Wright 
1233148c5f43SAlan Wright void
1234148c5f43SAlan Wright smb_server_add_txb(smb_server_t *sv, int64_t value)
1235148c5f43SAlan Wright {
1236148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1237148c5f43SAlan Wright 	atomic_add_64(&sv->sv_txb, value);
1238148c5f43SAlan Wright }
1239148c5f43SAlan Wright 
1240148c5f43SAlan Wright void
1241148c5f43SAlan Wright smb_server_inc_req(smb_server_t *sv)
1242148c5f43SAlan Wright {
1243148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1244148c5f43SAlan Wright 	atomic_inc_64(&sv->sv_nreq);
1245148c5f43SAlan Wright }
1246148c5f43SAlan Wright 
1247148c5f43SAlan Wright /*
1248faa1795aSjb150015  * *****************************************************************************
1249faa1795aSjb150015  * *************************** Static Functions ********************************
1250faa1795aSjb150015  * *****************************************************************************
1251faa1795aSjb150015  */
1252faa1795aSjb150015 
1253faa1795aSjb150015 static void
1254faa1795aSjb150015 smb_server_timers(smb_thread_t *thread, void *arg)
1255faa1795aSjb150015 {
1256faa1795aSjb150015 	smb_server_t	*sv = (smb_server_t *)arg;
1257faa1795aSjb150015 
1258faa1795aSjb150015 	ASSERT(sv != NULL);
1259faa1795aSjb150015 
1260b819cea2SGordon Ross 	/*
1261811599a4SMatt Barden 	 * This kills old inactive sessions and expired durable
1262811599a4SMatt Barden 	 * handles. The session code expects one call per minute.
1263b819cea2SGordon Ross 	 */
1264b819cea2SGordon Ross 	while (smb_thread_continue_timedwait(thread, 60 /* Seconds */)) {
1265811599a4SMatt Barden 		if (sv->sv_cfg.skc_keepalive != 0)
1266811599a4SMatt Barden 			smb_session_timers(sv);
1267811599a4SMatt Barden 		smb2_durable_timers(sv);
1268faa1795aSjb150015 	}
1269faa1795aSjb150015 }
1270faa1795aSjb150015 
1271faa1795aSjb150015 /*
1272faa1795aSjb150015  * smb_server_kstat_init
1273faa1795aSjb150015  */
1274148c5f43SAlan Wright static void
1275faa1795aSjb150015 smb_server_kstat_init(smb_server_t *sv)
1276faa1795aSjb150015 {
1277cb174861Sjoyce mcintosh 
12788622ec45SGordon Ross 	sv->sv_ksp = kstat_create_zone(SMBSRV_KSTAT_MODULE, 0,
1279148c5f43SAlan Wright 	    SMBSRV_KSTAT_STATISTICS, SMBSRV_KSTAT_CLASS, KSTAT_TYPE_RAW,
1280148c5f43SAlan Wright 	    sizeof (smbsrv_kstats_t), 0, sv->sv_zid);
1281faa1795aSjb150015 
1282148c5f43SAlan Wright 	if (sv->sv_ksp != NULL) {
1283148c5f43SAlan Wright 		sv->sv_ksp->ks_update = smb_server_kstat_update;
1284148c5f43SAlan Wright 		sv->sv_ksp->ks_private = sv;
1285148c5f43SAlan Wright 		((smbsrv_kstats_t *)sv->sv_ksp->ks_data)->ks_start_time =
1286148c5f43SAlan Wright 		    sv->sv_start_time;
12878622ec45SGordon Ross 		smb_dispatch_stats_init(sv);
1288a90cf9f2SGordon Ross 		smb2_dispatch_stats_init(sv);
1289faa1795aSjb150015 		kstat_install(sv->sv_ksp);
1290148c5f43SAlan Wright 	} else {
1291148c5f43SAlan Wright 		cmn_err(CE_WARN, "SMB Server: Statistics unavailable");
1292faa1795aSjb150015 	}
1293cb174861Sjoyce mcintosh 
12948622ec45SGordon Ross 	sv->sv_legacy_ksp = kstat_create_zone(SMBSRV_KSTAT_MODULE, 0,
12958622ec45SGordon Ross 	    SMBSRV_KSTAT_NAME, SMBSRV_KSTAT_CLASS, KSTAT_TYPE_NAMED,
12968622ec45SGordon Ross 	    sizeof (smb_server_legacy_kstat_t) / sizeof (kstat_named_t),
12978622ec45SGordon Ross 	    0, sv->sv_zid);
1298cb174861Sjoyce mcintosh 
1299cb174861Sjoyce mcintosh 	if (sv->sv_legacy_ksp != NULL) {
1300cb174861Sjoyce mcintosh 		smb_server_legacy_kstat_t *ksd;
1301cb174861Sjoyce mcintosh 
1302cb174861Sjoyce mcintosh 		ksd = sv->sv_legacy_ksp->ks_data;
1303cb174861Sjoyce mcintosh 
1304cb174861Sjoyce mcintosh 		(void) strlcpy(ksd->ls_files.name, "open_files",
1305cb174861Sjoyce mcintosh 		    sizeof (ksd->ls_files.name));
1306cb174861Sjoyce mcintosh 		ksd->ls_files.data_type = KSTAT_DATA_UINT32;
1307cb174861Sjoyce mcintosh 
1308cb174861Sjoyce mcintosh 		(void) strlcpy(ksd->ls_trees.name, "connections",
1309cb174861Sjoyce mcintosh 		    sizeof (ksd->ls_trees.name));
1310cb174861Sjoyce mcintosh 		ksd->ls_trees.data_type = KSTAT_DATA_UINT32;
1311cb174861Sjoyce mcintosh 
1312cb174861Sjoyce mcintosh 		(void) strlcpy(ksd->ls_users.name, "connections",
1313cb174861Sjoyce mcintosh 		    sizeof (ksd->ls_users.name));
1314cb174861Sjoyce mcintosh 		ksd->ls_users.data_type = KSTAT_DATA_UINT32;
1315cb174861Sjoyce mcintosh 
1316cb174861Sjoyce mcintosh 		mutex_init(&sv->sv_legacy_ksmtx, NULL, MUTEX_DEFAULT, NULL);
1317cb174861Sjoyce mcintosh 		sv->sv_legacy_ksp->ks_lock = &sv->sv_legacy_ksmtx;
1318cb174861Sjoyce mcintosh 		sv->sv_legacy_ksp->ks_update = smb_server_legacy_kstat_update;
1319cb174861Sjoyce mcintosh 		kstat_install(sv->sv_legacy_ksp);
1320cb174861Sjoyce mcintosh 	}
1321faa1795aSjb150015 }
1322faa1795aSjb150015 
1323faa1795aSjb150015 /*
1324faa1795aSjb150015  * smb_server_kstat_fini
1325faa1795aSjb150015  */
1326faa1795aSjb150015 static void
1327faa1795aSjb150015 smb_server_kstat_fini(smb_server_t *sv)
1328faa1795aSjb150015 {
1329cb174861Sjoyce mcintosh 	if (sv->sv_legacy_ksp != NULL) {
1330cb174861Sjoyce mcintosh 		kstat_delete(sv->sv_legacy_ksp);
1331cb174861Sjoyce mcintosh 		mutex_destroy(&sv->sv_legacy_ksmtx);
1332cb174861Sjoyce mcintosh 		sv->sv_legacy_ksp = NULL;
1333cb174861Sjoyce mcintosh 	}
1334cb174861Sjoyce mcintosh 
1335148c5f43SAlan Wright 	if (sv->sv_ksp != NULL) {
1336faa1795aSjb150015 		kstat_delete(sv->sv_ksp);
1337faa1795aSjb150015 		sv->sv_ksp = NULL;
13388622ec45SGordon Ross 		smb_dispatch_stats_fini(sv);
1339a90cf9f2SGordon Ross 		smb2_dispatch_stats_fini(sv);
1340faa1795aSjb150015 	}
1341faa1795aSjb150015 }
1342faa1795aSjb150015 
1343148c5f43SAlan Wright /*
1344148c5f43SAlan Wright  * smb_server_kstat_update
1345148c5f43SAlan Wright  */
1346faa1795aSjb150015 static int
1347148c5f43SAlan Wright smb_server_kstat_update(kstat_t *ksp, int rw)
1348faa1795aSjb150015 {
1349faa1795aSjb150015 	smb_server_t	*sv;
1350148c5f43SAlan Wright 	smbsrv_kstats_t	*ksd;
1351faa1795aSjb150015 
1352148c5f43SAlan Wright 	if (rw == KSTAT_READ) {
1353148c5f43SAlan Wright 		sv = ksp->ks_private;
13549fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_SERVER_VALID(sv);
1355148c5f43SAlan Wright 		ksd = (smbsrv_kstats_t *)ksp->ks_data;
1356148c5f43SAlan Wright 		/*
1357148c5f43SAlan Wright 		 * Counters
1358148c5f43SAlan Wright 		 */
1359148c5f43SAlan Wright 		ksd->ks_nbt_sess = sv->sv_nbt_sess;
1360148c5f43SAlan Wright 		ksd->ks_tcp_sess = sv->sv_tcp_sess;
1361148c5f43SAlan Wright 		ksd->ks_users = sv->sv_users;
1362148c5f43SAlan Wright 		ksd->ks_trees = sv->sv_trees;
1363148c5f43SAlan Wright 		ksd->ks_files = sv->sv_files;
1364148c5f43SAlan Wright 		ksd->ks_pipes = sv->sv_pipes;
1365148c5f43SAlan Wright 		/*
1366148c5f43SAlan Wright 		 * Throughput
1367148c5f43SAlan Wright 		 */
1368148c5f43SAlan Wright 		ksd->ks_txb = sv->sv_txb;
1369148c5f43SAlan Wright 		ksd->ks_rxb = sv->sv_rxb;
1370148c5f43SAlan Wright 		ksd->ks_nreq = sv->sv_nreq;
1371148c5f43SAlan Wright 		/*
1372148c5f43SAlan Wright 		 * Busyness
1373148c5f43SAlan Wright 		 */
1374148c5f43SAlan Wright 		ksd->ks_maxreqs = sv->sv_cfg.skc_maxworkers;
1375148c5f43SAlan Wright 		smb_srqueue_update(&sv->sv_srqueue,
1376148c5f43SAlan Wright 		    &ksd->ks_utilization);
1377148c5f43SAlan Wright 		/*
1378148c5f43SAlan Wright 		 * Latency & Throughput of the requests
1379148c5f43SAlan Wright 		 */
1380a90cf9f2SGordon Ross 		smb_dispatch_stats_update(sv, ksd->ks_reqs1, 0, SMB_COM_NUM);
1381a90cf9f2SGordon Ross 		smb2_dispatch_stats_update(sv, ksd->ks_reqs2, 0, SMB2__NCMDS);
1382faa1795aSjb150015 		return (0);
1383faa1795aSjb150015 	}
1384148c5f43SAlan Wright 	if (rw == KSTAT_WRITE)
1385148c5f43SAlan Wright 		return (EACCES);
1386148c5f43SAlan Wright 
1387148c5f43SAlan Wright 	return (EIO);
1388148c5f43SAlan Wright }
1389faa1795aSjb150015 
1390cb174861Sjoyce mcintosh static int
1391cb174861Sjoyce mcintosh smb_server_legacy_kstat_update(kstat_t *ksp, int rw)
1392cb174861Sjoyce mcintosh {
1393cb174861Sjoyce mcintosh 	smb_server_t			*sv;
1394cb174861Sjoyce mcintosh 	smb_server_legacy_kstat_t	*ksd;
1395cb174861Sjoyce mcintosh 	int				rc;
1396cb174861Sjoyce mcintosh 
1397cb174861Sjoyce mcintosh 	switch (rw) {
1398cb174861Sjoyce mcintosh 	case KSTAT_WRITE:
1399cb174861Sjoyce mcintosh 		rc = EACCES;
1400cb174861Sjoyce mcintosh 		break;
1401cb174861Sjoyce mcintosh 	case KSTAT_READ:
1402cb174861Sjoyce mcintosh 		if (!smb_server_lookup(&sv)) {
1403cb174861Sjoyce mcintosh 			ASSERT(MUTEX_HELD(ksp->ks_lock));
1404cb174861Sjoyce mcintosh 			ASSERT(sv->sv_legacy_ksp == ksp);
1405cb174861Sjoyce mcintosh 			ksd = (smb_server_legacy_kstat_t *)ksp->ks_data;
1406cb174861Sjoyce mcintosh 			ksd->ls_files.value.ui32 = sv->sv_files + sv->sv_pipes;
1407cb174861Sjoyce mcintosh 			ksd->ls_trees.value.ui32 = sv->sv_trees;
1408cb174861Sjoyce mcintosh 			ksd->ls_users.value.ui32 = sv->sv_users;
1409cb174861Sjoyce mcintosh 			smb_server_release(sv);
1410cb174861Sjoyce mcintosh 			rc = 0;
1411cb174861Sjoyce mcintosh 			break;
1412cb174861Sjoyce mcintosh 		}
14132d63d7e2SToomas Soome 		/* FALLTHROUGH */
1414cb174861Sjoyce mcintosh 	default:
1415cb174861Sjoyce mcintosh 		rc = EIO;
1416cb174861Sjoyce mcintosh 		break;
1417cb174861Sjoyce mcintosh 	}
1418cb174861Sjoyce mcintosh 	return (rc);
1419cb174861Sjoyce mcintosh 
1420cb174861Sjoyce mcintosh }
1421cb174861Sjoyce mcintosh 
1422faa1795aSjb150015 /*
14234163af6aSjose borrego  * smb_server_shutdown
1424faa1795aSjb150015  */
1425faa1795aSjb150015 static void
14269fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_server_shutdown(smb_server_t *sv)
1427faa1795aSjb150015 {
1428811599a4SMatt Barden 	smb_llist_t *sl = &sv->sv_session_list;
1429811599a4SMatt Barden 	smb_session_t *session;
1430811599a4SMatt Barden 	clock_t	time;
1431811599a4SMatt Barden 
14329fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	SMB_SERVER_VALID(sv);
1433faa1795aSjb150015 
1434856399cfSGordon Ross 	/*
1435856399cfSGordon Ross 	 * Stop the listeners first, so we don't get any more
1436856399cfSGordon Ross 	 * new work while we're trying to shut down.
1437856399cfSGordon Ross 	 */
1438856399cfSGordon Ross 	smb_server_listener_stop(&sv->sv_nbt_daemon);
1439856399cfSGordon Ross 	smb_server_listener_stop(&sv->sv_tcp_daemon);
1440faa1795aSjb150015 	smb_thread_stop(&sv->si_thread_timers);
1441856399cfSGordon Ross 
1442811599a4SMatt Barden 	/* Disconnect all of the sessions */
1443811599a4SMatt Barden 	smb_llist_enter(sl, RW_READER);
1444811599a4SMatt Barden 	session = smb_llist_head(sl);
1445811599a4SMatt Barden 	while (session != NULL) {
1446811599a4SMatt Barden 		smb_session_disconnect(session);
1447811599a4SMatt Barden 		session = smb_llist_next(sl, session);
1448811599a4SMatt Barden 	}
1449811599a4SMatt Barden 	smb_llist_exit(sl);
1450811599a4SMatt Barden 
1451856399cfSGordon Ross 	/*
1452856399cfSGordon Ross 	 * Wake up any threads we might have blocked.
1453856399cfSGordon Ross 	 * Must precede kdoor_close etc. because those will
1454856399cfSGordon Ross 	 * wait for such threads to get out.
1455856399cfSGordon Ross 	 */
1456856399cfSGordon Ross 	smb_event_cancel(sv, 0);
1457856399cfSGordon Ross 	smb_threshold_wake_all(&sv->sv_ssetup_ct);
1458856399cfSGordon Ross 	smb_threshold_wake_all(&sv->sv_tcon_ct);
1459856399cfSGordon Ross 	smb_threshold_wake_all(&sv->sv_opipe_ct);
1460856399cfSGordon Ross 
1461811599a4SMatt Barden 	/*
1462811599a4SMatt Barden 	 * Wait for the session list to empty.
1463811599a4SMatt Barden 	 * (cv_signal in smb_server_destroy_session)
1464811599a4SMatt Barden 	 *
1465811599a4SMatt Barden 	 * This should not take long, but if there are any leaked
1466811599a4SMatt Barden 	 * references to ofiles, trees, or users, there could be a
1467811599a4SMatt Barden 	 * session hanging around.  If that happens, the ll_count
1468811599a4SMatt Barden 	 * never gets to zero and we'll never get the sv_signal.
1469811599a4SMatt Barden 	 * Defend against that problem using timed wait, then
1470811599a4SMatt Barden 	 * complain if we find sessions left over and continue
1471811599a4SMatt Barden 	 * with shutdown in spite of any leaked sessions.
1472811599a4SMatt Barden 	 * That's better than a server that won't reboot.
1473811599a4SMatt Barden 	 */
1474811599a4SMatt Barden 	time = SEC_TO_TICK(10) + ddi_get_lbolt();
1475811599a4SMatt Barden 	mutex_enter(&sv->sv_mutex);
1476811599a4SMatt Barden 	while (sv->sv_session_list.ll_count != 0) {
1477811599a4SMatt Barden 		if (cv_timedwait(&sv->sv_cv, &sv->sv_mutex, time) < 0)
1478811599a4SMatt Barden 			break;
1479811599a4SMatt Barden 	}
1480811599a4SMatt Barden 	mutex_exit(&sv->sv_mutex);
1481811599a4SMatt Barden #ifdef	DEBUG
1482811599a4SMatt Barden 	if (sv->sv_session_list.ll_count != 0) {
1483811599a4SMatt Barden 		cmn_err(CE_NOTE, "shutdown leaked sessions");
1484811599a4SMatt Barden 		debug_enter("shutdown leaked sessions");
1485811599a4SMatt Barden 	}
1486811599a4SMatt Barden #endif
1487811599a4SMatt Barden 
1488811599a4SMatt Barden 	/*
1489811599a4SMatt Barden 	 * Clean out any durable handles.  After this we should
1490811599a4SMatt Barden 	 * have no ofiles remaining (and no more oplock breaks).
1491811599a4SMatt Barden 	 */
1492811599a4SMatt Barden 	smb2_dh_shutdown(sv);
1493811599a4SMatt Barden 
14948622ec45SGordon Ross 	smb_kdoor_close(sv);
1495b819cea2SGordon Ross #ifdef	_KERNEL
1496148c5f43SAlan Wright 	smb_kshare_door_fini(sv->sv_lmshrd);
1497b819cea2SGordon Ross #endif	/* _KERNEL */
14980dcb3379Sjb150015 	sv->sv_lmshrd = NULL;
1499b819cea2SGordon Ross 
15008622ec45SGordon Ross 	smb_export_stop(sv);
1501811599a4SMatt Barden 	smb_kshare_stop(sv);
15028d96b23eSAlan Wright 
15034846df9bSKevin Crowe 	/*
1504811599a4SMatt Barden 	 * Both kshare and the oplock break sub-systems may have
1505811599a4SMatt Barden 	 * taskq jobs on the spcial "server" session, until we've
1506811599a4SMatt Barden 	 * closed all ofiles and stopped the kshare exporter.
1507811599a4SMatt Barden 	 * Now it's safe to destroy the server session, but first
1508811599a4SMatt Barden 	 * wait for any requests on it to finish.  Note that for
1509811599a4SMatt Barden 	 * normal sessions, this happens in smb_session_cancel,
1510811599a4SMatt Barden 	 * but that's not called for the server session.
15114846df9bSKevin Crowe 	 */
1512*8d94f651SGordon Ross 	if (sv->sv_rootuser != NULL) {
1513*8d94f651SGordon Ross 		smb_user_logoff(sv->sv_rootuser);
1514*8d94f651SGordon Ross 		smb_user_release(sv->sv_rootuser);
1515*8d94f651SGordon Ross 		sv->sv_rootuser = NULL;
1516*8d94f651SGordon Ross 	}
1517811599a4SMatt Barden 	if (sv->sv_session != NULL) {
15184846df9bSKevin Crowe 		smb_slist_wait_for_empty(&sv->sv_session->s_req_list);
15194846df9bSKevin Crowe 
1520*8d94f651SGordon Ross 		/* Just in case import left users and trees */
1521*8d94f651SGordon Ross 		smb_session_logoff(sv->sv_session);
1522*8d94f651SGordon Ross 
1523faa1795aSjb150015 		smb_session_delete(sv->sv_session);
1524faa1795aSjb150015 		sv->sv_session = NULL;
1525faa1795aSjb150015 	}
15268d96b23eSAlan Wright 
15274163af6aSjose borrego 	if (sv->sv_receiver_pool != NULL) {
15284163af6aSjose borrego 		taskq_destroy(sv->sv_receiver_pool);
15294163af6aSjose borrego 		sv->sv_receiver_pool = NULL;
15304163af6aSjose borrego 	}
15314163af6aSjose borrego 
15324163af6aSjose borrego 	if (sv->sv_worker_pool != NULL) {
15334163af6aSjose borrego 		taskq_destroy(sv->sv_worker_pool);
15344163af6aSjose borrego 		sv->sv_worker_pool = NULL;
15358d96b23eSAlan Wright 	}
15368622ec45SGordon Ross 
15378622ec45SGordon Ross 	smb_server_fsop_stop(sv);
1538faa1795aSjb150015 }
1539faa1795aSjb150015 
15404163af6aSjose borrego /*
15414163af6aSjose borrego  * smb_server_listener_init
15424163af6aSjose borrego  *
15434163af6aSjose borrego  * Initializes listener contexts.
15444163af6aSjose borrego  */
15454163af6aSjose borrego static void
15464163af6aSjose borrego smb_server_listener_init(
1547faa1795aSjb150015     smb_server_t		*sv,
1548faa1795aSjb150015     smb_listener_daemon_t	*ld,
15494163af6aSjose borrego     char			*name,
1550faa1795aSjb150015     in_port_t			port,
15514163af6aSjose borrego     int				family)
1552faa1795aSjb150015 {
15534163af6aSjose borrego 	ASSERT(ld->ld_magic != SMB_LISTENER_MAGIC);
1554faa1795aSjb150015 
15554163af6aSjose borrego 	bzero(ld, sizeof (*ld));
1556faa1795aSjb150015 
15574163af6aSjose borrego 	ld->ld_sv = sv;
15584163af6aSjose borrego 	ld->ld_family = family;
15594163af6aSjose borrego 	ld->ld_port = port;
15604163af6aSjose borrego 
15617f667e74Sjose borrego 	if (family == AF_INET) {
15627f667e74Sjose borrego 		ld->ld_sin.sin_family = (uint32_t)family;
1563faa1795aSjb150015 		ld->ld_sin.sin_port = htons(port);
1564faa1795aSjb150015 		ld->ld_sin.sin_addr.s_addr = htonl(INADDR_ANY);
15657f667e74Sjose borrego 	} else {
15667f667e74Sjose borrego 		ld->ld_sin6.sin6_family = (uint32_t)family;
15677f667e74Sjose borrego 		ld->ld_sin6.sin6_port = htons(port);
15687f667e74Sjose borrego 		(void) memset(&ld->ld_sin6.sin6_addr.s6_addr, 0,
15697f667e74Sjose borrego 		    sizeof (ld->ld_sin6.sin6_addr.s6_addr));
15707f667e74Sjose borrego 	}
1571faa1795aSjb150015 
157208344b29SGordon Ross 	smb_thread_init(&ld->ld_thread, name, smb_server_listener, ld,
157308344b29SGordon Ross 	    smbsrv_listen_pri);
15744163af6aSjose borrego 	ld->ld_magic = SMB_LISTENER_MAGIC;
15754163af6aSjose borrego }
15764163af6aSjose borrego 
15774163af6aSjose borrego /*
15784163af6aSjose borrego  * smb_server_listener_destroy
15794163af6aSjose borrego  *
15804163af6aSjose borrego  * Destroyes listener contexts.
15814163af6aSjose borrego  */
15824163af6aSjose borrego static void
15834163af6aSjose borrego smb_server_listener_destroy(smb_listener_daemon_t *ld)
15844163af6aSjose borrego {
158583d2dfe6SGordon Ross 	/*
158683d2dfe6SGordon Ross 	 * Note that if startup fails early, we can legitimately
158783d2dfe6SGordon Ross 	 * get here with an all-zeros object.
158883d2dfe6SGordon Ross 	 */
158983d2dfe6SGordon Ross 	if (ld->ld_magic == 0)
159083d2dfe6SGordon Ross 		return;
159183d2dfe6SGordon Ross 
15924163af6aSjose borrego 	SMB_LISTENER_VALID(ld);
15934163af6aSjose borrego 	ASSERT(ld->ld_so == NULL);
15944163af6aSjose borrego 	smb_thread_destroy(&ld->ld_thread);
15954163af6aSjose borrego 	ld->ld_magic = 0;
15964163af6aSjose borrego }
15974163af6aSjose borrego 
15984163af6aSjose borrego /*
15994163af6aSjose borrego  * smb_server_listener_start
16004163af6aSjose borrego  *
16014163af6aSjose borrego  * Starts the listener associated with the context passed in.
16024163af6aSjose borrego  *
16034163af6aSjose borrego  * Return:	0	Success
16044163af6aSjose borrego  *		not 0	Failure
16054163af6aSjose borrego  */
16064163af6aSjose borrego static int
16074163af6aSjose borrego smb_server_listener_start(smb_listener_daemon_t *ld)
16084163af6aSjose borrego {
16094163af6aSjose borrego 	int		rc;
16104163af6aSjose borrego 	uint32_t	on;
16114163af6aSjose borrego 	uint32_t	off;
16124163af6aSjose borrego 
16134163af6aSjose borrego 	SMB_LISTENER_VALID(ld);
16144163af6aSjose borrego 
16154163af6aSjose borrego 	if (ld->ld_so != NULL)
16164163af6aSjose borrego 		return (EINVAL);
16174163af6aSjose borrego 
16184163af6aSjose borrego 	ld->ld_so = smb_socreate(ld->ld_family, SOCK_STREAM, 0);
16199fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (ld->ld_so == NULL) {
16204163af6aSjose borrego 		cmn_err(CE_WARN, "port %d: socket create failed", ld->ld_port);
16219fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (ENOMEM);
16229fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
16239fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
16249fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	off = 0;
16250f1702c5SYu Xiangning 	(void) ksocket_setsockopt(ld->ld_so, SOL_SOCKET,
1626fc724630SAlan Wright 	    SO_MAC_EXEMPT, &off, sizeof (off), CRED());
16279fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
16289fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	on = 1;
1629fc724630SAlan Wright 	(void) ksocket_setsockopt(ld->ld_so, SOL_SOCKET,
1630fc724630SAlan Wright 	    SO_REUSEADDR, &on, sizeof (on), CRED());
1631fc724630SAlan Wright 
16324163af6aSjose borrego 	if (ld->ld_family == AF_INET) {
16330f1702c5SYu Xiangning 		rc = ksocket_bind(ld->ld_so,
16340f1702c5SYu Xiangning 		    (struct sockaddr *)&ld->ld_sin,
16350f1702c5SYu Xiangning 		    sizeof (ld->ld_sin), CRED());
16367f667e74Sjose borrego 	} else {
16377f667e74Sjose borrego 		rc = ksocket_bind(ld->ld_so,
16387f667e74Sjose borrego 		    (struct sockaddr *)&ld->ld_sin6,
16397f667e74Sjose borrego 		    sizeof (ld->ld_sin6), CRED());
16407f667e74Sjose borrego 	}
16419fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
16429fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (rc != 0) {
16434163af6aSjose borrego 		cmn_err(CE_WARN, "port %d: bind failed", ld->ld_port);
16449fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (rc);
16459fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
16469fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
16470f1702c5SYu Xiangning 	rc =  ksocket_listen(ld->ld_so, 20, CRED());
1648faa1795aSjb150015 	if (rc < 0) {
16494163af6aSjose borrego 		cmn_err(CE_WARN, "port %d: listen failed", ld->ld_port);
1650faa1795aSjb150015 		return (rc);
1651faa1795aSjb150015 	}
16524163af6aSjose borrego 
16534163af6aSjose borrego 	ksocket_hold(ld->ld_so);
16544163af6aSjose borrego 	rc = smb_thread_start(&ld->ld_thread);
16554163af6aSjose borrego 	if (rc != 0) {
16564163af6aSjose borrego 		ksocket_rele(ld->ld_so);
16574163af6aSjose borrego 		cmn_err(CE_WARN, "port %d: listener failed to start",
16584163af6aSjose borrego 		    ld->ld_port);
16594163af6aSjose borrego 		return (rc);
1660faa1795aSjb150015 	}
16614163af6aSjose borrego 	return (0);
16624163af6aSjose borrego }
16634163af6aSjose borrego 
16644163af6aSjose borrego /*
16654163af6aSjose borrego  * smb_server_listener_stop
16664163af6aSjose borrego  *
16674163af6aSjose borrego  * Stops the listener associated with the context passed in.
16684163af6aSjose borrego  */
16694163af6aSjose borrego static void
16704163af6aSjose borrego smb_server_listener_stop(smb_listener_daemon_t *ld)
16714163af6aSjose borrego {
16724163af6aSjose borrego 	SMB_LISTENER_VALID(ld);
16734163af6aSjose borrego 
16744163af6aSjose borrego 	if (ld->ld_so != NULL) {
16754163af6aSjose borrego 		smb_soshutdown(ld->ld_so);
16764163af6aSjose borrego 		smb_sodestroy(ld->ld_so);
16774163af6aSjose borrego 		smb_thread_stop(&ld->ld_thread);
16784163af6aSjose borrego 		ld->ld_so = NULL;
16794163af6aSjose borrego 	}
16804163af6aSjose borrego }
16814163af6aSjose borrego 
16824163af6aSjose borrego /*
16834163af6aSjose borrego  * smb_server_listener
16844163af6aSjose borrego  *
16854163af6aSjose borrego  * Entry point of the listeners.
16864163af6aSjose borrego  */
16874163af6aSjose borrego static void
16884163af6aSjose borrego smb_server_listener(smb_thread_t *thread, void *arg)
16894163af6aSjose borrego {
16904163af6aSjose borrego 	_NOTE(ARGUNUSED(thread))
16914163af6aSjose borrego 	smb_listener_daemon_t	*ld;
16924163af6aSjose borrego 	ksocket_t		s_so;
16934163af6aSjose borrego 	int			on;
16944163af6aSjose borrego 	int			txbuf_size;
16954163af6aSjose borrego 
16964163af6aSjose borrego 	ld = (smb_listener_daemon_t *)arg;
16974163af6aSjose borrego 
16984163af6aSjose borrego 	SMB_LISTENER_VALID(ld);
1699faa1795aSjb150015 
1700faa1795aSjb150015 	DTRACE_PROBE1(so__wait__accept, struct sonode *, ld->ld_so);
1701faa1795aSjb150015 
170241bd8510Skcrowenex 	for (;;) {
170341bd8510Skcrowenex 		int ret = ksocket_accept(ld->ld_so, NULL, NULL, &s_so, CRED());
170441bd8510Skcrowenex 
170541bd8510Skcrowenex 		switch (ret) {
170641bd8510Skcrowenex 		case 0:
170741bd8510Skcrowenex 			break;
170841bd8510Skcrowenex 		case ECONNABORTED:
170941bd8510Skcrowenex 			continue;
171041bd8510Skcrowenex 		case EINTR:
171141bd8510Skcrowenex 		case EBADF:	/* libfakekernel */
171241bd8510Skcrowenex 			goto out;
171341bd8510Skcrowenex 		default:
171441bd8510Skcrowenex 			cmn_err(CE_WARN,
171541bd8510Skcrowenex 			    "smb_server_listener: ksocket_accept(%d)",
171641bd8510Skcrowenex 			    ret);
171741bd8510Skcrowenex 			goto out;
171841bd8510Skcrowenex 		}
171941bd8510Skcrowenex 
1720faa1795aSjb150015 		DTRACE_PROBE1(so__accept, struct sonode *, s_so);
1721faa1795aSjb150015 
17229fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		on = 1;
17239fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		(void) ksocket_setsockopt(s_so, IPPROTO_TCP, TCP_NODELAY,
17249fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		    &on, sizeof (on), CRED());
17259fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
17269fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		on = 1;
17279fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		(void) ksocket_setsockopt(s_so, SOL_SOCKET, SO_KEEPALIVE,
17289fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		    &on, sizeof (on), CRED());
17299fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
17309fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		txbuf_size = 128*1024;
17310f1702c5SYu Xiangning 		(void) ksocket_setsockopt(s_so, SOL_SOCKET, SO_SNDBUF,
17329fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		    (const void *)&txbuf_size, sizeof (txbuf_size), CRED());
17339fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
1734faa1795aSjb150015 		/*
1735faa1795aSjb150015 		 * Create a session for this connection.
1736faa1795aSjb150015 		 */
17374163af6aSjose borrego 		smb_server_create_session(ld, s_so);
1738faa1795aSjb150015 	}
173941bd8510Skcrowenex out:
17404163af6aSjose borrego 	ksocket_rele(ld->ld_so);
1741faa1795aSjb150015 }
17429fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
17434163af6aSjose borrego /*
17444163af6aSjose borrego  * smb_server_receiver
17454163af6aSjose borrego  *
17464163af6aSjose borrego  * Entry point of the receiver threads.
1747811599a4SMatt Barden  * Also does cleanup when socket disconnected.
17484163af6aSjose borrego  */
17499fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void
17504163af6aSjose borrego smb_server_receiver(void *arg)
17519fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
17524163af6aSjose borrego 	smb_session_t	*session;
1753faa1795aSjb150015 
1754811599a4SMatt Barden 	session = (smb_session_t *)arg;
1755811599a4SMatt Barden 
1756811599a4SMatt Barden 	/* We stay in here until socket disconnect. */
17574163af6aSjose borrego 	smb_session_receiver(session);
1758811599a4SMatt Barden 
1759811599a4SMatt Barden 	ASSERT(session->s_state == SMB_SESSION_STATE_SHUTDOWN);
1760811599a4SMatt Barden 	smb_server_destroy_session(session);
1761faa1795aSjb150015 }
1762faa1795aSjb150015 
1763faa1795aSjb150015 /*
1764faa1795aSjb150015  * smb_server_lookup
1765faa1795aSjb150015  *
17668622ec45SGordon Ross  * This function finds the server associated with the zone of the
17678622ec45SGordon Ross  * caller.  Note: requires a fix in the dynamic taskq code:
17688622ec45SGordon Ross  * 1501 taskq_create_proc ... TQ_DYNAMIC puts tasks in p0
1769faa1795aSjb150015  */
17704846df9bSKevin Crowe int
1771faa1795aSjb150015 smb_server_lookup(smb_server_t **psv)
1772faa1795aSjb150015 {
1773faa1795aSjb150015 	zoneid_t	zid;
1774faa1795aSjb150015 	smb_server_t	*sv;
1775faa1795aSjb150015 
1776faa1795aSjb150015 	zid = getzoneid();
1777faa1795aSjb150015 
1778faa1795aSjb150015 	smb_llist_enter(&smb_servers, RW_READER);
1779faa1795aSjb150015 	sv = smb_llist_head(&smb_servers);
1780faa1795aSjb150015 	while (sv) {
17819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_SERVER_VALID(sv);
1782faa1795aSjb150015 		if (sv->sv_zid == zid) {
1783faa1795aSjb150015 			mutex_enter(&sv->sv_mutex);
1784faa1795aSjb150015 			if (sv->sv_state != SMB_SERVER_STATE_DELETING) {
1785faa1795aSjb150015 				sv->sv_refcnt++;
1786faa1795aSjb150015 				mutex_exit(&sv->sv_mutex);
1787faa1795aSjb150015 				smb_llist_exit(&smb_servers);
1788faa1795aSjb150015 				*psv = sv;
1789faa1795aSjb150015 				return (0);
1790faa1795aSjb150015 			}
1791faa1795aSjb150015 			mutex_exit(&sv->sv_mutex);
1792faa1795aSjb150015 			break;
1793faa1795aSjb150015 		}
1794faa1795aSjb150015 		sv = smb_llist_next(&smb_servers, sv);
1795faa1795aSjb150015 	}
1796faa1795aSjb150015 	smb_llist_exit(&smb_servers);
1797faa1795aSjb150015 	return (EPERM);
1798faa1795aSjb150015 }
1799faa1795aSjb150015 
1800faa1795aSjb150015 /*
1801faa1795aSjb150015  * smb_server_release
1802faa1795aSjb150015  *
1803faa1795aSjb150015  * This function decrements the reference count of the server and signals its
1804faa1795aSjb150015  * condition variable if the state of the server is SMB_SERVER_STATE_DELETING.
1805faa1795aSjb150015  */
18064846df9bSKevin Crowe void
1807faa1795aSjb150015 smb_server_release(smb_server_t *sv)
1808faa1795aSjb150015 {
18099fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	SMB_SERVER_VALID(sv);
1810faa1795aSjb150015 
1811faa1795aSjb150015 	mutex_enter(&sv->sv_mutex);
1812faa1795aSjb150015 	ASSERT(sv->sv_refcnt);
1813faa1795aSjb150015 	sv->sv_refcnt--;
1814faa1795aSjb150015 	if ((sv->sv_refcnt == 0) && (sv->sv_state == SMB_SERVER_STATE_DELETING))
1815faa1795aSjb150015 		cv_signal(&sv->sv_cv);
1816faa1795aSjb150015 	mutex_exit(&sv->sv_mutex);
1817faa1795aSjb150015 }
1818faa1795aSjb150015 
18191fcced4cSJordan Brown /*
18201fcced4cSJordan Brown  * Enumerate the users associated with a session list.
18211fcced4cSJordan Brown  */
18221fcced4cSJordan Brown static void
1823*8d94f651SGordon Ross smb_server_enum_users(smb_server_t *sv, smb_svcenum_t *svcenum)
1824faa1795aSjb150015 {
1825*8d94f651SGordon Ross 	smb_llist_t	*ll = &sv->sv_session_list;
18261fcced4cSJordan Brown 	smb_session_t	*sn;
1827faa1795aSjb150015 	smb_llist_t	*ulist;
18281fcced4cSJordan Brown 	smb_user_t	*user;
182929bd2886SAlan Wright 	int		rc = 0;
1830faa1795aSjb150015 
18314163af6aSjose borrego 	smb_llist_enter(ll, RW_READER);
18324163af6aSjose borrego 	sn = smb_llist_head(ll);
18331fcced4cSJordan Brown 
18341fcced4cSJordan Brown 	while (sn != NULL) {
18354163af6aSjose borrego 		SMB_SESSION_VALID(sn);
1836faa1795aSjb150015 		ulist = &sn->s_user_list;
1837faa1795aSjb150015 		smb_llist_enter(ulist, RW_READER);
1838faa1795aSjb150015 		user = smb_llist_head(ulist);
18391fcced4cSJordan Brown 
18401fcced4cSJordan Brown 		while (user != NULL) {
18411fcced4cSJordan Brown 			if (smb_user_hold(user)) {
18421fcced4cSJordan Brown 				rc = smb_user_enum(user, svcenum);
18431fcced4cSJordan Brown 				smb_user_release(user);
18443b13a1efSThomas Keiser 				if (rc != 0)
18453b13a1efSThomas Keiser 					break;
1846faa1795aSjb150015 			}
18471fcced4cSJordan Brown 
1848faa1795aSjb150015 			user = smb_llist_next(ulist, user);
1849faa1795aSjb150015 		}
18501fcced4cSJordan Brown 
18511fcced4cSJordan Brown 		smb_llist_exit(ulist);
18521fcced4cSJordan Brown 
18531fcced4cSJordan Brown 		if (rc != 0)
18541fcced4cSJordan Brown 			break;
18551fcced4cSJordan Brown 
18564163af6aSjose borrego 		sn = smb_llist_next(ll, sn);
18571fcced4cSJordan Brown 	}
18581fcced4cSJordan Brown 
18594163af6aSjose borrego 	smb_llist_exit(ll);
18601fcced4cSJordan Brown }
18611fcced4cSJordan Brown 
18621fcced4cSJordan Brown /*
18633b13a1efSThomas Keiser  * Enumerate the trees/files associated with a session list.
18643b13a1efSThomas Keiser  */
18653b13a1efSThomas Keiser static void
1866*8d94f651SGordon Ross smb_server_enum_trees(smb_server_t *sv, smb_svcenum_t *svcenum)
18673b13a1efSThomas Keiser {
1868*8d94f651SGordon Ross 	smb_llist_t	*ll = &sv->sv_session_list;
18693b13a1efSThomas Keiser 	smb_session_t	*sn;
18703b13a1efSThomas Keiser 	smb_llist_t	*tlist;
18713b13a1efSThomas Keiser 	smb_tree_t	*tree;
18723b13a1efSThomas Keiser 	int		rc = 0;
18733b13a1efSThomas Keiser 
18743b13a1efSThomas Keiser 	smb_llist_enter(ll, RW_READER);
18753b13a1efSThomas Keiser 	sn = smb_llist_head(ll);
18763b13a1efSThomas Keiser 
18773b13a1efSThomas Keiser 	while (sn != NULL) {
18783b13a1efSThomas Keiser 		SMB_SESSION_VALID(sn);
18793b13a1efSThomas Keiser 		tlist = &sn->s_tree_list;
18803b13a1efSThomas Keiser 		smb_llist_enter(tlist, RW_READER);
18813b13a1efSThomas Keiser 		tree = smb_llist_head(tlist);
18823b13a1efSThomas Keiser 
18833b13a1efSThomas Keiser 		while (tree != NULL) {
18843b13a1efSThomas Keiser 			if (smb_tree_hold(tree)) {
18853b13a1efSThomas Keiser 				rc = smb_tree_enum(tree, svcenum);
18863b13a1efSThomas Keiser 				smb_tree_release(tree);
18873b13a1efSThomas Keiser 				if (rc != 0)
18883b13a1efSThomas Keiser 					break;
18893b13a1efSThomas Keiser 			}
18903b13a1efSThomas Keiser 
18913b13a1efSThomas Keiser 			tree = smb_llist_next(tlist, tree);
18923b13a1efSThomas Keiser 		}
18933b13a1efSThomas Keiser 
18943b13a1efSThomas Keiser 		smb_llist_exit(tlist);
18953b13a1efSThomas Keiser 
18963b13a1efSThomas Keiser 		if (rc != 0)
18973b13a1efSThomas Keiser 			break;
18983b13a1efSThomas Keiser 
18993b13a1efSThomas Keiser 		sn = smb_llist_next(ll, sn);
19003b13a1efSThomas Keiser 	}
19013b13a1efSThomas Keiser 
19023b13a1efSThomas Keiser 	smb_llist_exit(ll);
19033b13a1efSThomas Keiser }
19043b13a1efSThomas Keiser 
19053b13a1efSThomas Keiser /*
19061fcced4cSJordan Brown  * Disconnect sessions associated with the specified client and username.
19071fcced4cSJordan Brown  * Empty strings are treated as wildcards.
19081fcced4cSJordan Brown  */
19091fcced4cSJordan Brown static int
1910*8d94f651SGordon Ross smb_server_session_disconnect(smb_server_t *sv,
19111fcced4cSJordan Brown     const char *client, const char *name)
19121fcced4cSJordan Brown {
1913*8d94f651SGordon Ross 	smb_llist_t	*ll = &sv->sv_session_list;
19141fcced4cSJordan Brown 	smb_session_t	*sn;
19151fcced4cSJordan Brown 	smb_llist_t	*ulist;
19161fcced4cSJordan Brown 	smb_user_t	*user;
19171fcced4cSJordan Brown 	int		count = 0;
19181fcced4cSJordan Brown 
19194163af6aSjose borrego 	smb_llist_enter(ll, RW_READER);
19201fcced4cSJordan Brown 
1921811599a4SMatt Barden 	for (sn = smb_llist_head(ll);
1922811599a4SMatt Barden 	    sn != NULL;
1923811599a4SMatt Barden 	    sn = smb_llist_next(ll, sn)) {
19244163af6aSjose borrego 		SMB_SESSION_VALID(sn);
19251fcced4cSJordan Brown 
1926811599a4SMatt Barden 		if (*client != '\0' && !smb_session_isclient(sn, client))
19271fcced4cSJordan Brown 			continue;
19281fcced4cSJordan Brown 
19291fcced4cSJordan Brown 		ulist = &sn->s_user_list;
19301fcced4cSJordan Brown 		smb_llist_enter(ulist, RW_READER);
19311fcced4cSJordan Brown 
1932811599a4SMatt Barden 		for (user = smb_llist_head(ulist);
1933811599a4SMatt Barden 		    user != NULL;
1934811599a4SMatt Barden 		    user = smb_llist_next(ulist, user)) {
1935811599a4SMatt Barden 			SMB_USER_VALID(user);
19361fcced4cSJordan Brown 
1937811599a4SMatt Barden 			if (*name != '\0' && !smb_user_namecmp(user, name))
19381fcced4cSJordan Brown 				continue;
19391fcced4cSJordan Brown 
1940811599a4SMatt Barden 			if (smb_user_hold(user)) {
1941811599a4SMatt Barden 				smb_user_logoff(user);
19421fcced4cSJordan Brown 				smb_user_release(user);
1943811599a4SMatt Barden 				count++;
19441fcced4cSJordan Brown 			}
19451fcced4cSJordan Brown 		}
19461fcced4cSJordan Brown 
1947faa1795aSjb150015 		smb_llist_exit(ulist);
1948faa1795aSjb150015 	}
19491fcced4cSJordan Brown 
19504163af6aSjose borrego 	smb_llist_exit(ll);
19511fcced4cSJordan Brown 	return (count);
19521fcced4cSJordan Brown }
19531fcced4cSJordan Brown 
19541fcced4cSJordan Brown /*
19551fcced4cSJordan Brown  * Close a file by its unique id.
19561fcced4cSJordan Brown  */
19571fcced4cSJordan Brown static int
1958*8d94f651SGordon Ross smb_server_fclose(smb_server_t *sv, uint32_t uniqid)
19591fcced4cSJordan Brown {
1960*8d94f651SGordon Ross 	smb_llist_t	*ll;
19611fcced4cSJordan Brown 	smb_session_t	*sn;
19623b13a1efSThomas Keiser 	smb_llist_t	*tlist;
19633b13a1efSThomas Keiser 	smb_tree_t	*tree;
19641fcced4cSJordan Brown 	int		rc = ENOENT;
19651fcced4cSJordan Brown 
1966*8d94f651SGordon Ross 	ll = &sv->sv_session_list;
19674163af6aSjose borrego 	smb_llist_enter(ll, RW_READER);
19684163af6aSjose borrego 	sn = smb_llist_head(ll);
19691fcced4cSJordan Brown 
19701fcced4cSJordan Brown 	while ((sn != NULL) && (rc == ENOENT)) {
19714163af6aSjose borrego 		SMB_SESSION_VALID(sn);
19723b13a1efSThomas Keiser 		tlist = &sn->s_tree_list;
19733b13a1efSThomas Keiser 		smb_llist_enter(tlist, RW_READER);
19743b13a1efSThomas Keiser 		tree = smb_llist_head(tlist);
19751fcced4cSJordan Brown 
19763b13a1efSThomas Keiser 		while ((tree != NULL) && (rc == ENOENT)) {
19773b13a1efSThomas Keiser 			if (smb_tree_hold(tree)) {
19783b13a1efSThomas Keiser 				rc = smb_tree_fclose(tree, uniqid);
19793b13a1efSThomas Keiser 				smb_tree_release(tree);
19801fcced4cSJordan Brown 			}
19811fcced4cSJordan Brown 
19823b13a1efSThomas Keiser 			tree = smb_llist_next(tlist, tree);
19831fcced4cSJordan Brown 		}
19841fcced4cSJordan Brown 
19853b13a1efSThomas Keiser 		smb_llist_exit(tlist);
19864163af6aSjose borrego 		sn = smb_llist_next(ll, sn);
19871fcced4cSJordan Brown 	}
19881fcced4cSJordan Brown 
19894163af6aSjose borrego 	smb_llist_exit(ll);
19901fcced4cSJordan Brown 	return (rc);
1991faa1795aSjb150015 }
1992faa1795aSjb150015 
1993811599a4SMatt Barden /*
1994811599a4SMatt Barden  * This is used by SMB2 session setup to logoff a previous session,
1995811599a4SMatt Barden  * so it can force a logoff that we haven't noticed yet.
1996811599a4SMatt Barden  * This is not called frequently, so we just walk the list of
1997811599a4SMatt Barden  * connections searching for the user.
1998811599a4SMatt Barden  */
1999811599a4SMatt Barden void
2000811599a4SMatt Barden smb_server_logoff_ssnid(smb_request_t *sr, uint64_t ssnid)
2001811599a4SMatt Barden {
2002811599a4SMatt Barden 	smb_server_t	*sv = sr->sr_server;
2003811599a4SMatt Barden 	smb_llist_t	*sess_list;
2004811599a4SMatt Barden 	smb_session_t	*sess;
2005811599a4SMatt Barden 
2006811599a4SMatt Barden 	if (sv->sv_state != SMB_SERVER_STATE_RUNNING)
2007811599a4SMatt Barden 		return;
2008811599a4SMatt Barden 
2009811599a4SMatt Barden 	sess_list = &sv->sv_session_list;
2010811599a4SMatt Barden 	smb_llist_enter(sess_list, RW_READER);
2011811599a4SMatt Barden 
2012811599a4SMatt Barden 	for (sess = smb_llist_head(sess_list);
2013811599a4SMatt Barden 	    sess != NULL;
2014811599a4SMatt Barden 	    sess = smb_llist_next(sess_list, sess)) {
2015811599a4SMatt Barden 
2016811599a4SMatt Barden 		smb_user_t	*user;
2017811599a4SMatt Barden 
2018811599a4SMatt Barden 		SMB_SESSION_VALID(sess);
2019811599a4SMatt Barden 
2020811599a4SMatt Barden 		if (sess->dialect < SMB_VERS_2_BASE)
2021811599a4SMatt Barden 			continue;
2022811599a4SMatt Barden 
2023811599a4SMatt Barden 		if (sess->s_state != SMB_SESSION_STATE_NEGOTIATED)
2024811599a4SMatt Barden 			continue;
2025811599a4SMatt Barden 
2026811599a4SMatt Barden 		user = smb_session_lookup_ssnid(sess, ssnid);
2027811599a4SMatt Barden 		if (user == NULL)
2028811599a4SMatt Barden 			continue;
2029811599a4SMatt Barden 
2030811599a4SMatt Barden 		if (!smb_is_same_user(user->u_cred, sr->user_cr)) {
2031811599a4SMatt Barden 			smb_user_release(user);
2032811599a4SMatt Barden 			continue;
2033811599a4SMatt Barden 		}
2034811599a4SMatt Barden 
2035811599a4SMatt Barden 		/* Treat this as if we lost the connection */
2036811599a4SMatt Barden 		user->preserve_opens = SMB2_DH_PRESERVE_SOME;
2037811599a4SMatt Barden 		smb_user_logoff(user);
2038811599a4SMatt Barden 		smb_user_release(user);
2039811599a4SMatt Barden 
2040811599a4SMatt Barden 		/*
2041811599a4SMatt Barden 		 * The above may have left work on the delete queues
2042811599a4SMatt Barden 		 */
2043811599a4SMatt Barden 		smb_llist_flush(&sess->s_tree_list);
2044811599a4SMatt Barden 		smb_llist_flush(&sess->s_user_list);
2045811599a4SMatt Barden 	}
2046811599a4SMatt Barden 
2047811599a4SMatt Barden 	smb_llist_exit(sess_list);
2048811599a4SMatt Barden }
2049811599a4SMatt Barden 
205012b65585SGordon Ross /* See also: libsmb smb_kmod_setcfg */
2051faa1795aSjb150015 static void
205229bd2886SAlan Wright smb_server_store_cfg(smb_server_t *sv, smb_ioc_cfg_t *ioc)
2053faa1795aSjb150015 {
205429bd2886SAlan Wright 	if (ioc->maxconnections == 0)
205529bd2886SAlan Wright 		ioc->maxconnections = 0xFFFFFFFF;
2056faa1795aSjb150015 
20571160dcf7SMatt Barden 	if (ioc->encrypt == SMB_CONFIG_REQUIRED &&
20581160dcf7SMatt Barden 	    ioc->max_protocol < SMB_VERS_3_0) {
20591160dcf7SMatt Barden 		cmn_err(CE_WARN, "Server set to require encryption; "
20601160dcf7SMatt Barden 		    "forcing max_protocol to 3.0");
20611160dcf7SMatt Barden 		ioc->max_protocol = SMB_VERS_3_0;
20621160dcf7SMatt Barden 	}
20631160dcf7SMatt Barden 
206429bd2886SAlan Wright 	sv->sv_cfg.skc_maxworkers = ioc->maxworkers;
206529bd2886SAlan Wright 	sv->sv_cfg.skc_maxconnections = ioc->maxconnections;
206629bd2886SAlan Wright 	sv->sv_cfg.skc_keepalive = ioc->keepalive;
206729bd2886SAlan Wright 	sv->sv_cfg.skc_restrict_anon = ioc->restrict_anon;
206829bd2886SAlan Wright 	sv->sv_cfg.skc_signing_enable = ioc->signing_enable;
206929bd2886SAlan Wright 	sv->sv_cfg.skc_signing_required = ioc->signing_required;
207029bd2886SAlan Wright 	sv->sv_cfg.skc_oplock_enable = ioc->oplock_enable;
207129bd2886SAlan Wright 	sv->sv_cfg.skc_sync_enable = ioc->sync_enable;
207229bd2886SAlan Wright 	sv->sv_cfg.skc_secmode = ioc->secmode;
207312b65585SGordon Ross 	sv->sv_cfg.skc_netbios_enable = ioc->netbios_enable;
207429bd2886SAlan Wright 	sv->sv_cfg.skc_ipv6_enable = ioc->ipv6_enable;
2075cb174861Sjoyce mcintosh 	sv->sv_cfg.skc_print_enable = ioc->print_enable;
20765f1ef25cSAram Hăvărneanu 	sv->sv_cfg.skc_traverse_mounts = ioc->traverse_mounts;
2077a90cf9f2SGordon Ross 	sv->sv_cfg.skc_max_protocol = ioc->max_protocol;
20783e2c0c09SMatt Barden 	sv->sv_cfg.skc_min_protocol = ioc->min_protocol;
20791160dcf7SMatt Barden 	sv->sv_cfg.skc_encrypt = ioc->encrypt;
2080148c5f43SAlan Wright 	sv->sv_cfg.skc_execflags = ioc->exec_flags;
208112b65585SGordon Ross 	sv->sv_cfg.skc_negtok_len = ioc->negtok_len;
2082148c5f43SAlan Wright 	sv->sv_cfg.skc_version = ioc->version;
2083a90cf9f2SGordon Ross 	sv->sv_cfg.skc_initial_credits = ioc->initial_credits;
2084a90cf9f2SGordon Ross 	sv->sv_cfg.skc_maximum_credits = ioc->maximum_credits;
2085a90cf9f2SGordon Ross 
208612b65585SGordon Ross 	(void) memcpy(sv->sv_cfg.skc_machine_uuid, ioc->machine_uuid,
208712b65585SGordon Ross 	    sizeof (uuid_t));
208812b65585SGordon Ross 	(void) memcpy(sv->sv_cfg.skc_negtok, ioc->negtok,
208912b65585SGordon Ross 	    sizeof (sv->sv_cfg.skc_negtok));
209012b65585SGordon Ross 	(void) memcpy(sv->sv_cfg.skc_native_os, ioc->native_os,
209112b65585SGordon Ross 	    sizeof (sv->sv_cfg.skc_native_os));
209212b65585SGordon Ross 	(void) memcpy(sv->sv_cfg.skc_native_lm, ioc->native_lm,
209312b65585SGordon Ross 	    sizeof (sv->sv_cfg.skc_native_lm));
209412b65585SGordon Ross 
209529bd2886SAlan Wright 	(void) strlcpy(sv->sv_cfg.skc_nbdomain, ioc->nbdomain,
209629bd2886SAlan Wright 	    sizeof (sv->sv_cfg.skc_nbdomain));
209729bd2886SAlan Wright 	(void) strlcpy(sv->sv_cfg.skc_fqdn, ioc->fqdn,
209829bd2886SAlan Wright 	    sizeof (sv->sv_cfg.skc_fqdn));
209929bd2886SAlan Wright 	(void) strlcpy(sv->sv_cfg.skc_hostname, ioc->hostname,
210029bd2886SAlan Wright 	    sizeof (sv->sv_cfg.skc_hostname));
210129bd2886SAlan Wright 	(void) strlcpy(sv->sv_cfg.skc_system_comment, ioc->system_comment,
210229bd2886SAlan Wright 	    sizeof (sv->sv_cfg.skc_system_comment));
2103faa1795aSjb150015 }
2104faa1795aSjb150015 
2105faa1795aSjb150015 static int
2106faa1795aSjb150015 smb_server_fsop_start(smb_server_t *sv)
2107faa1795aSjb150015 {
2108faa1795aSjb150015 	int	error;
2109faa1795aSjb150015 
21108622ec45SGordon Ross 	error = smb_node_root_init(sv, &sv->si_root_smb_node);
2111faa1795aSjb150015 	if (error != 0)
2112faa1795aSjb150015 		sv->si_root_smb_node = NULL;
2113faa1795aSjb150015 
2114faa1795aSjb150015 	return (error);
2115faa1795aSjb150015 }
2116faa1795aSjb150015 
2117faa1795aSjb150015 static void
2118faa1795aSjb150015 smb_server_fsop_stop(smb_server_t *sv)
2119faa1795aSjb150015 {
2120faa1795aSjb150015 	if (sv->si_root_smb_node != NULL) {
2121faa1795aSjb150015 		smb_node_release(sv->si_root_smb_node);
2122faa1795aSjb150015 		sv->si_root_smb_node = NULL;
2123faa1795aSjb150015 	}
2124faa1795aSjb150015 }
21259fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
21269fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_event_t *
21278622ec45SGordon Ross smb_event_create(smb_server_t *sv, int timeout)
21289fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
21299fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_event_t	*event;
21309fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
21318622ec45SGordon Ross 	if (smb_server_is_stopping(sv))
21329fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (NULL);
21339fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
21348622ec45SGordon Ross 	event = kmem_cache_alloc(smb_cache_event, KM_SLEEP);
21359fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
21369fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	bzero(event, sizeof (smb_event_t));
21379fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_init(&event->se_mutex, NULL, MUTEX_DEFAULT, NULL);
21389fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	cv_init(&event->se_cv, NULL, CV_DEFAULT, NULL);
21399fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event->se_magic = SMB_EVENT_MAGIC;
21409fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event->se_txid = smb_event_alloc_txid();
21419fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event->se_server = sv;
2142cb174861Sjoyce mcintosh 	event->se_timeout = timeout;
21439fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
21449fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_enter(&sv->sv_event_list, RW_WRITER);
21459fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_insert_tail(&sv->sv_event_list, event);
21469fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_exit(&sv->sv_event_list);
21479fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
21489fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	return (event);
21499fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
21509fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
21519fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States void
21529fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_event_destroy(smb_event_t *event)
21539fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
21549fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_server_t	*sv;
21559fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
21569fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (event == NULL)
21579fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return;
21589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
21599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	SMB_EVENT_VALID(event);
21609fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	ASSERT(event->se_waittime == 0);
21618622ec45SGordon Ross 	sv = event->se_server;
21628622ec45SGordon Ross 	SMB_SERVER_VALID(sv);
21639fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
21649fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_enter(&sv->sv_event_list, RW_WRITER);
21659fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_remove(&sv->sv_event_list, event);
21669fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_exit(&sv->sv_event_list);
21679fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
21689fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event->se_magic = (uint32_t)~SMB_EVENT_MAGIC;
21699fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	cv_destroy(&event->se_cv);
21709fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_destroy(&event->se_mutex);
21719fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
21728622ec45SGordon Ross 	kmem_cache_free(smb_cache_event, event);
21739fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
21749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
21759fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
21769fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Get the txid for the specified event.
21779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  */
21789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States uint32_t
21799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_event_txid(smb_event_t *event)
21809fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
21819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (event != NULL) {
21829fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_EVENT_VALID(event);
21839fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (event->se_txid);
21849fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
21859fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
21869fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	cmn_err(CE_NOTE, "smb_event_txid failed");
21879fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	return ((uint32_t)-1);
21889fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
21899fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
21909fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
21919fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Wait for event notification.
21929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  */
21939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States int
21949fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_event_wait(smb_event_t *event)
21959fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
21969fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	int	seconds = 1;
21979fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	int	ticks;
2198856399cfSGordon Ross 	int	err;
21999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
22009fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (event == NULL)
22019fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (EINVAL);
22029fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
22039fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	SMB_EVENT_VALID(event);
22049fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
22059fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_enter(&event->se_mutex);
22069fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event->se_waittime = 1;
22079fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event->se_errno = 0;
22089fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
22099fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	while (!(event->se_notified)) {
2210c5866007SKeyur Desai 		if (smb_event_debug && ((event->se_waittime % 30) == 0))
22119fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			cmn_err(CE_NOTE, "smb_event_wait[%d] (%d sec)",
22129fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			    event->se_txid, event->se_waittime);
22139fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
22149fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		if (event->se_errno != 0)
22159fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			break;
22169fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
2217cb174861Sjoyce mcintosh 		if (event->se_waittime > event->se_timeout) {
22189fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			event->se_errno = ETIME;
22199fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			break;
22209fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		}
22219fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
22229fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		ticks = SEC_TO_TICK(seconds);
22239fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		(void) cv_reltimedwait(&event->se_cv,
22249fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		    &event->se_mutex, (clock_t)ticks, TR_CLOCK_TICK);
22259fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		++event->se_waittime;
22269fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
22279fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
2228856399cfSGordon Ross 	err = event->se_errno;
22299fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event->se_waittime = 0;
22309fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event->se_notified = B_FALSE;
22319fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	cv_signal(&event->se_cv);
22329fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_exit(&event->se_mutex);
2233856399cfSGordon Ross 	return (err);
22349fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
22359fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
22369fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
22379fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * If txid is non-zero, cancel the specified event.
22389fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Otherwise, cancel all events.
22399fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  */
22409fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void
22419fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_event_cancel(smb_server_t *sv, uint32_t txid)
22429fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
22439fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_event_t	*event;
22449fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_t	*event_list;
22459fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
22469fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	SMB_SERVER_VALID(sv);
22479fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
22489fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event_list = &sv->sv_event_list;
22499fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_enter(event_list, RW_WRITER);
22509fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
22519fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event = smb_llist_head(event_list);
22529fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	while (event) {
22539fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_EVENT_VALID(event);
22549fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
22559fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		if (txid == 0 || event->se_txid == txid) {
22569fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			mutex_enter(&event->se_mutex);
22579fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			event->se_errno = ECANCELED;
22589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			event->se_notified = B_TRUE;
22599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			cv_signal(&event->se_cv);
22609fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			mutex_exit(&event->se_mutex);
22619fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
22629fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			if (txid != 0)
22639fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 				break;
22649fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		}
22659fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
22669fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		event = smb_llist_next(event_list, event);
22679fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
22689fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
22699fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_exit(event_list);
22709fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
22719fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
22729fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
22739fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * If txid is non-zero, notify the specified event.
22749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Otherwise, notify all events.
22759fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  */
2276cb174861Sjoyce mcintosh void
22779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_event_notify(smb_server_t *sv, uint32_t txid)
22789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
22799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_event_t	*event;
22809fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_t	*event_list;
22819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
22829fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	SMB_SERVER_VALID(sv);
22839fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
22849fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event_list = &sv->sv_event_list;
22859fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_enter(event_list, RW_READER);
22869fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
22879fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event = smb_llist_head(event_list);
22889fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	while (event) {
22899fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_EVENT_VALID(event);
22909fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
22919fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		if (txid == 0 || event->se_txid == txid) {
22929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			mutex_enter(&event->se_mutex);
22939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			event->se_notified = B_TRUE;
22949fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			cv_signal(&event->se_cv);
22959fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			mutex_exit(&event->se_mutex);
22969fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
22979fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			if (txid != 0)
22989fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 				break;
22999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		}
23009fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
23019fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		event = smb_llist_next(event_list, event);
23029fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
23039fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
23049fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_exit(event_list);
23059fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
23069fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
23079fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
23089fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Allocate a new transaction id (txid).
23099fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  *
23109fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * 0 or -1 are not assigned because they are used to detect invalid
23119fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * conditions or to indicate all open id's.
23129fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  */
23139fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static uint32_t
23149fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_event_alloc_txid(void)
23159fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
23169fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	static kmutex_t	txmutex;
23179fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	static uint32_t	txid;
23189fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	uint32_t	txid_ret;
23199fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
23209fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_enter(&txmutex);
23219fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
23229fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (txid == 0)
23239fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		txid = ddi_get_lbolt() << 11;
23249fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
23259fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	do {
23269fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		++txid;
23279fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	} while (txid == 0 || txid == (uint32_t)-1);
23289fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
23299fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	txid_ret = txid;
23309fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_exit(&txmutex);
23319fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
23329fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	return (txid_ret);
23339fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
2334cb174861Sjoyce mcintosh 
2335cb174861Sjoyce mcintosh /*
2336cb174861Sjoyce mcintosh  * Called by the ioctl to find the corresponding
2337cb174861Sjoyce mcintosh  * spooldoc node.  removes node on success
2338cb174861Sjoyce mcintosh  *
2339cb174861Sjoyce mcintosh  * Return values
2340cb174861Sjoyce mcintosh  * rc
2341cb174861Sjoyce mcintosh  * B_FALSE - not found
2342cb174861Sjoyce mcintosh  * B_TRUE  - found
2343cb174861Sjoyce mcintosh  *
2344cb174861Sjoyce mcintosh  */
2345cb174861Sjoyce mcintosh 
234623a9c295SGordon Ross static boolean_t
234723a9c295SGordon Ross smb_spool_lookup_doc_byfid(smb_server_t *sv, uint16_t fid,
234823a9c295SGordon Ross     smb_kspooldoc_t *spdoc)
2349cb174861Sjoyce mcintosh {
2350cb174861Sjoyce mcintosh 	smb_kspooldoc_t *sp;
2351cb174861Sjoyce mcintosh 	smb_llist_t	*splist;
2352cb174861Sjoyce mcintosh 
2353cb174861Sjoyce mcintosh 	splist = &sv->sp_info.sp_list;
2354cb174861Sjoyce mcintosh 	smb_llist_enter(splist, RW_WRITER);
2355cb174861Sjoyce mcintosh 	sp = smb_llist_head(splist);
2356cb174861Sjoyce mcintosh 	while (sp != NULL) {
2357cb174861Sjoyce mcintosh 		/*
2358cb174861Sjoyce mcintosh 		 * check for a matching fid
2359cb174861Sjoyce mcintosh 		 */
2360cb174861Sjoyce mcintosh 		if (sp->sd_fid == fid) {
2361cb174861Sjoyce mcintosh 			*spdoc = *sp;
2362cb174861Sjoyce mcintosh 			smb_llist_remove(splist, sp);
2363cb174861Sjoyce mcintosh 			smb_llist_exit(splist);
2364cb174861Sjoyce mcintosh 			kmem_free(sp, sizeof (smb_kspooldoc_t));
2365cb174861Sjoyce mcintosh 			return (B_TRUE);
2366cb174861Sjoyce mcintosh 		}
2367cb174861Sjoyce mcintosh 		sp = smb_llist_next(splist, sp);
2368cb174861Sjoyce mcintosh 	}
2369cb174861Sjoyce mcintosh 	cmn_err(CE_WARN, "smb_spool_lookup_user_byfid: no fid:%d", fid);
2370cb174861Sjoyce mcintosh 	smb_llist_exit(splist);
2371cb174861Sjoyce mcintosh 	return (B_FALSE);
2372cb174861Sjoyce mcintosh }
2373cb174861Sjoyce mcintosh 
2374cb174861Sjoyce mcintosh /*
2375cb174861Sjoyce mcintosh  * Adds the spool fid to a linked list to be used
2376cb174861Sjoyce mcintosh  * as a search key in the spooldoc queue
2377cb174861Sjoyce mcintosh  *
2378cb174861Sjoyce mcintosh  * Return values
2379cb174861Sjoyce mcintosh  *      rc non-zero error
2380cb174861Sjoyce mcintosh  *	rc zero success
2381cb174861Sjoyce mcintosh  *
2382cb174861Sjoyce mcintosh  */
2383cb174861Sjoyce mcintosh 
238486d7016bSGordon Ross void
238586d7016bSGordon Ross smb_spool_add_fid(smb_server_t *sv, uint16_t fid)
2386cb174861Sjoyce mcintosh {
2387cb174861Sjoyce mcintosh 	smb_llist_t	*fidlist;
2388cb174861Sjoyce mcintosh 	smb_spoolfid_t  *sf;
2389cb174861Sjoyce mcintosh 
239086d7016bSGordon Ross 	if (sv->sv_cfg.skc_print_enable == 0)
239186d7016bSGordon Ross 		return;
2392cb174861Sjoyce mcintosh 
2393cb174861Sjoyce mcintosh 	sf = kmem_zalloc(sizeof (smb_spoolfid_t), KM_SLEEP);
2394cb174861Sjoyce mcintosh 	fidlist = &sv->sp_info.sp_fidlist;
2395cb174861Sjoyce mcintosh 	smb_llist_enter(fidlist, RW_WRITER);
2396cb174861Sjoyce mcintosh 	sf->sf_fid = fid;
2397cb174861Sjoyce mcintosh 	smb_llist_insert_tail(fidlist, sf);
2398cb174861Sjoyce mcintosh 	smb_llist_exit(fidlist);
239986d7016bSGordon Ross 	cv_broadcast(&sv->sp_info.sp_cv);
2400cb174861Sjoyce mcintosh }
2401cb174861Sjoyce mcintosh 
2402cb174861Sjoyce mcintosh /*
2403cb174861Sjoyce mcintosh  * Called by the ioctl to get and remove the head of the fid list
2404cb174861Sjoyce mcintosh  *
2405cb174861Sjoyce mcintosh  * Return values
2406cb174861Sjoyce mcintosh  * int fd
2407cb174861Sjoyce mcintosh  * greater than 0 success
2408cb174861Sjoyce mcintosh  * 0 - error
2409cb174861Sjoyce mcintosh  *
2410cb174861Sjoyce mcintosh  */
2411cb174861Sjoyce mcintosh 
241223a9c295SGordon Ross static uint16_t
241323a9c295SGordon Ross smb_spool_get_fid(smb_server_t *sv)
2414cb174861Sjoyce mcintosh {
2415cb174861Sjoyce mcintosh 	smb_spoolfid_t	*spfid;
2416cb174861Sjoyce mcintosh 	smb_llist_t	*splist;
2417cb174861Sjoyce mcintosh 	uint16_t	fid;
2418cb174861Sjoyce mcintosh 
2419cb174861Sjoyce mcintosh 	splist = &sv->sp_info.sp_fidlist;
2420cb174861Sjoyce mcintosh 	smb_llist_enter(splist, RW_WRITER);
2421cb174861Sjoyce mcintosh 	spfid = smb_llist_head(splist);
2422cb174861Sjoyce mcintosh 	if (spfid != NULL) {
2423cb174861Sjoyce mcintosh 		fid = spfid->sf_fid;
2424cb174861Sjoyce mcintosh 		smb_llist_remove(&sv->sp_info.sp_fidlist, spfid);
2425cb174861Sjoyce mcintosh 		kmem_free(spfid, sizeof (smb_spoolfid_t));
2426cb174861Sjoyce mcintosh 	} else {
2427cb174861Sjoyce mcintosh 		fid = 0;
2428cb174861Sjoyce mcintosh 	}
2429cb174861Sjoyce mcintosh 	smb_llist_exit(splist);
2430cb174861Sjoyce mcintosh 	return (fid);
2431cb174861Sjoyce mcintosh }
2432cb174861Sjoyce mcintosh 
2433cb174861Sjoyce mcintosh /*
2434cb174861Sjoyce mcintosh  * Adds the spooldoc to the tail of the spooldoc list
2435cb174861Sjoyce mcintosh  *
2436cb174861Sjoyce mcintosh  * Return values
2437cb174861Sjoyce mcintosh  *      rc non-zero error
2438cb174861Sjoyce mcintosh  *	rc zero success
2439cb174861Sjoyce mcintosh  */
2440cb174861Sjoyce mcintosh int
24418622ec45SGordon Ross smb_spool_add_doc(smb_tree_t *tree, smb_kspooldoc_t *sp)
2442cb174861Sjoyce mcintosh {
2443cb174861Sjoyce mcintosh 	smb_llist_t	*splist;
24448622ec45SGordon Ross 	smb_server_t	*sv = tree->t_server;
2445cb174861Sjoyce mcintosh 	int rc = 0;
2446cb174861Sjoyce mcintosh 
2447cb174861Sjoyce mcintosh 	splist = &sv->sp_info.sp_list;
2448cb174861Sjoyce mcintosh 	smb_llist_enter(splist, RW_WRITER);
244923a9c295SGordon Ross 	sp->sd_spool_num = atomic_inc_32_nv(&sv->sp_info.sp_cnt);
2450cb174861Sjoyce mcintosh 	smb_llist_insert_tail(splist, sp);
2451cb174861Sjoyce mcintosh 	smb_llist_exit(splist);
24528622ec45SGordon Ross 
2453cb174861Sjoyce mcintosh 	return (rc);
2454cb174861Sjoyce mcintosh }
24554163af6aSjose borrego 
24564163af6aSjose borrego /*
24574163af6aSjose borrego  * smb_server_create_session
24584163af6aSjose borrego  */
24594163af6aSjose borrego static void
24604163af6aSjose borrego smb_server_create_session(smb_listener_daemon_t *ld, ksocket_t s_so)
24614163af6aSjose borrego {
24624163af6aSjose borrego 	smb_session_t		*session;
24638622ec45SGordon Ross 	taskqid_t		tqid;
2464811599a4SMatt Barden 	smb_llist_t		*sl;
2465811599a4SMatt Barden 	smb_server_t		*sv = ld->ld_sv;
24664163af6aSjose borrego 
2467811599a4SMatt Barden 	session = smb_session_create(s_so, ld->ld_port, sv,
24684163af6aSjose borrego 	    ld->ld_family);
24694163af6aSjose borrego 
24708622ec45SGordon Ross 	if (session == NULL) {
24718622ec45SGordon Ross 		smb_soshutdown(s_so);
24728622ec45SGordon Ross 		smb_sodestroy(s_so);
24738622ec45SGordon Ross 		cmn_err(CE_WARN, "SMB Session: alloc failed");
24748622ec45SGordon Ross 		return;
24758622ec45SGordon Ross 	}
24768622ec45SGordon Ross 
2477811599a4SMatt Barden 	sl = &sv->sv_session_list;
2478811599a4SMatt Barden 	smb_llist_enter(sl, RW_WRITER);
2479811599a4SMatt Barden 	smb_llist_insert_tail(sl, session);
2480811599a4SMatt Barden 	smb_llist_exit(sl);
24814163af6aSjose borrego 
24828622ec45SGordon Ross 	/*
24838622ec45SGordon Ross 	 * These taskq entries must run independently of one another,
24848622ec45SGordon Ross 	 * so TQ_NOQUEUE.  TQ_SLEEP (==0) just for clarity.
24858622ec45SGordon Ross 	 */
2486811599a4SMatt Barden 	tqid = taskq_dispatch(sv->sv_receiver_pool,
2487811599a4SMatt Barden 	    smb_server_receiver, session, TQ_NOQUEUE | TQ_SLEEP);
2488fc8ae2ecSToomas Soome 	if (tqid == TASKQID_INVALID) {
24894163af6aSjose borrego 		smb_session_disconnect(session);
2490811599a4SMatt Barden 		smb_server_destroy_session(session);
24918622ec45SGordon Ross 		cmn_err(CE_WARN, "SMB Session: taskq_dispatch failed");
24928622ec45SGordon Ross 		return;
24934163af6aSjose borrego 	}
24948622ec45SGordon Ross 	/* handy for debugging */
24958622ec45SGordon Ross 	session->s_receiver_tqid = tqid;
24964163af6aSjose borrego }
24974163af6aSjose borrego 
24984163af6aSjose borrego static void
2499811599a4SMatt Barden smb_server_destroy_session(smb_session_t *session)
25004163af6aSjose borrego {
2501811599a4SMatt Barden 	smb_server_t *sv;
2502811599a4SMatt Barden 	smb_llist_t *ll;
2503811599a4SMatt Barden 	uint32_t count;
2504811599a4SMatt Barden 
2505811599a4SMatt Barden 	ASSERT(session->s_server != NULL);
2506811599a4SMatt Barden 	sv = session->s_server;
2507811599a4SMatt Barden 	ll = &sv->sv_session_list;
2508811599a4SMatt Barden 
2509811599a4SMatt Barden 	smb_llist_flush(&session->s_tree_list);
2510811599a4SMatt Barden 	smb_llist_flush(&session->s_user_list);
2511811599a4SMatt Barden 
2512811599a4SMatt Barden 	/*
2513811599a4SMatt Barden 	 * The user and tree lists should be empty now.
2514811599a4SMatt Barden 	 */
2515811599a4SMatt Barden #ifdef DEBUG
2516811599a4SMatt Barden 	if (session->s_user_list.ll_count != 0) {
2517811599a4SMatt Barden 		cmn_err(CE_WARN, "user list not empty?");
2518811599a4SMatt Barden 		debug_enter("s_user_list");
2519811599a4SMatt Barden 	}
2520811599a4SMatt Barden 	if (session->s_tree_list.ll_count != 0) {
2521811599a4SMatt Barden 		cmn_err(CE_WARN, "tree list not empty?");
2522811599a4SMatt Barden 		debug_enter("s_tree_list");
2523811599a4SMatt Barden 	}
2524811599a4SMatt Barden #endif
2525811599a4SMatt Barden 
2526811599a4SMatt Barden 	smb_llist_enter(ll, RW_WRITER);
2527811599a4SMatt Barden 	smb_llist_remove(ll, session);
2528811599a4SMatt Barden 	count = ll->ll_count;
2529811599a4SMatt Barden 	smb_llist_exit(ll);
2530811599a4SMatt Barden 
25314163af6aSjose borrego 	smb_session_delete(session);
2532811599a4SMatt Barden 	if (count == 0) {
2533811599a4SMatt Barden 		/* See smb_server_shutdown */
2534811599a4SMatt Barden 		cv_signal(&sv->sv_cv);
2535811599a4SMatt Barden 	}
25364163af6aSjose borrego }
2537