1faa1795aSjb /*
2faa1795aSjb  * CDDL HEADER START
3faa1795aSjb  *
4faa1795aSjb  * The contents of this file are subject to the terms of the
5faa1795aSjb  * Common Development and Distribution License (the "License").
6faa1795aSjb  * You may not use this file except in compliance with the License.
7faa1795aSjb  *
8faa1795aSjb  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9faa1795aSjb  * or http://www.opensolaris.org/os/licensing.
10faa1795aSjb  * See the License for the specific language governing permissions
11faa1795aSjb  * and limitations under the License.
12faa1795aSjb  *
13faa1795aSjb  * When distributing Covered Code, include this CDDL HEADER in each
14faa1795aSjb  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15faa1795aSjb  * If applicable, add the following below this CDDL HEADER, with the
16faa1795aSjb  * fields enclosed by brackets "[]" replaced with your own identifying
17faa1795aSjb  * information: Portions Copyright [yyyy] [name of copyright owner]
18faa1795aSjb  *
19faa1795aSjb  * CDDL HEADER END
20faa1795aSjb  */
21faa1795aSjb /*
22c5866007SKeyur Desai  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
23adc68ba9SPavel Zakharov  * Copyright (c) 2017 by Delphix. All rights reserved.
24896d9552SGordon Ross  * Copyright 2019 Nexenta by DDN, Inc. All rights reserved.
255d8538b6SGordon Ross  * Copyright 2021-2023 RackTop Systems, Inc.
26faa1795aSjb  */
27faa1795aSjb 
28faa1795aSjb /*
29faa1795aSjb  * General Structures Layout
30faa1795aSjb  * -------------------------
31faa1795aSjb  *
32faa1795aSjb  * This is a simplified diagram showing the relationship between most of the
33faa1795aSjb  * main structures.
34faa1795aSjb  *
35faa1795aSjb  * +-------------------+
36faa1795aSjb  * |     SMB_SERVER    |
37faa1795aSjb  * +-------------------+
38faa1795aSjb  *          |
39faa1795aSjb  *          |
40faa1795aSjb  *          v
41faa1795aSjb  * +-------------------+       +-------------------+      +-------------------+
42faa1795aSjb  * |     SESSION       |<----->|     SESSION       |......|      SESSION      |
43faa1795aSjb  * +-------------------+       +-------------------+      +-------------------+
44faa1795aSjb  *          |
45faa1795aSjb  *          |
46faa1795aSjb  *          v
47faa1795aSjb  * +-------------------+       +-------------------+      +-------------------+
48faa1795aSjb  * |       USER        |<----->|       USER        |......|       USER        |
49faa1795aSjb  * +-------------------+       +-------------------+      +-------------------+
50faa1795aSjb  *          |
51faa1795aSjb  *          |
52faa1795aSjb  *          v
53faa1795aSjb  * +-------------------+       +-------------------+      +-------------------+
54faa1795aSjb  * |       TREE        |<----->|       TREE        |......|       TREE        |
55faa1795aSjb  * +-------------------+       +-------------------+      +-------------------+
56faa1795aSjb  *      |         |
57faa1795aSjb  *      |         |
58faa1795aSjb  *      |         v
59faa1795aSjb  *      |     +-------+       +-------+      +-------+
60faa1795aSjb  *      |     | OFILE |<----->| OFILE |......| OFILE |
61faa1795aSjb  *      |     +-------+       +-------+      +-------+
62faa1795aSjb  *      |
63faa1795aSjb  *      |
64faa1795aSjb  *      v
65faa1795aSjb  *  +-------+       +------+      +------+
66faa1795aSjb  *  | ODIR  |<----->| ODIR |......| ODIR |
67faa1795aSjb  *  +-------+       +------+      +------+
68faa1795aSjb  *
69faa1795aSjb  *
70faa1795aSjb  * Module Interface Overview
71faa1795aSjb  * -------------------------
72faa1795aSjb  *
73faa1795aSjb  *
74faa1795aSjb  *	    +===================================+
75faa1795aSjb  *	    |		 smbd daemon		|
76faa1795aSjb  *	    +===================================+
77faa1795aSjb  *	      |		     |		      ^
78faa1795aSjb  *	      |		     |		      |
79faa1795aSjb  * User	      |		     |		      |
80faa1795aSjb  * -----------|--------------|----------------|--------------------------------
81faa1795aSjb  * Kernel     |		     |		      |
82faa1795aSjb  *            |		     |		      |
83faa1795aSjb  *	      |		     |		      |
84faa1795aSjb  *  +=========|==============|================|=================+
85faa1795aSjb  *  |	      v		     v		      |			|
86faa1795aSjb  *  | +-----------+ +--------------------+ +------------------+ |
87faa1795aSjb  *  | |     IO    | | Kernel Door Server | | User Door Servers|	|
88faa1795aSjb  *  | | Interface | |     Interface      | |   Interface      | |
89faa1795aSjb  *  | +-----------+ +--------------------+ +------------------+ |
90faa1795aSjb  *  |		|	     |		      ^		^	|
91faa1795aSjb  *  |		v	     v		      |		|	|    +=========+
92faa1795aSjb  *  |	     +-----------------------------------+	|	|    |	       |
93faa1795aSjb  *  |	     + SMB Server Management (this file) |<------------------|	 ZFS   |
94faa1795aSjb  *  |	     +-----------------------------------+	|	|    |	       |
95faa1795aSjb  *  |							|	|    |  Module |
96faa1795aSjb  *  |	     +-----------------------------------+	|	|    |	       |
97faa1795aSjb  *  |	     +     SMB Server Internal Layers    |------+	|    +=========+
98faa1795aSjb  *  |	     +-----------------------------------+		|
99faa1795aSjb  *  |								|
100faa1795aSjb  *  |								|
101faa1795aSjb  *  +===========================================================+
102faa1795aSjb  *
103faa1795aSjb  *
104faa1795aSjb  * Server State Machine
105faa1795aSjb  * --------------------
106faa1795aSjb  *                                  |
107faa1795aSjb  *                                  | T0
108faa1795aSjb  *                                  |
109faa1795aSjb  *                                  v
110faa1795aSjb  *                    +-----------------------------+
111faa1795aSjb  *		      |   SMB_SERVER_STATE_CREATED  |
112faa1795aSjb  *		      +-----------------------------+
113faa1795aSjb  *				    |
114faa1795aSjb  *				    | T1
115faa1795aSjb  *				    |
116faa1795aSjb  *				    v
117faa1795aSjb  *		      +-----------------------------+
118faa1795aSjb  *		      | SMB_SERVER_STATE_CONFIGURED |
119faa1795aSjb  *		      +-----------------------------+
120faa1795aSjb  *				    |
121faa1795aSjb  *				    | T2
122faa1795aSjb  *				    |
123faa1795aSjb  *				    v
124faa1795aSjb  *		      +-----------------------------+
1259fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  *		      |  SMB_SERVER_STATE_RUNNING / |
1269fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  *		      |  SMB_SERVER_STATE_STOPPING  |
127faa1795aSjb  *		      +-----------------------------+
128faa1795aSjb  *				    |
129faa1795aSjb  *				    | T3
130faa1795aSjb  *				    |
131faa1795aSjb  *				    v
132faa1795aSjb  *		      +-----------------------------+
133faa1795aSjb  *		      |  SMB_SERVER_STATE_DELETING  |
134faa1795aSjb  *                    +-----------------------------+
135faa1795aSjb  *				    |
136faa1795aSjb  *				    |
137faa1795aSjb  *				    |
138faa1795aSjb  *				    v
139faa1795aSjb  *
140faa1795aSjb  * States
141faa1795aSjb  * ------
142faa1795aSjb  *
143faa1795aSjb  * SMB_SERVER_STATE_CREATED
144faa1795aSjb  *
145faa1795aSjb  *    This is the state of the server just after creation.
146faa1795aSjb  *
147faa1795aSjb  * SMB_SERVER_STATE_CONFIGURED
148faa1795aSjb  *
149faa1795aSjb  *    The server has been configured.
150faa1795aSjb  *
151faa1795aSjb  * SMB_SERVER_STATE_RUNNING
152faa1795aSjb  *
153faa1795aSjb  *    The server has been started. While in this state the threads listening on
1544163af6aSjose borrego  *    the sockets are started.
155faa1795aSjb  *
1564163af6aSjose borrego  *    When a client establishes a connection the thread listening dispatches
1574163af6aSjose borrego  *    a task with the new session as an argument. If the dispatch fails the new
1584163af6aSjose borrego  *    session context is destroyed.
159faa1795aSjb  *
160faa1795aSjb  * SMB_SERVER_STATE_STOPPING
161faa1795aSjb  *
162faa1795aSjb  *    The threads listening on the NBT and TCP sockets are being terminated.
163faa1795aSjb  *
164faa1795aSjb  *
165faa1795aSjb  * Transitions
166faa1795aSjb  * -----------
167faa1795aSjb  *
168faa1795aSjb  * Transition T0
169faa1795aSjb  *
170faa1795aSjb  *    The daemon smbd triggers its creation by opening the smbsrv device. If
171faa1795aSjb  *    the zone where the daemon lives doesn't have an smb server yet it is
172faa1795aSjb  *    created.
173faa1795aSjb  *
174faa1795aSjb  *		smb_drv_open() --> smb_server_create()
175faa1795aSjb  *
176faa1795aSjb  * Transition T1
177faa1795aSjb  *
178faa1795aSjb  *    This transition occurs in smb_server_configure(). It is triggered by the
179faa1795aSjb  *    daemon through an Ioctl.
180faa1795aSjb  *
181faa1795aSjb  *	smb_drv_ioctl(SMB_IOC_CONFIG) --> smb_server_configure()
182faa1795aSjb  *
183faa1795aSjb  * Transition T2
184faa1795aSjb  *
185faa1795aSjb  *    This transition occurs in smb_server_start(). It is triggered by the
186faa1795aSjb  *    daemon through an Ioctl.
187faa1795aSjb  *
188faa1795aSjb  *	smb_drv_ioctl(SMB_IOC_START) --> smb_server_start()
189faa1795aSjb  *
190faa1795aSjb  * Transition T3
191faa1795aSjb  *
192faa1795aSjb  *    This transition occurs in smb_server_delete(). It is triggered by the
193faa1795aSjb  *    daemon when closing the smbsrv device
194faa1795aSjb  *
195faa1795aSjb  *		smb_drv_close() --> smb_server_delete()
196faa1795aSjb  *
197faa1795aSjb  * Comments
198faa1795aSjb  * --------
199faa1795aSjb  *
200faa1795aSjb  * This files assumes that there will one SMB server per zone. For now the
201faa1795aSjb  * smb server works only in global zone. There's nothing in this file preventing
202faa1795aSjb  * an smb server from being created in a non global zone. That limitation is
203faa1795aSjb  * enforced in user space.
204faa1795aSjb  */
205faa1795aSjb 
206faa1795aSjb #include <sys/cmn_err.h>
207faa1795aSjb #include <sys/priv.h>
208faa1795aSjb #include <sys/zone.h>
2095d8538b6SGordon Ross #include <sys/sysmacros.h>
2105d8538b6SGordon Ross #include <sys/callb.h>
2115d8538b6SGordon Ross #include <sys/class.h>
2125d8538b6SGordon Ross #include <sys/disp.h>
213bbf6f00cSJordan Brown #include <netinet/in.h>
214bbf6f00cSJordan Brown #include <netinet/in_systm.h>
215bbf6f00cSJordan Brown #include <netinet/ip.h>
216bbf6f00cSJordan Brown #include <netinet/ip_icmp.h>
217bbf6f00cSJordan Brown #include <netinet/ip_var.h>
218bbf6f00cSJordan Brown #include <netinet/tcp.h>
219a90cf9f2SGordon Ross #include <smbsrv/smb2_kproto.h>
220bbf6f00cSJordan Brown #include <smbsrv/string.h>
221faa1795aSjb #include <smbsrv/netbios.h>
222faa1795aSjb #include <smbsrv/smb_fsops.h>
2233db3f65cSamw #include <smbsrv/smb_share.h>
2249fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States #include <smbsrv/smb_door.h>
2256537f381Sas #include <smbsrv/smb_kstat.h>
226faa1795aSjb 
227148c5f43SAlan Wright static void smb_server_kstat_init(smb_server_t *);
228faa1795aSjb static void smb_server_kstat_fini(smb_server_t *);
229faa1795aSjb static void smb_server_timers(smb_thread_t *, void *);
23029bd2886SAlan Wright static void smb_server_store_cfg(smb_server_t *, smb_ioc_cfg_t *);
2319fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void smb_server_shutdown(smb_server_t *);
232faa1795aSjb static int smb_server_fsop_start(smb_server_t *);
233faa1795aSjb static void smb_server_fsop_stop(smb_server_t *);
2349fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void smb_event_cancel(smb_server_t *, uint32_t);
2359fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static uint32_t smb_event_alloc_txid(void);
236faa1795aSjb 
2378d94f651SGordon Ross static void smb_server_disconnect_share(smb_server_t *, const char *);
2388d94f651SGordon Ross static void smb_server_enum_users(smb_server_t *, smb_svcenum_t *);
2398d94f651SGordon Ross static void smb_server_enum_trees(smb_server_t *, smb_svcenum_t *);
2408d94f651SGordon Ross static int smb_server_session_disconnect(smb_server_t *, const char *,
2411fcced4cSJordan Brown     const char *);
2428d94f651SGordon Ross static int smb_server_fclose(smb_server_t *, uint32_t);
243148c5f43SAlan Wright static int smb_server_kstat_update(kstat_t *, int);
244cb174861Sjoyce mcintosh static int smb_server_legacy_kstat_update(kstat_t *, int);
2454163af6aSjose borrego static void smb_server_listener_init(smb_server_t *, smb_listener_daemon_t *,
2464163af6aSjose borrego     char *, in_port_t, int);
2474163af6aSjose borrego static void smb_server_listener_destroy(smb_listener_daemon_t *);
2484163af6aSjose borrego static int smb_server_listener_start(smb_listener_daemon_t *);
2494163af6aSjose borrego static void smb_server_listener_stop(smb_listener_daemon_t *);
2504163af6aSjose borrego static void smb_server_listener(smb_thread_t *, void *);
2514163af6aSjose borrego static void smb_server_receiver(void *);
2524163af6aSjose borrego static void smb_server_create_session(smb_listener_daemon_t *, ksocket_t);
253811599a4SMatt Barden static void smb_server_destroy_session(smb_session_t *);
25423a9c295SGordon Ross static uint16_t smb_spool_get_fid(smb_server_t *);
25523a9c295SGordon Ross static boolean_t smb_spool_lookup_doc_byfid(smb_server_t *, uint16_t,
25623a9c295SGordon Ross     smb_kspooldoc_t *);
2571fcced4cSJordan Brown 
2585d8538b6SGordon Ross #ifdef	_KERNEL
2595d8538b6SGordon Ross int smb_create_process = 1;
2605d8538b6SGordon Ross static void smb_server_delproc(smb_server_t *);
2615d8538b6SGordon Ross static int smb_server_newproc(smb_server_t *);
2625d8538b6SGordon Ross static void smb_server_proc_main(void *);
2635d8538b6SGordon Ross #endif
2645d8538b6SGordon Ross 
265811599a4SMatt Barden /*
266811599a4SMatt Barden  * How many "buckets" should our hash tables use?  On a "real" server,
267811599a4SMatt Barden  * make them much larger than the number of CPUs we're likely to have.
268811599a4SMatt Barden  * On "fksmbd" make it smaller so dtrace logs are shorter.
269811599a4SMatt Barden  * These must be powers of two.
270811599a4SMatt Barden  */
271811599a4SMatt Barden #ifdef	_KERNEL
272811599a4SMatt Barden #define	DEFAULT_HASH_NBUCKETS	256	/* real server */
273811599a4SMatt Barden #else
274811599a4SMatt Barden #define	DEFAULT_HASH_NBUCKETS	16	/* for "fksmbd" */
275811599a4SMatt Barden #endif
276811599a4SMatt Barden uint32_t SMB_OFILE_HASH_NBUCKETS = DEFAULT_HASH_NBUCKETS;
277811599a4SMatt Barden uint32_t SMB_LEASE_HASH_NBUCKETS = DEFAULT_HASH_NBUCKETS;
278811599a4SMatt Barden 
2799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States int smb_event_debug = 0;
2809fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
281faa1795aSjb static smb_llist_t	smb_servers;
282faa1795aSjb 
2837f5d80fdSGordon Ross /* for smb_server_destroy_session() */
2847f5d80fdSGordon Ross static smb_llist_t smb_server_session_zombies;
2857f5d80fdSGordon Ross 
2868622ec45SGordon Ross kmem_cache_t		*smb_cache_request;
2878622ec45SGordon Ross kmem_cache_t		*smb_cache_session;
2888622ec45SGordon Ross kmem_cache_t		*smb_cache_user;
2898622ec45SGordon Ross kmem_cache_t		*smb_cache_tree;
2908622ec45SGordon Ross kmem_cache_t		*smb_cache_ofile;
2918622ec45SGordon Ross kmem_cache_t		*smb_cache_odir;
2928622ec45SGordon Ross kmem_cache_t		*smb_cache_opipe;
2938622ec45SGordon Ross kmem_cache_t		*smb_cache_event;
2940897f7fbSGordon Ross kmem_cache_t		*smb_cache_lock;
2958622ec45SGordon Ross 
296faa1795aSjb /*
297faa1795aSjb  * *****************************************************************************
298faa1795aSjb  * **************** Functions called from the device interface *****************
299faa1795aSjb  * *****************************************************************************
300faa1795aSjb  *
3011fcced4cSJordan Brown  * These functions typically have to determine the relevant smb server
3021fcced4cSJordan Brown  * to which the call applies.
303faa1795aSjb  */
304faa1795aSjb 
305a90cf9f2SGordon Ross /*
306a90cf9f2SGordon Ross  * How many zones have an SMB server active?
307a90cf9f2SGordon Ross  */
308a90cf9f2SGordon Ross int
smb_server_get_count(void)309a90cf9f2SGordon Ross smb_server_get_count(void)
310a90cf9f2SGordon Ross {
311a90cf9f2SGordon Ross 	return (smb_llist_get_count(&smb_servers));
312a90cf9f2SGordon Ross }
313a90cf9f2SGordon Ross 
314faa1795aSjb /*
3158622ec45SGordon Ross  * smb_server_g_init
316faa1795aSjb  *
317c8ec8eeaSjose borrego  * This function must be called from smb_drv_attach().
318faa1795aSjb  */
319faa1795aSjb int
smb_server_g_init(void)3208622ec45SGordon Ross smb_server_g_init(void)
321faa1795aSjb {
3228622ec45SGordon Ross 	int rc;
323faa1795aSjb 
3248622ec45SGordon Ross 	if ((rc = smb_vop_init()) != 0)
3258622ec45SGordon Ross 		goto errout;
3268622ec45SGordon Ross 	if ((rc = smb_fem_init()) != 0)
3278622ec45SGordon Ross 		goto errout;
3289fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
3298622ec45SGordon Ross 	smb_kshare_g_init();
3308622ec45SGordon Ross 	smb_codepage_init();
3318622ec45SGordon Ross 	smb_mbc_init();		/* smb_mbc_cache */
3328622ec45SGordon Ross 	smb_node_init();	/* smb_node_cache, lists */
33394047d49SGordon Ross 	smb2_lease_init();
3348622ec45SGordon Ross 
3358622ec45SGordon Ross 	smb_cache_request = kmem_cache_create("smb_request_cache",
3368622ec45SGordon Ross 	    sizeof (smb_request_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
3378622ec45SGordon Ross 	smb_cache_session = kmem_cache_create("smb_session_cache",
3388622ec45SGordon Ross 	    sizeof (smb_session_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
3398622ec45SGordon Ross 	smb_cache_user = kmem_cache_create("smb_user_cache",
3408622ec45SGordon Ross 	    sizeof (smb_user_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
3418622ec45SGordon Ross 	smb_cache_tree = kmem_cache_create("smb_tree_cache",
3428622ec45SGordon Ross 	    sizeof (smb_tree_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
3438622ec45SGordon Ross 	smb_cache_ofile = kmem_cache_create("smb_ofile_cache",
3448622ec45SGordon Ross 	    sizeof (smb_ofile_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
3458622ec45SGordon Ross 	smb_cache_odir = kmem_cache_create("smb_odir_cache",
3468622ec45SGordon Ross 	    sizeof (smb_odir_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
3478622ec45SGordon Ross 	smb_cache_opipe = kmem_cache_create("smb_opipe_cache",
3488622ec45SGordon Ross 	    sizeof (smb_opipe_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
3498622ec45SGordon Ross 	smb_cache_event = kmem_cache_create("smb_event_cache",
3508622ec45SGordon Ross 	    sizeof (smb_event_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
3510897f7fbSGordon Ross 	smb_cache_lock = kmem_cache_create("smb_lock_cache",
3520897f7fbSGordon Ross 	    sizeof (smb_lock_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
3538622ec45SGordon Ross 
3548622ec45SGordon Ross 	smb_llist_init();
3558622ec45SGordon Ross 	smb_llist_constructor(&smb_servers, sizeof (smb_server_t),
3568622ec45SGordon Ross 	    offsetof(smb_server_t, sv_lnd));
3578622ec45SGordon Ross 
3587f5d80fdSGordon Ross 	smb_llist_constructor(&smb_server_session_zombies,
3597f5d80fdSGordon Ross 	    sizeof (smb_session_t), offsetof(smb_session_t, s_lnd));
3607f5d80fdSGordon Ross 
3618622ec45SGordon Ross 	return (0);
3628622ec45SGordon Ross 
3638622ec45SGordon Ross errout:
364faa1795aSjb 	smb_fem_fini();
365faa1795aSjb 	smb_vop_fini();
366faa1795aSjb 	return (rc);
367faa1795aSjb }
368faa1795aSjb 
369faa1795aSjb /*
3708622ec45SGordon Ross  * smb_server_g_fini
371faa1795aSjb  *
372faa1795aSjb  * This function must called from smb_drv_detach(). It will fail if servers
373faa1795aSjb  * still exist.
374faa1795aSjb  */
375a90cf9f2SGordon Ross void
smb_server_g_fini(void)3768622ec45SGordon Ross smb_server_g_fini(void)
3778622ec45SGordon Ross {
3788622ec45SGordon Ross 
379a90cf9f2SGordon Ross 	ASSERT(smb_llist_get_count(&smb_servers) == 0);
380a90cf9f2SGordon Ross 
3818622ec45SGordon Ross 	smb_llist_fini();
3828622ec45SGordon Ross 
3838622ec45SGordon Ross 	kmem_cache_destroy(smb_cache_request);
3848622ec45SGordon Ross 	kmem_cache_destroy(smb_cache_session);
3858622ec45SGordon Ross 	kmem_cache_destroy(smb_cache_user);
3868622ec45SGordon Ross 	kmem_cache_destroy(smb_cache_tree);
3878622ec45SGordon Ross 	kmem_cache_destroy(smb_cache_ofile);
3888622ec45SGordon Ross 	kmem_cache_destroy(smb_cache_odir);
3898622ec45SGordon Ross 	kmem_cache_destroy(smb_cache_opipe);
3908622ec45SGordon Ross 	kmem_cache_destroy(smb_cache_event);
3910897f7fbSGordon Ross 	kmem_cache_destroy(smb_cache_lock);
3928622ec45SGordon Ross 
39394047d49SGordon Ross 	smb2_lease_fini();
3948622ec45SGordon Ross 	smb_node_fini();
3958622ec45SGordon Ross 	smb_mbc_fini();
396adc68ba9SPavel Zakharov 	smb_codepage_fini();
3978622ec45SGordon Ross 	smb_kshare_g_fini();
3988622ec45SGordon Ross 
3998622ec45SGordon Ross 	smb_fem_fini();
4008622ec45SGordon Ross 	smb_vop_fini();
4018622ec45SGordon Ross 
4028622ec45SGordon Ross 	smb_llist_destructor(&smb_servers);
403faa1795aSjb }
404faa1795aSjb 
405faa1795aSjb /*
406faa1795aSjb  * smb_server_create
407faa1795aSjb  *
4085d8538b6SGordon Ross  * Called by driver open
4095d8538b6SGordon Ross  *
410faa1795aSjb  * This function will fail if there's already a server associated with the
411faa1795aSjb  * caller's zone.
4125d8538b6SGordon Ross  *
4135d8538b6SGordon Ross  * This object is one-to-one with zones, so we could instead
4145d8538b6SGordon Ross  * create/destroy this via zone_key_create callbacks.
4155d8538b6SGordon Ross  * See smb_server_delete() for destruction.
416faa1795aSjb  */
417faa1795aSjb int
smb_server_create(dev_t dev)418*34bbc83aSGordon Ross smb_server_create(dev_t dev)
419faa1795aSjb {
420faa1795aSjb 	zoneid_t	zid;
421faa1795aSjb 	smb_server_t	*sv;
422faa1795aSjb 
423faa1795aSjb 	zid = getzoneid();
424faa1795aSjb 
425faa1795aSjb 	smb_llist_enter(&smb_servers, RW_WRITER);
426faa1795aSjb 	sv = smb_llist_head(&smb_servers);
427*34bbc83aSGordon Ross 	while (sv != NULL) {
4289fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_SERVER_VALID(sv);
429faa1795aSjb 		if (sv->sv_zid == zid) {
430faa1795aSjb 			smb_llist_exit(&smb_servers);
431*34bbc83aSGordon Ross 			return (SET_ERROR(EBUSY));
432faa1795aSjb 		}
433faa1795aSjb 		sv = smb_llist_next(&smb_servers, sv);
434faa1795aSjb 	}
435faa1795aSjb 
4368622ec45SGordon Ross 	sv = kmem_zalloc(sizeof (smb_server_t), KM_SLEEP);
4378622ec45SGordon Ross 
4388622ec45SGordon Ross 	sv->sv_magic = SMB_SERVER_MAGIC;
4398622ec45SGordon Ross 	sv->sv_state = SMB_SERVER_STATE_CREATED;
4408622ec45SGordon Ross 	sv->sv_zid = zid;
441b819cea2SGordon Ross 	sv->sv_pid = ddi_get_pid();
442*34bbc83aSGordon Ross 	sv->sv_dev = dev;
4435d8538b6SGordon Ross 	sv->sv_proc_state = SMB_THREAD_STATE_EXITED;
4448622ec45SGordon Ross 
4458622ec45SGordon Ross 	mutex_init(&sv->sv_mutex, NULL, MUTEX_DEFAULT, NULL);
4468622ec45SGordon Ross 	cv_init(&sv->sv_cv, NULL, CV_DEFAULT, NULL);
4478622ec45SGordon Ross 	cv_init(&sv->sp_info.sp_cv, NULL, CV_DEFAULT, NULL);
448faa1795aSjb 
449811599a4SMatt Barden 	sv->sv_persistid_ht = smb_hash_create(sizeof (smb_ofile_t),
450811599a4SMatt Barden 	    offsetof(smb_ofile_t, f_dh_lnd), SMB_OFILE_HASH_NBUCKETS);
451811599a4SMatt Barden 
45294047d49SGordon Ross 	sv->sv_lease_ht = smb_hash_create(sizeof (smb_lease_t),
45394047d49SGordon Ross 	    offsetof(smb_lease_t, ls_lnd), SMB_LEASE_HASH_NBUCKETS);
45494047d49SGordon Ross 
455811599a4SMatt Barden 	smb_llist_constructor(&sv->sv_session_list, sizeof (smb_session_t),
456811599a4SMatt Barden 	    offsetof(smb_session_t, s_lnd));
457811599a4SMatt Barden 
4589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_constructor(&sv->sv_event_list, sizeof (smb_event_t),
4599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	    offsetof(smb_event_t, se_lnd));
4609fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
461cb174861Sjoyce mcintosh 	smb_llist_constructor(&sv->sp_info.sp_list, sizeof (smb_kspooldoc_t),
462cb174861Sjoyce mcintosh 	    offsetof(smb_kspooldoc_t, sd_lnd));
463cb174861Sjoyce mcintosh 
464cb174861Sjoyce mcintosh 	smb_llist_constructor(&sv->sp_info.sp_fidlist,
465cb174861Sjoyce mcintosh 	    sizeof (smb_spoolfid_t), offsetof(smb_spoolfid_t, sf_lnd));
466cb174861Sjoyce mcintosh 
467a90cf9f2SGordon Ross 	sv->sv_disp_stats1 = kmem_zalloc(SMB_COM_NUM *
468a90cf9f2SGordon Ross 	    sizeof (smb_disp_stats_t), KM_SLEEP);
469a90cf9f2SGordon Ross 
470a90cf9f2SGordon Ross 	sv->sv_disp_stats2 = kmem_zalloc(SMB2__NCMDS *
4718622ec45SGordon Ross 	    sizeof (smb_disp_stats_t), KM_SLEEP);
472faa1795aSjb 
47308344b29SGordon Ross 	smb_thread_init(&sv->si_thread_timers, "smb_timers",
4745d8538b6SGordon Ross 	    smb_server_timers, sv, smbsrv_timer_pri, sv);
475faa1795aSjb 
476148c5f43SAlan Wright 	smb_srqueue_init(&sv->sv_srqueue);
477faa1795aSjb 
4788622ec45SGordon Ross 	smb_kdoor_init(sv);
4798622ec45SGordon Ross 	smb_kshare_init(sv);
480148c5f43SAlan Wright 	smb_server_kstat_init(sv);
481faa1795aSjb 
482856399cfSGordon Ross 	smb_threshold_init(&sv->sv_ssetup_ct, SMB_SSETUP_CMD,
483cb174861Sjoyce mcintosh 	    smb_ssetup_threshold, smb_ssetup_timeout);
484856399cfSGordon Ross 	smb_threshold_init(&sv->sv_tcon_ct, SMB_TCON_CMD,
4858622ec45SGordon Ross 	    smb_tcon_threshold, smb_tcon_timeout);
486856399cfSGordon Ross 	smb_threshold_init(&sv->sv_opipe_ct, SMB_OPIPE_CMD,
4878622ec45SGordon Ross 	    smb_opipe_threshold, smb_opipe_timeout);
488a9609934SGordon Ross 	smb_threshold_init(&sv->sv_logoff_ct, SMB_LOGOFF_CMD,
489a9609934SGordon Ross 	    smb_logoff_threshold, smb_logoff_timeout);
490cb174861Sjoyce mcintosh 
491856399cfSGordon Ross 	smb_llist_insert_tail(&smb_servers, sv);
492856399cfSGordon Ross 	smb_llist_exit(&smb_servers);
493856399cfSGordon Ross 
494faa1795aSjb 	return (0);
495faa1795aSjb }
496faa1795aSjb 
497faa1795aSjb /*
498faa1795aSjb  * smb_server_delete
499faa1795aSjb  *
5005d8538b6SGordon Ross  * Called by driver close
5015d8538b6SGordon Ross  *
502faa1795aSjb  * This function will delete the server passed in. It will make sure that all
503faa1795aSjb  * activity associated that server has ceased before destroying it.
504faa1795aSjb  */
505faa1795aSjb int
smb_server_delete(smb_server_t * sv)5068d94f651SGordon Ross smb_server_delete(smb_server_t	*sv)
507faa1795aSjb {
508faa1795aSjb 
509faa1795aSjb 	mutex_enter(&sv->sv_mutex);
510faa1795aSjb 	switch (sv->sv_state) {
511faa1795aSjb 	case SMB_SERVER_STATE_RUNNING:
5129fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		sv->sv_state = SMB_SERVER_STATE_STOPPING;
513faa1795aSjb 		mutex_exit(&sv->sv_mutex);
5144163af6aSjose borrego 		smb_server_shutdown(sv);
515faa1795aSjb 		mutex_enter(&sv->sv_mutex);
5164163af6aSjose borrego 		cv_broadcast(&sv->sp_info.sp_cv);
5174163af6aSjose borrego 		sv->sv_state = SMB_SERVER_STATE_DELETING;
5184163af6aSjose borrego 		break;
5194163af6aSjose borrego 	case SMB_SERVER_STATE_STOPPING:
5204163af6aSjose borrego 		sv->sv_state = SMB_SERVER_STATE_DELETING;
521faa1795aSjb 		break;
522faa1795aSjb 	case SMB_SERVER_STATE_CONFIGURED:
523faa1795aSjb 	case SMB_SERVER_STATE_CREATED:
524faa1795aSjb 		sv->sv_state = SMB_SERVER_STATE_DELETING;
525faa1795aSjb 		break;
526faa1795aSjb 	default:
5279fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_SERVER_STATE_VALID(sv->sv_state);
528faa1795aSjb 		mutex_exit(&sv->sv_mutex);
529faa1795aSjb 		smb_server_release(sv);
530faa1795aSjb 		return (ENOTTY);
531faa1795aSjb 	}
532faa1795aSjb 
533faa1795aSjb 	ASSERT(sv->sv_state == SMB_SERVER_STATE_DELETING);
534faa1795aSjb 
535faa1795aSjb 	sv->sv_refcnt--;
536faa1795aSjb 	while (sv->sv_refcnt)
537faa1795aSjb 		cv_wait(&sv->sv_cv, &sv->sv_mutex);
538faa1795aSjb 
539faa1795aSjb 	mutex_exit(&sv->sv_mutex);
540faa1795aSjb 
541faa1795aSjb 	smb_llist_enter(&smb_servers, RW_WRITER);
542faa1795aSjb 	smb_llist_remove(&smb_servers, sv);
543faa1795aSjb 	smb_llist_exit(&smb_servers);
544faa1795aSjb 
545856399cfSGordon Ross 	smb_threshold_fini(&sv->sv_ssetup_ct);
546856399cfSGordon Ross 	smb_threshold_fini(&sv->sv_tcon_ct);
547856399cfSGordon Ross 	smb_threshold_fini(&sv->sv_opipe_ct);
548a9609934SGordon Ross 	smb_threshold_fini(&sv->sv_logoff_ct);
549856399cfSGordon Ross 
5504163af6aSjose borrego 	smb_server_listener_destroy(&sv->sv_nbt_daemon);
5514163af6aSjose borrego 	smb_server_listener_destroy(&sv->sv_tcp_daemon);
552faa1795aSjb 	rw_destroy(&sv->sv_cfg_lock);
553faa1795aSjb 	smb_server_kstat_fini(sv);
5548622ec45SGordon Ross 	smb_kshare_fini(sv);
5558622ec45SGordon Ross 	smb_kdoor_fini(sv);
5569fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_destructor(&sv->sv_event_list);
557811599a4SMatt Barden 	smb_llist_destructor(&sv->sv_session_list);
5582c1b14e5Sjose borrego 
559a90cf9f2SGordon Ross 	kmem_free(sv->sv_disp_stats1,
5608622ec45SGordon Ross 	    SMB_COM_NUM * sizeof (smb_disp_stats_t));
561faa1795aSjb 
562a90cf9f2SGordon Ross 	kmem_free(sv->sv_disp_stats2,
563a90cf9f2SGordon Ross 	    SMB2__NCMDS * sizeof (smb_disp_stats_t));
564a90cf9f2SGordon Ross 
565148c5f43SAlan Wright 	smb_srqueue_destroy(&sv->sv_srqueue);
566faa1795aSjb 	smb_thread_destroy(&sv->si_thread_timers);
5678622ec45SGordon Ross 
568faa1795aSjb 	mutex_destroy(&sv->sv_mutex);
56994047d49SGordon Ross 	smb_hash_destroy(sv->sv_lease_ht);
570811599a4SMatt Barden 	smb_hash_destroy(sv->sv_persistid_ht);
571faa1795aSjb 	cv_destroy(&sv->sv_cv);
572faa1795aSjb 	sv->sv_magic = 0;
573faa1795aSjb 	kmem_free(sv, sizeof (smb_server_t));
574faa1795aSjb 
575faa1795aSjb 	return (0);
576faa1795aSjb }
577faa1795aSjb 
578faa1795aSjb /*
579faa1795aSjb  * smb_server_configure
5805d8538b6SGordon Ross  *
5815d8538b6SGordon Ross  * Called via SMB_IOC_CONFIG, for smbd startup or refresh.
582faa1795aSjb  */
583faa1795aSjb int
smb_server_configure(smb_server_t * sv,smb_ioc_cfg_t * ioc)584*34bbc83aSGordon Ross smb_server_configure(smb_server_t *sv, smb_ioc_cfg_t *ioc)
585faa1795aSjb {
586faa1795aSjb 	int		rc = 0;
587faa1795aSjb 
5881d443a93SDan McDonald 	/*
5891d443a93SDan McDonald 	 * Reality check negotiation token length vs. #define'd maximum.
5901d443a93SDan McDonald 	 */
5911d443a93SDan McDonald 	if (ioc->negtok_len > SMB_PI_MAX_NEGTOK)
5921d443a93SDan McDonald 		return (EINVAL);
5931d443a93SDan McDonald 
594faa1795aSjb 	mutex_enter(&sv->sv_mutex);
595faa1795aSjb 	switch (sv->sv_state) {
596faa1795aSjb 	case SMB_SERVER_STATE_CREATED:
59729bd2886SAlan Wright 		smb_server_store_cfg(sv, ioc);
598faa1795aSjb 		sv->sv_state = SMB_SERVER_STATE_CONFIGURED;
599faa1795aSjb 		break;
600faa1795aSjb 
601faa1795aSjb 	case SMB_SERVER_STATE_CONFIGURED:
60229bd2886SAlan Wright 		smb_server_store_cfg(sv, ioc);
603faa1795aSjb 		break;
604faa1795aSjb 
605faa1795aSjb 	case SMB_SERVER_STATE_RUNNING:
6069fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	case SMB_SERVER_STATE_STOPPING:
607faa1795aSjb 		rw_enter(&sv->sv_cfg_lock, RW_WRITER);
60829bd2886SAlan Wright 		smb_server_store_cfg(sv, ioc);
609faa1795aSjb 		rw_exit(&sv->sv_cfg_lock);
610faa1795aSjb 		break;
611faa1795aSjb 
612faa1795aSjb 	default:
6139fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_SERVER_STATE_VALID(sv->sv_state);
614faa1795aSjb 		rc = EFAULT;
615faa1795aSjb 		break;
616faa1795aSjb 	}
617faa1795aSjb 	mutex_exit(&sv->sv_mutex);
618faa1795aSjb 
619faa1795aSjb 	return (rc);
620faa1795aSjb }
621faa1795aSjb 
622faa1795aSjb /*
623faa1795aSjb  * smb_server_start
6245d8538b6SGordon Ross  *
6255d8538b6SGordon Ross  * Called via SMB_IOC_START during smbd startup.
6265d8538b6SGordon Ross  * Bring up the activities requried for SMB service.
627faa1795aSjb  */
628faa1795aSjb int
smb_server_start(smb_server_t * sv,smb_ioc_start_t * ioc)629*34bbc83aSGordon Ross smb_server_start(smb_server_t *sv, smb_ioc_start_t *ioc)
630faa1795aSjb {
631faa1795aSjb 	int		rc = 0;
6324163af6aSjose borrego 	int		family;
6338d94f651SGordon Ross 	cred_t		*ucr;
6345d8538b6SGordon Ross 	struct proc	*tqproc;
635faa1795aSjb 
636faa1795aSjb 	mutex_enter(&sv->sv_mutex);
637faa1795aSjb 	switch (sv->sv_state) {
638faa1795aSjb 	case SMB_SERVER_STATE_CONFIGURED:
639faa1795aSjb 
6405d8538b6SGordon Ross #ifdef	_KERNEL
6415d8538b6SGordon Ross 		if (smb_create_process) {
6425d8538b6SGordon Ross 			rc = smb_server_newproc(sv);
6435d8538b6SGordon Ross 			if (rc != 0)
6445d8538b6SGordon Ross 				break;
6455d8538b6SGordon Ross 		}
6465d8538b6SGordon Ross #endif	/* _KERNEL */
6475d8538b6SGordon Ross 
6488622ec45SGordon Ross 		if ((rc = smb_server_fsop_start(sv)) != 0)
6498622ec45SGordon Ross 			break;
6508622ec45SGordon Ross 
6518d94f651SGordon Ross 		/*
6528d94f651SGordon Ross 		 * Note: smb_kshare_start needs sv_session.
6538d94f651SGordon Ross 		 */
6548d94f651SGordon Ross 		sv->sv_session = smb_session_create(NULL, 0, sv, 0);
6558d94f651SGordon Ross 		if (sv->sv_session == NULL) {
6568d94f651SGordon Ross 			rc = ENOMEM;
6578d94f651SGordon Ross 			break;
6588d94f651SGordon Ross 		}
6598d94f651SGordon Ross 
6608d94f651SGordon Ross 		/*
6618d94f651SGordon Ross 		 * Create a logon on the server session,
6628d94f651SGordon Ross 		 * used when importing CA shares.
6638d94f651SGordon Ross 		 */
6648d94f651SGordon Ross 		sv->sv_rootuser = smb_user_new(sv->sv_session);
6658d94f651SGordon Ross 		ucr = smb_kcred_create();
6668d94f651SGordon Ross 		rc = smb_user_logon(sv->sv_rootuser, ucr, "", "root",
6678d94f651SGordon Ross 		    SMB_USER_FLAG_ADMIN, 0, 0);
6688d94f651SGordon Ross 		crfree(ucr);
6698d94f651SGordon Ross 		ucr = NULL;
6708d94f651SGordon Ross 		if (rc != 0) {
6718d94f651SGordon Ross 			cmn_err(CE_NOTE, "smb_server_start: "
6728d94f651SGordon Ross 			    "failed to create root user");
6738d94f651SGordon Ross 			break;
6748d94f651SGordon Ross 		}
6758d94f651SGordon Ross 
6768622ec45SGordon Ross 		if ((rc = smb_kshare_start(sv)) != 0)
6778622ec45SGordon Ross 			break;
6788622ec45SGordon Ross 
679b819cea2SGordon Ross 		/*
680e515d096SGordon Ross 		 * Create our taskq's (thread pools)
681e515d096SGordon Ross 		 *
682b819cea2SGordon Ross 		 * NB: the proc passed here has to be a "system" one.
683b819cea2SGordon Ross 		 * Normally that's p0, or the NGZ eqivalent.
684e515d096SGordon Ross 		 *
685e515d096SGordon Ross 		 * The notify pool is sized at a quarter the number of
686e515d096SGordon Ross 		 * worker threads (instead of another config item).
687b819cea2SGordon Ross 		 */
6885d8538b6SGordon Ross 		tqproc = (sv->sv_proc_p != NULL) ?
6895d8538b6SGordon Ross 		    sv->sv_proc_p : curzone->zone_zsched;
6905d8538b6SGordon Ross 
691e515d096SGordon Ross 		sv->sv_notify_pool = taskq_create_proc("smb_notify",
692e515d096SGordon Ross 		    sv->sv_cfg.skc_maxworkers / 4, smbsrv_notify_pri,
693e515d096SGordon Ross 		    sv->sv_cfg.skc_maxworkers / 4, INT_MAX,
694a02a2451SGordon Ross 		    tqproc, TASKQ_DYNAMIC|TASKQ_THREADS_LWP);
695e515d096SGordon Ross 
6968622ec45SGordon Ross 		sv->sv_worker_pool = taskq_create_proc("smb_workers",
69708344b29SGordon Ross 		    sv->sv_cfg.skc_maxworkers, smbsrv_worker_pri,
698faa1795aSjb 		    sv->sv_cfg.skc_maxworkers, INT_MAX,
699a02a2451SGordon Ross 		    tqproc, TASKQ_DYNAMIC|TASKQ_THREADS_LWP);
700faa1795aSjb 
7018622ec45SGordon Ross 		sv->sv_receiver_pool = taskq_create_proc("smb_receivers",
70208344b29SGordon Ross 		    sv->sv_cfg.skc_maxconnections, smbsrv_receive_pri,
7034163af6aSjose borrego 		    sv->sv_cfg.skc_maxconnections, INT_MAX,
704a02a2451SGordon Ross 		    tqproc, TASKQ_DYNAMIC|TASKQ_THREADS_LWP);
7054163af6aSjose borrego 
706e515d096SGordon Ross 		if (sv->sv_notify_pool == NULL ||
707e515d096SGordon Ross 		    sv->sv_worker_pool == NULL ||
7088d94f651SGordon Ross 		    sv->sv_receiver_pool == NULL) {
709faa1795aSjb 			rc = ENOMEM;
710faa1795aSjb 			break;
711faa1795aSjb 		}
712faa1795aSjb 
713b819cea2SGordon Ross #ifdef	_KERNEL
714faa1795aSjb 		ASSERT(sv->sv_lmshrd == NULL);
715148c5f43SAlan Wright 		sv->sv_lmshrd = smb_kshare_door_init(ioc->lmshrd);
716faa1795aSjb 		if (sv->sv_lmshrd == NULL)
717faa1795aSjb 			break;
71854026d5aSGordon Ross 		if ((rc = smb_kdoor_open(sv, ioc->udoor)) != 0) {
7199fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			cmn_err(CE_WARN, "Cannot open smbd door");
7202c1b14e5Sjose borrego 			break;
7219fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		}
722b819cea2SGordon Ross #else	/* _KERNEL */
723b819cea2SGordon Ross 		/* Fake kernel does not use the kshare_door */
724b819cea2SGordon Ross 		fksmb_kdoor_open(sv, ioc->udoor_func);
725b819cea2SGordon Ross #endif	/* _KERNEL */
726b819cea2SGordon Ross 
72754026d5aSGordon Ross 		if ((rc = smb_thread_start(&sv->si_thread_timers)) != 0)
7289fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			break;
7294163af6aSjose borrego 
7304163af6aSjose borrego 		family = AF_INET;
7314163af6aSjose borrego 		smb_server_listener_init(sv, &sv->sv_nbt_daemon,
7324163af6aSjose borrego 		    "smb_nbt_listener", IPPORT_NETBIOS_SSN, family);
7334163af6aSjose borrego 		if (sv->sv_cfg.skc_ipv6_enable)
7344163af6aSjose borrego 			family = AF_INET6;
7354163af6aSjose borrego 		smb_server_listener_init(sv, &sv->sv_tcp_daemon,
7364163af6aSjose borrego 		    "smb_tcp_listener", IPPORT_SMB, family);
7374163af6aSjose borrego 		rc = smb_server_listener_start(&sv->sv_tcp_daemon);
7384163af6aSjose borrego 		if (rc != 0)
7394163af6aSjose borrego 			break;
74083d2dfe6SGordon Ross 		if (sv->sv_cfg.skc_netbios_enable)
74183d2dfe6SGordon Ross 			(void) smb_server_listener_start(&sv->sv_nbt_daemon);
7424163af6aSjose borrego 
743faa1795aSjb 		sv->sv_state = SMB_SERVER_STATE_RUNNING;
744148c5f43SAlan Wright 		sv->sv_start_time = gethrtime();
745faa1795aSjb 		mutex_exit(&sv->sv_mutex);
7468622ec45SGordon Ross 		smb_export_start(sv);
747faa1795aSjb 		return (0);
748faa1795aSjb 	default:
7499fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_SERVER_STATE_VALID(sv->sv_state);
750faa1795aSjb 		mutex_exit(&sv->sv_mutex);
751faa1795aSjb 		return (ENOTTY);
752faa1795aSjb 	}
753faa1795aSjb 
7549fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_exit(&sv->sv_mutex);
7554163af6aSjose borrego 	smb_server_shutdown(sv);
7569fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	return (rc);
7579fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
7589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
7609fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * An smbd is shutting down.
7619fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  */
7629fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States int
smb_server_stop(smb_server_t * sv)763*34bbc83aSGordon Ross smb_server_stop(smb_server_t *sv)
7649fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
7659fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7669fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_enter(&sv->sv_mutex);
7679fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	switch (sv->sv_state) {
7689fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	case SMB_SERVER_STATE_RUNNING:
7699fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		sv->sv_state = SMB_SERVER_STATE_STOPPING;
7704163af6aSjose borrego 		mutex_exit(&sv->sv_mutex);
7714163af6aSjose borrego 		smb_server_shutdown(sv);
7724163af6aSjose borrego 		mutex_enter(&sv->sv_mutex);
773cb174861Sjoyce mcintosh 		cv_broadcast(&sv->sp_info.sp_cv);
7749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		break;
7759fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	default:
7769fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_SERVER_STATE_VALID(sv->sv_state);
7779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		break;
7789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
7799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_exit(&sv->sv_mutex);
7809fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	return (0);
7829fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
7839fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7849fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States boolean_t
smb_server_is_stopping(smb_server_t * sv)7858622ec45SGordon Ross smb_server_is_stopping(smb_server_t *sv)
7869fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
7879fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	boolean_t	status;
7889fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7899fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	SMB_SERVER_VALID(sv);
7909fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7919fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_enter(&sv->sv_mutex);
7929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	switch (sv->sv_state) {
7949fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	case SMB_SERVER_STATE_STOPPING:
7959fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	case SMB_SERVER_STATE_DELETING:
7969fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		status = B_TRUE;
7979fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		break;
7989fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	default:
7999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		status = B_FALSE;
8009fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		break;
8019fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
8029fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
803faa1795aSjb 	mutex_exit(&sv->sv_mutex);
8049fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	return (status);
8059fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
8069fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
8078622ec45SGordon Ross void
smb_server_cancel_event(smb_server_t * sv,uint32_t txid)8088622ec45SGordon Ross smb_server_cancel_event(smb_server_t *sv, uint32_t txid)
8099fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
8108622ec45SGordon Ross 	smb_event_cancel(sv, txid);
8119fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
8129fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
8139fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States int
smb_server_notify_event(smb_server_t * sv,smb_ioc_event_t * ioc)814*34bbc83aSGordon Ross smb_server_notify_event(smb_server_t *sv, smb_ioc_event_t *ioc)
8159fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
8169fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
817*34bbc83aSGordon Ross 	smb_event_notify(sv, ioc->txid);
8189fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
819*34bbc83aSGordon Ross 	return (0);
820faa1795aSjb }
821faa1795aSjb 
822cb174861Sjoyce mcintosh /*
823cb174861Sjoyce mcintosh  * smb_server_spooldoc
824cb174861Sjoyce mcintosh  *
825cb174861Sjoyce mcintosh  * Waits for print file close broadcast.
826cb174861Sjoyce mcintosh  * Gets the head of the fid list,
827cb174861Sjoyce mcintosh  * then searches the spooldoc list and returns
828cb174861Sjoyce mcintosh  * this info via the ioctl to user land.
829cb174861Sjoyce mcintosh  *
830cb174861Sjoyce mcintosh  * rc - 0 success
831cb174861Sjoyce mcintosh  */
832cb174861Sjoyce mcintosh int
smb_server_spooldoc(smb_server_t * sv,smb_ioc_spooldoc_t * ioc)833*34bbc83aSGordon Ross smb_server_spooldoc(smb_server_t *sv, smb_ioc_spooldoc_t *ioc)
834cb174861Sjoyce mcintosh {
835*34bbc83aSGordon Ross 	int		rc = 0;
836cb174861Sjoyce mcintosh 	smb_kspooldoc_t *spdoc;
837cb174861Sjoyce mcintosh 	uint16_t	fid;
838cb174861Sjoyce mcintosh 
839b7301bf5SGordon Ross 	if (sv->sv_cfg.skc_print_enable == 0) {
840b7301bf5SGordon Ross 		rc = ENOTTY;
841b7301bf5SGordon Ross 		goto out;
842b7301bf5SGordon Ross 	}
843b7301bf5SGordon Ross 
84423a9c295SGordon Ross 	mutex_enter(&sv->sv_mutex);
84523a9c295SGordon Ross 	for (;;) {
846cb174861Sjoyce mcintosh 		if (sv->sv_state != SMB_SERVER_STATE_RUNNING) {
847cb174861Sjoyce mcintosh 			rc = ECANCELED;
84823a9c295SGordon Ross 			break;
84923a9c295SGordon Ross 		}
85023a9c295SGordon Ross 		if ((fid = smb_spool_get_fid(sv)) != 0) {
85123a9c295SGordon Ross 			rc = 0;
85223a9c295SGordon Ross 			break;
85323a9c295SGordon Ross 		}
85423a9c295SGordon Ross 		if (cv_wait_sig(&sv->sp_info.sp_cv, &sv->sv_mutex) == 0) {
85523a9c295SGordon Ross 			rc = EINTR;
85623a9c295SGordon Ross 			break;
857cb174861Sjoyce mcintosh 		}
858cb174861Sjoyce mcintosh 	}
85923a9c295SGordon Ross 	mutex_exit(&sv->sv_mutex);
860b7301bf5SGordon Ross 	if (rc != 0)
861b7301bf5SGordon Ross 		goto out;
862b7301bf5SGordon Ross 
863b7301bf5SGordon Ross 	spdoc = kmem_zalloc(sizeof (*spdoc), KM_SLEEP);
864b7301bf5SGordon Ross 	if (smb_spool_lookup_doc_byfid(sv, fid, spdoc)) {
865b7301bf5SGordon Ross 		ioc->spool_num = spdoc->sd_spool_num;
866b7301bf5SGordon Ross 		ioc->ipaddr = spdoc->sd_ipaddr;
867b7301bf5SGordon Ross 		(void) strlcpy(ioc->path, spdoc->sd_path,
868b7301bf5SGordon Ross 		    MAXPATHLEN);
869b7301bf5SGordon Ross 		(void) strlcpy(ioc->username,
870b7301bf5SGordon Ross 		    spdoc->sd_username, MAXNAMELEN);
871b7301bf5SGordon Ross 	} else {
872b7301bf5SGordon Ross 		/* Did not find that print job. */
873b7301bf5SGordon Ross 		rc = EAGAIN;
87423a9c295SGordon Ross 	}
875b7301bf5SGordon Ross 	kmem_free(spdoc, sizeof (*spdoc));
87623a9c295SGordon Ross 
877b7301bf5SGordon Ross out:
878cb174861Sjoyce mcintosh 	return (rc);
879cb174861Sjoyce mcintosh }
880cb174861Sjoyce mcintosh 
881faa1795aSjb int
smb_server_set_gmtoff(smb_server_t * sv,smb_ioc_gmt_t * ioc)882*34bbc83aSGordon Ross smb_server_set_gmtoff(smb_server_t *sv, smb_ioc_gmt_t *ioc)
883faa1795aSjb {
884faa1795aSjb 
885*34bbc83aSGordon Ross 	sv->si_gmtoff = ioc->offset;
886faa1795aSjb 
887*34bbc83aSGordon Ross 	return (0);
888faa1795aSjb }
889faa1795aSjb 
89029bd2886SAlan Wright int
smb_server_numopen(smb_server_t * sv,smb_ioc_opennum_t * ioc)891*34bbc83aSGordon Ross smb_server_numopen(smb_server_t *sv, smb_ioc_opennum_t *ioc)
89229bd2886SAlan Wright {
89329bd2886SAlan Wright 
894*34bbc83aSGordon Ross 	ioc->open_users = sv->sv_users;
895*34bbc83aSGordon Ross 	ioc->open_trees = sv->sv_trees;
896*34bbc83aSGordon Ross 	ioc->open_files = sv->sv_files + sv->sv_pipes;
897*34bbc83aSGordon Ross 
898*34bbc83aSGordon Ross 	return (0);
89929bd2886SAlan Wright }
90029bd2886SAlan Wright 
9011fcced4cSJordan Brown /*
9021fcced4cSJordan Brown  * Enumerate objects within the server.  The svcenum provides the
9031fcced4cSJordan Brown  * enumeration context, i.e. what the caller want to get back.
9041fcced4cSJordan Brown  */
90529bd2886SAlan Wright int
smb_server_enum(smb_server_t * sv,smb_ioc_svcenum_t * ioc)906*34bbc83aSGordon Ross smb_server_enum(smb_server_t *sv, smb_ioc_svcenum_t *ioc)
90729bd2886SAlan Wright {
9084163af6aSjose borrego 	smb_svcenum_t	*svcenum = &ioc->svcenum;
909*34bbc83aSGordon Ross 	int		rc = 0;
91029bd2886SAlan Wright 
9111d443a93SDan McDonald 	/*
9121d443a93SDan McDonald 	 * Reality check that the buffer-length insize the enum doesn't
9131d443a93SDan McDonald 	 * overrun the ioctl's total length.
9141d443a93SDan McDonald 	 */
9151d443a93SDan McDonald 	if (svcenum->se_buflen + sizeof (*ioc) > ioc->hdr.len)
9161d443a93SDan McDonald 		return (EINVAL);
9171d443a93SDan McDonald 
9181fcced4cSJordan Brown 	svcenum->se_bavail = svcenum->se_buflen;
9191fcced4cSJordan Brown 	svcenum->se_bused = 0;
9201fcced4cSJordan Brown 	svcenum->se_nitems = 0;
92129bd2886SAlan Wright 
9223b13a1efSThomas Keiser 	switch (svcenum->se_type) {
9233b13a1efSThomas Keiser 	case SMB_SVCENUM_TYPE_USER:
9248d94f651SGordon Ross 		smb_server_enum_users(sv, svcenum);
9253b13a1efSThomas Keiser 		break;
9263b13a1efSThomas Keiser 	case SMB_SVCENUM_TYPE_TREE:
9273b13a1efSThomas Keiser 	case SMB_SVCENUM_TYPE_FILE:
9288d94f651SGordon Ross 		smb_server_enum_trees(sv, svcenum);
9293b13a1efSThomas Keiser 		break;
9303b13a1efSThomas Keiser 	default:
9313b13a1efSThomas Keiser 		rc = EINVAL;
9323b13a1efSThomas Keiser 	}
93329bd2886SAlan Wright 
9343b13a1efSThomas Keiser 	return (rc);
93529bd2886SAlan Wright }
93629bd2886SAlan Wright 
937faa1795aSjb /*
9381fcced4cSJordan Brown  * Look for sessions to disconnect by client and user name.
939faa1795aSjb  */
9401fcced4cSJordan Brown int
smb_server_session_close(smb_server_t * sv,smb_ioc_session_t * ioc)941*34bbc83aSGordon Ross smb_server_session_close(smb_server_t *sv, smb_ioc_session_t *ioc)
9421fcced4cSJordan Brown {
943811599a4SMatt Barden 	int		cnt;
9441fcced4cSJordan Brown 
9458d94f651SGordon Ross 	cnt = smb_server_session_disconnect(sv, ioc->client, ioc->username);
9461fcced4cSJordan Brown 
947811599a4SMatt Barden 	if (cnt == 0)
9481fcced4cSJordan Brown 		return (ENOENT);
9491fcced4cSJordan Brown 	return (0);
9501fcced4cSJordan Brown }
9511fcced4cSJordan Brown 
9521fcced4cSJordan Brown /*
9531fcced4cSJordan Brown  * Close a file by uniqid.
9541fcced4cSJordan Brown  */
9551fcced4cSJordan Brown int
smb_server_file_close(smb_server_t * sv,smb_ioc_fileid_t * ioc)956*34bbc83aSGordon Ross smb_server_file_close(smb_server_t *sv, smb_ioc_fileid_t *ioc)
957faa1795aSjb {
9584163af6aSjose borrego 	uint32_t	uniqid = ioc->uniqid;
9594163af6aSjose borrego 	int		rc;
960faa1795aSjb 
9618d94f651SGordon Ross 	rc = smb_server_fclose(sv, uniqid);
9621fcced4cSJordan Brown 	return (rc);
963faa1795aSjb }
964faa1795aSjb 
9651fcced4cSJordan Brown /*
9661fcced4cSJordan Brown  * These functions determine the relevant smb server to which the call apply.
9671fcced4cSJordan Brown  */
9681fcced4cSJordan Brown 
969faa1795aSjb uint32_t
smb_server_get_session_count(smb_server_t * sv)9708622ec45SGordon Ross smb_server_get_session_count(smb_server_t *sv)
971faa1795aSjb {
972faa1795aSjb 	uint32_t	counter = 0;
973faa1795aSjb 
974811599a4SMatt Barden 	counter = smb_llist_get_count(&sv->sv_session_list);
975faa1795aSjb 
976faa1795aSjb 	return (counter);
977faa1795aSjb }
978faa1795aSjb 
979faa1795aSjb /*
9808d94f651SGordon Ross  * Gets the smb_node of the specified share path.
9818d94f651SGordon Ross  * Node is returned held (caller must rele.)
982faa1795aSjb  */
983faa1795aSjb int
smb_server_share_lookup(smb_server_t * sv,const char * shr_path,smb_node_t ** nodepp)9848d94f651SGordon Ross smb_server_share_lookup(smb_server_t *sv, const char *shr_path,
9858d94f651SGordon Ross     smb_node_t **nodepp)
986faa1795aSjb {
987148c5f43SAlan Wright 	smb_request_t	*sr;
988faa1795aSjb 	smb_node_t	*fnode = NULL;
9898d94f651SGordon Ross 	smb_node_t	*dnode = NULL;
990faa1795aSjb 	char		last_comp[MAXNAMELEN];
991148c5f43SAlan Wright 	int		rc = 0;
992faa1795aSjb 
993148c5f43SAlan Wright 	ASSERT(shr_path);
994148c5f43SAlan Wright 
99529bd2886SAlan Wright 	mutex_enter(&sv->sv_mutex);
99629bd2886SAlan Wright 	switch (sv->sv_state) {
99729bd2886SAlan Wright 	case SMB_SERVER_STATE_RUNNING:
99829bd2886SAlan Wright 		break;
99929bd2886SAlan Wright 	default:
100029bd2886SAlan Wright 		mutex_exit(&sv->sv_mutex);
100129bd2886SAlan Wright 		return (ENOTACTIVE);
100229bd2886SAlan Wright 	}
100329bd2886SAlan Wright 	mutex_exit(&sv->sv_mutex);
100429bd2886SAlan Wright 
1005148c5f43SAlan Wright 	if ((sr = smb_request_alloc(sv->sv_session, 0)) == NULL) {
1006811599a4SMatt Barden 		return (ENOTCONN);
1007faa1795aSjb 	}
10088622ec45SGordon Ross 	sr->user_cr = zone_kcred();
1009faa1795aSjb 
1010148c5f43SAlan Wright 	rc = smb_pathname_reduce(sr, sr->user_cr, shr_path,
101129bd2886SAlan Wright 	    NULL, NULL, &dnode, last_comp);
1012faa1795aSjb 
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);
1017faa1795aSjb 	}
1018faa1795aSjb 
1019148c5f43SAlan Wright 	smb_request_free(sr);
1020faa1795aSjb 
1021148c5f43SAlan Wright 	if (rc != 0)
1022148c5f43SAlan Wright 		return (rc);
1023faa1795aSjb 
1024faa1795aSjb 	ASSERT(fnode->vp && fnode->vp->v_vfsp);
1025faa1795aSjb 
10268d94f651SGordon Ross 	*nodepp = fnode;
1027148c5f43SAlan Wright 
1028148c5f43SAlan Wright 	return (0);
1029faa1795aSjb }
1030faa1795aSjb 
1031b819cea2SGordon Ross #ifdef	_KERNEL
1032faa1795aSjb /*
1033148c5f43SAlan Wright  * This is a special interface that will be utilized by ZFS to cause a share to
1034148c5f43SAlan Wright  * be added/removed.
1035faa1795aSjb  *
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.
1039faa1795aSjb  */
1040faa1795aSjb int
smb_server_share(void * arg,boolean_t add_share)1041148c5f43SAlan Wright smb_server_share(void *arg, boolean_t add_share)
1042faa1795aSjb {
1043faa1795aSjb 	smb_server_t	*sv;
10442c1b14e5Sjose borrego 	int		rc;
1045faa1795aSjb 
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
smb_server_unshare(const char * sharename)1065148c5f43SAlan Wright smb_server_unshare(const char *sharename)
1066148c5f43SAlan Wright {
10674163af6aSjose borrego 	smb_server_t	*sv;
10684163af6aSjose borrego 	int		rc;
1069148c5f43SAlan Wright 
10702c1b14e5Sjose borrego 	if ((rc = smb_server_lookup(&sv)))
10712c1b14e5Sjose borrego 		return (rc);
1072faa1795aSjb 
107329bd2886SAlan Wright 	mutex_enter(&sv->sv_mutex);
107429bd2886SAlan Wright 	switch (sv->sv_state) {
107529bd2886SAlan Wright 	case SMB_SERVER_STATE_RUNNING:
10769fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	case SMB_SERVER_STATE_STOPPING:
107729bd2886SAlan Wright 		break;
107829bd2886SAlan Wright 	default:
107929bd2886SAlan Wright 		mutex_exit(&sv->sv_mutex);
1080148c5f43SAlan Wright 		smb_server_release(sv);
108129bd2886SAlan Wright 		return (ENOTACTIVE);
108229bd2886SAlan Wright 	}
108329bd2886SAlan Wright 	mutex_exit(&sv->sv_mutex);
108429bd2886SAlan Wright 
10858d94f651SGordon Ross 	smb_server_disconnect_share(sv, sharename);
10862c1b14e5Sjose borrego 
1087faa1795aSjb 	smb_server_release(sv);
1088faa1795aSjb 	return (0);
1089faa1795aSjb }
1090faa1795aSjb 
10912c1b14e5Sjose borrego /*
1092148c5f43SAlan Wright  * Disconnect the specified share.
1093148c5f43SAlan Wright  * Typically called when a share has been removed.
10942c1b14e5Sjose borrego  */
10952c1b14e5Sjose borrego static void
smb_server_disconnect_share(smb_server_t * sv,const char * sharename)10968d94f651SGordon Ross smb_server_disconnect_share(smb_server_t *sv, const char *sharename)
10972c1b14e5Sjose borrego {
10988d94f651SGordon Ross 	smb_llist_t	*ll;
10994163af6aSjose borrego 	smb_session_t	*session;
11002c1b14e5Sjose borrego 
11018d94f651SGordon Ross 	ll = &sv->sv_session_list;
11024163af6aSjose borrego 	smb_llist_enter(ll, RW_READER);
1103faa1795aSjb 
11044163af6aSjose borrego 	session = smb_llist_head(ll);
1105148c5f43SAlan Wright 	while (session) {
11064163af6aSjose borrego 		SMB_SESSION_VALID(session);
1107148c5f43SAlan Wright 		smb_rwx_rwenter(&session->s_lock, RW_READER);
1108148c5f43SAlan Wright 		switch (session->s_state) {
1109148c5f43SAlan Wright 		case SMB_SESSION_STATE_NEGOTIATED:
1110811599a4SMatt Barden 			smb_rwx_rwexit(&session->s_lock);
1111148c5f43SAlan Wright 			smb_session_disconnect_share(session, sharename);
111229bd2886SAlan Wright 			break;
111329bd2886SAlan Wright 		default:
1114811599a4SMatt Barden 			smb_rwx_rwexit(&session->s_lock);
111529bd2886SAlan Wright 			break;
1116faa1795aSjb 		}
11174163af6aSjose borrego 		session = smb_llist_next(ll, session);
1118faa1795aSjb 	}
1119148c5f43SAlan Wright 
11204163af6aSjose borrego 	smb_llist_exit(ll);
1121faa1795aSjb }
1122faa1795aSjb 
11235d8538b6SGordon Ross #ifdef	_KERNEL
11245d8538b6SGordon Ross 
11255d8538b6SGordon Ross /*
11267957766eSGordon Ross  * Create a process to own SMB server threads (like zfs spa.c)
11277957766eSGordon Ross  * so we can see the CPU usage etc. with "prstat -L".
11287957766eSGordon Ross  * The new process MUST be in the same zone as the caller.
11295d8538b6SGordon Ross  */
11305d8538b6SGordon Ross static int
smb_server_newproc(smb_server_t * sv)11315d8538b6SGordon Ross smb_server_newproc(smb_server_t *sv)
11325d8538b6SGordon Ross {
11335d8538b6SGordon Ross 	int rc;
11345d8538b6SGordon Ross 
11357957766eSGordon Ross 	/*
11367957766eSGordon Ross 	 * Todo: Fix newproc() for zones.
11377957766eSGordon Ross 	 * At present, it always creates in p0.
11387957766eSGordon Ross 	 * For now, only do this for the global zone.
11397957766eSGordon Ross 	 */
11407957766eSGordon Ross 	if (getzoneid() != GLOBAL_ZONEID)
11417957766eSGordon Ross 		return (0);
11427957766eSGordon Ross 
11435d8538b6SGordon Ross 	mutex_enter(&sv->sv_proc_lock);
11445d8538b6SGordon Ross 	if (sv->sv_proc_p != NULL) {
11455d8538b6SGordon Ross 		/* restart? re-use proc */
11465d8538b6SGordon Ross 		rc = 0;
11475d8538b6SGordon Ross 		goto out;
11485d8538b6SGordon Ross 	}
11495d8538b6SGordon Ross 
11505d8538b6SGordon Ross 	sv->sv_proc_state = SMB_THREAD_STATE_STARTING;
11515d8538b6SGordon Ross 	rc = newproc(smb_server_proc_main, (caddr_t)sv,
11525d8538b6SGordon Ross 	    syscid, smbsrv_base_pri, NULL, 0);
11535d8538b6SGordon Ross 	if (rc != 0) {
11545d8538b6SGordon Ross 		cmn_err(CE_WARN, "newproc failed, rc=%d", rc);
11555d8538b6SGordon Ross 		goto out;
11565d8538b6SGordon Ross 	}
11575d8538b6SGordon Ross 
11585d8538b6SGordon Ross 	/* Rendez-vous with new proc thread. */
11595d8538b6SGordon Ross 	while (sv->sv_proc_state == SMB_THREAD_STATE_STARTING) {
11605d8538b6SGordon Ross 		cv_wait(&sv->sv_proc_cv, &sv->sv_proc_lock);
11615d8538b6SGordon Ross 
11625d8538b6SGordon Ross 	}
11635d8538b6SGordon Ross 	if (sv->sv_proc_state != SMB_THREAD_STATE_RUNNING) {
11645d8538b6SGordon Ross 		rc = ESRCH;
11655d8538b6SGordon Ross 		goto out;
11665d8538b6SGordon Ross 	}
11675d8538b6SGordon Ross 	ASSERT(sv->sv_proc_p != NULL);
11685d8538b6SGordon Ross 
11695d8538b6SGordon Ross out:
11705d8538b6SGordon Ross 	mutex_exit(&sv->sv_proc_lock);
11715d8538b6SGordon Ross 	return (rc);
11725d8538b6SGordon Ross }
11735d8538b6SGordon Ross 
11745d8538b6SGordon Ross /*
11755d8538b6SGordon Ross  * Main thread for the process we create to own SMB server threads.
11765d8538b6SGordon Ross  */
11775d8538b6SGordon Ross static void
smb_server_proc_main(void * arg)11785d8538b6SGordon Ross smb_server_proc_main(void *arg)
11795d8538b6SGordon Ross {
11805d8538b6SGordon Ross 	callb_cpr_t	cprinfo;
11815d8538b6SGordon Ross 	smb_server_t	*sv = arg;
11825d8538b6SGordon Ross 	user_t		*pu = PTOU(curproc);
11835d8538b6SGordon Ross 	zoneid_t	zid = getzoneid();
11845d8538b6SGordon Ross 
11855d8538b6SGordon Ross 	ASSERT(curproc != &p0);
11865d8538b6SGordon Ross 	ASSERT(zid == sv->sv_zid);
11875d8538b6SGordon Ross 
11885d8538b6SGordon Ross 	(void) strlcpy(pu->u_comm, "smbsrv", sizeof (pu->u_comm));
11895d8538b6SGordon Ross 	(void) snprintf(pu->u_psargs, sizeof (pu->u_psargs),
11905d8538b6SGordon Ross 	    "smbsrv %d", (int)zid);
11915d8538b6SGordon Ross 
11925d8538b6SGordon Ross 	CALLB_CPR_INIT(&cprinfo, &sv->sv_proc_lock, callb_generic_cpr,
11935d8538b6SGordon Ross 	    pu->u_psargs);
11945d8538b6SGordon Ross 
11955d8538b6SGordon Ross 	mutex_enter(&sv->sv_proc_lock);
11965d8538b6SGordon Ross 	ASSERT(sv->sv_proc_state == SMB_THREAD_STATE_STARTING);
11975d8538b6SGordon Ross 
11985d8538b6SGordon Ross 	sv->sv_proc_p = curproc;
11995d8538b6SGordon Ross 	sv->sv_proc_did = curthread->t_did;
12005d8538b6SGordon Ross 
12015d8538b6SGordon Ross 	sv->sv_proc_state = SMB_THREAD_STATE_RUNNING;
12025d8538b6SGordon Ross 	cv_broadcast(&sv->sv_proc_cv);
12035d8538b6SGordon Ross 
12045d8538b6SGordon Ross 	CALLB_CPR_SAFE_BEGIN(&cprinfo);
12055d8538b6SGordon Ross 	while (sv->sv_proc_state == SMB_THREAD_STATE_RUNNING)
12065d8538b6SGordon Ross 		cv_wait(&sv->sv_proc_cv, &sv->sv_proc_lock);
12075d8538b6SGordon Ross 	CALLB_CPR_SAFE_END(&cprinfo, &sv->sv_proc_lock);
12085d8538b6SGordon Ross 
12095d8538b6SGordon Ross 	ASSERT(sv->sv_proc_state == SMB_THREAD_STATE_EXITING);
12105d8538b6SGordon Ross 	sv->sv_proc_state = SMB_THREAD_STATE_EXITED;
12115d8538b6SGordon Ross 	sv->sv_proc_p = NULL;
12125d8538b6SGordon Ross 	cv_broadcast(&sv->sv_proc_cv);
12135d8538b6SGordon Ross 	CALLB_CPR_EXIT(&cprinfo);	/* mutex_exit sv_proc_lock */
12145d8538b6SGordon Ross 
12155d8538b6SGordon Ross 	/* Note: lwp_exit() expects p_lock entered. */
12165d8538b6SGordon Ross 	mutex_enter(&curproc->p_lock);
12175d8538b6SGordon Ross 	lwp_exit();
12185d8538b6SGordon Ross }
12195d8538b6SGordon Ross 
12205d8538b6SGordon Ross /*
12215d8538b6SGordon Ross  * Delete the server proc (if any)
12225d8538b6SGordon Ross  */
12235d8538b6SGordon Ross static void
smb_server_delproc(smb_server_t * sv)12245d8538b6SGordon Ross smb_server_delproc(smb_server_t *sv)
12255d8538b6SGordon Ross {
12265d8538b6SGordon Ross 
12275d8538b6SGordon Ross 	mutex_enter(&sv->sv_proc_lock);
12285d8538b6SGordon Ross 
12295d8538b6SGordon Ross 	if (sv->sv_proc_state != SMB_THREAD_STATE_RUNNING)
12305d8538b6SGordon Ross 		goto out;
12315d8538b6SGordon Ross 	ASSERT(sv->sv_proc_p != NULL);
12325d8538b6SGordon Ross 
12335d8538b6SGordon Ross 	sv->sv_proc_state = SMB_THREAD_STATE_EXITING;
12345d8538b6SGordon Ross 	cv_broadcast(&sv->sv_proc_cv);
12355d8538b6SGordon Ross 
12365d8538b6SGordon Ross 	/* Rendez-vous with proc thread. */
12375d8538b6SGordon Ross 	while (sv->sv_proc_state == SMB_THREAD_STATE_EXITING) {
12385d8538b6SGordon Ross 		cv_wait(&sv->sv_proc_cv, &sv->sv_proc_lock);
12395d8538b6SGordon Ross 
12405d8538b6SGordon Ross 	}
12415d8538b6SGordon Ross 	if (sv->sv_proc_state != SMB_THREAD_STATE_EXITED) {
12425d8538b6SGordon Ross 		cmn_err(CE_WARN, "smb_server_delproc, state=%d",
12435d8538b6SGordon Ross 		    sv->sv_proc_state);
12445d8538b6SGordon Ross 		goto out;
12455d8538b6SGordon Ross 	}
12465d8538b6SGordon Ross 	if (sv->sv_proc_did != 0) {
12475d8538b6SGordon Ross 		thread_join(sv->sv_proc_did);
12485d8538b6SGordon Ross 		sv->sv_proc_did = 0;
12495d8538b6SGordon Ross 	}
12505d8538b6SGordon Ross 
12515d8538b6SGordon Ross out:
12525d8538b6SGordon Ross 	mutex_exit(&sv->sv_proc_lock);
12535d8538b6SGordon Ross }
12545d8538b6SGordon Ross 
12555d8538b6SGordon Ross #endif	/* _KERNEL */
12565d8538b6SGordon Ross 
1257faa1795aSjb /*
1258faa1795aSjb  * *****************************************************************************
1259faa1795aSjb  * **************** Functions called from the internal layers ******************
1260faa1795aSjb  * *****************************************************************************
1261faa1795aSjb  *
1262faa1795aSjb  * These functions are provided the relevant smb server by the caller.
1263faa1795aSjb  */
1264faa1795aSjb 
1265faa1795aSjb void
smb_server_get_cfg(smb_server_t * sv,smb_kmod_cfg_t * cfg)1266faa1795aSjb smb_server_get_cfg(smb_server_t *sv, smb_kmod_cfg_t *cfg)
1267faa1795aSjb {
1268faa1795aSjb 	rw_enter(&sv->sv_cfg_lock, RW_READER);
1269faa1795aSjb 	bcopy(&sv->sv_cfg, cfg, sizeof (*cfg));
1270faa1795aSjb 	rw_exit(&sv->sv_cfg_lock);
1271faa1795aSjb }
1272faa1795aSjb 
1273148c5f43SAlan Wright /*
1274148c5f43SAlan Wright  *
1275148c5f43SAlan Wright  */
1276148c5f43SAlan Wright void
smb_server_inc_nbt_sess(smb_server_t * sv)1277148c5f43SAlan Wright smb_server_inc_nbt_sess(smb_server_t *sv)
1278148c5f43SAlan Wright {
1279148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1280148c5f43SAlan Wright 	atomic_inc_32(&sv->sv_nbt_sess);
1281148c5f43SAlan Wright }
1282148c5f43SAlan Wright 
1283148c5f43SAlan Wright void
smb_server_dec_nbt_sess(smb_server_t * sv)1284148c5f43SAlan Wright smb_server_dec_nbt_sess(smb_server_t *sv)
1285148c5f43SAlan Wright {
1286148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1287148c5f43SAlan Wright 	atomic_dec_32(&sv->sv_nbt_sess);
1288148c5f43SAlan Wright }
1289148c5f43SAlan Wright 
1290148c5f43SAlan Wright void
smb_server_inc_tcp_sess(smb_server_t * sv)1291148c5f43SAlan Wright smb_server_inc_tcp_sess(smb_server_t *sv)
1292148c5f43SAlan Wright {
1293148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1294148c5f43SAlan Wright 	atomic_inc_32(&sv->sv_tcp_sess);
1295148c5f43SAlan Wright }
1296148c5f43SAlan Wright 
1297148c5f43SAlan Wright void
smb_server_dec_tcp_sess(smb_server_t * sv)1298148c5f43SAlan Wright smb_server_dec_tcp_sess(smb_server_t *sv)
1299148c5f43SAlan Wright {
1300148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1301148c5f43SAlan Wright 	atomic_dec_32(&sv->sv_tcp_sess);
1302148c5f43SAlan Wright }
1303148c5f43SAlan Wright 
1304148c5f43SAlan Wright void
smb_server_inc_users(smb_server_t * sv)1305148c5f43SAlan Wright smb_server_inc_users(smb_server_t *sv)
1306148c5f43SAlan Wright {
1307148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1308148c5f43SAlan Wright 	atomic_inc_32(&sv->sv_users);
1309148c5f43SAlan Wright }
1310148c5f43SAlan Wright 
1311148c5f43SAlan Wright void
smb_server_dec_users(smb_server_t * sv)1312148c5f43SAlan Wright smb_server_dec_users(smb_server_t *sv)
1313148c5f43SAlan Wright {
1314148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1315148c5f43SAlan Wright 	atomic_dec_32(&sv->sv_users);
1316148c5f43SAlan Wright }
1317148c5f43SAlan Wright 
1318148c5f43SAlan Wright void
smb_server_inc_trees(smb_server_t * sv)1319148c5f43SAlan Wright smb_server_inc_trees(smb_server_t *sv)
1320148c5f43SAlan Wright {
1321148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1322148c5f43SAlan Wright 	atomic_inc_32(&sv->sv_trees);
1323148c5f43SAlan Wright }
1324148c5f43SAlan Wright 
1325148c5f43SAlan Wright void
smb_server_dec_trees(smb_server_t * sv)1326148c5f43SAlan Wright smb_server_dec_trees(smb_server_t *sv)
1327148c5f43SAlan Wright {
1328148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1329148c5f43SAlan Wright 	atomic_dec_32(&sv->sv_trees);
1330148c5f43SAlan Wright }
1331148c5f43SAlan Wright 
1332148c5f43SAlan Wright void
smb_server_inc_files(smb_server_t * sv)1333148c5f43SAlan Wright smb_server_inc_files(smb_server_t *sv)
1334148c5f43SAlan Wright {
1335148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1336148c5f43SAlan Wright 	atomic_inc_32(&sv->sv_files);
1337148c5f43SAlan Wright }
1338148c5f43SAlan Wright 
1339148c5f43SAlan Wright void
smb_server_dec_files(smb_server_t * sv)1340148c5f43SAlan Wright smb_server_dec_files(smb_server_t *sv)
1341148c5f43SAlan Wright {
1342148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1343148c5f43SAlan Wright 	atomic_dec_32(&sv->sv_files);
1344148c5f43SAlan Wright }
1345148c5f43SAlan Wright 
1346148c5f43SAlan Wright void
smb_server_inc_pipes(smb_server_t * sv)1347148c5f43SAlan Wright smb_server_inc_pipes(smb_server_t *sv)
1348148c5f43SAlan Wright {
1349148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1350148c5f43SAlan Wright 	atomic_inc_32(&sv->sv_pipes);
1351148c5f43SAlan Wright }
1352148c5f43SAlan Wright 
1353148c5f43SAlan Wright void
smb_server_dec_pipes(smb_server_t * sv)1354148c5f43SAlan Wright smb_server_dec_pipes(smb_server_t *sv)
1355148c5f43SAlan Wright {
1356148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1357148c5f43SAlan Wright 	atomic_dec_32(&sv->sv_pipes);
1358148c5f43SAlan Wright }
1359148c5f43SAlan Wright 
1360148c5f43SAlan Wright void
smb_server_add_rxb(smb_server_t * sv,int64_t value)1361148c5f43SAlan Wright smb_server_add_rxb(smb_server_t *sv, int64_t value)
1362148c5f43SAlan Wright {
1363148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1364148c5f43SAlan Wright 	atomic_add_64(&sv->sv_rxb, value);
1365148c5f43SAlan Wright }
1366148c5f43SAlan Wright 
1367148c5f43SAlan Wright void
smb_server_add_txb(smb_server_t * sv,int64_t value)1368148c5f43SAlan Wright smb_server_add_txb(smb_server_t *sv, int64_t value)
1369148c5f43SAlan Wright {
1370148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1371148c5f43SAlan Wright 	atomic_add_64(&sv->sv_txb, value);
1372148c5f43SAlan Wright }
1373148c5f43SAlan Wright 
1374148c5f43SAlan Wright void
smb_server_inc_req(smb_server_t * sv)1375148c5f43SAlan Wright smb_server_inc_req(smb_server_t *sv)
1376148c5f43SAlan Wright {
1377148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1378148c5f43SAlan Wright 	atomic_inc_64(&sv->sv_nreq);
1379148c5f43SAlan Wright }
1380148c5f43SAlan Wright 
1381faa1795aSjb /*
1382faa1795aSjb  * *****************************************************************************
1383faa1795aSjb  * *************************** Static Functions ********************************
1384faa1795aSjb  * *****************************************************************************
1385faa1795aSjb  */
1386faa1795aSjb 
1387faa1795aSjb static void
smb_server_timers(smb_thread_t * thread,void * arg)1388faa1795aSjb smb_server_timers(smb_thread_t *thread, void *arg)
1389faa1795aSjb {
1390faa1795aSjb 	smb_server_t	*sv = (smb_server_t *)arg;
1391faa1795aSjb 
1392faa1795aSjb 	ASSERT(sv != NULL);
1393faa1795aSjb 
1394b819cea2SGordon Ross 	/*
1395811599a4SMatt Barden 	 * This kills old inactive sessions and expired durable
1396811599a4SMatt Barden 	 * handles. The session code expects one call per minute.
1397b819cea2SGordon Ross 	 */
1398b819cea2SGordon Ross 	while (smb_thread_continue_timedwait(thread, 60 /* Seconds */)) {
1399811599a4SMatt Barden 		if (sv->sv_cfg.skc_keepalive != 0)
1400811599a4SMatt Barden 			smb_session_timers(sv);
1401811599a4SMatt Barden 		smb2_durable_timers(sv);
1402faa1795aSjb 	}
1403faa1795aSjb }
1404faa1795aSjb 
1405faa1795aSjb /*
1406faa1795aSjb  * smb_server_kstat_init
1407faa1795aSjb  */
1408148c5f43SAlan Wright static void
smb_server_kstat_init(smb_server_t * sv)1409faa1795aSjb smb_server_kstat_init(smb_server_t *sv)
1410faa1795aSjb {
1411cb174861Sjoyce mcintosh 
14128622ec45SGordon Ross 	sv->sv_ksp = kstat_create_zone(SMBSRV_KSTAT_MODULE, 0,
1413148c5f43SAlan Wright 	    SMBSRV_KSTAT_STATISTICS, SMBSRV_KSTAT_CLASS, KSTAT_TYPE_RAW,
1414148c5f43SAlan Wright 	    sizeof (smbsrv_kstats_t), 0, sv->sv_zid);
1415148c5f43SAlan Wright 
1416148c5f43SAlan Wright 	if (sv->sv_ksp != NULL) {
1417148c5f43SAlan Wright 		sv->sv_ksp->ks_update = smb_server_kstat_update;
1418148c5f43SAlan Wright 		sv->sv_ksp->ks_private = sv;
1419148c5f43SAlan Wright 		((smbsrv_kstats_t *)sv->sv_ksp->ks_data)->ks_start_time =
1420148c5f43SAlan Wright 		    sv->sv_start_time;
14218622ec45SGordon Ross 		smb_dispatch_stats_init(sv);
1422a90cf9f2SGordon Ross 		smb2_dispatch_stats_init(sv);
1423faa1795aSjb 		kstat_install(sv->sv_ksp);
1424148c5f43SAlan Wright 	} else {
1425148c5f43SAlan Wright 		cmn_err(CE_WARN, "SMB Server: Statistics unavailable");
1426faa1795aSjb 	}
1427cb174861Sjoyce mcintosh 
14288622ec45SGordon Ross 	sv->sv_legacy_ksp = kstat_create_zone(SMBSRV_KSTAT_MODULE, 0,
14298622ec45SGordon Ross 	    SMBSRV_KSTAT_NAME, SMBSRV_KSTAT_CLASS, KSTAT_TYPE_NAMED,
14308622ec45SGordon Ross 	    sizeof (smb_server_legacy_kstat_t) / sizeof (kstat_named_t),
14318622ec45SGordon Ross 	    0, sv->sv_zid);
1432cb174861Sjoyce mcintosh 
1433cb174861Sjoyce mcintosh 	if (sv->sv_legacy_ksp != NULL) {
1434cb174861Sjoyce mcintosh 		smb_server_legacy_kstat_t *ksd;
1435cb174861Sjoyce mcintosh 
1436cb174861Sjoyce mcintosh 		ksd = sv->sv_legacy_ksp->ks_data;
1437cb174861Sjoyce mcintosh 
1438cb174861Sjoyce mcintosh 		(void) strlcpy(ksd->ls_files.name, "open_files",
1439cb174861Sjoyce mcintosh 		    sizeof (ksd->ls_files.name));
1440cb174861Sjoyce mcintosh 		ksd->ls_files.data_type = KSTAT_DATA_UINT32;
1441cb174861Sjoyce mcintosh 
1442cb174861Sjoyce mcintosh 		(void) strlcpy(ksd->ls_trees.name, "connections",
1443cb174861Sjoyce mcintosh 		    sizeof (ksd->ls_trees.name));
1444cb174861Sjoyce mcintosh 		ksd->ls_trees.data_type = KSTAT_DATA_UINT32;
1445cb174861Sjoyce mcintosh 
1446cb174861Sjoyce mcintosh 		(void) strlcpy(ksd->ls_users.name, "connections",
1447cb174861Sjoyce mcintosh 		    sizeof (ksd->ls_users.name));
1448cb174861Sjoyce mcintosh 		ksd->ls_users.data_type = KSTAT_DATA_UINT32;
1449cb174861Sjoyce mcintosh 
1450cb174861Sjoyce mcintosh 		mutex_init(&sv->sv_legacy_ksmtx, NULL, MUTEX_DEFAULT, NULL);
1451cb174861Sjoyce mcintosh 		sv->sv_legacy_ksp->ks_lock = &sv->sv_legacy_ksmtx;
1452cb174861Sjoyce mcintosh 		sv->sv_legacy_ksp->ks_update = smb_server_legacy_kstat_update;
1453cb174861Sjoyce mcintosh 		kstat_install(sv->sv_legacy_ksp);
1454cb174861Sjoyce mcintosh 	}
1455faa1795aSjb }
1456faa1795aSjb 
1457faa1795aSjb /*
1458faa1795aSjb  * smb_server_kstat_fini
1459faa1795aSjb  */
1460faa1795aSjb static void
smb_server_kstat_fini(smb_server_t * sv)1461faa1795aSjb smb_server_kstat_fini(smb_server_t *sv)
1462faa1795aSjb {
1463cb174861Sjoyce mcintosh 	if (sv->sv_legacy_ksp != NULL) {
1464cb174861Sjoyce mcintosh 		kstat_delete(sv->sv_legacy_ksp);
1465cb174861Sjoyce mcintosh 		mutex_destroy(&sv->sv_legacy_ksmtx);
1466cb174861Sjoyce mcintosh 		sv->sv_legacy_ksp = NULL;
1467cb174861Sjoyce mcintosh 	}
1468cb174861Sjoyce mcintosh 
1469148c5f43SAlan Wright 	if (sv->sv_ksp != NULL) {
1470faa1795aSjb 		kstat_delete(sv->sv_ksp);
1471faa1795aSjb 		sv->sv_ksp = NULL;
14728622ec45SGordon Ross 		smb_dispatch_stats_fini(sv);
1473a90cf9f2SGordon Ross 		smb2_dispatch_stats_fini(sv);
1474faa1795aSjb 	}
1475faa1795aSjb }
1476faa1795aSjb 
14778365a6eaSGordon Ross /*
14788365a6eaSGordon Ross  * Verify the defines in smb_kstat.h used by ks_reqs1 ks_reqs2
14798365a6eaSGordon Ross  */
14808365a6eaSGordon Ross CTASSERT(SMBSRV_KS_NREQS1 == SMB_COM_NUM);
14818365a6eaSGordon Ross CTASSERT(SMBSRV_KS_NREQS2 == SMB2__NCMDS);
14828365a6eaSGordon Ross 
1483148c5f43SAlan Wright /*
1484148c5f43SAlan Wright  * smb_server_kstat_update
1485148c5f43SAlan Wright  */
1486faa1795aSjb static int
smb_server_kstat_update(kstat_t * ksp,int rw)1487148c5f43SAlan Wright smb_server_kstat_update(kstat_t *ksp, int rw)
1488faa1795aSjb {
1489faa1795aSjb 	smb_server_t	*sv;
1490148c5f43SAlan Wright 	smbsrv_kstats_t	*ksd;
1491faa1795aSjb 
1492148c5f43SAlan Wright 	if (rw == KSTAT_READ) {
1493148c5f43SAlan Wright 		sv = ksp->ks_private;
14949fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_SERVER_VALID(sv);
1495148c5f43SAlan Wright 		ksd = (smbsrv_kstats_t *)ksp->ks_data;
1496148c5f43SAlan Wright 		/*
1497148c5f43SAlan Wright 		 * Counters
1498148c5f43SAlan Wright 		 */
1499148c5f43SAlan Wright 		ksd->ks_nbt_sess = sv->sv_nbt_sess;
1500148c5f43SAlan Wright 		ksd->ks_tcp_sess = sv->sv_tcp_sess;
1501148c5f43SAlan Wright 		ksd->ks_users = sv->sv_users;
1502148c5f43SAlan Wright 		ksd->ks_trees = sv->sv_trees;
1503148c5f43SAlan Wright 		ksd->ks_files = sv->sv_files;
1504148c5f43SAlan Wright 		ksd->ks_pipes = sv->sv_pipes;
1505148c5f43SAlan Wright 		/*
1506148c5f43SAlan Wright 		 * Throughput
1507148c5f43SAlan Wright 		 */
1508148c5f43SAlan Wright 		ksd->ks_txb = sv->sv_txb;
1509148c5f43SAlan Wright 		ksd->ks_rxb = sv->sv_rxb;
1510148c5f43SAlan Wright 		ksd->ks_nreq = sv->sv_nreq;
1511148c5f43SAlan Wright 		/*
1512148c5f43SAlan Wright 		 * Busyness
1513148c5f43SAlan Wright 		 */
1514148c5f43SAlan Wright 		ksd->ks_maxreqs = sv->sv_cfg.skc_maxworkers;
1515148c5f43SAlan Wright 		smb_srqueue_update(&sv->sv_srqueue,
1516148c5f43SAlan Wright 		    &ksd->ks_utilization);
1517148c5f43SAlan Wright 		/*
1518148c5f43SAlan Wright 		 * Latency & Throughput of the requests
1519148c5f43SAlan Wright 		 */
1520a90cf9f2SGordon Ross 		smb_dispatch_stats_update(sv, ksd->ks_reqs1, 0, SMB_COM_NUM);
1521a90cf9f2SGordon Ross 		smb2_dispatch_stats_update(sv, ksd->ks_reqs2, 0, SMB2__NCMDS);
1522148c5f43SAlan Wright 		return (0);
1523faa1795aSjb 	}
1524148c5f43SAlan Wright 	if (rw == KSTAT_WRITE)
1525148c5f43SAlan Wright 		return (EACCES);
1526148c5f43SAlan Wright 
1527148c5f43SAlan Wright 	return (EIO);
1528faa1795aSjb }
1529faa1795aSjb 
1530cb174861Sjoyce mcintosh static int
smb_server_legacy_kstat_update(kstat_t * ksp,int rw)1531cb174861Sjoyce mcintosh smb_server_legacy_kstat_update(kstat_t *ksp, int rw)
1532cb174861Sjoyce mcintosh {
1533cb174861Sjoyce mcintosh 	smb_server_t			*sv;
1534cb174861Sjoyce mcintosh 	smb_server_legacy_kstat_t	*ksd;
1535cb174861Sjoyce mcintosh 	int				rc;
1536cb174861Sjoyce mcintosh 
1537cb174861Sjoyce mcintosh 	switch (rw) {
1538cb174861Sjoyce mcintosh 	case KSTAT_WRITE:
1539cb174861Sjoyce mcintosh 		rc = EACCES;
1540cb174861Sjoyce mcintosh 		break;
1541cb174861Sjoyce mcintosh 	case KSTAT_READ:
1542cb174861Sjoyce mcintosh 		if (!smb_server_lookup(&sv)) {
1543cb174861Sjoyce mcintosh 			ASSERT(MUTEX_HELD(ksp->ks_lock));
1544cb174861Sjoyce mcintosh 			ASSERT(sv->sv_legacy_ksp == ksp);
1545cb174861Sjoyce mcintosh 			ksd = (smb_server_legacy_kstat_t *)ksp->ks_data;
1546cb174861Sjoyce mcintosh 			ksd->ls_files.value.ui32 = sv->sv_files + sv->sv_pipes;
1547cb174861Sjoyce mcintosh 			ksd->ls_trees.value.ui32 = sv->sv_trees;
1548cb174861Sjoyce mcintosh 			ksd->ls_users.value.ui32 = sv->sv_users;
1549cb174861Sjoyce mcintosh 			smb_server_release(sv);
1550cb174861Sjoyce mcintosh 			rc = 0;
1551cb174861Sjoyce mcintosh 			break;
1552cb174861Sjoyce mcintosh 		}
15532d63d7e2SToomas Soome 		/* FALLTHROUGH */
1554cb174861Sjoyce mcintosh 	default:
1555cb174861Sjoyce mcintosh 		rc = EIO;
1556cb174861Sjoyce mcintosh 		break;
1557cb174861Sjoyce mcintosh 	}
1558cb174861Sjoyce mcintosh 	return (rc);
1559cb174861Sjoyce mcintosh 
1560cb174861Sjoyce mcintosh }
1561cb174861Sjoyce mcintosh 
156286184067SGordon Ross int smb_server_shutdown_wait1 = 15;	/* seconds */
156386184067SGordon Ross 
1564faa1795aSjb /*
15654163af6aSjose borrego  * smb_server_shutdown
1566faa1795aSjb  */
1567faa1795aSjb static void
smb_server_shutdown(smb_server_t * sv)15689fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_server_shutdown(smb_server_t *sv)
1569faa1795aSjb {
1570811599a4SMatt Barden 	smb_llist_t *sl = &sv->sv_session_list;
1571811599a4SMatt Barden 	smb_session_t *session;
157286184067SGordon Ross 	clock_t	time0, time1, time2;
1573811599a4SMatt Barden 
15749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	SMB_SERVER_VALID(sv);
1575faa1795aSjb 
1576856399cfSGordon Ross 	/*
157786184067SGordon Ross 	 * Stop the listeners first, so we can't get any more
157886184067SGordon Ross 	 * new sessions while we're trying to shut down.
1579856399cfSGordon Ross 	 */
1580856399cfSGordon Ross 	smb_server_listener_stop(&sv->sv_nbt_daemon);
1581856399cfSGordon Ross 	smb_server_listener_stop(&sv->sv_tcp_daemon);
1582856399cfSGordon Ross 
158386184067SGordon Ross 	/*
158486184067SGordon Ross 	 * Disconnect all of the sessions. This causes all the
158586184067SGordon Ross 	 * smb_server_receiver threads to see a disconnect and
158686184067SGordon Ross 	 * begin tear-down (in parallel) in smb_session_cancel.
158786184067SGordon Ross 	 */
1588811599a4SMatt Barden 	smb_llist_enter(sl, RW_READER);
1589811599a4SMatt Barden 	session = smb_llist_head(sl);
1590811599a4SMatt Barden 	while (session != NULL) {
1591811599a4SMatt Barden 		smb_session_disconnect(session);
1592811599a4SMatt Barden 		session = smb_llist_next(sl, session);
1593811599a4SMatt Barden 	}
1594811599a4SMatt Barden 	smb_llist_exit(sl);
1595811599a4SMatt Barden 
1596856399cfSGordon Ross 	/*
1597856399cfSGordon Ross 	 * Wake up any threads we might have blocked.
1598856399cfSGordon Ross 	 * Must precede kdoor_close etc. because those will
1599856399cfSGordon Ross 	 * wait for such threads to get out.
1600856399cfSGordon Ross 	 */
1601856399cfSGordon Ross 	smb_event_cancel(sv, 0);
1602856399cfSGordon Ross 	smb_threshold_wake_all(&sv->sv_ssetup_ct);
1603856399cfSGordon Ross 	smb_threshold_wake_all(&sv->sv_tcon_ct);
1604856399cfSGordon Ross 	smb_threshold_wake_all(&sv->sv_opipe_ct);
1605a9609934SGordon Ross 	smb_threshold_wake_all(&sv->sv_logoff_ct);
1606856399cfSGordon Ross 
1607811599a4SMatt Barden 	/*
1608811599a4SMatt Barden 	 * Wait for the session list to empty.
1609811599a4SMatt Barden 	 * (cv_signal in smb_server_destroy_session)
1610811599a4SMatt Barden 	 *
161186184067SGordon Ross 	 * We must wait for all the SMB session readers to finish, or
161286184067SGordon Ross 	 * we could proceed here while there might be worker threads
161386184067SGordon Ross 	 * running in any of those sessions.  See smb_session_logoff
161486184067SGordon Ross 	 * for timeouts applied to session tear-down. If this takes
161586184067SGordon Ross 	 * longer than expected, make some noise, and fire a dtrace
161686184067SGordon Ross 	 * probe one might use to investigate.
1617811599a4SMatt Barden 	 */
161886184067SGordon Ross 	time0 = ddi_get_lbolt();
161986184067SGordon Ross 	time1 = SEC_TO_TICK(smb_server_shutdown_wait1) + time0;
1620811599a4SMatt Barden 	mutex_enter(&sv->sv_mutex);
1621811599a4SMatt Barden 	while (sv->sv_session_list.ll_count != 0) {
162286184067SGordon Ross 		if (cv_timedwait(&sv->sv_cv, &sv->sv_mutex, time1) < 0) {
162386184067SGordon Ross 			cmn_err(CE_NOTE, "!shutdown waited %d seconds"
162486184067SGordon Ross 			    " with %d sessions still remaining",
162586184067SGordon Ross 			    smb_server_shutdown_wait1,
162686184067SGordon Ross 			    sv->sv_session_list.ll_count);
162786184067SGordon Ross 			DTRACE_PROBE1(max__wait, smb_server_t *, sv);
1628811599a4SMatt Barden 			break;
162986184067SGordon Ross 		}
1630811599a4SMatt Barden 	}
163186184067SGordon Ross 	while (sv->sv_session_list.ll_count != 0) {
163286184067SGordon Ross 		cv_wait(&sv->sv_cv, &sv->sv_mutex);
1633811599a4SMatt Barden 	}
163486184067SGordon Ross 	mutex_exit(&sv->sv_mutex);
1635811599a4SMatt Barden 
163686184067SGordon Ross 	time2 = ddi_get_lbolt();
163786184067SGordon Ross 	if (time2 > time1) {
163886184067SGordon Ross 		cmn_err(CE_NOTE, "!shutdown waited %d seconds"
163986184067SGordon Ross 		    " for all sessions to finish",
164086184067SGordon Ross 		    (int)TICK_TO_SEC(time2 - time0));
164186184067SGordon Ross 	}
1642811599a4SMatt Barden 
16438622ec45SGordon Ross 	smb_kdoor_close(sv);
1644b819cea2SGordon Ross #ifdef	_KERNEL
1645148c5f43SAlan Wright 	smb_kshare_door_fini(sv->sv_lmshrd);
1646b819cea2SGordon Ross #endif	/* _KERNEL */
16470dcb3379Sjb 	sv->sv_lmshrd = NULL;
1648b819cea2SGordon Ross 
16498622ec45SGordon Ross 	smb_export_stop(sv);
1650811599a4SMatt Barden 	smb_kshare_stop(sv);
165186184067SGordon Ross 	smb_thread_stop(&sv->si_thread_timers);
16528d96b23eSAlan Wright 
1653811599a4SMatt Barden 	/*
1654811599a4SMatt Barden 	 * Both kshare and the oplock break sub-systems may have
1655811599a4SMatt Barden 	 * taskq jobs on the spcial "server" session, until we've
1656811599a4SMatt Barden 	 * closed all ofiles and stopped the kshare exporter.
1657811599a4SMatt Barden 	 * Now it's safe to destroy the server session, but first
1658811599a4SMatt Barden 	 * wait for any requests on it to finish.  Note that for
1659811599a4SMatt Barden 	 * normal sessions, this happens in smb_session_cancel,
1660811599a4SMatt Barden 	 * but that's not called for the server session.
1661811599a4SMatt Barden 	 */
16628d94f651SGordon Ross 	if (sv->sv_rootuser != NULL) {
16638d94f651SGordon Ross 		smb_user_logoff(sv->sv_rootuser);
16648d94f651SGordon Ross 		smb_user_release(sv->sv_rootuser);
16658d94f651SGordon Ross 		sv->sv_rootuser = NULL;
16668d94f651SGordon Ross 	}
16674163af6aSjose borrego 	if (sv->sv_session != NULL) {
1668525641e8SGordon Ross 		smb_session_cancel_requests(sv->sv_session, NULL, NULL);
16694846df9bSKevin Crowe 		smb_slist_wait_for_empty(&sv->sv_session->s_req_list);
16704846df9bSKevin Crowe 
16718d94f651SGordon Ross 		/* Just in case import left users and trees */
16728d94f651SGordon Ross 		smb_session_logoff(sv->sv_session);
16738d94f651SGordon Ross 
1674faa1795aSjb 		smb_session_delete(sv->sv_session);
1675faa1795aSjb 		sv->sv_session = NULL;
1676faa1795aSjb 	}
16778d96b23eSAlan Wright 
16784163af6aSjose borrego 	if (sv->sv_receiver_pool != NULL) {
16794163af6aSjose borrego 		taskq_destroy(sv->sv_receiver_pool);
16804163af6aSjose borrego 		sv->sv_receiver_pool = NULL;
16814163af6aSjose borrego 	}
16824163af6aSjose borrego 
16834163af6aSjose borrego 	if (sv->sv_worker_pool != NULL) {
16844163af6aSjose borrego 		taskq_destroy(sv->sv_worker_pool);
16854163af6aSjose borrego 		sv->sv_worker_pool = NULL;
16868d96b23eSAlan Wright 	}
16878622ec45SGordon Ross 
1688e515d096SGordon Ross 	if (sv->sv_notify_pool != NULL) {
1689e515d096SGordon Ross 		taskq_destroy(sv->sv_notify_pool);
1690e515d096SGordon Ross 		sv->sv_notify_pool = NULL;
1691e515d096SGordon Ross 	}
1692e515d096SGordon Ross 
169386184067SGordon Ross 	/*
169486184067SGordon Ross 	 * Clean out any durable handles.  After this we should
169586184067SGordon Ross 	 * have no ofiles remaining (and no more oplock breaks).
169686184067SGordon Ross 	 */
169786184067SGordon Ross 	smb2_dh_shutdown(sv);
169886184067SGordon Ross 
16998622ec45SGordon Ross 	smb_server_fsop_stop(sv);
17005d8538b6SGordon Ross 
17015d8538b6SGordon Ross #ifdef	_KERNEL
17025d8538b6SGordon Ross 	if (sv->sv_proc_p != NULL) {
17035d8538b6SGordon Ross 		smb_server_delproc(sv);
17045d8538b6SGordon Ross 	}
17055d8538b6SGordon Ross #endif
1706faa1795aSjb }
1707faa1795aSjb 
17084163af6aSjose borrego /*
17094163af6aSjose borrego  * smb_server_listener_init
17104163af6aSjose borrego  *
17114163af6aSjose borrego  * Initializes listener contexts.
17124163af6aSjose borrego  */
17134163af6aSjose borrego static void
smb_server_listener_init(smb_server_t * sv,smb_listener_daemon_t * ld,char * name,in_port_t port,int family)17144163af6aSjose borrego smb_server_listener_init(
1715faa1795aSjb     smb_server_t		*sv,
1716faa1795aSjb     smb_listener_daemon_t	*ld,
17174163af6aSjose borrego     char			*name,
1718faa1795aSjb     in_port_t			port,
17194163af6aSjose borrego     int				family)
1720faa1795aSjb {
17214163af6aSjose borrego 	ASSERT(ld->ld_magic != SMB_LISTENER_MAGIC);
1722faa1795aSjb 
17234163af6aSjose borrego 	bzero(ld, sizeof (*ld));
17244163af6aSjose borrego 
17254163af6aSjose borrego 	ld->ld_sv = sv;
17264163af6aSjose borrego 	ld->ld_family = family;
17274163af6aSjose borrego 	ld->ld_port = port;
17284163af6aSjose borrego 
17294163af6aSjose borrego 	if (family == AF_INET) {
17304163af6aSjose borrego 		ld->ld_sin.sin_family = (uint32_t)family;
17314163af6aSjose borrego 		ld->ld_sin.sin_port = htons(port);
17324163af6aSjose borrego 		ld->ld_sin.sin_addr.s_addr = htonl(INADDR_ANY);
17334163af6aSjose borrego 	} else {
17344163af6aSjose borrego 		ld->ld_sin6.sin6_family = (uint32_t)family;
17354163af6aSjose borrego 		ld->ld_sin6.sin6_port = htons(port);
17364163af6aSjose borrego 		(void) memset(&ld->ld_sin6.sin6_addr.s6_addr, 0,
17374163af6aSjose borrego 		    sizeof (ld->ld_sin6.sin6_addr.s6_addr));
1738faa1795aSjb 	}
1739faa1795aSjb 
174008344b29SGordon Ross 	smb_thread_init(&ld->ld_thread, name, smb_server_listener, ld,
17415d8538b6SGordon Ross 	    smbsrv_listen_pri, sv);
17424163af6aSjose borrego 	ld->ld_magic = SMB_LISTENER_MAGIC;
17434163af6aSjose borrego }
17444163af6aSjose borrego 
17454163af6aSjose borrego /*
17464163af6aSjose borrego  * smb_server_listener_destroy
17474163af6aSjose borrego  *
17484163af6aSjose borrego  * Destroyes listener contexts.
17494163af6aSjose borrego  */
17504163af6aSjose borrego static void
smb_server_listener_destroy(smb_listener_daemon_t * ld)17514163af6aSjose borrego smb_server_listener_destroy(smb_listener_daemon_t *ld)
17524163af6aSjose borrego {
175383d2dfe6SGordon Ross 	/*
175483d2dfe6SGordon Ross 	 * Note that if startup fails early, we can legitimately
175583d2dfe6SGordon Ross 	 * get here with an all-zeros object.
175683d2dfe6SGordon Ross 	 */
175783d2dfe6SGordon Ross 	if (ld->ld_magic == 0)
175883d2dfe6SGordon Ross 		return;
175983d2dfe6SGordon Ross 
17604163af6aSjose borrego 	SMB_LISTENER_VALID(ld);
17614163af6aSjose borrego 	ASSERT(ld->ld_so == NULL);
17624163af6aSjose borrego 	smb_thread_destroy(&ld->ld_thread);
17634163af6aSjose borrego 	ld->ld_magic = 0;
17644163af6aSjose borrego }
17654163af6aSjose borrego 
17664163af6aSjose borrego /*
17674163af6aSjose borrego  * smb_server_listener_start
17684163af6aSjose borrego  *
17694163af6aSjose borrego  * Starts the listener associated with the context passed in.
17704163af6aSjose borrego  *
17714163af6aSjose borrego  * Return:	0	Success
17724163af6aSjose borrego  *		not 0	Failure
17734163af6aSjose borrego  */
17744163af6aSjose borrego static int
smb_server_listener_start(smb_listener_daemon_t * ld)17754163af6aSjose borrego smb_server_listener_start(smb_listener_daemon_t *ld)
17764163af6aSjose borrego {
17774163af6aSjose borrego 	int		rc;
17784163af6aSjose borrego 	uint32_t	on;
17794163af6aSjose borrego 	uint32_t	off;
17804163af6aSjose borrego 
17814163af6aSjose borrego 	SMB_LISTENER_VALID(ld);
17824163af6aSjose borrego 
17834163af6aSjose borrego 	if (ld->ld_so != NULL)
17844163af6aSjose borrego 		return (EINVAL);
17854163af6aSjose borrego 
17864163af6aSjose borrego 	ld->ld_so = smb_socreate(ld->ld_family, SOCK_STREAM, 0);
1787faa1795aSjb 	if (ld->ld_so == NULL) {
17884163af6aSjose borrego 		cmn_err(CE_WARN, "port %d: socket create failed", ld->ld_port);
17894163af6aSjose borrego 		return (ENOMEM);
17904163af6aSjose borrego 	}
17919fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
17924163af6aSjose borrego 	off = 0;
17934163af6aSjose borrego 	(void) ksocket_setsockopt(ld->ld_so, SOL_SOCKET,
17944163af6aSjose borrego 	    SO_MAC_EXEMPT, &off, sizeof (off), CRED());
17959fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
17964163af6aSjose borrego 	on = 1;
17974163af6aSjose borrego 	(void) ksocket_setsockopt(ld->ld_so, SOL_SOCKET,
17984163af6aSjose borrego 	    SO_REUSEADDR, &on, sizeof (on), CRED());
17999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
18004163af6aSjose borrego 	if (ld->ld_family == AF_INET) {
18014163af6aSjose borrego 		rc = ksocket_bind(ld->ld_so,
18024163af6aSjose borrego 		    (struct sockaddr *)&ld->ld_sin,
18034163af6aSjose borrego 		    sizeof (ld->ld_sin), CRED());
18044163af6aSjose borrego 	} else {
18054163af6aSjose borrego 		rc = ksocket_bind(ld->ld_so,
18064163af6aSjose borrego 		    (struct sockaddr *)&ld->ld_sin6,
18074163af6aSjose borrego 		    sizeof (ld->ld_sin6), CRED());
18084163af6aSjose borrego 	}
18099fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
18104163af6aSjose borrego 	if (rc != 0) {
18114163af6aSjose borrego 		cmn_err(CE_WARN, "port %d: bind failed", ld->ld_port);
18124163af6aSjose borrego 		return (rc);
18134163af6aSjose borrego 	}
18149fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
18154163af6aSjose borrego 	rc =  ksocket_listen(ld->ld_so, 20, CRED());
18164163af6aSjose borrego 	if (rc < 0) {
18174163af6aSjose borrego 		cmn_err(CE_WARN, "port %d: listen failed", ld->ld_port);
18184163af6aSjose borrego 		return (rc);
1819faa1795aSjb 	}
1820faa1795aSjb 
18214163af6aSjose borrego 	ksocket_hold(ld->ld_so);
18224163af6aSjose borrego 	rc = smb_thread_start(&ld->ld_thread);
18234163af6aSjose borrego 	if (rc != 0) {
18244163af6aSjose borrego 		ksocket_rele(ld->ld_so);
18254163af6aSjose borrego 		cmn_err(CE_WARN, "port %d: listener failed to start",
18264163af6aSjose borrego 		    ld->ld_port);
18274163af6aSjose borrego 		return (rc);
18284163af6aSjose borrego 	}
18294163af6aSjose borrego 	return (0);
18304163af6aSjose borrego }
1831faa1795aSjb 
18324163af6aSjose borrego /*
18334163af6aSjose borrego  * smb_server_listener_stop
18344163af6aSjose borrego  *
18354163af6aSjose borrego  * Stops the listener associated with the context passed in.
18364163af6aSjose borrego  */
18374163af6aSjose borrego static void
smb_server_listener_stop(smb_listener_daemon_t * ld)18384163af6aSjose borrego smb_server_listener_stop(smb_listener_daemon_t *ld)
18394163af6aSjose borrego {
18404163af6aSjose borrego 	SMB_LISTENER_VALID(ld);
18419fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
18424163af6aSjose borrego 	if (ld->ld_so != NULL) {
18434163af6aSjose borrego 		smb_soshutdown(ld->ld_so);
18444163af6aSjose borrego 		smb_sodestroy(ld->ld_so);
18454163af6aSjose borrego 		smb_thread_stop(&ld->ld_thread);
18464163af6aSjose borrego 		ld->ld_so = NULL;
18474163af6aSjose borrego 	}
18484163af6aSjose borrego }
18499fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
18504163af6aSjose borrego /*
18514163af6aSjose borrego  * smb_server_listener
18524163af6aSjose borrego  *
18534163af6aSjose borrego  * Entry point of the listeners.
18544163af6aSjose borrego  */
18554163af6aSjose borrego static void
smb_server_listener(smb_thread_t * thread,void * arg)18564163af6aSjose borrego smb_server_listener(smb_thread_t *thread, void *arg)
18574163af6aSjose borrego {
18584163af6aSjose borrego 	_NOTE(ARGUNUSED(thread))
18594163af6aSjose borrego 	smb_listener_daemon_t	*ld;
18604163af6aSjose borrego 	ksocket_t		s_so;
18614163af6aSjose borrego 	int			on;
18624163af6aSjose borrego 	int			txbuf_size;
18634163af6aSjose borrego 
18644163af6aSjose borrego 	ld = (smb_listener_daemon_t *)arg;
18654163af6aSjose borrego 
18664163af6aSjose borrego 	SMB_LISTENER_VALID(ld);
18674163af6aSjose borrego 
18684163af6aSjose borrego 	DTRACE_PROBE1(so__wait__accept, struct sonode *, ld->ld_so);
18699fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
18709a244c8eSGordon Ross 	while (smb_thread_continue_nowait(&ld->ld_thread) &&
18719a244c8eSGordon Ross 	    ld->ld_sv->sv_state != SMB_SERVER_STATE_STOPPING) {
187241bd8510Skcrowenex 		int ret = ksocket_accept(ld->ld_so, NULL, NULL, &s_so, CRED());
187341bd8510Skcrowenex 
187441bd8510Skcrowenex 		switch (ret) {
187541bd8510Skcrowenex 		case 0:
187641bd8510Skcrowenex 			break;
187741bd8510Skcrowenex 		case ECONNABORTED:
187841bd8510Skcrowenex 			continue;
18799a244c8eSGordon Ross 
188041bd8510Skcrowenex 		case EINTR:
18819a244c8eSGordon Ross 		case EBADF:
18829a244c8eSGordon Ross 		case ENOTSOCK:
18839a244c8eSGordon Ross 			/* These are normal during shutdown. Silence. */
18849a244c8eSGordon Ross 			if (ld->ld_sv->sv_state == SMB_SERVER_STATE_STOPPING)
18859a244c8eSGordon Ross 				goto out;
18869a244c8eSGordon Ross 			/* FALLTHROUGH */
188741bd8510Skcrowenex 		default:
188841bd8510Skcrowenex 			cmn_err(CE_WARN,
18897b072888SToomas Soome 			    "smb_server_listener: ksocket_accept failed (%d)",
189041bd8510Skcrowenex 			    ret);
18919a244c8eSGordon Ross 			/* avoid a tight CPU-burn loop here */
18929a244c8eSGordon Ross 			delay(MSEC_TO_TICK(10));
18939a244c8eSGordon Ross 			continue;
189441bd8510Skcrowenex 		}
189541bd8510Skcrowenex 
18969fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		DTRACE_PROBE1(so__accept, struct sonode *, s_so);
18979fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
18989fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		on = 1;
18999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		(void) ksocket_setsockopt(s_so, IPPROTO_TCP, TCP_NODELAY,
19009fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		    &on, sizeof (on), CRED());
19019fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
19029fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		on = 1;
19039fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		(void) ksocket_setsockopt(s_so, SOL_SOCKET, SO_KEEPALIVE,
19049fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		    &on, sizeof (on), CRED());
19059fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
19069fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		txbuf_size = 128*1024;
19079fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		(void) ksocket_setsockopt(s_so, SOL_SOCKET, SO_SNDBUF,
19089fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		    (const void *)&txbuf_size, sizeof (txbuf_size), CRED());
19099fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
19109fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		/*
19119fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		 * Create a session for this connection.
19129fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		 */
19134163af6aSjose borrego 		smb_server_create_session(ld, s_so);
19149fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
191541bd8510Skcrowenex out:
19164163af6aSjose borrego 	ksocket_rele(ld->ld_so);
19179fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
1918faa1795aSjb 
19194163af6aSjose borrego /*
19204163af6aSjose borrego  * smb_server_receiver
19214163af6aSjose borrego  *
19224163af6aSjose borrego  * Entry point of the receiver threads.
1923811599a4SMatt Barden  * Also does cleanup when socket disconnected.
19244163af6aSjose borrego  */
19254163af6aSjose borrego static void
smb_server_receiver(void * arg)19264163af6aSjose borrego smb_server_receiver(void *arg)
19279fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
1928811599a4SMatt Barden 	smb_session_t	*session;
1929811599a4SMatt Barden 
1930811599a4SMatt Barden 	session = (smb_session_t *)arg;
19319fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
1932811599a4SMatt Barden 	/* We stay in here until socket disconnect. */
19334163af6aSjose borrego 	smb_session_receiver(session);
1934811599a4SMatt Barden 
1935811599a4SMatt Barden 	smb_server_destroy_session(session);
1936faa1795aSjb }
1937faa1795aSjb 
1938faa1795aSjb /*
1939faa1795aSjb  * smb_server_lookup
1940faa1795aSjb  *
19418622ec45SGordon Ross  * This function finds the server associated with the zone of the
19428622ec45SGordon Ross  * caller.  Note: requires a fix in the dynamic taskq code:
19438622ec45SGordon Ross  * 1501 taskq_create_proc ... TQ_DYNAMIC puts tasks in p0
1944faa1795aSjb  */
19454846df9bSKevin Crowe int
smb_server_lookup(smb_server_t ** psv)1946faa1795aSjb smb_server_lookup(smb_server_t **psv)
1947faa1795aSjb {
1948faa1795aSjb 	zoneid_t	zid;
1949faa1795aSjb 	smb_server_t	*sv;
1950faa1795aSjb 
1951faa1795aSjb 	zid = getzoneid();
1952faa1795aSjb 
1953faa1795aSjb 	smb_llist_enter(&smb_servers, RW_READER);
1954faa1795aSjb 	sv = smb_llist_head(&smb_servers);
1955faa1795aSjb 	while (sv) {
19569fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_SERVER_VALID(sv);
1957faa1795aSjb 		if (sv->sv_zid == zid) {
1958faa1795aSjb 			mutex_enter(&sv->sv_mutex);
1959faa1795aSjb 			if (sv->sv_state != SMB_SERVER_STATE_DELETING) {
1960faa1795aSjb 				sv->sv_refcnt++;
1961faa1795aSjb 				mutex_exit(&sv->sv_mutex);
1962faa1795aSjb 				smb_llist_exit(&smb_servers);
1963faa1795aSjb 				*psv = sv;
1964faa1795aSjb 				return (0);
1965faa1795aSjb 			}
1966faa1795aSjb 			mutex_exit(&sv->sv_mutex);
1967faa1795aSjb 			break;
1968faa1795aSjb 		}
1969faa1795aSjb 		sv = smb_llist_next(&smb_servers, sv);
1970faa1795aSjb 	}
1971faa1795aSjb 	smb_llist_exit(&smb_servers);
1972*34bbc83aSGordon Ross 	return (ENXIO);
1973faa1795aSjb }
1974faa1795aSjb 
1975faa1795aSjb /*
1976faa1795aSjb  * smb_server_release
1977faa1795aSjb  *
1978faa1795aSjb  * This function decrements the reference count of the server and signals its
1979faa1795aSjb  * condition variable if the state of the server is SMB_SERVER_STATE_DELETING.
1980faa1795aSjb  */
19814846df9bSKevin Crowe void
smb_server_release(smb_server_t * sv)1982faa1795aSjb smb_server_release(smb_server_t *sv)
1983faa1795aSjb {
19849fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	SMB_SERVER_VALID(sv);
1985faa1795aSjb 
1986faa1795aSjb 	mutex_enter(&sv->sv_mutex);
1987faa1795aSjb 	ASSERT(sv->sv_refcnt);
1988faa1795aSjb 	sv->sv_refcnt--;
1989faa1795aSjb 	if ((sv->sv_refcnt == 0) && (sv->sv_state == SMB_SERVER_STATE_DELETING))
1990faa1795aSjb 		cv_signal(&sv->sv_cv);
1991faa1795aSjb 	mutex_exit(&sv->sv_mutex);
1992faa1795aSjb }
1993faa1795aSjb 
199497264293SGordon Ross /*
199597264293SGordon Ross  * smb_server_lookup_user
199697264293SGordon Ross  *
199797264293SGordon Ross  * Find an smb_user by its user_id
199897264293SGordon Ross  * Optional ssn_id (if non-zero) restricts search to a specific session.
199997264293SGordon Ross  *
200097264293SGordon Ross  * Returns smb_user_t * held. Caller must smb_user_rele(user)
200197264293SGordon Ross  * Returns NULL if not found.
200297264293SGordon Ross  */
200397264293SGordon Ross smb_user_t *
smb_server_lookup_user(smb_server_t * sv,uint64_t ssn_id,uint64_t user_id)200497264293SGordon Ross smb_server_lookup_user(smb_server_t *sv, uint64_t ssn_id, uint64_t user_id)
200597264293SGordon Ross {
200697264293SGordon Ross 	smb_llist_t	*slist = &sv->sv_session_list;
200797264293SGordon Ross 	smb_session_t	*sn;
200897264293SGordon Ross 	smb_user_t	*user = NULL;
200997264293SGordon Ross 
201097264293SGordon Ross 	smb_llist_enter(slist, RW_READER);
201197264293SGordon Ross 
201297264293SGordon Ross 	for (sn = smb_llist_head(slist);
201397264293SGordon Ross 	    sn != NULL && user == NULL;
201497264293SGordon Ross 	    sn = smb_llist_next(slist, sn)) {
201597264293SGordon Ross 		SMB_SESSION_VALID(sn);
201697264293SGordon Ross 
201797264293SGordon Ross 		if (ssn_id != 0 && ssn_id != sn->s_kid)
201897264293SGordon Ross 			continue;
201997264293SGordon Ross 		if (sn->s_state != SMB_SESSION_STATE_NEGOTIATED)
202097264293SGordon Ross 			continue;
202197264293SGordon Ross 
202297264293SGordon Ross 		user = smb_session_lookup_ssnid(sn, user_id);
202397264293SGordon Ross 	}
202497264293SGordon Ross 	smb_llist_exit(slist);
202597264293SGordon Ross 
202697264293SGordon Ross 	return (user);
202797264293SGordon Ross }
202897264293SGordon Ross 
20291fcced4cSJordan Brown /*
20301fcced4cSJordan Brown  * Enumerate the users associated with a session list.
20311fcced4cSJordan Brown  */
20321fcced4cSJordan Brown static void
smb_server_enum_users(smb_server_t * sv,smb_svcenum_t * svcenum)20338d94f651SGordon Ross smb_server_enum_users(smb_server_t *sv, smb_svcenum_t *svcenum)
20341fcced4cSJordan Brown {
20358d94f651SGordon Ross 	smb_llist_t	*ll = &sv->sv_session_list;
20361fcced4cSJordan Brown 	smb_session_t	*sn;
20371fcced4cSJordan Brown 	smb_llist_t	*ulist;
20381fcced4cSJordan Brown 	smb_user_t	*user;
20391fcced4cSJordan Brown 	int		rc = 0;
20401fcced4cSJordan Brown 
20414163af6aSjose borrego 	smb_llist_enter(ll, RW_READER);
20424163af6aSjose borrego 	sn = smb_llist_head(ll);
20431fcced4cSJordan Brown 
20441fcced4cSJordan Brown 	while (sn != NULL) {
20454163af6aSjose borrego 		SMB_SESSION_VALID(sn);
20461fcced4cSJordan Brown 		ulist = &sn->s_user_list;
20471fcced4cSJordan Brown 		smb_llist_enter(ulist, RW_READER);
20481fcced4cSJordan Brown 		user = smb_llist_head(ulist);
20491fcced4cSJordan Brown 
20501fcced4cSJordan Brown 		while (user != NULL) {
20511fcced4cSJordan Brown 			if (smb_user_hold(user)) {
20521fcced4cSJordan Brown 				rc = smb_user_enum(user, svcenum);
20531fcced4cSJordan Brown 				smb_user_release(user);
20543b13a1efSThomas Keiser 				if (rc != 0)
20553b13a1efSThomas Keiser 					break;
20561fcced4cSJordan Brown 			}
20571fcced4cSJordan Brown 
20581fcced4cSJordan Brown 			user = smb_llist_next(ulist, user);
20591fcced4cSJordan Brown 		}
20601fcced4cSJordan Brown 
20611fcced4cSJordan Brown 		smb_llist_exit(ulist);
20621fcced4cSJordan Brown 
20631fcced4cSJordan Brown 		if (rc != 0)
20641fcced4cSJordan Brown 			break;
20651fcced4cSJordan Brown 
20664163af6aSjose borrego 		sn = smb_llist_next(ll, sn);
20671fcced4cSJordan Brown 	}
20681fcced4cSJordan Brown 
20694163af6aSjose borrego 	smb_llist_exit(ll);
20701fcced4cSJordan Brown }
20711fcced4cSJordan Brown 
20723b13a1efSThomas Keiser /*
20733b13a1efSThomas Keiser  * Enumerate the trees/files associated with a session list.
20743b13a1efSThomas Keiser  */
20753b13a1efSThomas Keiser static void
smb_server_enum_trees(smb_server_t * sv,smb_svcenum_t * svcenum)20768d94f651SGordon Ross smb_server_enum_trees(smb_server_t *sv, smb_svcenum_t *svcenum)
20773b13a1efSThomas Keiser {
20788d94f651SGordon Ross 	smb_llist_t	*ll = &sv->sv_session_list;
20793b13a1efSThomas Keiser 	smb_session_t	*sn;
20803b13a1efSThomas Keiser 	smb_llist_t	*tlist;
20813b13a1efSThomas Keiser 	smb_tree_t	*tree;
20823b13a1efSThomas Keiser 	int		rc = 0;
20833b13a1efSThomas Keiser 
20843b13a1efSThomas Keiser 	smb_llist_enter(ll, RW_READER);
20853b13a1efSThomas Keiser 	sn = smb_llist_head(ll);
20863b13a1efSThomas Keiser 
20873b13a1efSThomas Keiser 	while (sn != NULL) {
20883b13a1efSThomas Keiser 		SMB_SESSION_VALID(sn);
20893b13a1efSThomas Keiser 		tlist = &sn->s_tree_list;
20903b13a1efSThomas Keiser 		smb_llist_enter(tlist, RW_READER);
20913b13a1efSThomas Keiser 		tree = smb_llist_head(tlist);
20923b13a1efSThomas Keiser 
20933b13a1efSThomas Keiser 		while (tree != NULL) {
20943b13a1efSThomas Keiser 			if (smb_tree_hold(tree)) {
20953b13a1efSThomas Keiser 				rc = smb_tree_enum(tree, svcenum);
20963b13a1efSThomas Keiser 				smb_tree_release(tree);
20973b13a1efSThomas Keiser 				if (rc != 0)
20983b13a1efSThomas Keiser 					break;
20993b13a1efSThomas Keiser 			}
21003b13a1efSThomas Keiser 
21013b13a1efSThomas Keiser 			tree = smb_llist_next(tlist, tree);
21023b13a1efSThomas Keiser 		}
21033b13a1efSThomas Keiser 
21043b13a1efSThomas Keiser 		smb_llist_exit(tlist);
21053b13a1efSThomas Keiser 
21063b13a1efSThomas Keiser 		if (rc != 0)
21073b13a1efSThomas Keiser 			break;
21083b13a1efSThomas Keiser 
21093b13a1efSThomas Keiser 		sn = smb_llist_next(ll, sn);
21103b13a1efSThomas Keiser 	}
21113b13a1efSThomas Keiser 
21123b13a1efSThomas Keiser 	smb_llist_exit(ll);
21133b13a1efSThomas Keiser }
21143b13a1efSThomas Keiser 
21151fcced4cSJordan Brown /*
21161fcced4cSJordan Brown  * Disconnect sessions associated with the specified client and username.
21171fcced4cSJordan Brown  * Empty strings are treated as wildcards.
21181fcced4cSJordan Brown  */
2119faa1795aSjb static int
smb_server_session_disconnect(smb_server_t * sv,const char * client,const char * name)21208d94f651SGordon Ross smb_server_session_disconnect(smb_server_t *sv,
21211fcced4cSJordan Brown     const char *client, const char *name)
2122faa1795aSjb {
21238d94f651SGordon Ross 	smb_llist_t	*ll = &sv->sv_session_list;
21241fcced4cSJordan Brown 	smb_session_t	*sn;
21251fcced4cSJordan Brown 	smb_llist_t	*ulist;
21261fcced4cSJordan Brown 	smb_user_t	*user;
21271fcced4cSJordan Brown 	int		count = 0;
2128faa1795aSjb 
21294163af6aSjose borrego 	smb_llist_enter(ll, RW_READER);
21301fcced4cSJordan Brown 
2131811599a4SMatt Barden 	for (sn = smb_llist_head(ll);
2132811599a4SMatt Barden 	    sn != NULL;
2133811599a4SMatt Barden 	    sn = smb_llist_next(ll, sn)) {
21344163af6aSjose borrego 		SMB_SESSION_VALID(sn);
21351fcced4cSJordan Brown 
2136811599a4SMatt Barden 		if (*client != '\0' && !smb_session_isclient(sn, client))
21371fcced4cSJordan Brown 			continue;
21381fcced4cSJordan Brown 
2139faa1795aSjb 		ulist = &sn->s_user_list;
2140faa1795aSjb 		smb_llist_enter(ulist, RW_READER);
21411fcced4cSJordan Brown 
2142811599a4SMatt Barden 		for (user = smb_llist_head(ulist);
2143811599a4SMatt Barden 		    user != NULL;
2144811599a4SMatt Barden 		    user = smb_llist_next(ulist, user)) {
21451fcced4cSJordan Brown 
2146811599a4SMatt Barden 			if (smb_user_hold(user)) {
2147896d9552SGordon Ross 
2148896d9552SGordon Ross 				if (*name == '\0' ||
2149896d9552SGordon Ross 				    smb_user_namecmp(user, name)) {
2150896d9552SGordon Ross 					smb_user_logoff(user);
2151896d9552SGordon Ross 					count++;
2152896d9552SGordon Ross 				}
2153896d9552SGordon Ross 
21541fcced4cSJordan Brown 				smb_user_release(user);
2155faa1795aSjb 			}
2156faa1795aSjb 		}
21571fcced4cSJordan Brown 
2158faa1795aSjb 		smb_llist_exit(ulist);
2159faa1795aSjb 	}
21601fcced4cSJordan Brown 
21614163af6aSjose borrego 	smb_llist_exit(ll);
21621fcced4cSJordan Brown 	return (count);
21631fcced4cSJordan Brown }
21641fcced4cSJordan Brown 
21651fcced4cSJordan Brown /*
21661fcced4cSJordan Brown  * Close a file by its unique id.
21671fcced4cSJordan Brown  */
21681fcced4cSJordan Brown static int
smb_server_fclose(smb_server_t * sv,uint32_t uniqid)21698d94f651SGordon Ross smb_server_fclose(smb_server_t *sv, uint32_t uniqid)
21701fcced4cSJordan Brown {
21718d94f651SGordon Ross 	smb_llist_t	*ll;
21721fcced4cSJordan Brown 	smb_session_t	*sn;
21733b13a1efSThomas Keiser 	smb_llist_t	*tlist;
21743b13a1efSThomas Keiser 	smb_tree_t	*tree;
21751fcced4cSJordan Brown 	int		rc = ENOENT;
21761fcced4cSJordan Brown 
21778d94f651SGordon Ross 	ll = &sv->sv_session_list;
21784163af6aSjose borrego 	smb_llist_enter(ll, RW_READER);
21794163af6aSjose borrego 	sn = smb_llist_head(ll);
21801fcced4cSJordan Brown 
21811fcced4cSJordan Brown 	while ((sn != NULL) && (rc == ENOENT)) {
21824163af6aSjose borrego 		SMB_SESSION_VALID(sn);
21833b13a1efSThomas Keiser 		tlist = &sn->s_tree_list;
21843b13a1efSThomas Keiser 		smb_llist_enter(tlist, RW_READER);
21853b13a1efSThomas Keiser 		tree = smb_llist_head(tlist);
21863b13a1efSThomas Keiser 
21873b13a1efSThomas Keiser 		while ((tree != NULL) && (rc == ENOENT)) {
21883b13a1efSThomas Keiser 			if (smb_tree_hold(tree)) {
21893b13a1efSThomas Keiser 				rc = smb_tree_fclose(tree, uniqid);
21903b13a1efSThomas Keiser 				smb_tree_release(tree);
21911fcced4cSJordan Brown 			}
21921fcced4cSJordan Brown 
21933b13a1efSThomas Keiser 			tree = smb_llist_next(tlist, tree);
21941fcced4cSJordan Brown 		}
21951fcced4cSJordan Brown 
21963b13a1efSThomas Keiser 		smb_llist_exit(tlist);
21974163af6aSjose borrego 		sn = smb_llist_next(ll, sn);
21981fcced4cSJordan Brown 	}
21991fcced4cSJordan Brown 
22004163af6aSjose borrego 	smb_llist_exit(ll);
22011fcced4cSJordan Brown 	return (rc);
2202faa1795aSjb }
2203faa1795aSjb 
2204811599a4SMatt Barden /*
2205811599a4SMatt Barden  * This is used by SMB2 session setup to logoff a previous session,
2206811599a4SMatt Barden  * so it can force a logoff that we haven't noticed yet.
2207811599a4SMatt Barden  * This is not called frequently, so we just walk the list of
2208811599a4SMatt Barden  * connections searching for the user.
22091baeef30SPrashanth Badari  *
22101baeef30SPrashanth Badari  * Note that this must wait for any durable handles (ofiles)
22111baeef30SPrashanth Badari  * owned by this user to become "orphaned", so that a reconnect
22121baeef30SPrashanth Badari  * that may immediately follow can find and use such ofiles.
2213811599a4SMatt Barden  */
2214811599a4SMatt Barden void
smb_server_logoff_ssnid(smb_request_t * sr,uint64_t ssnid)2215811599a4SMatt Barden smb_server_logoff_ssnid(smb_request_t *sr, uint64_t ssnid)
2216811599a4SMatt Barden {
2217811599a4SMatt Barden 	smb_server_t	*sv = sr->sr_server;
2218811599a4SMatt Barden 	smb_llist_t	*sess_list;
2219811599a4SMatt Barden 	smb_session_t	*sess;
22201baeef30SPrashanth Badari 	smb_user_t	*user = NULL;
22210c5f22c1SGordon Ross 	boolean_t	do_logoff = B_FALSE;
22221baeef30SPrashanth Badari 
22231baeef30SPrashanth Badari 	SMB_SERVER_VALID(sv);
2224811599a4SMatt Barden 
2225811599a4SMatt Barden 	if (sv->sv_state != SMB_SERVER_STATE_RUNNING)
2226811599a4SMatt Barden 		return;
2227811599a4SMatt Barden 
2228811599a4SMatt Barden 	sess_list = &sv->sv_session_list;
2229811599a4SMatt Barden 	smb_llist_enter(sess_list, RW_READER);
2230811599a4SMatt Barden 
2231811599a4SMatt Barden 	for (sess = smb_llist_head(sess_list);
2232811599a4SMatt Barden 	    sess != NULL;
2233811599a4SMatt Barden 	    sess = smb_llist_next(sess_list, sess)) {
2234811599a4SMatt Barden 
2235811599a4SMatt Barden 		SMB_SESSION_VALID(sess);
2236811599a4SMatt Barden 
2237811599a4SMatt Barden 		if (sess->dialect < SMB_VERS_2_BASE)
2238811599a4SMatt Barden 			continue;
2239811599a4SMatt Barden 
22401baeef30SPrashanth Badari 		switch (sess->s_state) {
22411baeef30SPrashanth Badari 		case SMB_SESSION_STATE_NEGOTIATED:
22421baeef30SPrashanth Badari 		case SMB_SESSION_STATE_TERMINATED:
22431baeef30SPrashanth Badari 		case SMB_SESSION_STATE_DISCONNECTED:
22441baeef30SPrashanth Badari 			break;
22451baeef30SPrashanth Badari 		default:
2246811599a4SMatt Barden 			continue;
22471baeef30SPrashanth Badari 		}
2248811599a4SMatt Barden 
22491baeef30SPrashanth Badari 		/*
22501baeef30SPrashanth Badari 		 * Normal situation is to find a LOGGED_ON user.
22511baeef30SPrashanth Badari 		 */
22521baeef30SPrashanth Badari 		user = smb_session_lookup_uid_st(sess, ssnid, 0,
22531baeef30SPrashanth Badari 		    SMB_USER_STATE_LOGGED_ON);
22541baeef30SPrashanth Badari 		if (user != NULL) {
22551baeef30SPrashanth Badari 			if (smb_is_same_user(user->u_cred, sr->user_cr)) {
22560c5f22c1SGordon Ross 				do_logoff = B_TRUE;
22571baeef30SPrashanth Badari 				break;
22581baeef30SPrashanth Badari 			}
22591baeef30SPrashanth Badari 			smb_user_release(user);
22601baeef30SPrashanth Badari 			user = NULL;
22611baeef30SPrashanth Badari 		}
2262811599a4SMatt Barden 
22631baeef30SPrashanth Badari 		/*
22641baeef30SPrashanth Badari 		 * If we raced with disconnect, may find LOGGING_OFF,
22651baeef30SPrashanth Badari 		 * in which case we want to just wait for it.
22661baeef30SPrashanth Badari 		 */
22671baeef30SPrashanth Badari 		user = smb_session_lookup_uid_st(sess, ssnid, 0,
22681baeef30SPrashanth Badari 		    SMB_USER_STATE_LOGGING_OFF);
22691baeef30SPrashanth Badari 		if (user != NULL) {
22701baeef30SPrashanth Badari 			if (smb_is_same_user(user->u_cred, sr->user_cr))
22711baeef30SPrashanth Badari 				break;
2272811599a4SMatt Barden 			smb_user_release(user);
22731baeef30SPrashanth Badari 			user = NULL;
2274811599a4SMatt Barden 		}
22751baeef30SPrashanth Badari 	}
2276811599a4SMatt Barden 
22771baeef30SPrashanth Badari 	smb_llist_exit(sess_list);
22781baeef30SPrashanth Badari 
22790c5f22c1SGordon Ross 	/*
22800c5f22c1SGordon Ross 	 * Note that smb_user_logoff() can block for a while if
22810c5f22c1SGordon Ross 	 * smb_session_disconnect_owned_trees, smb_ofile_close_all
22820c5f22c1SGordon Ross 	 * ends up blocked on locks held by running requests.
22830c5f22c1SGordon Ross 	 * Do that while not holding the session list rwlock.
22840c5f22c1SGordon Ross 	 */
22851baeef30SPrashanth Badari 	if (user != NULL) {
22860c5f22c1SGordon Ross 		if (do_logoff) {
22870c5f22c1SGordon Ross 			/* Treat this as if we lost the connection */
22880c5f22c1SGordon Ross 			user->preserve_opens = SMB2_DH_PRESERVE_SOME;
22890c5f22c1SGordon Ross 			smb_user_logoff(user);
22900c5f22c1SGordon Ross 		}
22910c5f22c1SGordon Ross 
22921baeef30SPrashanth Badari 		/*
22931baeef30SPrashanth Badari 		 * Wait for durable handles to be orphaned.
22941baeef30SPrashanth Badari 		 * Note: not holding the sess list rwlock.
22951baeef30SPrashanth Badari 		 */
22961baeef30SPrashanth Badari 		smb_user_wait_trees(user);
2297811599a4SMatt Barden 
2298811599a4SMatt Barden 		/*
22991baeef30SPrashanth Badari 		 * Could be doing the last release on a user below,
23001baeef30SPrashanth Badari 		 * which can leave work on the delete queues for
23011baeef30SPrashanth Badari 		 * s_user_list or s_tree_list so flush those.
23021baeef30SPrashanth Badari 		 * Must hold the session list after the user release
23031baeef30SPrashanth Badari 		 * so that the session can't go away while we flush.
2304811599a4SMatt Barden 		 */
23051baeef30SPrashanth Badari 		smb_llist_enter(sess_list, RW_READER);
23061baeef30SPrashanth Badari 
23071baeef30SPrashanth Badari 		sess = user->u_session;
23081baeef30SPrashanth Badari 		smb_user_release(user);
23091baeef30SPrashanth Badari 
2310811599a4SMatt Barden 		smb_llist_flush(&sess->s_tree_list);
2311811599a4SMatt Barden 		smb_llist_flush(&sess->s_user_list);
2312811599a4SMatt Barden 
23131baeef30SPrashanth Badari 		smb_llist_exit(sess_list);
23141baeef30SPrashanth Badari 	}
2315811599a4SMatt Barden }
2316811599a4SMatt Barden 
231712b65585SGordon Ross /* See also: libsmb smb_kmod_setcfg */
2318faa1795aSjb static void
smb_server_store_cfg(smb_server_t * sv,smb_ioc_cfg_t * ioc)231929bd2886SAlan Wright smb_server_store_cfg(smb_server_t *sv, smb_ioc_cfg_t *ioc)
2320faa1795aSjb {
232129bd2886SAlan Wright 	if (ioc->maxconnections == 0)
232229bd2886SAlan Wright 		ioc->maxconnections = 0xFFFFFFFF;
2323faa1795aSjb 
23241160dcf7SMatt Barden 	if (ioc->encrypt == SMB_CONFIG_REQUIRED &&
23251160dcf7SMatt Barden 	    ioc->max_protocol < SMB_VERS_3_0) {
23261160dcf7SMatt Barden 		cmn_err(CE_WARN, "Server set to require encryption; "
23271160dcf7SMatt Barden 		    "forcing max_protocol to 3.0");
23281160dcf7SMatt Barden 		ioc->max_protocol = SMB_VERS_3_0;
23291160dcf7SMatt Barden 	}
233029bd2886SAlan Wright 	sv->sv_cfg.skc_maxworkers = ioc->maxworkers;
233129bd2886SAlan Wright 	sv->sv_cfg.skc_maxconnections = ioc->maxconnections;
233229bd2886SAlan Wright 	sv->sv_cfg.skc_keepalive = ioc->keepalive;
233329bd2886SAlan Wright 	sv->sv_cfg.skc_restrict_anon = ioc->restrict_anon;
233429bd2886SAlan Wright 	sv->sv_cfg.skc_signing_enable = ioc->signing_enable;
233529bd2886SAlan Wright 	sv->sv_cfg.skc_signing_required = ioc->signing_required;
233629bd2886SAlan Wright 	sv->sv_cfg.skc_oplock_enable = ioc->oplock_enable;
233729bd2886SAlan Wright 	sv->sv_cfg.skc_sync_enable = ioc->sync_enable;
233829bd2886SAlan Wright 	sv->sv_cfg.skc_secmode = ioc->secmode;
233912b65585SGordon Ross 	sv->sv_cfg.skc_netbios_enable = ioc->netbios_enable;
234029bd2886SAlan Wright 	sv->sv_cfg.skc_ipv6_enable = ioc->ipv6_enable;
2341cb174861Sjoyce mcintosh 	sv->sv_cfg.skc_print_enable = ioc->print_enable;
23425f1ef25cSAram Hăvărneanu 	sv->sv_cfg.skc_traverse_mounts = ioc->traverse_mounts;
2343814e0daaSGordon Ross 	sv->sv_cfg.skc_short_names = ioc->short_names;
2344a90cf9f2SGordon Ross 	sv->sv_cfg.skc_max_protocol = ioc->max_protocol;
23453e2c0c09SMatt Barden 	sv->sv_cfg.skc_min_protocol = ioc->min_protocol;
23461160dcf7SMatt Barden 	sv->sv_cfg.skc_encrypt = ioc->encrypt;
2347b0bb0d63SGordon Ross 	sv->sv_cfg.skc_encrypt_ciphers = ioc->encrypt_ciphers;
2348148c5f43SAlan Wright 	sv->sv_cfg.skc_execflags = ioc->exec_flags;
234912b65585SGordon Ross 	sv->sv_cfg.skc_negtok_len = ioc->negtok_len;
23502cf6b79fSGordon Ross 	sv->sv_cfg.skc_max_opens = ioc->max_opens;
2351148c5f43SAlan Wright 	sv->sv_cfg.skc_version = ioc->version;
2352a90cf9f2SGordon Ross 	sv->sv_cfg.skc_initial_credits = ioc->initial_credits;
2353a90cf9f2SGordon Ross 	sv->sv_cfg.skc_maximum_credits = ioc->maximum_credits;
2354a90cf9f2SGordon Ross 
235512b65585SGordon Ross 	(void) memcpy(sv->sv_cfg.skc_machine_uuid, ioc->machine_uuid,
235612b65585SGordon Ross 	    sizeof (uuid_t));
235712b65585SGordon Ross 	(void) memcpy(sv->sv_cfg.skc_negtok, ioc->negtok,
235812b65585SGordon Ross 	    sizeof (sv->sv_cfg.skc_negtok));
235912b65585SGordon Ross 	(void) memcpy(sv->sv_cfg.skc_native_os, ioc->native_os,
236012b65585SGordon Ross 	    sizeof (sv->sv_cfg.skc_native_os));
236112b65585SGordon Ross 	(void) memcpy(sv->sv_cfg.skc_native_lm, ioc->native_lm,
236212b65585SGordon Ross 	    sizeof (sv->sv_cfg.skc_native_lm));
236312b65585SGordon Ross 
236429bd2886SAlan Wright 	(void) strlcpy(sv->sv_cfg.skc_nbdomain, ioc->nbdomain,
236529bd2886SAlan Wright 	    sizeof (sv->sv_cfg.skc_nbdomain));
236629bd2886SAlan Wright 	(void) strlcpy(sv->sv_cfg.skc_fqdn, ioc->fqdn,
236729bd2886SAlan Wright 	    sizeof (sv->sv_cfg.skc_fqdn));
236829bd2886SAlan Wright 	(void) strlcpy(sv->sv_cfg.skc_hostname, ioc->hostname,
236929bd2886SAlan Wright 	    sizeof (sv->sv_cfg.skc_hostname));
237029bd2886SAlan Wright 	(void) strlcpy(sv->sv_cfg.skc_system_comment, ioc->system_comment,
237129bd2886SAlan Wright 	    sizeof (sv->sv_cfg.skc_system_comment));
2372faa1795aSjb }
2373faa1795aSjb 
2374faa1795aSjb static int
smb_server_fsop_start(smb_server_t * sv)2375faa1795aSjb smb_server_fsop_start(smb_server_t *sv)
2376faa1795aSjb {
2377faa1795aSjb 	int	error;
2378faa1795aSjb 
23798622ec45SGordon Ross 	error = smb_node_root_init(sv, &sv->si_root_smb_node);
2380faa1795aSjb 	if (error != 0)
2381faa1795aSjb 		sv->si_root_smb_node = NULL;
2382faa1795aSjb 
2383faa1795aSjb 	return (error);
2384faa1795aSjb }
2385faa1795aSjb 
2386faa1795aSjb static void
smb_server_fsop_stop(smb_server_t * sv)2387faa1795aSjb smb_server_fsop_stop(smb_server_t *sv)
2388faa1795aSjb {
2389faa1795aSjb 	if (sv->si_root_smb_node != NULL) {
2390faa1795aSjb 		smb_node_release(sv->si_root_smb_node);
2391faa1795aSjb 		sv->si_root_smb_node = NULL;
2392faa1795aSjb 	}
2393faa1795aSjb }
23949fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
23959fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_event_t *
smb_event_create(smb_server_t * sv,int timeout)23968622ec45SGordon Ross smb_event_create(smb_server_t *sv, int timeout)
23979fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
23989fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_event_t	*event;
23999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
24008622ec45SGordon Ross 	if (smb_server_is_stopping(sv))
24019fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (NULL);
24029fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
24038622ec45SGordon Ross 	event = kmem_cache_alloc(smb_cache_event, KM_SLEEP);
24049fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
24059fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	bzero(event, sizeof (smb_event_t));
24069fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_init(&event->se_mutex, NULL, MUTEX_DEFAULT, NULL);
24079fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	cv_init(&event->se_cv, NULL, CV_DEFAULT, NULL);
24089fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event->se_magic = SMB_EVENT_MAGIC;
24099fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event->se_txid = smb_event_alloc_txid();
24109fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event->se_server = sv;
2411cb174861Sjoyce mcintosh 	event->se_timeout = timeout;
24129fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
24139fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_enter(&sv->sv_event_list, RW_WRITER);
24149fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_insert_tail(&sv->sv_event_list, event);
24159fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_exit(&sv->sv_event_list);
24169fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
24179fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	return (event);
24189fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
24199fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
24209fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States void
smb_event_destroy(smb_event_t * event)24219fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_event_destroy(smb_event_t *event)
24229fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
24239fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_server_t	*sv;
24249fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
24259fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (event == NULL)
24269fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return;
24279fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
24289fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	SMB_EVENT_VALID(event);
24299fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	ASSERT(event->se_waittime == 0);
24308622ec45SGordon Ross 	sv = event->se_server;
24318622ec45SGordon Ross 	SMB_SERVER_VALID(sv);
24329fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
24339fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_enter(&sv->sv_event_list, RW_WRITER);
24349fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_remove(&sv->sv_event_list, event);
24359fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_exit(&sv->sv_event_list);
24369fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
24379fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event->se_magic = (uint32_t)~SMB_EVENT_MAGIC;
24389fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	cv_destroy(&event->se_cv);
24399fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_destroy(&event->se_mutex);
24409fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
24418622ec45SGordon Ross 	kmem_cache_free(smb_cache_event, event);
24429fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
24439fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
24449fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
24459fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Get the txid for the specified event.
24469fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  */
24479fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States uint32_t
smb_event_txid(smb_event_t * event)24489fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_event_txid(smb_event_t *event)
24499fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
24509fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (event != NULL) {
24519fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_EVENT_VALID(event);
24529fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (event->se_txid);
24539fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
24549fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
24559fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	cmn_err(CE_NOTE, "smb_event_txid failed");
24569fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	return ((uint32_t)-1);
24579fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
24589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
24599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
24609fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Wait for event notification.
24619fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  */
24629fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States int
smb_event_wait(smb_event_t * event)24639fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_event_wait(smb_event_t *event)
24649fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
24659fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	int	seconds = 1;
24669fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	int	ticks;
2467856399cfSGordon Ross 	int	err;
24689fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
24699fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (event == NULL)
24709fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (EINVAL);
24719fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
24729fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	SMB_EVENT_VALID(event);
24739fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
24749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_enter(&event->se_mutex);
24759fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event->se_waittime = 1;
24769fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event->se_errno = 0;
24779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
24789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	while (!(event->se_notified)) {
2479c5866007SKeyur Desai 		if (smb_event_debug && ((event->se_waittime % 30) == 0))
24809fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			cmn_err(CE_NOTE, "smb_event_wait[%d] (%d sec)",
24819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			    event->se_txid, event->se_waittime);
24829fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
24839fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		if (event->se_errno != 0)
24849fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			break;
24859fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
2486cb174861Sjoyce mcintosh 		if (event->se_waittime > event->se_timeout) {
24879fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			event->se_errno = ETIME;
24889fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			break;
24899fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		}
24909fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
24919fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		ticks = SEC_TO_TICK(seconds);
24929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		(void) cv_reltimedwait(&event->se_cv,
24939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		    &event->se_mutex, (clock_t)ticks, TR_CLOCK_TICK);
24949fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		++event->se_waittime;
24959fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
24969fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
2497856399cfSGordon Ross 	err = event->se_errno;
24989fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event->se_waittime = 0;
24999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event->se_notified = B_FALSE;
25009fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	cv_signal(&event->se_cv);
25019fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_exit(&event->se_mutex);
2502856399cfSGordon Ross 	return (err);
25039fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
25049fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
25059fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
25069fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * If txid is non-zero, cancel the specified event.
25079fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Otherwise, cancel all events.
25089fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  */
25099fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void
smb_event_cancel(smb_server_t * sv,uint32_t txid)25109fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_event_cancel(smb_server_t *sv, uint32_t txid)
25119fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
25129fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_event_t	*event;
25139fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_t	*event_list;
25149fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
25159fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	SMB_SERVER_VALID(sv);
25169fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
25179fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event_list = &sv->sv_event_list;
25189fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_enter(event_list, RW_WRITER);
25199fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
25209fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event = smb_llist_head(event_list);
25219fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	while (event) {
25229fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_EVENT_VALID(event);
25239fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
25249fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		if (txid == 0 || event->se_txid == txid) {
25259fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			mutex_enter(&event->se_mutex);
25269fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			event->se_errno = ECANCELED;
25279fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			event->se_notified = B_TRUE;
25289fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			cv_signal(&event->se_cv);
25299fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			mutex_exit(&event->se_mutex);
25309fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
25319fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			if (txid != 0)
25329fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 				break;
25339fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		}
25349fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
25359fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		event = smb_llist_next(event_list, event);
25369fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
25379fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
25389fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_exit(event_list);
25399fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
25409fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
25419fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
25429fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * If txid is non-zero, notify the specified event.
25439fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Otherwise, notify all events.
25449fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  */
2545cb174861Sjoyce mcintosh void
smb_event_notify(smb_server_t * sv,uint32_t txid)25469fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_event_notify(smb_server_t *sv, uint32_t txid)
25479fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
25489fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_event_t	*event;
25499fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_t	*event_list;
25509fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
25519fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	SMB_SERVER_VALID(sv);
25529fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
25539fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event_list = &sv->sv_event_list;
25549fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_enter(event_list, RW_READER);
25559fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
25569fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event = smb_llist_head(event_list);
25579fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	while (event) {
25589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_EVENT_VALID(event);
25599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
25609fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		if (txid == 0 || event->se_txid == txid) {
25619fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			mutex_enter(&event->se_mutex);
25629fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			event->se_notified = B_TRUE;
25639fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			cv_signal(&event->se_cv);
25649fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			mutex_exit(&event->se_mutex);
25659fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
25669fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			if (txid != 0)
25679fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 				break;
25689fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		}
25699fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
25709fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		event = smb_llist_next(event_list, event);
25719fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
25729fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
25739fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_exit(event_list);
25749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
25759fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
25769fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
25779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Allocate a new transaction id (txid).
25789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  *
25799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * 0 or -1 are not assigned because they are used to detect invalid
25809fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * conditions or to indicate all open id's.
25819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  */
25829fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static uint32_t
smb_event_alloc_txid(void)25839fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_event_alloc_txid(void)
25849fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
25859fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	static kmutex_t	txmutex;
25869fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	static uint32_t	txid;
25879fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	uint32_t	txid_ret;
25889fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
25899fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_enter(&txmutex);
25909fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
25919fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (txid == 0)
25929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		txid = ddi_get_lbolt() << 11;
25939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
25949fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	do {
25959fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		++txid;
25969fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	} while (txid == 0 || txid == (uint32_t)-1);
25979fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
25989fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	txid_ret = txid;
25999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_exit(&txmutex);
26009fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
26019fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	return (txid_ret);
26029fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
2603cb174861Sjoyce mcintosh 
2604cb174861Sjoyce mcintosh /*
2605cb174861Sjoyce mcintosh  * Called by the ioctl to find the corresponding
2606cb174861Sjoyce mcintosh  * spooldoc node.  removes node on success
2607cb174861Sjoyce mcintosh  *
2608cb174861Sjoyce mcintosh  * Return values
2609cb174861Sjoyce mcintosh  * rc
2610cb174861Sjoyce mcintosh  * B_FALSE - not found
2611cb174861Sjoyce mcintosh  * B_TRUE  - found
2612cb174861Sjoyce mcintosh  *
2613cb174861Sjoyce mcintosh  */
2614cb174861Sjoyce mcintosh 
261523a9c295SGordon Ross static boolean_t
smb_spool_lookup_doc_byfid(smb_server_t * sv,uint16_t fid,smb_kspooldoc_t * spdoc)261623a9c295SGordon Ross smb_spool_lookup_doc_byfid(smb_server_t *sv, uint16_t fid,
261723a9c295SGordon Ross     smb_kspooldoc_t *spdoc)
2618cb174861Sjoyce mcintosh {
2619cb174861Sjoyce mcintosh 	smb_kspooldoc_t *sp;
2620cb174861Sjoyce mcintosh 	smb_llist_t	*splist;
2621cb174861Sjoyce mcintosh 
2622cb174861Sjoyce mcintosh 	splist = &sv->sp_info.sp_list;
2623cb174861Sjoyce mcintosh 	smb_llist_enter(splist, RW_WRITER);
2624cb174861Sjoyce mcintosh 	sp = smb_llist_head(splist);
2625cb174861Sjoyce mcintosh 	while (sp != NULL) {
2626cb174861Sjoyce mcintosh 		/*
2627cb174861Sjoyce mcintosh 		 * check for a matching fid
2628cb174861Sjoyce mcintosh 		 */
2629cb174861Sjoyce mcintosh 		if (sp->sd_fid == fid) {
2630cb174861Sjoyce mcintosh 			*spdoc = *sp;
2631cb174861Sjoyce mcintosh 			smb_llist_remove(splist, sp);
2632cb174861Sjoyce mcintosh 			smb_llist_exit(splist);
2633cb174861Sjoyce mcintosh 			kmem_free(sp, sizeof (smb_kspooldoc_t));
2634cb174861Sjoyce mcintosh 			return (B_TRUE);
2635cb174861Sjoyce mcintosh 		}
2636cb174861Sjoyce mcintosh 		sp = smb_llist_next(splist, sp);
2637cb174861Sjoyce mcintosh 	}
2638cb174861Sjoyce mcintosh 	cmn_err(CE_WARN, "smb_spool_lookup_user_byfid: no fid:%d", fid);
2639cb174861Sjoyce mcintosh 	smb_llist_exit(splist);
2640cb174861Sjoyce mcintosh 	return (B_FALSE);
2641cb174861Sjoyce mcintosh }
2642cb174861Sjoyce mcintosh 
2643cb174861Sjoyce mcintosh /*
2644cb174861Sjoyce mcintosh  * Adds the spool fid to a linked list to be used
2645cb174861Sjoyce mcintosh  * as a search key in the spooldoc queue
2646cb174861Sjoyce mcintosh  *
2647cb174861Sjoyce mcintosh  * Return values
2648cb174861Sjoyce mcintosh  *      rc non-zero error
2649cb174861Sjoyce mcintosh  *	rc zero success
2650cb174861Sjoyce mcintosh  *
2651cb174861Sjoyce mcintosh  */
2652cb174861Sjoyce mcintosh 
265386d7016bSGordon Ross void
smb_spool_add_fid(smb_server_t * sv,uint16_t fid)265486d7016bSGordon Ross smb_spool_add_fid(smb_server_t *sv, uint16_t fid)
2655cb174861Sjoyce mcintosh {
2656cb174861Sjoyce mcintosh 	smb_llist_t	*fidlist;
2657cb174861Sjoyce mcintosh 	smb_spoolfid_t  *sf;
2658cb174861Sjoyce mcintosh 
265986d7016bSGordon Ross 	if (sv->sv_cfg.skc_print_enable == 0)
266086d7016bSGordon Ross 		return;
2661cb174861Sjoyce mcintosh 
2662cb174861Sjoyce mcintosh 	sf = kmem_zalloc(sizeof (smb_spoolfid_t), KM_SLEEP);
2663cb174861Sjoyce mcintosh 	fidlist = &sv->sp_info.sp_fidlist;
2664cb174861Sjoyce mcintosh 	smb_llist_enter(fidlist, RW_WRITER);
2665cb174861Sjoyce mcintosh 	sf->sf_fid = fid;
2666cb174861Sjoyce mcintosh 	smb_llist_insert_tail(fidlist, sf);
2667cb174861Sjoyce mcintosh 	smb_llist_exit(fidlist);
266886d7016bSGordon Ross 	cv_broadcast(&sv->sp_info.sp_cv);
2669cb174861Sjoyce mcintosh }
2670cb174861Sjoyce mcintosh 
2671cb174861Sjoyce mcintosh /*
2672cb174861Sjoyce mcintosh  * Called by the ioctl to get and remove the head of the fid list
2673cb174861Sjoyce mcintosh  *
2674cb174861Sjoyce mcintosh  * Return values
2675cb174861Sjoyce mcintosh  * int fd
2676cb174861Sjoyce mcintosh  * greater than 0 success
2677cb174861Sjoyce mcintosh  * 0 - error
2678cb174861Sjoyce mcintosh  *
2679cb174861Sjoyce mcintosh  */
2680cb174861Sjoyce mcintosh 
268123a9c295SGordon Ross static uint16_t
smb_spool_get_fid(smb_server_t * sv)268223a9c295SGordon Ross smb_spool_get_fid(smb_server_t *sv)
2683cb174861Sjoyce mcintosh {
2684cb174861Sjoyce mcintosh 	smb_spoolfid_t	*spfid;
2685cb174861Sjoyce mcintosh 	smb_llist_t	*splist;
2686cb174861Sjoyce mcintosh 	uint16_t	fid;
2687cb174861Sjoyce mcintosh 
2688cb174861Sjoyce mcintosh 	splist = &sv->sp_info.sp_fidlist;
2689cb174861Sjoyce mcintosh 	smb_llist_enter(splist, RW_WRITER);
2690cb174861Sjoyce mcintosh 	spfid = smb_llist_head(splist);
2691cb174861Sjoyce mcintosh 	if (spfid != NULL) {
2692cb174861Sjoyce mcintosh 		fid = spfid->sf_fid;
2693cb174861Sjoyce mcintosh 		smb_llist_remove(&sv->sp_info.sp_fidlist, spfid);
2694cb174861Sjoyce mcintosh 		kmem_free(spfid, sizeof (smb_spoolfid_t));
2695cb174861Sjoyce mcintosh 	} else {
2696cb174861Sjoyce mcintosh 		fid = 0;
2697cb174861Sjoyce mcintosh 	}
2698cb174861Sjoyce mcintosh 	smb_llist_exit(splist);
2699cb174861Sjoyce mcintosh 	return (fid);
2700cb174861Sjoyce mcintosh }
2701cb174861Sjoyce mcintosh 
2702cb174861Sjoyce mcintosh /*
2703cb174861Sjoyce mcintosh  * Adds the spooldoc to the tail of the spooldoc list
2704cb174861Sjoyce mcintosh  *
2705cb174861Sjoyce mcintosh  * Return values
2706cb174861Sjoyce mcintosh  *      rc non-zero error
2707cb174861Sjoyce mcintosh  *	rc zero success
2708cb174861Sjoyce mcintosh  */
2709cb174861Sjoyce mcintosh int
smb_spool_add_doc(smb_tree_t * tree,smb_kspooldoc_t * sp)27108622ec45SGordon Ross smb_spool_add_doc(smb_tree_t *tree, smb_kspooldoc_t *sp)
2711cb174861Sjoyce mcintosh {
2712cb174861Sjoyce mcintosh 	smb_llist_t	*splist;
27138622ec45SGordon Ross 	smb_server_t	*sv = tree->t_server;
2714cb174861Sjoyce mcintosh 	int rc = 0;
2715cb174861Sjoyce mcintosh 
2716cb174861Sjoyce mcintosh 	splist = &sv->sp_info.sp_list;
2717cb174861Sjoyce mcintosh 	smb_llist_enter(splist, RW_WRITER);
271823a9c295SGordon Ross 	sp->sd_spool_num = atomic_inc_32_nv(&sv->sp_info.sp_cnt);
2719cb174861Sjoyce mcintosh 	smb_llist_insert_tail(splist, sp);
2720cb174861Sjoyce mcintosh 	smb_llist_exit(splist);
27218622ec45SGordon Ross 
2722cb174861Sjoyce mcintosh 	return (rc);
2723cb174861Sjoyce mcintosh }
27244163af6aSjose borrego 
27254163af6aSjose borrego /*
27264163af6aSjose borrego  * smb_server_create_session
27274163af6aSjose borrego  */
27284163af6aSjose borrego static void
smb_server_create_session(smb_listener_daemon_t * ld,ksocket_t s_so)27294163af6aSjose borrego smb_server_create_session(smb_listener_daemon_t *ld, ksocket_t s_so)
27304163af6aSjose borrego {
273161b20185SGordon Ross 	smb_server_t		*sv = ld->ld_sv;
27324163af6aSjose borrego 	smb_session_t		*session;
2733811599a4SMatt Barden 	smb_llist_t		*sl;
273461b20185SGordon Ross 	taskqid_t		tqid;
273561b20185SGordon Ross 	clock_t			now;
27364163af6aSjose borrego 
2737811599a4SMatt Barden 	session = smb_session_create(s_so, ld->ld_port, sv,
27384163af6aSjose borrego 	    ld->ld_family);
27394163af6aSjose borrego 
27408622ec45SGordon Ross 	if (session == NULL) {
274161b20185SGordon Ross 		/* This should be rare (create sleeps) */
27428622ec45SGordon Ross 		smb_soshutdown(s_so);
27438622ec45SGordon Ross 		smb_sodestroy(s_so);
27448622ec45SGordon Ross 		cmn_err(CE_WARN, "SMB Session: alloc failed");
27458622ec45SGordon Ross 		return;
27468622ec45SGordon Ross 	}
27474163af6aSjose borrego 
2748811599a4SMatt Barden 	sl = &sv->sv_session_list;
2749811599a4SMatt Barden 	smb_llist_enter(sl, RW_WRITER);
275061b20185SGordon Ross 	if (smb_llist_get_count(sl) >= sv->sv_cfg.skc_maxconnections) {
275161b20185SGordon Ross 		/*
275261b20185SGordon Ross 		 * New session not in sv_session_list, so we can just
275361b20185SGordon Ross 		 * delete it directly.
275461b20185SGordon Ross 		 */
275561b20185SGordon Ross 		smb_llist_exit(sl);
275661b20185SGordon Ross 		DTRACE_PROBE1(maxconn, smb_session_t *, session);
275761b20185SGordon Ross 		smb_soshutdown(session->sock);
275861b20185SGordon Ross 		smb_session_delete(session);
275961b20185SGordon Ross 		goto logmaxconn;
276061b20185SGordon Ross 	}
2761811599a4SMatt Barden 	smb_llist_insert_tail(sl, session);
2762811599a4SMatt Barden 	smb_llist_exit(sl);
27638622ec45SGordon Ross 
27648622ec45SGordon Ross 	/*
27658622ec45SGordon Ross 	 * These taskq entries must run independently of one another,
27668622ec45SGordon Ross 	 * so TQ_NOQUEUE.  TQ_SLEEP (==0) just for clarity.
27678622ec45SGordon Ross 	 */
2768811599a4SMatt Barden 	tqid = taskq_dispatch(sv->sv_receiver_pool,
2769811599a4SMatt Barden 	    smb_server_receiver, session, TQ_NOQUEUE | TQ_SLEEP);
27709788d6deSGordon Ross 	if (tqid != TASKQID_INVALID) {
27719788d6deSGordon Ross 		/* Success */
27729788d6deSGordon Ross 		return;
27734163af6aSjose borrego 	}
277461b20185SGordon Ross 
27759788d6deSGordon Ross 	/*
27769788d6deSGordon Ross 	 * Have: tqid == TASKQID_INVALID
27779788d6deSGordon Ross 	 * We never entered smb_server_receiver()
27789788d6deSGordon Ross 	 * so need to do its return cleanup
27799788d6deSGordon Ross 	 */
27809788d6deSGordon Ross 	DTRACE_PROBE1(maxconn, smb_session_t *, session);
27819788d6deSGordon Ross 	smb_session_disconnect(session);
27829788d6deSGordon Ross 	smb_session_logoff(session);
27839788d6deSGordon Ross 	smb_server_destroy_session(session);
278461b20185SGordon Ross 
278561b20185SGordon Ross logmaxconn:
278661b20185SGordon Ross 	/*
278761b20185SGordon Ross 	 * If we hit max_connections, log something so an admin
278861b20185SGordon Ross 	 * can find out why new connections are failing, but
278961b20185SGordon Ross 	 * log this no more than once a minute.
279061b20185SGordon Ross 	 */
279161b20185SGordon Ross 	now = ddi_get_lbolt();
279261b20185SGordon Ross 	if (now > ld->ld_quiet) {
279361b20185SGordon Ross 		ld->ld_quiet = now + SEC_TO_TICK(60);
279461b20185SGordon Ross 		cmn_err(CE_WARN, "SMB can't create session: "
279561b20185SGordon Ross 		    "Would exceed max_connections.");
279661b20185SGordon Ross 	}
27974163af6aSjose borrego }
27984163af6aSjose borrego 
27994163af6aSjose borrego static void
smb_server_destroy_session(smb_session_t * session)2800811599a4SMatt Barden smb_server_destroy_session(smb_session_t *session)
28014163af6aSjose borrego {
2802811599a4SMatt Barden 	smb_server_t *sv;
2803811599a4SMatt Barden 	smb_llist_t *ll;
2804811599a4SMatt Barden 	uint32_t count;
2805811599a4SMatt Barden 
2806811599a4SMatt Barden 	ASSERT(session->s_server != NULL);
2807811599a4SMatt Barden 	sv = session->s_server;
2808811599a4SMatt Barden 	ll = &sv->sv_session_list;
2809811599a4SMatt Barden 
2810811599a4SMatt Barden 	smb_llist_flush(&session->s_tree_list);
2811811599a4SMatt Barden 	smb_llist_flush(&session->s_user_list);
2812811599a4SMatt Barden 
2813811599a4SMatt Barden 	smb_llist_enter(ll, RW_WRITER);
2814811599a4SMatt Barden 	smb_llist_remove(ll, session);
2815811599a4SMatt Barden 	count = ll->ll_count;
2816811599a4SMatt Barden 	smb_llist_exit(ll);
2817811599a4SMatt Barden 
28187f5d80fdSGordon Ross 	/*
28197f5d80fdSGordon Ross 	 * Normally, the session should have state SHUTDOWN here.
28207f5d80fdSGordon Ross 	 * If the session has any ofiles remaining, eg. due to
28217f5d80fdSGordon Ross 	 * forgotten ofile references or something, the state
28227f5d80fdSGordon Ross 	 * will be _DISCONNECTED or _TERMINATED.  Keep such
28237f5d80fdSGordon Ross 	 * sessions in the list of zombies (for debugging).
28247f5d80fdSGordon Ross 	 */
28257f5d80fdSGordon Ross 	if (session->s_state == SMB_SESSION_STATE_SHUTDOWN) {
28267f5d80fdSGordon Ross 		smb_session_delete(session);
28277f5d80fdSGordon Ross 	} else {
282886184067SGordon Ross 		cmn_err(CE_NOTE, "!Leaked session: 0x%p", (void *)session);
282986184067SGordon Ross 		DTRACE_PROBE1(new__zombie, smb_session_t *, session);
28307f5d80fdSGordon Ross 		smb_llist_enter(&smb_server_session_zombies, RW_WRITER);
28317f5d80fdSGordon Ross 		smb_llist_insert_head(&smb_server_session_zombies, session);
28327f5d80fdSGordon Ross 		smb_llist_exit(&smb_server_session_zombies);
28337f5d80fdSGordon Ross 	}
28347f5d80fdSGordon Ross 
2835811599a4SMatt Barden 	if (count == 0) {
2836811599a4SMatt Barden 		/* See smb_server_shutdown */
2837811599a4SMatt Barden 		cv_signal(&sv->sv_cv);
2838811599a4SMatt Barden 	}
28394163af6aSjose borrego }
2840