xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_server.c (revision e515d09638bef43f18c422960570a617671b523e)
1faa1795aSjb150015 /*
2faa1795aSjb150015  * CDDL HEADER START
3faa1795aSjb150015  *
4faa1795aSjb150015  * The contents of this file are subject to the terms of the
5faa1795aSjb150015  * Common Development and Distribution License (the "License").
6faa1795aSjb150015  * You may not use this file except in compliance with the License.
7faa1795aSjb150015  *
8faa1795aSjb150015  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9faa1795aSjb150015  * or http://www.opensolaris.org/os/licensing.
10faa1795aSjb150015  * See the License for the specific language governing permissions
11faa1795aSjb150015  * and limitations under the License.
12faa1795aSjb150015  *
13faa1795aSjb150015  * When distributing Covered Code, include this CDDL HEADER in each
14faa1795aSjb150015  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15faa1795aSjb150015  * If applicable, add the following below this CDDL HEADER, with the
16faa1795aSjb150015  * fields enclosed by brackets "[]" replaced with your own identifying
17faa1795aSjb150015  * information: Portions Copyright [yyyy] [name of copyright owner]
18faa1795aSjb150015  *
19faa1795aSjb150015  * CDDL HEADER END
20faa1795aSjb150015  */
21faa1795aSjb150015 /*
22c5866007SKeyur Desai  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
23adc68ba9SPavel Zakharov  * Copyright (c) 2017 by Delphix. All rights reserved.
24896d9552SGordon Ross  * Copyright 2019 Nexenta by DDN, Inc. All rights reserved.
255d8538b6SGordon Ross  * Copyright 2021-2023 RackTop Systems, Inc.
26faa1795aSjb150015  */
27faa1795aSjb150015 
28faa1795aSjb150015 /*
29faa1795aSjb150015  * General Structures Layout
30faa1795aSjb150015  * -------------------------
31faa1795aSjb150015  *
32faa1795aSjb150015  * This is a simplified diagram showing the relationship between most of the
33faa1795aSjb150015  * main structures.
34faa1795aSjb150015  *
35faa1795aSjb150015  * +-------------------+
36faa1795aSjb150015  * |     SMB_SERVER    |
37faa1795aSjb150015  * +-------------------+
38faa1795aSjb150015  *          |
39faa1795aSjb150015  *          |
40faa1795aSjb150015  *          v
41faa1795aSjb150015  * +-------------------+       +-------------------+      +-------------------+
42faa1795aSjb150015  * |     SESSION       |<----->|     SESSION       |......|      SESSION      |
43faa1795aSjb150015  * +-------------------+       +-------------------+      +-------------------+
44faa1795aSjb150015  *          |
45faa1795aSjb150015  *          |
46faa1795aSjb150015  *          v
47faa1795aSjb150015  * +-------------------+       +-------------------+      +-------------------+
48faa1795aSjb150015  * |       USER        |<----->|       USER        |......|       USER        |
49faa1795aSjb150015  * +-------------------+       +-------------------+      +-------------------+
50faa1795aSjb150015  *          |
51faa1795aSjb150015  *          |
52faa1795aSjb150015  *          v
53faa1795aSjb150015  * +-------------------+       +-------------------+      +-------------------+
54faa1795aSjb150015  * |       TREE        |<----->|       TREE        |......|       TREE        |
55faa1795aSjb150015  * +-------------------+       +-------------------+      +-------------------+
56faa1795aSjb150015  *      |         |
57faa1795aSjb150015  *      |         |
58faa1795aSjb150015  *      |         v
59faa1795aSjb150015  *      |     +-------+       +-------+      +-------+
60faa1795aSjb150015  *      |     | OFILE |<----->| OFILE |......| OFILE |
61faa1795aSjb150015  *      |     +-------+       +-------+      +-------+
62faa1795aSjb150015  *      |
63faa1795aSjb150015  *      |
64faa1795aSjb150015  *      v
65faa1795aSjb150015  *  +-------+       +------+      +------+
66faa1795aSjb150015  *  | ODIR  |<----->| ODIR |......| ODIR |
67faa1795aSjb150015  *  +-------+       +------+      +------+
68faa1795aSjb150015  *
69faa1795aSjb150015  *
70faa1795aSjb150015  * Module Interface Overview
71faa1795aSjb150015  * -------------------------
72faa1795aSjb150015  *
73faa1795aSjb150015  *
74faa1795aSjb150015  *	    +===================================+
75faa1795aSjb150015  *	    |		 smbd daemon		|
76faa1795aSjb150015  *	    +===================================+
77faa1795aSjb150015  *	      |		     |		      ^
78faa1795aSjb150015  *	      |		     |		      |
79faa1795aSjb150015  * User	      |		     |		      |
80faa1795aSjb150015  * -----------|--------------|----------------|--------------------------------
81faa1795aSjb150015  * Kernel     |		     |		      |
82faa1795aSjb150015  *            |		     |		      |
83faa1795aSjb150015  *	      |		     |		      |
84faa1795aSjb150015  *  +=========|==============|================|=================+
85faa1795aSjb150015  *  |	      v		     v		      |			|
86faa1795aSjb150015  *  | +-----------+ +--------------------+ +------------------+ |
87faa1795aSjb150015  *  | |     IO    | | Kernel Door Server | | User Door Servers|	|
88faa1795aSjb150015  *  | | Interface | |     Interface      | |   Interface      | |
89faa1795aSjb150015  *  | +-----------+ +--------------------+ +------------------+ |
90faa1795aSjb150015  *  |		|	     |		      ^		^	|
91faa1795aSjb150015  *  |		v	     v		      |		|	|    +=========+
92faa1795aSjb150015  *  |	     +-----------------------------------+	|	|    |	       |
93faa1795aSjb150015  *  |	     + SMB Server Management (this file) |<------------------|	 ZFS   |
94faa1795aSjb150015  *  |	     +-----------------------------------+	|	|    |	       |
95faa1795aSjb150015  *  |							|	|    |  Module |
96faa1795aSjb150015  *  |	     +-----------------------------------+	|	|    |	       |
97faa1795aSjb150015  *  |	     +     SMB Server Internal Layers    |------+	|    +=========+
98faa1795aSjb150015  *  |	     +-----------------------------------+		|
99faa1795aSjb150015  *  |								|
100faa1795aSjb150015  *  |								|
101faa1795aSjb150015  *  +===========================================================+
102faa1795aSjb150015  *
103faa1795aSjb150015  *
104faa1795aSjb150015  * Server State Machine
105faa1795aSjb150015  * --------------------
106faa1795aSjb150015  *                                  |
107faa1795aSjb150015  *                                  | T0
108faa1795aSjb150015  *                                  |
109faa1795aSjb150015  *                                  v
110faa1795aSjb150015  *                    +-----------------------------+
111faa1795aSjb150015  *		      |   SMB_SERVER_STATE_CREATED  |
112faa1795aSjb150015  *		      +-----------------------------+
113faa1795aSjb150015  *				    |
114faa1795aSjb150015  *				    | T1
115faa1795aSjb150015  *				    |
116faa1795aSjb150015  *				    v
117faa1795aSjb150015  *		      +-----------------------------+
118faa1795aSjb150015  *		      | SMB_SERVER_STATE_CONFIGURED |
119faa1795aSjb150015  *		      +-----------------------------+
120faa1795aSjb150015  *				    |
121faa1795aSjb150015  *				    | T2
122faa1795aSjb150015  *				    |
123faa1795aSjb150015  *				    v
124faa1795aSjb150015  *		      +-----------------------------+
1259fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  *		      |  SMB_SERVER_STATE_RUNNING / |
1269fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  *		      |  SMB_SERVER_STATE_STOPPING  |
127faa1795aSjb150015  *		      +-----------------------------+
128faa1795aSjb150015  *				    |
129faa1795aSjb150015  *				    | T3
130faa1795aSjb150015  *				    |
131faa1795aSjb150015  *				    v
132faa1795aSjb150015  *		      +-----------------------------+
133faa1795aSjb150015  *		      |  SMB_SERVER_STATE_DELETING  |
134faa1795aSjb150015  *                    +-----------------------------+
135faa1795aSjb150015  *				    |
136faa1795aSjb150015  *				    |
137faa1795aSjb150015  *				    |
138faa1795aSjb150015  *				    v
139faa1795aSjb150015  *
140faa1795aSjb150015  * States
141faa1795aSjb150015  * ------
142faa1795aSjb150015  *
143faa1795aSjb150015  * SMB_SERVER_STATE_CREATED
144faa1795aSjb150015  *
145faa1795aSjb150015  *    This is the state of the server just after creation.
146faa1795aSjb150015  *
147faa1795aSjb150015  * SMB_SERVER_STATE_CONFIGURED
148faa1795aSjb150015  *
149faa1795aSjb150015  *    The server has been configured.
150faa1795aSjb150015  *
151faa1795aSjb150015  * SMB_SERVER_STATE_RUNNING
152faa1795aSjb150015  *
153faa1795aSjb150015  *    The server has been started. While in this state the threads listening on
1544163af6aSjose borrego  *    the sockets are started.
155faa1795aSjb150015  *
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.
159faa1795aSjb150015  *
160faa1795aSjb150015  * SMB_SERVER_STATE_STOPPING
161faa1795aSjb150015  *
162faa1795aSjb150015  *    The threads listening on the NBT and TCP sockets are being terminated.
163faa1795aSjb150015  *
164faa1795aSjb150015  *
165faa1795aSjb150015  * Transitions
166faa1795aSjb150015  * -----------
167faa1795aSjb150015  *
168faa1795aSjb150015  * Transition T0
169faa1795aSjb150015  *
170faa1795aSjb150015  *    The daemon smbd triggers its creation by opening the smbsrv device. If
171faa1795aSjb150015  *    the zone where the daemon lives doesn't have an smb server yet it is
172faa1795aSjb150015  *    created.
173faa1795aSjb150015  *
174faa1795aSjb150015  *		smb_drv_open() --> smb_server_create()
175faa1795aSjb150015  *
176faa1795aSjb150015  * Transition T1
177faa1795aSjb150015  *
178faa1795aSjb150015  *    This transition occurs in smb_server_configure(). It is triggered by the
179faa1795aSjb150015  *    daemon through an Ioctl.
180faa1795aSjb150015  *
181faa1795aSjb150015  *	smb_drv_ioctl(SMB_IOC_CONFIG) --> smb_server_configure()
182faa1795aSjb150015  *
183faa1795aSjb150015  * Transition T2
184faa1795aSjb150015  *
185faa1795aSjb150015  *    This transition occurs in smb_server_start(). It is triggered by the
186faa1795aSjb150015  *    daemon through an Ioctl.
187faa1795aSjb150015  *
188faa1795aSjb150015  *	smb_drv_ioctl(SMB_IOC_START) --> smb_server_start()
189faa1795aSjb150015  *
190faa1795aSjb150015  * Transition T3
191faa1795aSjb150015  *
192faa1795aSjb150015  *    This transition occurs in smb_server_delete(). It is triggered by the
193faa1795aSjb150015  *    daemon when closing the smbsrv device
194faa1795aSjb150015  *
195faa1795aSjb150015  *		smb_drv_close() --> smb_server_delete()
196faa1795aSjb150015  *
197faa1795aSjb150015  * Comments
198faa1795aSjb150015  * --------
199faa1795aSjb150015  *
200faa1795aSjb150015  * This files assumes that there will one SMB server per zone. For now the
201faa1795aSjb150015  * smb server works only in global zone. There's nothing in this file preventing
202faa1795aSjb150015  * an smb server from being created in a non global zone. That limitation is
203faa1795aSjb150015  * enforced in user space.
204faa1795aSjb150015  */
205faa1795aSjb150015 
206faa1795aSjb150015 #include <sys/cmn_err.h>
207faa1795aSjb150015 #include <sys/priv.h>
208faa1795aSjb150015 #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>
221faa1795aSjb150015 #include <smbsrv/netbios.h>
222faa1795aSjb150015 #include <smbsrv/smb_fsops.h>
2233db3f65cSamw #include <smbsrv/smb_share.h>
2249fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States #include <smbsrv/smb_door.h>
2256537f381Sas200622 #include <smbsrv/smb_kstat.h>
226faa1795aSjb150015 
227148c5f43SAlan Wright static void smb_server_kstat_init(smb_server_t *);
228faa1795aSjb150015 static void smb_server_kstat_fini(smb_server_t *);
229faa1795aSjb150015 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 *);
232faa1795aSjb150015 static int smb_server_fsop_start(smb_server_t *);
233faa1795aSjb150015 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);
236faa1795aSjb150015 
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 
281faa1795aSjb150015 static smb_llist_t	smb_servers;
282faa1795aSjb150015 
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 
296faa1795aSjb150015 /*
297faa1795aSjb150015  * *****************************************************************************
298faa1795aSjb150015  * **************** Functions called from the device interface *****************
299faa1795aSjb150015  * *****************************************************************************
300faa1795aSjb150015  *
3011fcced4cSJordan Brown  * These functions typically have to determine the relevant smb server
3021fcced4cSJordan Brown  * to which the call applies.
303faa1795aSjb150015  */
304faa1795aSjb150015 
305faa1795aSjb150015 /*
306a90cf9f2SGordon Ross  * How many zones have an SMB server active?
307a90cf9f2SGordon Ross  */
308a90cf9f2SGordon Ross int
309a90cf9f2SGordon Ross smb_server_get_count(void)
310a90cf9f2SGordon Ross {
311a90cf9f2SGordon Ross 	return (smb_llist_get_count(&smb_servers));
312a90cf9f2SGordon Ross }
313a90cf9f2SGordon Ross 
314a90cf9f2SGordon Ross /*
3158622ec45SGordon Ross  * smb_server_g_init
316faa1795aSjb150015  *
317c8ec8eeaSjose borrego  * This function must be called from smb_drv_attach().
318faa1795aSjb150015  */
319faa1795aSjb150015 int
3208622ec45SGordon Ross smb_server_g_init(void)
321faa1795aSjb150015 {
3228622ec45SGordon Ross 	int rc;
323faa1795aSjb150015 
3248622ec45SGordon Ross 	if ((rc = smb_vop_init()) != 0)
3258622ec45SGordon Ross 		goto errout;
3268622ec45SGordon Ross 	if ((rc = smb_fem_init()) != 0)
3278622ec45SGordon Ross 		goto errout;
3288622ec45SGordon Ross 
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 
3549fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_init();
355faa1795aSjb150015 	smb_llist_constructor(&smb_servers, sizeof (smb_server_t),
356faa1795aSjb150015 	    offsetof(smb_server_t, sv_lnd));
3579fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
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:
364faa1795aSjb150015 	smb_fem_fini();
365faa1795aSjb150015 	smb_vop_fini();
366faa1795aSjb150015 	return (rc);
367faa1795aSjb150015 }
368faa1795aSjb150015 
369faa1795aSjb150015 /*
3708622ec45SGordon Ross  * smb_server_g_fini
371faa1795aSjb150015  *
372faa1795aSjb150015  * This function must called from smb_drv_detach(). It will fail if servers
373faa1795aSjb150015  * still exist.
374faa1795aSjb150015  */
375a90cf9f2SGordon Ross void
3768622ec45SGordon Ross smb_server_g_fini(void)
377faa1795aSjb150015 {
378faa1795aSjb150015 
379a90cf9f2SGordon Ross 	ASSERT(smb_llist_get_count(&smb_servers) == 0);
380a90cf9f2SGordon Ross 
3819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	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();
394faa1795aSjb150015 	smb_node_fini();
3952c2961f8Sjose borrego 	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 
402faa1795aSjb150015 	smb_llist_destructor(&smb_servers);
403faa1795aSjb150015 }
404faa1795aSjb150015 
405faa1795aSjb150015 /*
406faa1795aSjb150015  * smb_server_create
407faa1795aSjb150015  *
4085d8538b6SGordon Ross  * Called by driver open
4095d8538b6SGordon Ross  *
410faa1795aSjb150015  * This function will fail if there's already a server associated with the
411faa1795aSjb150015  * 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.
416faa1795aSjb150015  */
417faa1795aSjb150015 int
418faa1795aSjb150015 smb_server_create(void)
419faa1795aSjb150015 {
420faa1795aSjb150015 	zoneid_t	zid;
421faa1795aSjb150015 	smb_server_t	*sv;
422faa1795aSjb150015 
423faa1795aSjb150015 	zid = getzoneid();
424faa1795aSjb150015 
425faa1795aSjb150015 	smb_llist_enter(&smb_servers, RW_WRITER);
426faa1795aSjb150015 	sv = smb_llist_head(&smb_servers);
427faa1795aSjb150015 	while (sv) {
4289fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_SERVER_VALID(sv);
429faa1795aSjb150015 		if (sv->sv_zid == zid) {
430faa1795aSjb150015 			smb_llist_exit(&smb_servers);
43194fff790SAlan Wright 			return (EPERM);
432faa1795aSjb150015 		}
433faa1795aSjb150015 		sv = smb_llist_next(&smb_servers, sv);
434faa1795aSjb150015 	}
435faa1795aSjb150015 
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();
4425d8538b6SGordon Ross 	sv->sv_proc_state = SMB_THREAD_STATE_EXITED;
4438622ec45SGordon Ross 
4448622ec45SGordon Ross 	mutex_init(&sv->sv_mutex, NULL, MUTEX_DEFAULT, NULL);
4458622ec45SGordon Ross 	cv_init(&sv->sv_cv, NULL, CV_DEFAULT, NULL);
4468622ec45SGordon Ross 	cv_init(&sv->sp_info.sp_cv, NULL, CV_DEFAULT, NULL);
447faa1795aSjb150015 
448811599a4SMatt Barden 	sv->sv_persistid_ht = smb_hash_create(sizeof (smb_ofile_t),
449811599a4SMatt Barden 	    offsetof(smb_ofile_t, f_dh_lnd), SMB_OFILE_HASH_NBUCKETS);
450811599a4SMatt Barden 
45194047d49SGordon Ross 	sv->sv_lease_ht = smb_hash_create(sizeof (smb_lease_t),
45294047d49SGordon Ross 	    offsetof(smb_lease_t, ls_lnd), SMB_LEASE_HASH_NBUCKETS);
45394047d49SGordon Ross 
454811599a4SMatt Barden 	smb_llist_constructor(&sv->sv_session_list, sizeof (smb_session_t),
455811599a4SMatt Barden 	    offsetof(smb_session_t, s_lnd));
456811599a4SMatt Barden 
4579fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_constructor(&sv->sv_event_list, sizeof (smb_event_t),
4589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	    offsetof(smb_event_t, se_lnd));
4599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
460cb174861Sjoyce mcintosh 	smb_llist_constructor(&sv->sp_info.sp_list, sizeof (smb_kspooldoc_t),
461cb174861Sjoyce mcintosh 	    offsetof(smb_kspooldoc_t, sd_lnd));
462cb174861Sjoyce mcintosh 
463cb174861Sjoyce mcintosh 	smb_llist_constructor(&sv->sp_info.sp_fidlist,
464cb174861Sjoyce mcintosh 	    sizeof (smb_spoolfid_t), offsetof(smb_spoolfid_t, sf_lnd));
465cb174861Sjoyce mcintosh 
466a90cf9f2SGordon Ross 	sv->sv_disp_stats1 = kmem_zalloc(SMB_COM_NUM *
467a90cf9f2SGordon Ross 	    sizeof (smb_disp_stats_t), KM_SLEEP);
468a90cf9f2SGordon Ross 
469a90cf9f2SGordon Ross 	sv->sv_disp_stats2 = kmem_zalloc(SMB2__NCMDS *
4708622ec45SGordon Ross 	    sizeof (smb_disp_stats_t), KM_SLEEP);
471faa1795aSjb150015 
47208344b29SGordon Ross 	smb_thread_init(&sv->si_thread_timers, "smb_timers",
4735d8538b6SGordon Ross 	    smb_server_timers, sv, smbsrv_timer_pri, sv);
474faa1795aSjb150015 
475148c5f43SAlan Wright 	smb_srqueue_init(&sv->sv_srqueue);
476faa1795aSjb150015 
4778622ec45SGordon Ross 	smb_kdoor_init(sv);
4788622ec45SGordon Ross 	smb_kshare_init(sv);
479148c5f43SAlan Wright 	smb_server_kstat_init(sv);
480faa1795aSjb150015 
481856399cfSGordon Ross 	smb_threshold_init(&sv->sv_ssetup_ct, SMB_SSETUP_CMD,
482856399cfSGordon Ross 	    smb_ssetup_threshold, smb_ssetup_timeout);
483856399cfSGordon Ross 	smb_threshold_init(&sv->sv_tcon_ct, SMB_TCON_CMD,
484856399cfSGordon Ross 	    smb_tcon_threshold, smb_tcon_timeout);
485856399cfSGordon Ross 	smb_threshold_init(&sv->sv_opipe_ct, SMB_OPIPE_CMD,
486856399cfSGordon Ross 	    smb_opipe_threshold, smb_opipe_timeout);
487856399cfSGordon Ross 
488faa1795aSjb150015 	smb_llist_insert_tail(&smb_servers, sv);
489faa1795aSjb150015 	smb_llist_exit(&smb_servers);
490cb174861Sjoyce mcintosh 
491faa1795aSjb150015 	return (0);
492faa1795aSjb150015 }
493faa1795aSjb150015 
494faa1795aSjb150015 /*
495faa1795aSjb150015  * smb_server_delete
496faa1795aSjb150015  *
4975d8538b6SGordon Ross  * Called by driver close
4985d8538b6SGordon Ross  *
499faa1795aSjb150015  * This function will delete the server passed in. It will make sure that all
500faa1795aSjb150015  * activity associated that server has ceased before destroying it.
501faa1795aSjb150015  */
502faa1795aSjb150015 int
5038d94f651SGordon Ross smb_server_delete(smb_server_t	*sv)
504faa1795aSjb150015 {
505faa1795aSjb150015 
506faa1795aSjb150015 	mutex_enter(&sv->sv_mutex);
507faa1795aSjb150015 	switch (sv->sv_state) {
508faa1795aSjb150015 	case SMB_SERVER_STATE_RUNNING:
5099fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		sv->sv_state = SMB_SERVER_STATE_STOPPING;
510faa1795aSjb150015 		mutex_exit(&sv->sv_mutex);
5114163af6aSjose borrego 		smb_server_shutdown(sv);
512faa1795aSjb150015 		mutex_enter(&sv->sv_mutex);
5134163af6aSjose borrego 		cv_broadcast(&sv->sp_info.sp_cv);
5144163af6aSjose borrego 		sv->sv_state = SMB_SERVER_STATE_DELETING;
5154163af6aSjose borrego 		break;
5164163af6aSjose borrego 	case SMB_SERVER_STATE_STOPPING:
5174163af6aSjose borrego 		sv->sv_state = SMB_SERVER_STATE_DELETING;
518faa1795aSjb150015 		break;
519faa1795aSjb150015 	case SMB_SERVER_STATE_CONFIGURED:
520faa1795aSjb150015 	case SMB_SERVER_STATE_CREATED:
521faa1795aSjb150015 		sv->sv_state = SMB_SERVER_STATE_DELETING;
522faa1795aSjb150015 		break;
523faa1795aSjb150015 	default:
5249fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_SERVER_STATE_VALID(sv->sv_state);
525faa1795aSjb150015 		mutex_exit(&sv->sv_mutex);
526faa1795aSjb150015 		smb_server_release(sv);
527faa1795aSjb150015 		return (ENOTTY);
528faa1795aSjb150015 	}
529faa1795aSjb150015 
530faa1795aSjb150015 	ASSERT(sv->sv_state == SMB_SERVER_STATE_DELETING);
531faa1795aSjb150015 
532faa1795aSjb150015 	sv->sv_refcnt--;
533faa1795aSjb150015 	while (sv->sv_refcnt)
534faa1795aSjb150015 		cv_wait(&sv->sv_cv, &sv->sv_mutex);
535faa1795aSjb150015 
536faa1795aSjb150015 	mutex_exit(&sv->sv_mutex);
537faa1795aSjb150015 
538faa1795aSjb150015 	smb_llist_enter(&smb_servers, RW_WRITER);
539faa1795aSjb150015 	smb_llist_remove(&smb_servers, sv);
540faa1795aSjb150015 	smb_llist_exit(&smb_servers);
541faa1795aSjb150015 
542856399cfSGordon Ross 	smb_threshold_fini(&sv->sv_ssetup_ct);
543856399cfSGordon Ross 	smb_threshold_fini(&sv->sv_tcon_ct);
544856399cfSGordon Ross 	smb_threshold_fini(&sv->sv_opipe_ct);
545856399cfSGordon Ross 
5464163af6aSjose borrego 	smb_server_listener_destroy(&sv->sv_nbt_daemon);
5474163af6aSjose borrego 	smb_server_listener_destroy(&sv->sv_tcp_daemon);
548faa1795aSjb150015 	rw_destroy(&sv->sv_cfg_lock);
549faa1795aSjb150015 	smb_server_kstat_fini(sv);
5508622ec45SGordon Ross 	smb_kshare_fini(sv);
5518622ec45SGordon Ross 	smb_kdoor_fini(sv);
5529fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_destructor(&sv->sv_event_list);
553811599a4SMatt Barden 	smb_llist_destructor(&sv->sv_session_list);
5542c1b14e5Sjose borrego 
555a90cf9f2SGordon Ross 	kmem_free(sv->sv_disp_stats1,
5568622ec45SGordon Ross 	    SMB_COM_NUM * sizeof (smb_disp_stats_t));
557faa1795aSjb150015 
558a90cf9f2SGordon Ross 	kmem_free(sv->sv_disp_stats2,
559a90cf9f2SGordon Ross 	    SMB2__NCMDS * sizeof (smb_disp_stats_t));
560a90cf9f2SGordon Ross 
561148c5f43SAlan Wright 	smb_srqueue_destroy(&sv->sv_srqueue);
562faa1795aSjb150015 	smb_thread_destroy(&sv->si_thread_timers);
5638622ec45SGordon Ross 
564faa1795aSjb150015 	mutex_destroy(&sv->sv_mutex);
56594047d49SGordon Ross 	smb_hash_destroy(sv->sv_lease_ht);
566811599a4SMatt Barden 	smb_hash_destroy(sv->sv_persistid_ht);
567faa1795aSjb150015 	cv_destroy(&sv->sv_cv);
568faa1795aSjb150015 	sv->sv_magic = 0;
569faa1795aSjb150015 	kmem_free(sv, sizeof (smb_server_t));
570faa1795aSjb150015 
571faa1795aSjb150015 	return (0);
572faa1795aSjb150015 }
573faa1795aSjb150015 
574faa1795aSjb150015 /*
575faa1795aSjb150015  * smb_server_configure
5765d8538b6SGordon Ross  *
5775d8538b6SGordon Ross  * Called via SMB_IOC_CONFIG, for smbd startup or refresh.
578faa1795aSjb150015  */
579faa1795aSjb150015 int
58029bd2886SAlan Wright smb_server_configure(smb_ioc_cfg_t *ioc)
581faa1795aSjb150015 {
582faa1795aSjb150015 	int		rc = 0;
583faa1795aSjb150015 	smb_server_t	*sv;
584faa1795aSjb150015 
5851d443a93SDan McDonald 	/*
5861d443a93SDan McDonald 	 * Reality check negotiation token length vs. #define'd maximum.
5871d443a93SDan McDonald 	 */
5881d443a93SDan McDonald 	if (ioc->negtok_len > SMB_PI_MAX_NEGTOK)
5891d443a93SDan McDonald 		return (EINVAL);
5901d443a93SDan McDonald 
591faa1795aSjb150015 	rc = smb_server_lookup(&sv);
592faa1795aSjb150015 	if (rc)
593faa1795aSjb150015 		return (rc);
594faa1795aSjb150015 
595faa1795aSjb150015 	mutex_enter(&sv->sv_mutex);
596faa1795aSjb150015 	switch (sv->sv_state) {
597faa1795aSjb150015 	case SMB_SERVER_STATE_CREATED:
59829bd2886SAlan Wright 		smb_server_store_cfg(sv, ioc);
599faa1795aSjb150015 		sv->sv_state = SMB_SERVER_STATE_CONFIGURED;
600faa1795aSjb150015 		break;
601faa1795aSjb150015 
602faa1795aSjb150015 	case SMB_SERVER_STATE_CONFIGURED:
60329bd2886SAlan Wright 		smb_server_store_cfg(sv, ioc);
604faa1795aSjb150015 		break;
605faa1795aSjb150015 
606faa1795aSjb150015 	case SMB_SERVER_STATE_RUNNING:
6079fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	case SMB_SERVER_STATE_STOPPING:
608faa1795aSjb150015 		rw_enter(&sv->sv_cfg_lock, RW_WRITER);
60929bd2886SAlan Wright 		smb_server_store_cfg(sv, ioc);
610faa1795aSjb150015 		rw_exit(&sv->sv_cfg_lock);
611faa1795aSjb150015 		break;
612faa1795aSjb150015 
613faa1795aSjb150015 	default:
6149fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_SERVER_STATE_VALID(sv->sv_state);
615faa1795aSjb150015 		rc = EFAULT;
616faa1795aSjb150015 		break;
617faa1795aSjb150015 	}
618faa1795aSjb150015 	mutex_exit(&sv->sv_mutex);
619faa1795aSjb150015 
620faa1795aSjb150015 	smb_server_release(sv);
621faa1795aSjb150015 
622faa1795aSjb150015 	return (rc);
623faa1795aSjb150015 }
624faa1795aSjb150015 
625faa1795aSjb150015 /*
626faa1795aSjb150015  * smb_server_start
6275d8538b6SGordon Ross  *
6285d8538b6SGordon Ross  * Called via SMB_IOC_START during smbd startup.
6295d8538b6SGordon Ross  * Bring up the activities requried for SMB service.
630faa1795aSjb150015  */
631faa1795aSjb150015 int
63229bd2886SAlan Wright smb_server_start(smb_ioc_start_t *ioc)
633faa1795aSjb150015 {
634faa1795aSjb150015 	int		rc = 0;
6354163af6aSjose borrego 	int		family;
636faa1795aSjb150015 	smb_server_t	*sv;
6378d94f651SGordon Ross 	cred_t		*ucr;
6385d8538b6SGordon Ross 	struct proc	*tqproc;
639faa1795aSjb150015 
640faa1795aSjb150015 	rc = smb_server_lookup(&sv);
641faa1795aSjb150015 	if (rc)
642faa1795aSjb150015 		return (rc);
643faa1795aSjb150015 
644faa1795aSjb150015 	mutex_enter(&sv->sv_mutex);
645faa1795aSjb150015 	switch (sv->sv_state) {
646faa1795aSjb150015 	case SMB_SERVER_STATE_CONFIGURED:
647faa1795aSjb150015 
6485d8538b6SGordon Ross #ifdef	_KERNEL
6495d8538b6SGordon Ross 		if (smb_create_process) {
6505d8538b6SGordon Ross 			rc = smb_server_newproc(sv);
6515d8538b6SGordon Ross 			if (rc != 0)
6525d8538b6SGordon Ross 				break;
6535d8538b6SGordon Ross 		}
6545d8538b6SGordon Ross #endif	/* _KERNEL */
6555d8538b6SGordon Ross 
6568622ec45SGordon Ross 		if ((rc = smb_server_fsop_start(sv)) != 0)
6578622ec45SGordon Ross 			break;
6588622ec45SGordon Ross 
6598d94f651SGordon Ross 		/*
6608d94f651SGordon Ross 		 * Note: smb_kshare_start needs sv_session.
6618d94f651SGordon Ross 		 */
6628d94f651SGordon Ross 		sv->sv_session = smb_session_create(NULL, 0, sv, 0);
6638d94f651SGordon Ross 		if (sv->sv_session == NULL) {
6648d94f651SGordon Ross 			rc = ENOMEM;
6658d94f651SGordon Ross 			break;
6668d94f651SGordon Ross 		}
6678d94f651SGordon Ross 
6688d94f651SGordon Ross 		/*
6698d94f651SGordon Ross 		 * Create a logon on the server session,
6708d94f651SGordon Ross 		 * used when importing CA shares.
6718d94f651SGordon Ross 		 */
6728d94f651SGordon Ross 		sv->sv_rootuser = smb_user_new(sv->sv_session);
6738d94f651SGordon Ross 		ucr = smb_kcred_create();
6748d94f651SGordon Ross 		rc = smb_user_logon(sv->sv_rootuser, ucr, "", "root",
6758d94f651SGordon Ross 		    SMB_USER_FLAG_ADMIN, 0, 0);
6768d94f651SGordon Ross 		crfree(ucr);
6778d94f651SGordon Ross 		ucr = NULL;
6788d94f651SGordon Ross 		if (rc != 0) {
6798d94f651SGordon Ross 			cmn_err(CE_NOTE, "smb_server_start: "
6808d94f651SGordon Ross 			    "failed to create root user");
6818d94f651SGordon Ross 			break;
6828d94f651SGordon Ross 		}
6838d94f651SGordon Ross 
6848622ec45SGordon Ross 		if ((rc = smb_kshare_start(sv)) != 0)
6858622ec45SGordon Ross 			break;
6868622ec45SGordon Ross 
687b819cea2SGordon Ross 		/*
688*e515d096SGordon Ross 		 * Create our taskq's (thread pools)
689*e515d096SGordon Ross 		 *
690b819cea2SGordon Ross 		 * NB: the proc passed here has to be a "system" one.
691b819cea2SGordon Ross 		 * Normally that's p0, or the NGZ eqivalent.
692*e515d096SGordon Ross 		 *
693*e515d096SGordon Ross 		 * The notify pool is sized at a quarter the number of
694*e515d096SGordon Ross 		 * worker threads (instead of another config item).
695b819cea2SGordon Ross 		 */
6965d8538b6SGordon Ross 		tqproc = (sv->sv_proc_p != NULL) ?
6975d8538b6SGordon Ross 		    sv->sv_proc_p : curzone->zone_zsched;
6985d8538b6SGordon Ross 
699*e515d096SGordon Ross 		sv->sv_notify_pool = taskq_create_proc("smb_notify",
700*e515d096SGordon Ross 		    sv->sv_cfg.skc_maxworkers / 4, smbsrv_notify_pri,
701*e515d096SGordon Ross 		    sv->sv_cfg.skc_maxworkers / 4, INT_MAX,
702*e515d096SGordon Ross 		    tqproc, TASKQ_DYNAMIC);
703*e515d096SGordon Ross 
7048622ec45SGordon Ross 		sv->sv_worker_pool = taskq_create_proc("smb_workers",
70508344b29SGordon Ross 		    sv->sv_cfg.skc_maxworkers, smbsrv_worker_pri,
706faa1795aSjb150015 		    sv->sv_cfg.skc_maxworkers, INT_MAX,
7075d8538b6SGordon Ross 		    tqproc, TASKQ_DYNAMIC);
708faa1795aSjb150015 
7098622ec45SGordon Ross 		sv->sv_receiver_pool = taskq_create_proc("smb_receivers",
71008344b29SGordon Ross 		    sv->sv_cfg.skc_maxconnections, smbsrv_receive_pri,
7114163af6aSjose borrego 		    sv->sv_cfg.skc_maxconnections, INT_MAX,
7125d8538b6SGordon Ross 		    tqproc, TASKQ_DYNAMIC);
7134163af6aSjose borrego 
714*e515d096SGordon Ross 		if (sv->sv_notify_pool == NULL ||
715*e515d096SGordon Ross 		    sv->sv_worker_pool == NULL ||
7168d94f651SGordon Ross 		    sv->sv_receiver_pool == NULL) {
717faa1795aSjb150015 			rc = ENOMEM;
718faa1795aSjb150015 			break;
719faa1795aSjb150015 		}
720faa1795aSjb150015 
721b819cea2SGordon Ross #ifdef	_KERNEL
722faa1795aSjb150015 		ASSERT(sv->sv_lmshrd == NULL);
723148c5f43SAlan Wright 		sv->sv_lmshrd = smb_kshare_door_init(ioc->lmshrd);
724faa1795aSjb150015 		if (sv->sv_lmshrd == NULL)
725faa1795aSjb150015 			break;
72654026d5aSGordon Ross 		if ((rc = smb_kdoor_open(sv, ioc->udoor)) != 0) {
7279fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			cmn_err(CE_WARN, "Cannot open smbd door");
728faa1795aSjb150015 			break;
7299fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		}
730b819cea2SGordon Ross #else	/* _KERNEL */
731b819cea2SGordon Ross 		/* Fake kernel does not use the kshare_door */
732b819cea2SGordon Ross 		fksmb_kdoor_open(sv, ioc->udoor_func);
733b819cea2SGordon Ross #endif	/* _KERNEL */
734b819cea2SGordon Ross 
73554026d5aSGordon Ross 		if ((rc = smb_thread_start(&sv->si_thread_timers)) != 0)
7369fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			break;
7374163af6aSjose borrego 
7384163af6aSjose borrego 		family = AF_INET;
7394163af6aSjose borrego 		smb_server_listener_init(sv, &sv->sv_nbt_daemon,
7404163af6aSjose borrego 		    "smb_nbt_listener", IPPORT_NETBIOS_SSN, family);
7414163af6aSjose borrego 		if (sv->sv_cfg.skc_ipv6_enable)
7424163af6aSjose borrego 			family = AF_INET6;
7434163af6aSjose borrego 		smb_server_listener_init(sv, &sv->sv_tcp_daemon,
7444163af6aSjose borrego 		    "smb_tcp_listener", IPPORT_SMB, family);
7454163af6aSjose borrego 		rc = smb_server_listener_start(&sv->sv_tcp_daemon);
7464163af6aSjose borrego 		if (rc != 0)
7474163af6aSjose borrego 			break;
74883d2dfe6SGordon Ross 		if (sv->sv_cfg.skc_netbios_enable)
74983d2dfe6SGordon Ross 			(void) smb_server_listener_start(&sv->sv_nbt_daemon);
7504163af6aSjose borrego 
751faa1795aSjb150015 		sv->sv_state = SMB_SERVER_STATE_RUNNING;
752148c5f43SAlan Wright 		sv->sv_start_time = gethrtime();
753faa1795aSjb150015 		mutex_exit(&sv->sv_mutex);
754faa1795aSjb150015 		smb_server_release(sv);
7558622ec45SGordon Ross 		smb_export_start(sv);
756faa1795aSjb150015 		return (0);
757faa1795aSjb150015 	default:
7589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_SERVER_STATE_VALID(sv->sv_state);
759faa1795aSjb150015 		mutex_exit(&sv->sv_mutex);
760faa1795aSjb150015 		smb_server_release(sv);
761faa1795aSjb150015 		return (ENOTTY);
762faa1795aSjb150015 	}
763faa1795aSjb150015 
764faa1795aSjb150015 	mutex_exit(&sv->sv_mutex);
7654163af6aSjose borrego 	smb_server_shutdown(sv);
766faa1795aSjb150015 	smb_server_release(sv);
767faa1795aSjb150015 	return (rc);
768faa1795aSjb150015 }
769faa1795aSjb150015 
770faa1795aSjb150015 /*
7719fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * An smbd is shutting down.
7729fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  */
7739fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States int
7749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_server_stop(void)
7759fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
7769fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_server_t	*sv;
7779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	int		rc;
7789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if ((rc = smb_server_lookup(&sv)) != 0)
7809fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (rc);
7819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7829fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_enter(&sv->sv_mutex);
7839fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	switch (sv->sv_state) {
7849fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	case SMB_SERVER_STATE_RUNNING:
7859fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		sv->sv_state = SMB_SERVER_STATE_STOPPING;
7864163af6aSjose borrego 		mutex_exit(&sv->sv_mutex);
7874163af6aSjose borrego 		smb_server_shutdown(sv);
7884163af6aSjose borrego 		mutex_enter(&sv->sv_mutex);
789cb174861Sjoyce mcintosh 		cv_broadcast(&sv->sp_info.sp_cv);
7909fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		break;
7919fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	default:
7929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_SERVER_STATE_VALID(sv->sv_state);
7939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		break;
7949fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
7959fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_exit(&sv->sv_mutex);
7969fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7979fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_server_release(sv);
7989fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	return (0);
7999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
8009fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
8019fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States boolean_t
8028622ec45SGordon Ross smb_server_is_stopping(smb_server_t *sv)
8039fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
8049fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	boolean_t	status;
8059fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
8069fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	SMB_SERVER_VALID(sv);
8079fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
8089fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_enter(&sv->sv_mutex);
8099fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
8109fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	switch (sv->sv_state) {
8119fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	case SMB_SERVER_STATE_STOPPING:
8129fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	case SMB_SERVER_STATE_DELETING:
8139fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		status = B_TRUE;
8149fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		break;
8159fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	default:
8169fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		status = B_FALSE;
8179fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		break;
8189fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
8199fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
8209fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_exit(&sv->sv_mutex);
8219fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	return (status);
8229fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
8239fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
8248622ec45SGordon Ross void
8258622ec45SGordon Ross smb_server_cancel_event(smb_server_t *sv, uint32_t txid)
8269fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
8279fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_event_cancel(sv, txid);
8289fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
8299fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
8309fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States int
8319fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_server_notify_event(smb_ioc_event_t *ioc)
8329fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
8339fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_server_t	*sv;
8349fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	int		rc;
8359fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
8369fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if ((rc = smb_server_lookup(&sv)) == 0) {
8379fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		smb_event_notify(sv, ioc->txid);
8389fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		smb_server_release(sv);
8399fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
8409fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
8419fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	return (rc);
8429fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
8439fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
8449fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
845cb174861Sjoyce mcintosh  * smb_server_spooldoc
846cb174861Sjoyce mcintosh  *
847cb174861Sjoyce mcintosh  * Waits for print file close broadcast.
848cb174861Sjoyce mcintosh  * Gets the head of the fid list,
849cb174861Sjoyce mcintosh  * then searches the spooldoc list and returns
850cb174861Sjoyce mcintosh  * this info via the ioctl to user land.
851cb174861Sjoyce mcintosh  *
852cb174861Sjoyce mcintosh  * rc - 0 success
853cb174861Sjoyce mcintosh  */
854cb174861Sjoyce mcintosh 
855cb174861Sjoyce mcintosh int
856cb174861Sjoyce mcintosh smb_server_spooldoc(smb_ioc_spooldoc_t *ioc)
857cb174861Sjoyce mcintosh {
858cb174861Sjoyce mcintosh 	smb_server_t	*sv;
859cb174861Sjoyce mcintosh 	int		rc;
860cb174861Sjoyce mcintosh 	smb_kspooldoc_t *spdoc;
861cb174861Sjoyce mcintosh 	uint16_t	fid;
862cb174861Sjoyce mcintosh 
86323a9c295SGordon Ross 	if ((rc = smb_server_lookup(&sv)) != 0)
86423a9c295SGordon Ross 		return (rc);
86523a9c295SGordon Ross 
866b7301bf5SGordon Ross 	if (sv->sv_cfg.skc_print_enable == 0) {
867b7301bf5SGordon Ross 		rc = ENOTTY;
868b7301bf5SGordon Ross 		goto out;
869b7301bf5SGordon Ross 	}
870b7301bf5SGordon Ross 
87123a9c295SGordon Ross 	mutex_enter(&sv->sv_mutex);
87223a9c295SGordon Ross 	for (;;) {
873cb174861Sjoyce mcintosh 		if (sv->sv_state != SMB_SERVER_STATE_RUNNING) {
874cb174861Sjoyce mcintosh 			rc = ECANCELED;
87523a9c295SGordon Ross 			break;
87623a9c295SGordon Ross 		}
87723a9c295SGordon Ross 		if ((fid = smb_spool_get_fid(sv)) != 0) {
87823a9c295SGordon Ross 			rc = 0;
87923a9c295SGordon Ross 			break;
88023a9c295SGordon Ross 		}
88123a9c295SGordon Ross 		if (cv_wait_sig(&sv->sp_info.sp_cv, &sv->sv_mutex) == 0) {
88223a9c295SGordon Ross 			rc = EINTR;
88323a9c295SGordon Ross 			break;
88423a9c295SGordon Ross 		}
88523a9c295SGordon Ross 	}
88623a9c295SGordon Ross 	mutex_exit(&sv->sv_mutex);
887b7301bf5SGordon Ross 	if (rc != 0)
888b7301bf5SGordon Ross 		goto out;
889b7301bf5SGordon Ross 
89023a9c295SGordon Ross 	spdoc = kmem_zalloc(sizeof (*spdoc), KM_SLEEP);
89123a9c295SGordon Ross 	if (smb_spool_lookup_doc_byfid(sv, fid, spdoc)) {
892cb174861Sjoyce mcintosh 		ioc->spool_num = spdoc->sd_spool_num;
893cb174861Sjoyce mcintosh 		ioc->ipaddr = spdoc->sd_ipaddr;
894cb174861Sjoyce mcintosh 		(void) strlcpy(ioc->path, spdoc->sd_path,
895cb174861Sjoyce mcintosh 		    MAXPATHLEN);
896cb174861Sjoyce mcintosh 		(void) strlcpy(ioc->username,
897cb174861Sjoyce mcintosh 		    spdoc->sd_username, MAXNAMELEN);
89823a9c295SGordon Ross 	} else {
89923a9c295SGordon Ross 		/* Did not find that print job. */
90023a9c295SGordon Ross 		rc = EAGAIN;
901cb174861Sjoyce mcintosh 	}
90223a9c295SGordon Ross 	kmem_free(spdoc, sizeof (*spdoc));
90323a9c295SGordon Ross 
904b7301bf5SGordon Ross out:
905cb174861Sjoyce mcintosh 	smb_server_release(sv);
906cb174861Sjoyce mcintosh 	return (rc);
907cb174861Sjoyce mcintosh }
908cb174861Sjoyce mcintosh 
909faa1795aSjb150015 int
91029bd2886SAlan Wright smb_server_set_gmtoff(smb_ioc_gmt_t *ioc)
911faa1795aSjb150015 {
912faa1795aSjb150015 	int		rc;
913faa1795aSjb150015 	smb_server_t	*sv;
914faa1795aSjb150015 
91508f0d8daSafshin salek ardakani - Sun Microsystems - Irvine United States 	if ((rc = smb_server_lookup(&sv)) == 0) {
91629bd2886SAlan Wright 		sv->si_gmtoff = ioc->offset;
917faa1795aSjb150015 		smb_server_release(sv);
91808f0d8daSafshin salek ardakani - Sun Microsystems - Irvine United States 	}
919faa1795aSjb150015 
920faa1795aSjb150015 	return (rc);
921faa1795aSjb150015 }
922faa1795aSjb150015 
92329bd2886SAlan Wright int
9241fcced4cSJordan Brown smb_server_numopen(smb_ioc_opennum_t *ioc)
92529bd2886SAlan Wright {
92629bd2886SAlan Wright 	smb_server_t	*sv;
92729bd2886SAlan Wright 	int		rc;
92829bd2886SAlan Wright 
92929bd2886SAlan Wright 	if ((rc = smb_server_lookup(&sv)) == 0) {
930148c5f43SAlan Wright 		ioc->open_users = sv->sv_users;
931148c5f43SAlan Wright 		ioc->open_trees = sv->sv_trees;
932148c5f43SAlan Wright 		ioc->open_files = sv->sv_files + sv->sv_pipes;
93329bd2886SAlan Wright 		smb_server_release(sv);
93429bd2886SAlan Wright 	}
93529bd2886SAlan Wright 	return (rc);
93629bd2886SAlan Wright }
93729bd2886SAlan Wright 
938faa1795aSjb150015 /*
9391fcced4cSJordan Brown  * Enumerate objects within the server.  The svcenum provides the
9401fcced4cSJordan Brown  * enumeration context, i.e. what the caller want to get back.
9411fcced4cSJordan Brown  */
9421fcced4cSJordan Brown int
9431fcced4cSJordan Brown smb_server_enum(smb_ioc_svcenum_t *ioc)
9441fcced4cSJordan Brown {
9451fcced4cSJordan Brown 	smb_svcenum_t	*svcenum = &ioc->svcenum;
9461fcced4cSJordan Brown 	smb_server_t	*sv;
9471fcced4cSJordan Brown 	int		rc;
9481fcced4cSJordan Brown 
9491d443a93SDan McDonald 	/*
9501d443a93SDan McDonald 	 * Reality check that the buffer-length insize the enum doesn't
9511d443a93SDan McDonald 	 * overrun the ioctl's total length.
9521d443a93SDan McDonald 	 */
9531d443a93SDan McDonald 	if (svcenum->se_buflen + sizeof (*ioc) > ioc->hdr.len)
9541d443a93SDan McDonald 		return (EINVAL);
9551d443a93SDan McDonald 
9561fcced4cSJordan Brown 	if ((rc = smb_server_lookup(&sv)) != 0)
9571fcced4cSJordan Brown 		return (rc);
9581fcced4cSJordan Brown 
9591fcced4cSJordan Brown 	svcenum->se_bavail = svcenum->se_buflen;
9601fcced4cSJordan Brown 	svcenum->se_bused = 0;
9611fcced4cSJordan Brown 	svcenum->se_nitems = 0;
9621fcced4cSJordan Brown 
9633b13a1efSThomas Keiser 	switch (svcenum->se_type) {
9643b13a1efSThomas Keiser 	case SMB_SVCENUM_TYPE_USER:
9658d94f651SGordon Ross 		smb_server_enum_users(sv, svcenum);
9663b13a1efSThomas Keiser 		break;
9673b13a1efSThomas Keiser 	case SMB_SVCENUM_TYPE_TREE:
9683b13a1efSThomas Keiser 	case SMB_SVCENUM_TYPE_FILE:
9698d94f651SGordon Ross 		smb_server_enum_trees(sv, svcenum);
9703b13a1efSThomas Keiser 		break;
9713b13a1efSThomas Keiser 	default:
9723b13a1efSThomas Keiser 		rc = EINVAL;
9733b13a1efSThomas Keiser 	}
9741fcced4cSJordan Brown 
9751fcced4cSJordan Brown 	smb_server_release(sv);
9763b13a1efSThomas Keiser 	return (rc);
9771fcced4cSJordan Brown }
9781fcced4cSJordan Brown 
9791fcced4cSJordan Brown /*
9801fcced4cSJordan Brown  * Look for sessions to disconnect by client and user name.
9811fcced4cSJordan Brown  */
9821fcced4cSJordan Brown int
9831fcced4cSJordan Brown smb_server_session_close(smb_ioc_session_t *ioc)
9841fcced4cSJordan Brown {
9851fcced4cSJordan Brown 	smb_server_t	*sv;
986811599a4SMatt Barden 	int		cnt;
9871fcced4cSJordan Brown 	int		rc;
9881fcced4cSJordan Brown 
9891fcced4cSJordan Brown 	if ((rc = smb_server_lookup(&sv)) != 0)
9901fcced4cSJordan Brown 		return (rc);
9911fcced4cSJordan Brown 
9928d94f651SGordon Ross 	cnt = smb_server_session_disconnect(sv, ioc->client, ioc->username);
9931fcced4cSJordan Brown 
9941fcced4cSJordan Brown 	smb_server_release(sv);
9951fcced4cSJordan Brown 
996811599a4SMatt Barden 	if (cnt == 0)
9971fcced4cSJordan Brown 		return (ENOENT);
9981fcced4cSJordan Brown 	return (0);
9991fcced4cSJordan Brown }
10001fcced4cSJordan Brown 
10011fcced4cSJordan Brown /*
10021fcced4cSJordan Brown  * Close a file by uniqid.
10031fcced4cSJordan Brown  */
10041fcced4cSJordan Brown int
10051fcced4cSJordan Brown smb_server_file_close(smb_ioc_fileid_t *ioc)
10061fcced4cSJordan Brown {
10071fcced4cSJordan Brown 	uint32_t	uniqid = ioc->uniqid;
10081fcced4cSJordan Brown 	smb_server_t	*sv;
10091fcced4cSJordan Brown 	int		rc;
10101fcced4cSJordan Brown 
10111fcced4cSJordan Brown 	if ((rc = smb_server_lookup(&sv)) != 0)
10121fcced4cSJordan Brown 		return (rc);
10131fcced4cSJordan Brown 
10148d94f651SGordon Ross 	rc = smb_server_fclose(sv, uniqid);
10151fcced4cSJordan Brown 
10161fcced4cSJordan Brown 	smb_server_release(sv);
10171fcced4cSJordan Brown 	return (rc);
10181fcced4cSJordan Brown }
10191fcced4cSJordan Brown 
10201fcced4cSJordan Brown /*
1021faa1795aSjb150015  * These functions determine the relevant smb server to which the call apply.
1022faa1795aSjb150015  */
1023faa1795aSjb150015 
1024faa1795aSjb150015 uint32_t
10258622ec45SGordon Ross smb_server_get_session_count(smb_server_t *sv)
1026faa1795aSjb150015 {
1027faa1795aSjb150015 	uint32_t	counter = 0;
1028faa1795aSjb150015 
1029811599a4SMatt Barden 	counter = smb_llist_get_count(&sv->sv_session_list);
1030faa1795aSjb150015 
1031faa1795aSjb150015 	return (counter);
1032faa1795aSjb150015 }
1033faa1795aSjb150015 
1034faa1795aSjb150015 /*
10358d94f651SGordon Ross  * Gets the smb_node of the specified share path.
10368d94f651SGordon Ross  * Node is returned held (caller must rele.)
1037148c5f43SAlan Wright  */
1038148c5f43SAlan Wright int
10398d94f651SGordon Ross smb_server_share_lookup(smb_server_t *sv, const char *shr_path,
10408d94f651SGordon Ross     smb_node_t **nodepp)
1041148c5f43SAlan Wright {
1042148c5f43SAlan Wright 	smb_request_t	*sr;
1043148c5f43SAlan Wright 	smb_node_t	*fnode = NULL;
10448d94f651SGordon Ross 	smb_node_t	*dnode = NULL;
1045148c5f43SAlan Wright 	char		last_comp[MAXNAMELEN];
1046148c5f43SAlan Wright 	int		rc = 0;
1047148c5f43SAlan Wright 
1048148c5f43SAlan Wright 	ASSERT(shr_path);
1049148c5f43SAlan Wright 
1050148c5f43SAlan Wright 	mutex_enter(&sv->sv_mutex);
1051148c5f43SAlan Wright 	switch (sv->sv_state) {
1052148c5f43SAlan Wright 	case SMB_SERVER_STATE_RUNNING:
1053148c5f43SAlan Wright 		break;
1054148c5f43SAlan Wright 	default:
1055148c5f43SAlan Wright 		mutex_exit(&sv->sv_mutex);
1056148c5f43SAlan Wright 		return (ENOTACTIVE);
1057148c5f43SAlan Wright 	}
1058148c5f43SAlan Wright 	mutex_exit(&sv->sv_mutex);
1059148c5f43SAlan Wright 
1060148c5f43SAlan Wright 	if ((sr = smb_request_alloc(sv->sv_session, 0)) == NULL) {
1061811599a4SMatt Barden 		return (ENOTCONN);
1062148c5f43SAlan Wright 	}
10638622ec45SGordon Ross 	sr->user_cr = zone_kcred();
1064148c5f43SAlan Wright 
1065148c5f43SAlan Wright 	rc = smb_pathname_reduce(sr, sr->user_cr, shr_path,
1066148c5f43SAlan Wright 	    NULL, NULL, &dnode, last_comp);
1067148c5f43SAlan Wright 
1068148c5f43SAlan Wright 	if (rc == 0) {
1069148c5f43SAlan Wright 		rc = smb_fsop_lookup(sr, sr->user_cr, SMB_FOLLOW_LINKS,
1070148c5f43SAlan Wright 		    sv->si_root_smb_node, dnode, last_comp, &fnode);
1071148c5f43SAlan Wright 		smb_node_release(dnode);
1072148c5f43SAlan Wright 	}
1073148c5f43SAlan Wright 
1074148c5f43SAlan Wright 	smb_request_free(sr);
1075148c5f43SAlan Wright 
1076148c5f43SAlan Wright 	if (rc != 0)
1077148c5f43SAlan Wright 		return (rc);
1078148c5f43SAlan Wright 
1079148c5f43SAlan Wright 	ASSERT(fnode->vp && fnode->vp->v_vfsp);
1080148c5f43SAlan Wright 
10818d94f651SGordon Ross 	*nodepp = fnode;
1082148c5f43SAlan Wright 
1083148c5f43SAlan Wright 	return (0);
1084148c5f43SAlan Wright }
1085148c5f43SAlan Wright 
1086b819cea2SGordon Ross #ifdef	_KERNEL
1087148c5f43SAlan Wright /*
1088148c5f43SAlan Wright  * This is a special interface that will be utilized by ZFS to cause a share to
1089148c5f43SAlan Wright  * be added/removed.
1090148c5f43SAlan Wright  *
1091148c5f43SAlan Wright  * arg is either a lmshare_info_t or share_name from userspace.
1092148c5f43SAlan Wright  * It will need to be copied into the kernel.   It is lmshare_info_t
1093148c5f43SAlan Wright  * for add operations and share_name for delete operations.
1094148c5f43SAlan Wright  */
1095148c5f43SAlan Wright int
1096148c5f43SAlan Wright smb_server_share(void *arg, boolean_t add_share)
1097148c5f43SAlan Wright {
1098148c5f43SAlan Wright 	smb_server_t	*sv;
1099148c5f43SAlan Wright 	int		rc;
1100148c5f43SAlan Wright 
1101148c5f43SAlan Wright 	if ((rc = smb_server_lookup(&sv)) == 0) {
1102148c5f43SAlan Wright 		mutex_enter(&sv->sv_mutex);
1103148c5f43SAlan Wright 		switch (sv->sv_state) {
1104148c5f43SAlan Wright 		case SMB_SERVER_STATE_RUNNING:
1105148c5f43SAlan Wright 			mutex_exit(&sv->sv_mutex);
1106148c5f43SAlan Wright 			(void) smb_kshare_upcall(sv->sv_lmshrd, arg, add_share);
1107148c5f43SAlan Wright 			break;
1108148c5f43SAlan Wright 		default:
1109148c5f43SAlan Wright 			mutex_exit(&sv->sv_mutex);
1110148c5f43SAlan Wright 			break;
1111148c5f43SAlan Wright 		}
1112148c5f43SAlan Wright 		smb_server_release(sv);
1113148c5f43SAlan Wright 	}
1114148c5f43SAlan Wright 
1115148c5f43SAlan Wright 	return (rc);
1116148c5f43SAlan Wright }
1117b819cea2SGordon Ross #endif	/* _KERNEL */
1118148c5f43SAlan Wright 
1119148c5f43SAlan Wright int
1120148c5f43SAlan Wright smb_server_unshare(const char *sharename)
1121148c5f43SAlan Wright {
1122148c5f43SAlan Wright 	smb_server_t	*sv;
1123148c5f43SAlan Wright 	int		rc;
1124148c5f43SAlan Wright 
1125148c5f43SAlan Wright 	if ((rc = smb_server_lookup(&sv)))
1126148c5f43SAlan Wright 		return (rc);
1127148c5f43SAlan Wright 
1128148c5f43SAlan Wright 	mutex_enter(&sv->sv_mutex);
1129148c5f43SAlan Wright 	switch (sv->sv_state) {
1130148c5f43SAlan Wright 	case SMB_SERVER_STATE_RUNNING:
1131148c5f43SAlan Wright 	case SMB_SERVER_STATE_STOPPING:
1132148c5f43SAlan Wright 		break;
1133148c5f43SAlan Wright 	default:
1134148c5f43SAlan Wright 		mutex_exit(&sv->sv_mutex);
1135148c5f43SAlan Wright 		smb_server_release(sv);
1136148c5f43SAlan Wright 		return (ENOTACTIVE);
1137148c5f43SAlan Wright 	}
1138148c5f43SAlan Wright 	mutex_exit(&sv->sv_mutex);
1139148c5f43SAlan Wright 
11408d94f651SGordon Ross 	smb_server_disconnect_share(sv, sharename);
1141148c5f43SAlan Wright 
1142148c5f43SAlan Wright 	smb_server_release(sv);
1143148c5f43SAlan Wright 	return (0);
1144148c5f43SAlan Wright }
1145148c5f43SAlan Wright 
1146148c5f43SAlan Wright /*
11479fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Disconnect the specified share.
11489fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Typically called when a share has been removed.
1149faa1795aSjb150015  */
11502c1b14e5Sjose borrego static void
11518d94f651SGordon Ross smb_server_disconnect_share(smb_server_t *sv, const char *sharename)
1152faa1795aSjb150015 {
11538d94f651SGordon Ross 	smb_llist_t	*ll;
11549fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_session_t	*session;
11559fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
11568d94f651SGordon Ross 	ll = &sv->sv_session_list;
11574163af6aSjose borrego 	smb_llist_enter(ll, RW_READER);
11589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
11594163af6aSjose borrego 	session = smb_llist_head(ll);
11609fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	while (session) {
11614163af6aSjose borrego 		SMB_SESSION_VALID(session);
11629fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		smb_rwx_rwenter(&session->s_lock, RW_READER);
11639fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		switch (session->s_state) {
11649fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		case SMB_SESSION_STATE_NEGOTIATED:
1165811599a4SMatt Barden 			smb_rwx_rwexit(&session->s_lock);
11669fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			smb_session_disconnect_share(session, sharename);
11679fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			break;
11689fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		default:
1169811599a4SMatt Barden 			smb_rwx_rwexit(&session->s_lock);
11709fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			break;
11719fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		}
11724163af6aSjose borrego 		session = smb_llist_next(ll, session);
11739fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
11749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
11754163af6aSjose borrego 	smb_llist_exit(ll);
1176faa1795aSjb150015 }
1177faa1795aSjb150015 
11785d8538b6SGordon Ross #ifdef	_KERNEL
11795d8538b6SGordon Ross 
11805d8538b6SGordon Ross /*
11815d8538b6SGordon Ross  * Create a process to own SMB server threads.
11825d8538b6SGordon Ross  */
11835d8538b6SGordon Ross static int
11845d8538b6SGordon Ross smb_server_newproc(smb_server_t *sv)
11855d8538b6SGordon Ross {
11865d8538b6SGordon Ross 	int rc;
11875d8538b6SGordon Ross 
11885d8538b6SGordon Ross 	mutex_enter(&sv->sv_proc_lock);
11895d8538b6SGordon Ross 	if (sv->sv_proc_p != NULL) {
11905d8538b6SGordon Ross 		/* restart? re-use proc */
11915d8538b6SGordon Ross 		rc = 0;
11925d8538b6SGordon Ross 		goto out;
11935d8538b6SGordon Ross 	}
11945d8538b6SGordon Ross 
11955d8538b6SGordon Ross 	sv->sv_proc_state = SMB_THREAD_STATE_STARTING;
11965d8538b6SGordon Ross 	rc = newproc(smb_server_proc_main, (caddr_t)sv,
11975d8538b6SGordon Ross 	    syscid, smbsrv_base_pri, NULL, 0);
11985d8538b6SGordon Ross 	if (rc != 0) {
11995d8538b6SGordon Ross 		cmn_err(CE_WARN, "newproc failed, rc=%d", rc);
12005d8538b6SGordon Ross 		goto out;
12015d8538b6SGordon Ross 	}
12025d8538b6SGordon Ross 
12035d8538b6SGordon Ross 	/* Rendez-vous with new proc thread. */
12045d8538b6SGordon Ross 	while (sv->sv_proc_state == SMB_THREAD_STATE_STARTING) {
12055d8538b6SGordon Ross 		cv_wait(&sv->sv_proc_cv, &sv->sv_proc_lock);
12065d8538b6SGordon Ross 
12075d8538b6SGordon Ross 	}
12085d8538b6SGordon Ross 	if (sv->sv_proc_state != SMB_THREAD_STATE_RUNNING) {
12095d8538b6SGordon Ross 		rc = ESRCH;
12105d8538b6SGordon Ross 		goto out;
12115d8538b6SGordon Ross 	}
12125d8538b6SGordon Ross 	ASSERT(sv->sv_proc_p != NULL);
12135d8538b6SGordon Ross 
12145d8538b6SGordon Ross out:
12155d8538b6SGordon Ross 	mutex_exit(&sv->sv_proc_lock);
12165d8538b6SGordon Ross 	return (rc);
12175d8538b6SGordon Ross }
12185d8538b6SGordon Ross 
12195d8538b6SGordon Ross /*
12205d8538b6SGordon Ross  * Main thread for the process we create to own SMB server threads.
12215d8538b6SGordon Ross  */
12225d8538b6SGordon Ross static void
12235d8538b6SGordon Ross smb_server_proc_main(void *arg)
12245d8538b6SGordon Ross {
12255d8538b6SGordon Ross 	callb_cpr_t	cprinfo;
12265d8538b6SGordon Ross 	smb_server_t	*sv = arg;
12275d8538b6SGordon Ross 	user_t		*pu = PTOU(curproc);
12285d8538b6SGordon Ross 	zoneid_t	zid = getzoneid();
12295d8538b6SGordon Ross 
12305d8538b6SGordon Ross 	ASSERT(curproc != &p0);
12315d8538b6SGordon Ross 	ASSERT(zid == sv->sv_zid);
12325d8538b6SGordon Ross 
12335d8538b6SGordon Ross 	(void) strlcpy(pu->u_comm, "smbsrv", sizeof (pu->u_comm));
12345d8538b6SGordon Ross 	(void) snprintf(pu->u_psargs, sizeof (pu->u_psargs),
12355d8538b6SGordon Ross 	    "smbsrv %d", (int)zid);
12365d8538b6SGordon Ross 
12375d8538b6SGordon Ross 	CALLB_CPR_INIT(&cprinfo, &sv->sv_proc_lock, callb_generic_cpr,
12385d8538b6SGordon Ross 	    pu->u_psargs);
12395d8538b6SGordon Ross 
12405d8538b6SGordon Ross 	mutex_enter(&sv->sv_proc_lock);
12415d8538b6SGordon Ross 	ASSERT(sv->sv_proc_state == SMB_THREAD_STATE_STARTING);
12425d8538b6SGordon Ross 
12435d8538b6SGordon Ross 	sv->sv_proc_p = curproc;
12445d8538b6SGordon Ross 	sv->sv_proc_did = curthread->t_did;
12455d8538b6SGordon Ross 
12465d8538b6SGordon Ross 	sv->sv_proc_state = SMB_THREAD_STATE_RUNNING;
12475d8538b6SGordon Ross 	cv_broadcast(&sv->sv_proc_cv);
12485d8538b6SGordon Ross 
12495d8538b6SGordon Ross 	CALLB_CPR_SAFE_BEGIN(&cprinfo);
12505d8538b6SGordon Ross 	while (sv->sv_proc_state == SMB_THREAD_STATE_RUNNING)
12515d8538b6SGordon Ross 		cv_wait(&sv->sv_proc_cv, &sv->sv_proc_lock);
12525d8538b6SGordon Ross 	CALLB_CPR_SAFE_END(&cprinfo, &sv->sv_proc_lock);
12535d8538b6SGordon Ross 
12545d8538b6SGordon Ross 	ASSERT(sv->sv_proc_state == SMB_THREAD_STATE_EXITING);
12555d8538b6SGordon Ross 	sv->sv_proc_state = SMB_THREAD_STATE_EXITED;
12565d8538b6SGordon Ross 	sv->sv_proc_p = NULL;
12575d8538b6SGordon Ross 	cv_broadcast(&sv->sv_proc_cv);
12585d8538b6SGordon Ross 	CALLB_CPR_EXIT(&cprinfo);	/* mutex_exit sv_proc_lock */
12595d8538b6SGordon Ross 
12605d8538b6SGordon Ross 	/* Note: lwp_exit() expects p_lock entered. */
12615d8538b6SGordon Ross 	mutex_enter(&curproc->p_lock);
12625d8538b6SGordon Ross 	lwp_exit();
12635d8538b6SGordon Ross }
12645d8538b6SGordon Ross 
12655d8538b6SGordon Ross /*
12665d8538b6SGordon Ross  * Delete the server proc (if any)
12675d8538b6SGordon Ross  */
12685d8538b6SGordon Ross static void
12695d8538b6SGordon Ross smb_server_delproc(smb_server_t *sv)
12705d8538b6SGordon Ross {
12715d8538b6SGordon Ross 
12725d8538b6SGordon Ross 	mutex_enter(&sv->sv_proc_lock);
12735d8538b6SGordon Ross 
12745d8538b6SGordon Ross 	if (sv->sv_proc_state != SMB_THREAD_STATE_RUNNING)
12755d8538b6SGordon Ross 		goto out;
12765d8538b6SGordon Ross 	ASSERT(sv->sv_proc_p != NULL);
12775d8538b6SGordon Ross 
12785d8538b6SGordon Ross 	sv->sv_proc_state = SMB_THREAD_STATE_EXITING;
12795d8538b6SGordon Ross 	cv_broadcast(&sv->sv_proc_cv);
12805d8538b6SGordon Ross 
12815d8538b6SGordon Ross 	/* Rendez-vous with proc thread. */
12825d8538b6SGordon Ross 	while (sv->sv_proc_state == SMB_THREAD_STATE_EXITING) {
12835d8538b6SGordon Ross 		cv_wait(&sv->sv_proc_cv, &sv->sv_proc_lock);
12845d8538b6SGordon Ross 
12855d8538b6SGordon Ross 	}
12865d8538b6SGordon Ross 	if (sv->sv_proc_state != SMB_THREAD_STATE_EXITED) {
12875d8538b6SGordon Ross 		cmn_err(CE_WARN, "smb_server_delproc, state=%d",
12885d8538b6SGordon Ross 		    sv->sv_proc_state);
12895d8538b6SGordon Ross 		goto out;
12905d8538b6SGordon Ross 	}
12915d8538b6SGordon Ross 	if (sv->sv_proc_did != 0) {
12925d8538b6SGordon Ross 		thread_join(sv->sv_proc_did);
12935d8538b6SGordon Ross 		sv->sv_proc_did = 0;
12945d8538b6SGordon Ross 	}
12955d8538b6SGordon Ross 
12965d8538b6SGordon Ross out:
12975d8538b6SGordon Ross 	mutex_exit(&sv->sv_proc_lock);
12985d8538b6SGordon Ross }
12995d8538b6SGordon Ross 
13005d8538b6SGordon Ross #endif	/* _KERNEL */
13015d8538b6SGordon Ross 
1302faa1795aSjb150015 /*
1303faa1795aSjb150015  * *****************************************************************************
1304faa1795aSjb150015  * **************** Functions called from the internal layers ******************
1305faa1795aSjb150015  * *****************************************************************************
1306faa1795aSjb150015  *
1307faa1795aSjb150015  * These functions are provided the relevant smb server by the caller.
1308faa1795aSjb150015  */
1309faa1795aSjb150015 
1310faa1795aSjb150015 void
1311faa1795aSjb150015 smb_server_get_cfg(smb_server_t *sv, smb_kmod_cfg_t *cfg)
1312faa1795aSjb150015 {
1313faa1795aSjb150015 	rw_enter(&sv->sv_cfg_lock, RW_READER);
1314faa1795aSjb150015 	bcopy(&sv->sv_cfg, cfg, sizeof (*cfg));
1315faa1795aSjb150015 	rw_exit(&sv->sv_cfg_lock);
1316faa1795aSjb150015 }
1317faa1795aSjb150015 
1318faa1795aSjb150015 /*
1319148c5f43SAlan Wright  *
1320148c5f43SAlan Wright  */
1321148c5f43SAlan Wright void
1322148c5f43SAlan Wright smb_server_inc_nbt_sess(smb_server_t *sv)
1323148c5f43SAlan Wright {
1324148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1325148c5f43SAlan Wright 	atomic_inc_32(&sv->sv_nbt_sess);
1326148c5f43SAlan Wright }
1327148c5f43SAlan Wright 
1328148c5f43SAlan Wright void
1329148c5f43SAlan Wright smb_server_dec_nbt_sess(smb_server_t *sv)
1330148c5f43SAlan Wright {
1331148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1332148c5f43SAlan Wright 	atomic_dec_32(&sv->sv_nbt_sess);
1333148c5f43SAlan Wright }
1334148c5f43SAlan Wright 
1335148c5f43SAlan Wright void
1336148c5f43SAlan Wright smb_server_inc_tcp_sess(smb_server_t *sv)
1337148c5f43SAlan Wright {
1338148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1339148c5f43SAlan Wright 	atomic_inc_32(&sv->sv_tcp_sess);
1340148c5f43SAlan Wright }
1341148c5f43SAlan Wright 
1342148c5f43SAlan Wright void
1343148c5f43SAlan Wright smb_server_dec_tcp_sess(smb_server_t *sv)
1344148c5f43SAlan Wright {
1345148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1346148c5f43SAlan Wright 	atomic_dec_32(&sv->sv_tcp_sess);
1347148c5f43SAlan Wright }
1348148c5f43SAlan Wright 
1349148c5f43SAlan Wright void
1350148c5f43SAlan Wright smb_server_inc_users(smb_server_t *sv)
1351148c5f43SAlan Wright {
1352148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1353148c5f43SAlan Wright 	atomic_inc_32(&sv->sv_users);
1354148c5f43SAlan Wright }
1355148c5f43SAlan Wright 
1356148c5f43SAlan Wright void
1357148c5f43SAlan Wright smb_server_dec_users(smb_server_t *sv)
1358148c5f43SAlan Wright {
1359148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1360148c5f43SAlan Wright 	atomic_dec_32(&sv->sv_users);
1361148c5f43SAlan Wright }
1362148c5f43SAlan Wright 
1363148c5f43SAlan Wright void
1364148c5f43SAlan Wright smb_server_inc_trees(smb_server_t *sv)
1365148c5f43SAlan Wright {
1366148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1367148c5f43SAlan Wright 	atomic_inc_32(&sv->sv_trees);
1368148c5f43SAlan Wright }
1369148c5f43SAlan Wright 
1370148c5f43SAlan Wright void
1371148c5f43SAlan Wright smb_server_dec_trees(smb_server_t *sv)
1372148c5f43SAlan Wright {
1373148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1374148c5f43SAlan Wright 	atomic_dec_32(&sv->sv_trees);
1375148c5f43SAlan Wright }
1376148c5f43SAlan Wright 
1377148c5f43SAlan Wright void
1378148c5f43SAlan Wright smb_server_inc_files(smb_server_t *sv)
1379148c5f43SAlan Wright {
1380148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1381148c5f43SAlan Wright 	atomic_inc_32(&sv->sv_files);
1382148c5f43SAlan Wright }
1383148c5f43SAlan Wright 
1384148c5f43SAlan Wright void
1385148c5f43SAlan Wright smb_server_dec_files(smb_server_t *sv)
1386148c5f43SAlan Wright {
1387148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1388148c5f43SAlan Wright 	atomic_dec_32(&sv->sv_files);
1389148c5f43SAlan Wright }
1390148c5f43SAlan Wright 
1391148c5f43SAlan Wright void
1392148c5f43SAlan Wright smb_server_inc_pipes(smb_server_t *sv)
1393148c5f43SAlan Wright {
1394148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1395148c5f43SAlan Wright 	atomic_inc_32(&sv->sv_pipes);
1396148c5f43SAlan Wright }
1397148c5f43SAlan Wright 
1398148c5f43SAlan Wright void
1399148c5f43SAlan Wright smb_server_dec_pipes(smb_server_t *sv)
1400148c5f43SAlan Wright {
1401148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1402148c5f43SAlan Wright 	atomic_dec_32(&sv->sv_pipes);
1403148c5f43SAlan Wright }
1404148c5f43SAlan Wright 
1405148c5f43SAlan Wright void
1406148c5f43SAlan Wright smb_server_add_rxb(smb_server_t *sv, int64_t value)
1407148c5f43SAlan Wright {
1408148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1409148c5f43SAlan Wright 	atomic_add_64(&sv->sv_rxb, value);
1410148c5f43SAlan Wright }
1411148c5f43SAlan Wright 
1412148c5f43SAlan Wright void
1413148c5f43SAlan Wright smb_server_add_txb(smb_server_t *sv, int64_t value)
1414148c5f43SAlan Wright {
1415148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1416148c5f43SAlan Wright 	atomic_add_64(&sv->sv_txb, value);
1417148c5f43SAlan Wright }
1418148c5f43SAlan Wright 
1419148c5f43SAlan Wright void
1420148c5f43SAlan Wright smb_server_inc_req(smb_server_t *sv)
1421148c5f43SAlan Wright {
1422148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1423148c5f43SAlan Wright 	atomic_inc_64(&sv->sv_nreq);
1424148c5f43SAlan Wright }
1425148c5f43SAlan Wright 
1426148c5f43SAlan Wright /*
1427faa1795aSjb150015  * *****************************************************************************
1428faa1795aSjb150015  * *************************** Static Functions ********************************
1429faa1795aSjb150015  * *****************************************************************************
1430faa1795aSjb150015  */
1431faa1795aSjb150015 
1432faa1795aSjb150015 static void
1433faa1795aSjb150015 smb_server_timers(smb_thread_t *thread, void *arg)
1434faa1795aSjb150015 {
1435faa1795aSjb150015 	smb_server_t	*sv = (smb_server_t *)arg;
1436faa1795aSjb150015 
1437faa1795aSjb150015 	ASSERT(sv != NULL);
1438faa1795aSjb150015 
1439b819cea2SGordon Ross 	/*
1440811599a4SMatt Barden 	 * This kills old inactive sessions and expired durable
1441811599a4SMatt Barden 	 * handles. The session code expects one call per minute.
1442b819cea2SGordon Ross 	 */
1443b819cea2SGordon Ross 	while (smb_thread_continue_timedwait(thread, 60 /* Seconds */)) {
1444811599a4SMatt Barden 		if (sv->sv_cfg.skc_keepalive != 0)
1445811599a4SMatt Barden 			smb_session_timers(sv);
1446811599a4SMatt Barden 		smb2_durable_timers(sv);
1447faa1795aSjb150015 	}
1448faa1795aSjb150015 }
1449faa1795aSjb150015 
1450faa1795aSjb150015 /*
1451faa1795aSjb150015  * smb_server_kstat_init
1452faa1795aSjb150015  */
1453148c5f43SAlan Wright static void
1454faa1795aSjb150015 smb_server_kstat_init(smb_server_t *sv)
1455faa1795aSjb150015 {
1456cb174861Sjoyce mcintosh 
14578622ec45SGordon Ross 	sv->sv_ksp = kstat_create_zone(SMBSRV_KSTAT_MODULE, 0,
1458148c5f43SAlan Wright 	    SMBSRV_KSTAT_STATISTICS, SMBSRV_KSTAT_CLASS, KSTAT_TYPE_RAW,
1459148c5f43SAlan Wright 	    sizeof (smbsrv_kstats_t), 0, sv->sv_zid);
1460faa1795aSjb150015 
1461148c5f43SAlan Wright 	if (sv->sv_ksp != NULL) {
1462148c5f43SAlan Wright 		sv->sv_ksp->ks_update = smb_server_kstat_update;
1463148c5f43SAlan Wright 		sv->sv_ksp->ks_private = sv;
1464148c5f43SAlan Wright 		((smbsrv_kstats_t *)sv->sv_ksp->ks_data)->ks_start_time =
1465148c5f43SAlan Wright 		    sv->sv_start_time;
14668622ec45SGordon Ross 		smb_dispatch_stats_init(sv);
1467a90cf9f2SGordon Ross 		smb2_dispatch_stats_init(sv);
1468faa1795aSjb150015 		kstat_install(sv->sv_ksp);
1469148c5f43SAlan Wright 	} else {
1470148c5f43SAlan Wright 		cmn_err(CE_WARN, "SMB Server: Statistics unavailable");
1471faa1795aSjb150015 	}
1472cb174861Sjoyce mcintosh 
14738622ec45SGordon Ross 	sv->sv_legacy_ksp = kstat_create_zone(SMBSRV_KSTAT_MODULE, 0,
14748622ec45SGordon Ross 	    SMBSRV_KSTAT_NAME, SMBSRV_KSTAT_CLASS, KSTAT_TYPE_NAMED,
14758622ec45SGordon Ross 	    sizeof (smb_server_legacy_kstat_t) / sizeof (kstat_named_t),
14768622ec45SGordon Ross 	    0, sv->sv_zid);
1477cb174861Sjoyce mcintosh 
1478cb174861Sjoyce mcintosh 	if (sv->sv_legacy_ksp != NULL) {
1479cb174861Sjoyce mcintosh 		smb_server_legacy_kstat_t *ksd;
1480cb174861Sjoyce mcintosh 
1481cb174861Sjoyce mcintosh 		ksd = sv->sv_legacy_ksp->ks_data;
1482cb174861Sjoyce mcintosh 
1483cb174861Sjoyce mcintosh 		(void) strlcpy(ksd->ls_files.name, "open_files",
1484cb174861Sjoyce mcintosh 		    sizeof (ksd->ls_files.name));
1485cb174861Sjoyce mcintosh 		ksd->ls_files.data_type = KSTAT_DATA_UINT32;
1486cb174861Sjoyce mcintosh 
1487cb174861Sjoyce mcintosh 		(void) strlcpy(ksd->ls_trees.name, "connections",
1488cb174861Sjoyce mcintosh 		    sizeof (ksd->ls_trees.name));
1489cb174861Sjoyce mcintosh 		ksd->ls_trees.data_type = KSTAT_DATA_UINT32;
1490cb174861Sjoyce mcintosh 
1491cb174861Sjoyce mcintosh 		(void) strlcpy(ksd->ls_users.name, "connections",
1492cb174861Sjoyce mcintosh 		    sizeof (ksd->ls_users.name));
1493cb174861Sjoyce mcintosh 		ksd->ls_users.data_type = KSTAT_DATA_UINT32;
1494cb174861Sjoyce mcintosh 
1495cb174861Sjoyce mcintosh 		mutex_init(&sv->sv_legacy_ksmtx, NULL, MUTEX_DEFAULT, NULL);
1496cb174861Sjoyce mcintosh 		sv->sv_legacy_ksp->ks_lock = &sv->sv_legacy_ksmtx;
1497cb174861Sjoyce mcintosh 		sv->sv_legacy_ksp->ks_update = smb_server_legacy_kstat_update;
1498cb174861Sjoyce mcintosh 		kstat_install(sv->sv_legacy_ksp);
1499cb174861Sjoyce mcintosh 	}
1500faa1795aSjb150015 }
1501faa1795aSjb150015 
1502faa1795aSjb150015 /*
1503faa1795aSjb150015  * smb_server_kstat_fini
1504faa1795aSjb150015  */
1505faa1795aSjb150015 static void
1506faa1795aSjb150015 smb_server_kstat_fini(smb_server_t *sv)
1507faa1795aSjb150015 {
1508cb174861Sjoyce mcintosh 	if (sv->sv_legacy_ksp != NULL) {
1509cb174861Sjoyce mcintosh 		kstat_delete(sv->sv_legacy_ksp);
1510cb174861Sjoyce mcintosh 		mutex_destroy(&sv->sv_legacy_ksmtx);
1511cb174861Sjoyce mcintosh 		sv->sv_legacy_ksp = NULL;
1512cb174861Sjoyce mcintosh 	}
1513cb174861Sjoyce mcintosh 
1514148c5f43SAlan Wright 	if (sv->sv_ksp != NULL) {
1515faa1795aSjb150015 		kstat_delete(sv->sv_ksp);
1516faa1795aSjb150015 		sv->sv_ksp = NULL;
15178622ec45SGordon Ross 		smb_dispatch_stats_fini(sv);
1518a90cf9f2SGordon Ross 		smb2_dispatch_stats_fini(sv);
1519faa1795aSjb150015 	}
1520faa1795aSjb150015 }
1521faa1795aSjb150015 
1522148c5f43SAlan Wright /*
15238365a6eaSGordon Ross  * Verify the defines in smb_kstat.h used by ks_reqs1 ks_reqs2
15248365a6eaSGordon Ross  */
15258365a6eaSGordon Ross CTASSERT(SMBSRV_KS_NREQS1 == SMB_COM_NUM);
15268365a6eaSGordon Ross CTASSERT(SMBSRV_KS_NREQS2 == SMB2__NCMDS);
15278365a6eaSGordon Ross 
15288365a6eaSGordon Ross /*
1529148c5f43SAlan Wright  * smb_server_kstat_update
1530148c5f43SAlan Wright  */
1531faa1795aSjb150015 static int
1532148c5f43SAlan Wright smb_server_kstat_update(kstat_t *ksp, int rw)
1533faa1795aSjb150015 {
1534faa1795aSjb150015 	smb_server_t	*sv;
1535148c5f43SAlan Wright 	smbsrv_kstats_t	*ksd;
1536faa1795aSjb150015 
1537148c5f43SAlan Wright 	if (rw == KSTAT_READ) {
1538148c5f43SAlan Wright 		sv = ksp->ks_private;
15399fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_SERVER_VALID(sv);
1540148c5f43SAlan Wright 		ksd = (smbsrv_kstats_t *)ksp->ks_data;
1541148c5f43SAlan Wright 		/*
1542148c5f43SAlan Wright 		 * Counters
1543148c5f43SAlan Wright 		 */
1544148c5f43SAlan Wright 		ksd->ks_nbt_sess = sv->sv_nbt_sess;
1545148c5f43SAlan Wright 		ksd->ks_tcp_sess = sv->sv_tcp_sess;
1546148c5f43SAlan Wright 		ksd->ks_users = sv->sv_users;
1547148c5f43SAlan Wright 		ksd->ks_trees = sv->sv_trees;
1548148c5f43SAlan Wright 		ksd->ks_files = sv->sv_files;
1549148c5f43SAlan Wright 		ksd->ks_pipes = sv->sv_pipes;
1550148c5f43SAlan Wright 		/*
1551148c5f43SAlan Wright 		 * Throughput
1552148c5f43SAlan Wright 		 */
1553148c5f43SAlan Wright 		ksd->ks_txb = sv->sv_txb;
1554148c5f43SAlan Wright 		ksd->ks_rxb = sv->sv_rxb;
1555148c5f43SAlan Wright 		ksd->ks_nreq = sv->sv_nreq;
1556148c5f43SAlan Wright 		/*
1557148c5f43SAlan Wright 		 * Busyness
1558148c5f43SAlan Wright 		 */
1559148c5f43SAlan Wright 		ksd->ks_maxreqs = sv->sv_cfg.skc_maxworkers;
1560148c5f43SAlan Wright 		smb_srqueue_update(&sv->sv_srqueue,
1561148c5f43SAlan Wright 		    &ksd->ks_utilization);
1562148c5f43SAlan Wright 		/*
1563148c5f43SAlan Wright 		 * Latency & Throughput of the requests
1564148c5f43SAlan Wright 		 */
1565a90cf9f2SGordon Ross 		smb_dispatch_stats_update(sv, ksd->ks_reqs1, 0, SMB_COM_NUM);
1566a90cf9f2SGordon Ross 		smb2_dispatch_stats_update(sv, ksd->ks_reqs2, 0, SMB2__NCMDS);
1567faa1795aSjb150015 		return (0);
1568faa1795aSjb150015 	}
1569148c5f43SAlan Wright 	if (rw == KSTAT_WRITE)
1570148c5f43SAlan Wright 		return (EACCES);
1571148c5f43SAlan Wright 
1572148c5f43SAlan Wright 	return (EIO);
1573148c5f43SAlan Wright }
1574faa1795aSjb150015 
1575cb174861Sjoyce mcintosh static int
1576cb174861Sjoyce mcintosh smb_server_legacy_kstat_update(kstat_t *ksp, int rw)
1577cb174861Sjoyce mcintosh {
1578cb174861Sjoyce mcintosh 	smb_server_t			*sv;
1579cb174861Sjoyce mcintosh 	smb_server_legacy_kstat_t	*ksd;
1580cb174861Sjoyce mcintosh 	int				rc;
1581cb174861Sjoyce mcintosh 
1582cb174861Sjoyce mcintosh 	switch (rw) {
1583cb174861Sjoyce mcintosh 	case KSTAT_WRITE:
1584cb174861Sjoyce mcintosh 		rc = EACCES;
1585cb174861Sjoyce mcintosh 		break;
1586cb174861Sjoyce mcintosh 	case KSTAT_READ:
1587cb174861Sjoyce mcintosh 		if (!smb_server_lookup(&sv)) {
1588cb174861Sjoyce mcintosh 			ASSERT(MUTEX_HELD(ksp->ks_lock));
1589cb174861Sjoyce mcintosh 			ASSERT(sv->sv_legacy_ksp == ksp);
1590cb174861Sjoyce mcintosh 			ksd = (smb_server_legacy_kstat_t *)ksp->ks_data;
1591cb174861Sjoyce mcintosh 			ksd->ls_files.value.ui32 = sv->sv_files + sv->sv_pipes;
1592cb174861Sjoyce mcintosh 			ksd->ls_trees.value.ui32 = sv->sv_trees;
1593cb174861Sjoyce mcintosh 			ksd->ls_users.value.ui32 = sv->sv_users;
1594cb174861Sjoyce mcintosh 			smb_server_release(sv);
1595cb174861Sjoyce mcintosh 			rc = 0;
1596cb174861Sjoyce mcintosh 			break;
1597cb174861Sjoyce mcintosh 		}
15982d63d7e2SToomas Soome 		/* FALLTHROUGH */
1599cb174861Sjoyce mcintosh 	default:
1600cb174861Sjoyce mcintosh 		rc = EIO;
1601cb174861Sjoyce mcintosh 		break;
1602cb174861Sjoyce mcintosh 	}
1603cb174861Sjoyce mcintosh 	return (rc);
1604cb174861Sjoyce mcintosh 
1605cb174861Sjoyce mcintosh }
1606cb174861Sjoyce mcintosh 
160786184067SGordon Ross int smb_server_shutdown_wait1 = 15;	/* seconds */
160886184067SGordon Ross 
1609faa1795aSjb150015 /*
16104163af6aSjose borrego  * smb_server_shutdown
1611faa1795aSjb150015  */
1612faa1795aSjb150015 static void
16139fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_server_shutdown(smb_server_t *sv)
1614faa1795aSjb150015 {
1615811599a4SMatt Barden 	smb_llist_t *sl = &sv->sv_session_list;
1616811599a4SMatt Barden 	smb_session_t *session;
161786184067SGordon Ross 	clock_t	time0, time1, time2;
1618811599a4SMatt Barden 
16199fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	SMB_SERVER_VALID(sv);
1620faa1795aSjb150015 
1621856399cfSGordon Ross 	/*
162286184067SGordon Ross 	 * Stop the listeners first, so we can't get any more
162386184067SGordon Ross 	 * new sessions while we're trying to shut down.
1624856399cfSGordon Ross 	 */
1625856399cfSGordon Ross 	smb_server_listener_stop(&sv->sv_nbt_daemon);
1626856399cfSGordon Ross 	smb_server_listener_stop(&sv->sv_tcp_daemon);
1627856399cfSGordon Ross 
162886184067SGordon Ross 	/*
162986184067SGordon Ross 	 * Disconnect all of the sessions. This causes all the
163086184067SGordon Ross 	 * smb_server_receiver threads to see a disconnect and
163186184067SGordon Ross 	 * begin tear-down (in parallel) in smb_session_cancel.
163286184067SGordon Ross 	 */
1633811599a4SMatt Barden 	smb_llist_enter(sl, RW_READER);
1634811599a4SMatt Barden 	session = smb_llist_head(sl);
1635811599a4SMatt Barden 	while (session != NULL) {
1636811599a4SMatt Barden 		smb_session_disconnect(session);
1637811599a4SMatt Barden 		session = smb_llist_next(sl, session);
1638811599a4SMatt Barden 	}
1639811599a4SMatt Barden 	smb_llist_exit(sl);
1640811599a4SMatt Barden 
1641856399cfSGordon Ross 	/*
1642856399cfSGordon Ross 	 * Wake up any threads we might have blocked.
1643856399cfSGordon Ross 	 * Must precede kdoor_close etc. because those will
1644856399cfSGordon Ross 	 * wait for such threads to get out.
1645856399cfSGordon Ross 	 */
1646856399cfSGordon Ross 	smb_event_cancel(sv, 0);
1647856399cfSGordon Ross 	smb_threshold_wake_all(&sv->sv_ssetup_ct);
1648856399cfSGordon Ross 	smb_threshold_wake_all(&sv->sv_tcon_ct);
1649856399cfSGordon Ross 	smb_threshold_wake_all(&sv->sv_opipe_ct);
1650856399cfSGordon Ross 
1651811599a4SMatt Barden 	/*
1652811599a4SMatt Barden 	 * Wait for the session list to empty.
1653811599a4SMatt Barden 	 * (cv_signal in smb_server_destroy_session)
1654811599a4SMatt Barden 	 *
165586184067SGordon Ross 	 * We must wait for all the SMB session readers to finish, or
165686184067SGordon Ross 	 * we could proceed here while there might be worker threads
165786184067SGordon Ross 	 * running in any of those sessions.  See smb_session_logoff
165886184067SGordon Ross 	 * for timeouts applied to session tear-down. If this takes
165986184067SGordon Ross 	 * longer than expected, make some noise, and fire a dtrace
166086184067SGordon Ross 	 * probe one might use to investigate.
1661811599a4SMatt Barden 	 */
166286184067SGordon Ross 	time0 = ddi_get_lbolt();
166386184067SGordon Ross 	time1 = SEC_TO_TICK(smb_server_shutdown_wait1) + time0;
1664811599a4SMatt Barden 	mutex_enter(&sv->sv_mutex);
1665811599a4SMatt Barden 	while (sv->sv_session_list.ll_count != 0) {
166686184067SGordon Ross 		if (cv_timedwait(&sv->sv_cv, &sv->sv_mutex, time1) < 0) {
166786184067SGordon Ross 			cmn_err(CE_NOTE, "!shutdown waited %d seconds"
166886184067SGordon Ross 			    " with %d sessions still remaining",
166986184067SGordon Ross 			    smb_server_shutdown_wait1,
167086184067SGordon Ross 			    sv->sv_session_list.ll_count);
167186184067SGordon Ross 			DTRACE_PROBE1(max__wait, smb_server_t *, sv);
1672811599a4SMatt Barden 			break;
1673811599a4SMatt Barden 		}
1674811599a4SMatt Barden 	}
167586184067SGordon Ross 	while (sv->sv_session_list.ll_count != 0) {
167686184067SGordon Ross 		cv_wait(&sv->sv_cv, &sv->sv_mutex);
167786184067SGordon Ross 	}
167886184067SGordon Ross 	mutex_exit(&sv->sv_mutex);
1679811599a4SMatt Barden 
168086184067SGordon Ross 	time2 = ddi_get_lbolt();
168186184067SGordon Ross 	if (time2 > time1) {
168286184067SGordon Ross 		cmn_err(CE_NOTE, "!shutdown waited %d seconds"
168386184067SGordon Ross 		    " for all sessions to finish",
168486184067SGordon Ross 		    (int)TICK_TO_SEC(time2 - time0));
168586184067SGordon Ross 	}
1686811599a4SMatt Barden 
16878622ec45SGordon Ross 	smb_kdoor_close(sv);
1688b819cea2SGordon Ross #ifdef	_KERNEL
1689148c5f43SAlan Wright 	smb_kshare_door_fini(sv->sv_lmshrd);
1690b819cea2SGordon Ross #endif	/* _KERNEL */
16910dcb3379Sjb150015 	sv->sv_lmshrd = NULL;
1692b819cea2SGordon Ross 
16938622ec45SGordon Ross 	smb_export_stop(sv);
1694811599a4SMatt Barden 	smb_kshare_stop(sv);
169586184067SGordon Ross 	smb_thread_stop(&sv->si_thread_timers);
16968d96b23eSAlan Wright 
16974846df9bSKevin Crowe 	/*
1698811599a4SMatt Barden 	 * Both kshare and the oplock break sub-systems may have
1699811599a4SMatt Barden 	 * taskq jobs on the spcial "server" session, until we've
1700811599a4SMatt Barden 	 * closed all ofiles and stopped the kshare exporter.
1701811599a4SMatt Barden 	 * Now it's safe to destroy the server session, but first
1702811599a4SMatt Barden 	 * wait for any requests on it to finish.  Note that for
1703811599a4SMatt Barden 	 * normal sessions, this happens in smb_session_cancel,
1704811599a4SMatt Barden 	 * but that's not called for the server session.
17054846df9bSKevin Crowe 	 */
17068d94f651SGordon Ross 	if (sv->sv_rootuser != NULL) {
17078d94f651SGordon Ross 		smb_user_logoff(sv->sv_rootuser);
17088d94f651SGordon Ross 		smb_user_release(sv->sv_rootuser);
17098d94f651SGordon Ross 		sv->sv_rootuser = NULL;
17108d94f651SGordon Ross 	}
1711811599a4SMatt Barden 	if (sv->sv_session != NULL) {
1712525641e8SGordon Ross 		smb_session_cancel_requests(sv->sv_session, NULL, NULL);
17134846df9bSKevin Crowe 		smb_slist_wait_for_empty(&sv->sv_session->s_req_list);
17144846df9bSKevin Crowe 
17158d94f651SGordon Ross 		/* Just in case import left users and trees */
17168d94f651SGordon Ross 		smb_session_logoff(sv->sv_session);
17178d94f651SGordon Ross 
1718faa1795aSjb150015 		smb_session_delete(sv->sv_session);
1719faa1795aSjb150015 		sv->sv_session = NULL;
1720faa1795aSjb150015 	}
17218d96b23eSAlan Wright 
17224163af6aSjose borrego 	if (sv->sv_receiver_pool != NULL) {
17234163af6aSjose borrego 		taskq_destroy(sv->sv_receiver_pool);
17244163af6aSjose borrego 		sv->sv_receiver_pool = NULL;
17254163af6aSjose borrego 	}
17264163af6aSjose borrego 
17274163af6aSjose borrego 	if (sv->sv_worker_pool != NULL) {
17284163af6aSjose borrego 		taskq_destroy(sv->sv_worker_pool);
17294163af6aSjose borrego 		sv->sv_worker_pool = NULL;
17308d96b23eSAlan Wright 	}
17318622ec45SGordon Ross 
1732*e515d096SGordon Ross 	if (sv->sv_notify_pool != NULL) {
1733*e515d096SGordon Ross 		taskq_destroy(sv->sv_notify_pool);
1734*e515d096SGordon Ross 		sv->sv_notify_pool = NULL;
1735*e515d096SGordon Ross 	}
1736*e515d096SGordon Ross 
173786184067SGordon Ross 	/*
173886184067SGordon Ross 	 * Clean out any durable handles.  After this we should
173986184067SGordon Ross 	 * have no ofiles remaining (and no more oplock breaks).
174086184067SGordon Ross 	 */
174186184067SGordon Ross 	smb2_dh_shutdown(sv);
174286184067SGordon Ross 
17438622ec45SGordon Ross 	smb_server_fsop_stop(sv);
17445d8538b6SGordon Ross 
17455d8538b6SGordon Ross #ifdef	_KERNEL
17465d8538b6SGordon Ross 	if (sv->sv_proc_p != NULL) {
17475d8538b6SGordon Ross 		smb_server_delproc(sv);
17485d8538b6SGordon Ross 	}
17495d8538b6SGordon Ross #endif
1750faa1795aSjb150015 }
1751faa1795aSjb150015 
17524163af6aSjose borrego /*
17534163af6aSjose borrego  * smb_server_listener_init
17544163af6aSjose borrego  *
17554163af6aSjose borrego  * Initializes listener contexts.
17564163af6aSjose borrego  */
17574163af6aSjose borrego static void
17584163af6aSjose borrego smb_server_listener_init(
1759faa1795aSjb150015     smb_server_t		*sv,
1760faa1795aSjb150015     smb_listener_daemon_t	*ld,
17614163af6aSjose borrego     char			*name,
1762faa1795aSjb150015     in_port_t			port,
17634163af6aSjose borrego     int				family)
1764faa1795aSjb150015 {
17654163af6aSjose borrego 	ASSERT(ld->ld_magic != SMB_LISTENER_MAGIC);
1766faa1795aSjb150015 
17674163af6aSjose borrego 	bzero(ld, sizeof (*ld));
1768faa1795aSjb150015 
17694163af6aSjose borrego 	ld->ld_sv = sv;
17704163af6aSjose borrego 	ld->ld_family = family;
17714163af6aSjose borrego 	ld->ld_port = port;
17724163af6aSjose borrego 
17737f667e74Sjose borrego 	if (family == AF_INET) {
17747f667e74Sjose borrego 		ld->ld_sin.sin_family = (uint32_t)family;
1775faa1795aSjb150015 		ld->ld_sin.sin_port = htons(port);
1776faa1795aSjb150015 		ld->ld_sin.sin_addr.s_addr = htonl(INADDR_ANY);
17777f667e74Sjose borrego 	} else {
17787f667e74Sjose borrego 		ld->ld_sin6.sin6_family = (uint32_t)family;
17797f667e74Sjose borrego 		ld->ld_sin6.sin6_port = htons(port);
17807f667e74Sjose borrego 		(void) memset(&ld->ld_sin6.sin6_addr.s6_addr, 0,
17817f667e74Sjose borrego 		    sizeof (ld->ld_sin6.sin6_addr.s6_addr));
17827f667e74Sjose borrego 	}
1783faa1795aSjb150015 
178408344b29SGordon Ross 	smb_thread_init(&ld->ld_thread, name, smb_server_listener, ld,
17855d8538b6SGordon Ross 	    smbsrv_listen_pri, sv);
17864163af6aSjose borrego 	ld->ld_magic = SMB_LISTENER_MAGIC;
17874163af6aSjose borrego }
17884163af6aSjose borrego 
17894163af6aSjose borrego /*
17904163af6aSjose borrego  * smb_server_listener_destroy
17914163af6aSjose borrego  *
17924163af6aSjose borrego  * Destroyes listener contexts.
17934163af6aSjose borrego  */
17944163af6aSjose borrego static void
17954163af6aSjose borrego smb_server_listener_destroy(smb_listener_daemon_t *ld)
17964163af6aSjose borrego {
179783d2dfe6SGordon Ross 	/*
179883d2dfe6SGordon Ross 	 * Note that if startup fails early, we can legitimately
179983d2dfe6SGordon Ross 	 * get here with an all-zeros object.
180083d2dfe6SGordon Ross 	 */
180183d2dfe6SGordon Ross 	if (ld->ld_magic == 0)
180283d2dfe6SGordon Ross 		return;
180383d2dfe6SGordon Ross 
18044163af6aSjose borrego 	SMB_LISTENER_VALID(ld);
18054163af6aSjose borrego 	ASSERT(ld->ld_so == NULL);
18064163af6aSjose borrego 	smb_thread_destroy(&ld->ld_thread);
18074163af6aSjose borrego 	ld->ld_magic = 0;
18084163af6aSjose borrego }
18094163af6aSjose borrego 
18104163af6aSjose borrego /*
18114163af6aSjose borrego  * smb_server_listener_start
18124163af6aSjose borrego  *
18134163af6aSjose borrego  * Starts the listener associated with the context passed in.
18144163af6aSjose borrego  *
18154163af6aSjose borrego  * Return:	0	Success
18164163af6aSjose borrego  *		not 0	Failure
18174163af6aSjose borrego  */
18184163af6aSjose borrego static int
18194163af6aSjose borrego smb_server_listener_start(smb_listener_daemon_t *ld)
18204163af6aSjose borrego {
18214163af6aSjose borrego 	int		rc;
18224163af6aSjose borrego 	uint32_t	on;
18234163af6aSjose borrego 	uint32_t	off;
18244163af6aSjose borrego 
18254163af6aSjose borrego 	SMB_LISTENER_VALID(ld);
18264163af6aSjose borrego 
18274163af6aSjose borrego 	if (ld->ld_so != NULL)
18284163af6aSjose borrego 		return (EINVAL);
18294163af6aSjose borrego 
18304163af6aSjose borrego 	ld->ld_so = smb_socreate(ld->ld_family, SOCK_STREAM, 0);
18319fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (ld->ld_so == NULL) {
18324163af6aSjose borrego 		cmn_err(CE_WARN, "port %d: socket create failed", ld->ld_port);
18339fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (ENOMEM);
18349fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
18359fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
18369fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	off = 0;
18370f1702c5SYu Xiangning 	(void) ksocket_setsockopt(ld->ld_so, SOL_SOCKET,
1838fc724630SAlan Wright 	    SO_MAC_EXEMPT, &off, sizeof (off), CRED());
18399fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
18409fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	on = 1;
1841fc724630SAlan Wright 	(void) ksocket_setsockopt(ld->ld_so, SOL_SOCKET,
1842fc724630SAlan Wright 	    SO_REUSEADDR, &on, sizeof (on), CRED());
1843fc724630SAlan Wright 
18444163af6aSjose borrego 	if (ld->ld_family == AF_INET) {
18450f1702c5SYu Xiangning 		rc = ksocket_bind(ld->ld_so,
18460f1702c5SYu Xiangning 		    (struct sockaddr *)&ld->ld_sin,
18470f1702c5SYu Xiangning 		    sizeof (ld->ld_sin), CRED());
18487f667e74Sjose borrego 	} else {
18497f667e74Sjose borrego 		rc = ksocket_bind(ld->ld_so,
18507f667e74Sjose borrego 		    (struct sockaddr *)&ld->ld_sin6,
18517f667e74Sjose borrego 		    sizeof (ld->ld_sin6), CRED());
18527f667e74Sjose borrego 	}
18539fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
18549fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (rc != 0) {
18554163af6aSjose borrego 		cmn_err(CE_WARN, "port %d: bind failed", ld->ld_port);
18569fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (rc);
18579fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
18589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
18590f1702c5SYu Xiangning 	rc =  ksocket_listen(ld->ld_so, 20, CRED());
1860faa1795aSjb150015 	if (rc < 0) {
18614163af6aSjose borrego 		cmn_err(CE_WARN, "port %d: listen failed", ld->ld_port);
1862faa1795aSjb150015 		return (rc);
1863faa1795aSjb150015 	}
18644163af6aSjose borrego 
18654163af6aSjose borrego 	ksocket_hold(ld->ld_so);
18664163af6aSjose borrego 	rc = smb_thread_start(&ld->ld_thread);
18674163af6aSjose borrego 	if (rc != 0) {
18684163af6aSjose borrego 		ksocket_rele(ld->ld_so);
18694163af6aSjose borrego 		cmn_err(CE_WARN, "port %d: listener failed to start",
18704163af6aSjose borrego 		    ld->ld_port);
18714163af6aSjose borrego 		return (rc);
1872faa1795aSjb150015 	}
18734163af6aSjose borrego 	return (0);
18744163af6aSjose borrego }
18754163af6aSjose borrego 
18764163af6aSjose borrego /*
18774163af6aSjose borrego  * smb_server_listener_stop
18784163af6aSjose borrego  *
18794163af6aSjose borrego  * Stops the listener associated with the context passed in.
18804163af6aSjose borrego  */
18814163af6aSjose borrego static void
18824163af6aSjose borrego smb_server_listener_stop(smb_listener_daemon_t *ld)
18834163af6aSjose borrego {
18844163af6aSjose borrego 	SMB_LISTENER_VALID(ld);
18854163af6aSjose borrego 
18864163af6aSjose borrego 	if (ld->ld_so != NULL) {
18874163af6aSjose borrego 		smb_soshutdown(ld->ld_so);
18884163af6aSjose borrego 		smb_sodestroy(ld->ld_so);
18894163af6aSjose borrego 		smb_thread_stop(&ld->ld_thread);
18904163af6aSjose borrego 		ld->ld_so = NULL;
18914163af6aSjose borrego 	}
18924163af6aSjose borrego }
18934163af6aSjose borrego 
18944163af6aSjose borrego /*
18954163af6aSjose borrego  * smb_server_listener
18964163af6aSjose borrego  *
18974163af6aSjose borrego  * Entry point of the listeners.
18984163af6aSjose borrego  */
18994163af6aSjose borrego static void
19004163af6aSjose borrego smb_server_listener(smb_thread_t *thread, void *arg)
19014163af6aSjose borrego {
19024163af6aSjose borrego 	_NOTE(ARGUNUSED(thread))
19034163af6aSjose borrego 	smb_listener_daemon_t	*ld;
19044163af6aSjose borrego 	ksocket_t		s_so;
19054163af6aSjose borrego 	int			on;
19064163af6aSjose borrego 	int			txbuf_size;
19074163af6aSjose borrego 
19084163af6aSjose borrego 	ld = (smb_listener_daemon_t *)arg;
19094163af6aSjose borrego 
19104163af6aSjose borrego 	SMB_LISTENER_VALID(ld);
1911faa1795aSjb150015 
1912faa1795aSjb150015 	DTRACE_PROBE1(so__wait__accept, struct sonode *, ld->ld_so);
1913faa1795aSjb150015 
19149a244c8eSGordon Ross 	while (smb_thread_continue_nowait(&ld->ld_thread) &&
19159a244c8eSGordon Ross 	    ld->ld_sv->sv_state != SMB_SERVER_STATE_STOPPING) {
191641bd8510Skcrowenex 		int ret = ksocket_accept(ld->ld_so, NULL, NULL, &s_so, CRED());
191741bd8510Skcrowenex 
191841bd8510Skcrowenex 		switch (ret) {
191941bd8510Skcrowenex 		case 0:
192041bd8510Skcrowenex 			break;
192141bd8510Skcrowenex 		case ECONNABORTED:
192241bd8510Skcrowenex 			continue;
19239a244c8eSGordon Ross 
192441bd8510Skcrowenex 		case EINTR:
19259a244c8eSGordon Ross 		case EBADF:
19269a244c8eSGordon Ross 		case ENOTSOCK:
19279a244c8eSGordon Ross 			/* These are normal during shutdown. Silence. */
19289a244c8eSGordon Ross 			if (ld->ld_sv->sv_state == SMB_SERVER_STATE_STOPPING)
192941bd8510Skcrowenex 				goto out;
19309a244c8eSGordon Ross 			/* FALLTHROUGH */
193141bd8510Skcrowenex 		default:
193241bd8510Skcrowenex 			cmn_err(CE_WARN,
19337b072888SToomas Soome 			    "smb_server_listener: ksocket_accept failed (%d)",
193441bd8510Skcrowenex 			    ret);
19359a244c8eSGordon Ross 			/* avoid a tight CPU-burn loop here */
19369a244c8eSGordon Ross 			delay(MSEC_TO_TICK(10));
19379a244c8eSGordon Ross 			continue;
193841bd8510Skcrowenex 		}
193941bd8510Skcrowenex 
1940faa1795aSjb150015 		DTRACE_PROBE1(so__accept, struct sonode *, s_so);
1941faa1795aSjb150015 
19429fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		on = 1;
19439fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		(void) ksocket_setsockopt(s_so, IPPROTO_TCP, TCP_NODELAY,
19449fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		    &on, sizeof (on), CRED());
19459fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
19469fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		on = 1;
19479fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		(void) ksocket_setsockopt(s_so, SOL_SOCKET, SO_KEEPALIVE,
19489fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		    &on, sizeof (on), CRED());
19499fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
19509fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		txbuf_size = 128*1024;
19510f1702c5SYu Xiangning 		(void) ksocket_setsockopt(s_so, SOL_SOCKET, SO_SNDBUF,
19529fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		    (const void *)&txbuf_size, sizeof (txbuf_size), CRED());
19539fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
1954faa1795aSjb150015 		/*
1955faa1795aSjb150015 		 * Create a session for this connection.
1956faa1795aSjb150015 		 */
19574163af6aSjose borrego 		smb_server_create_session(ld, s_so);
1958faa1795aSjb150015 	}
195941bd8510Skcrowenex out:
19604163af6aSjose borrego 	ksocket_rele(ld->ld_so);
1961faa1795aSjb150015 }
19629fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
19634163af6aSjose borrego /*
19644163af6aSjose borrego  * smb_server_receiver
19654163af6aSjose borrego  *
19664163af6aSjose borrego  * Entry point of the receiver threads.
1967811599a4SMatt Barden  * Also does cleanup when socket disconnected.
19684163af6aSjose borrego  */
19699fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void
19704163af6aSjose borrego smb_server_receiver(void *arg)
19719fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
19724163af6aSjose borrego 	smb_session_t	*session;
1973faa1795aSjb150015 
1974811599a4SMatt Barden 	session = (smb_session_t *)arg;
1975811599a4SMatt Barden 
1976811599a4SMatt Barden 	/* We stay in here until socket disconnect. */
19774163af6aSjose borrego 	smb_session_receiver(session);
1978811599a4SMatt Barden 
1979811599a4SMatt Barden 	smb_server_destroy_session(session);
1980faa1795aSjb150015 }
1981faa1795aSjb150015 
1982faa1795aSjb150015 /*
1983faa1795aSjb150015  * smb_server_lookup
1984faa1795aSjb150015  *
19858622ec45SGordon Ross  * This function finds the server associated with the zone of the
19868622ec45SGordon Ross  * caller.  Note: requires a fix in the dynamic taskq code:
19878622ec45SGordon Ross  * 1501 taskq_create_proc ... TQ_DYNAMIC puts tasks in p0
1988faa1795aSjb150015  */
19894846df9bSKevin Crowe int
1990faa1795aSjb150015 smb_server_lookup(smb_server_t **psv)
1991faa1795aSjb150015 {
1992faa1795aSjb150015 	zoneid_t	zid;
1993faa1795aSjb150015 	smb_server_t	*sv;
1994faa1795aSjb150015 
1995faa1795aSjb150015 	zid = getzoneid();
1996faa1795aSjb150015 
1997faa1795aSjb150015 	smb_llist_enter(&smb_servers, RW_READER);
1998faa1795aSjb150015 	sv = smb_llist_head(&smb_servers);
1999faa1795aSjb150015 	while (sv) {
20009fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_SERVER_VALID(sv);
2001faa1795aSjb150015 		if (sv->sv_zid == zid) {
2002faa1795aSjb150015 			mutex_enter(&sv->sv_mutex);
2003faa1795aSjb150015 			if (sv->sv_state != SMB_SERVER_STATE_DELETING) {
2004faa1795aSjb150015 				sv->sv_refcnt++;
2005faa1795aSjb150015 				mutex_exit(&sv->sv_mutex);
2006faa1795aSjb150015 				smb_llist_exit(&smb_servers);
2007faa1795aSjb150015 				*psv = sv;
2008faa1795aSjb150015 				return (0);
2009faa1795aSjb150015 			}
2010faa1795aSjb150015 			mutex_exit(&sv->sv_mutex);
2011faa1795aSjb150015 			break;
2012faa1795aSjb150015 		}
2013faa1795aSjb150015 		sv = smb_llist_next(&smb_servers, sv);
2014faa1795aSjb150015 	}
2015faa1795aSjb150015 	smb_llist_exit(&smb_servers);
2016faa1795aSjb150015 	return (EPERM);
2017faa1795aSjb150015 }
2018faa1795aSjb150015 
2019faa1795aSjb150015 /*
2020faa1795aSjb150015  * smb_server_release
2021faa1795aSjb150015  *
2022faa1795aSjb150015  * This function decrements the reference count of the server and signals its
2023faa1795aSjb150015  * condition variable if the state of the server is SMB_SERVER_STATE_DELETING.
2024faa1795aSjb150015  */
20254846df9bSKevin Crowe void
2026faa1795aSjb150015 smb_server_release(smb_server_t *sv)
2027faa1795aSjb150015 {
20289fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	SMB_SERVER_VALID(sv);
2029faa1795aSjb150015 
2030faa1795aSjb150015 	mutex_enter(&sv->sv_mutex);
2031faa1795aSjb150015 	ASSERT(sv->sv_refcnt);
2032faa1795aSjb150015 	sv->sv_refcnt--;
2033faa1795aSjb150015 	if ((sv->sv_refcnt == 0) && (sv->sv_state == SMB_SERVER_STATE_DELETING))
2034faa1795aSjb150015 		cv_signal(&sv->sv_cv);
2035faa1795aSjb150015 	mutex_exit(&sv->sv_mutex);
2036faa1795aSjb150015 }
2037faa1795aSjb150015 
20381fcced4cSJordan Brown /*
203997264293SGordon Ross  * smb_server_lookup_user
204097264293SGordon Ross  *
204197264293SGordon Ross  * Find an smb_user by its user_id
204297264293SGordon Ross  * Optional ssn_id (if non-zero) restricts search to a specific session.
204397264293SGordon Ross  *
204497264293SGordon Ross  * Returns smb_user_t * held. Caller must smb_user_rele(user)
204597264293SGordon Ross  * Returns NULL if not found.
204697264293SGordon Ross  */
204797264293SGordon Ross smb_user_t *
204897264293SGordon Ross smb_server_lookup_user(smb_server_t *sv, uint64_t ssn_id, uint64_t user_id)
204997264293SGordon Ross {
205097264293SGordon Ross 	smb_llist_t	*slist = &sv->sv_session_list;
205197264293SGordon Ross 	smb_session_t	*sn;
205297264293SGordon Ross 	smb_user_t	*user = NULL;
205397264293SGordon Ross 
205497264293SGordon Ross 	smb_llist_enter(slist, RW_READER);
205597264293SGordon Ross 
205697264293SGordon Ross 	for (sn = smb_llist_head(slist);
205797264293SGordon Ross 	    sn != NULL && user == NULL;
205897264293SGordon Ross 	    sn = smb_llist_next(slist, sn)) {
205997264293SGordon Ross 		SMB_SESSION_VALID(sn);
206097264293SGordon Ross 
206197264293SGordon Ross 		if (ssn_id != 0 && ssn_id != sn->s_kid)
206297264293SGordon Ross 			continue;
206397264293SGordon Ross 		if (sn->s_state != SMB_SESSION_STATE_NEGOTIATED)
206497264293SGordon Ross 			continue;
206597264293SGordon Ross 
206697264293SGordon Ross 		user = smb_session_lookup_ssnid(sn, user_id);
206797264293SGordon Ross 	}
206897264293SGordon Ross 	smb_llist_exit(slist);
206997264293SGordon Ross 
207097264293SGordon Ross 	return (user);
207197264293SGordon Ross }
207297264293SGordon Ross 
207397264293SGordon Ross /*
20741fcced4cSJordan Brown  * Enumerate the users associated with a session list.
20751fcced4cSJordan Brown  */
20761fcced4cSJordan Brown static void
20778d94f651SGordon Ross smb_server_enum_users(smb_server_t *sv, smb_svcenum_t *svcenum)
2078faa1795aSjb150015 {
20798d94f651SGordon Ross 	smb_llist_t	*ll = &sv->sv_session_list;
20801fcced4cSJordan Brown 	smb_session_t	*sn;
2081faa1795aSjb150015 	smb_llist_t	*ulist;
20821fcced4cSJordan Brown 	smb_user_t	*user;
208329bd2886SAlan Wright 	int		rc = 0;
2084faa1795aSjb150015 
20854163af6aSjose borrego 	smb_llist_enter(ll, RW_READER);
20864163af6aSjose borrego 	sn = smb_llist_head(ll);
20871fcced4cSJordan Brown 
20881fcced4cSJordan Brown 	while (sn != NULL) {
20894163af6aSjose borrego 		SMB_SESSION_VALID(sn);
2090faa1795aSjb150015 		ulist = &sn->s_user_list;
2091faa1795aSjb150015 		smb_llist_enter(ulist, RW_READER);
2092faa1795aSjb150015 		user = smb_llist_head(ulist);
20931fcced4cSJordan Brown 
20941fcced4cSJordan Brown 		while (user != NULL) {
20951fcced4cSJordan Brown 			if (smb_user_hold(user)) {
20961fcced4cSJordan Brown 				rc = smb_user_enum(user, svcenum);
20971fcced4cSJordan Brown 				smb_user_release(user);
20983b13a1efSThomas Keiser 				if (rc != 0)
20993b13a1efSThomas Keiser 					break;
2100faa1795aSjb150015 			}
21011fcced4cSJordan Brown 
2102faa1795aSjb150015 			user = smb_llist_next(ulist, user);
2103faa1795aSjb150015 		}
21041fcced4cSJordan Brown 
21051fcced4cSJordan Brown 		smb_llist_exit(ulist);
21061fcced4cSJordan Brown 
21071fcced4cSJordan Brown 		if (rc != 0)
21081fcced4cSJordan Brown 			break;
21091fcced4cSJordan Brown 
21104163af6aSjose borrego 		sn = smb_llist_next(ll, sn);
21111fcced4cSJordan Brown 	}
21121fcced4cSJordan Brown 
21134163af6aSjose borrego 	smb_llist_exit(ll);
21141fcced4cSJordan Brown }
21151fcced4cSJordan Brown 
21161fcced4cSJordan Brown /*
21173b13a1efSThomas Keiser  * Enumerate the trees/files associated with a session list.
21183b13a1efSThomas Keiser  */
21193b13a1efSThomas Keiser static void
21208d94f651SGordon Ross smb_server_enum_trees(smb_server_t *sv, smb_svcenum_t *svcenum)
21213b13a1efSThomas Keiser {
21228d94f651SGordon Ross 	smb_llist_t	*ll = &sv->sv_session_list;
21233b13a1efSThomas Keiser 	smb_session_t	*sn;
21243b13a1efSThomas Keiser 	smb_llist_t	*tlist;
21253b13a1efSThomas Keiser 	smb_tree_t	*tree;
21263b13a1efSThomas Keiser 	int		rc = 0;
21273b13a1efSThomas Keiser 
21283b13a1efSThomas Keiser 	smb_llist_enter(ll, RW_READER);
21293b13a1efSThomas Keiser 	sn = smb_llist_head(ll);
21303b13a1efSThomas Keiser 
21313b13a1efSThomas Keiser 	while (sn != NULL) {
21323b13a1efSThomas Keiser 		SMB_SESSION_VALID(sn);
21333b13a1efSThomas Keiser 		tlist = &sn->s_tree_list;
21343b13a1efSThomas Keiser 		smb_llist_enter(tlist, RW_READER);
21353b13a1efSThomas Keiser 		tree = smb_llist_head(tlist);
21363b13a1efSThomas Keiser 
21373b13a1efSThomas Keiser 		while (tree != NULL) {
21383b13a1efSThomas Keiser 			if (smb_tree_hold(tree)) {
21393b13a1efSThomas Keiser 				rc = smb_tree_enum(tree, svcenum);
21403b13a1efSThomas Keiser 				smb_tree_release(tree);
21413b13a1efSThomas Keiser 				if (rc != 0)
21423b13a1efSThomas Keiser 					break;
21433b13a1efSThomas Keiser 			}
21443b13a1efSThomas Keiser 
21453b13a1efSThomas Keiser 			tree = smb_llist_next(tlist, tree);
21463b13a1efSThomas Keiser 		}
21473b13a1efSThomas Keiser 
21483b13a1efSThomas Keiser 		smb_llist_exit(tlist);
21493b13a1efSThomas Keiser 
21503b13a1efSThomas Keiser 		if (rc != 0)
21513b13a1efSThomas Keiser 			break;
21523b13a1efSThomas Keiser 
21533b13a1efSThomas Keiser 		sn = smb_llist_next(ll, sn);
21543b13a1efSThomas Keiser 	}
21553b13a1efSThomas Keiser 
21563b13a1efSThomas Keiser 	smb_llist_exit(ll);
21573b13a1efSThomas Keiser }
21583b13a1efSThomas Keiser 
21593b13a1efSThomas Keiser /*
21601fcced4cSJordan Brown  * Disconnect sessions associated with the specified client and username.
21611fcced4cSJordan Brown  * Empty strings are treated as wildcards.
21621fcced4cSJordan Brown  */
21631fcced4cSJordan Brown static int
21648d94f651SGordon Ross smb_server_session_disconnect(smb_server_t *sv,
21651fcced4cSJordan Brown     const char *client, const char *name)
21661fcced4cSJordan Brown {
21678d94f651SGordon Ross 	smb_llist_t	*ll = &sv->sv_session_list;
21681fcced4cSJordan Brown 	smb_session_t	*sn;
21691fcced4cSJordan Brown 	smb_llist_t	*ulist;
21701fcced4cSJordan Brown 	smb_user_t	*user;
21711fcced4cSJordan Brown 	int		count = 0;
21721fcced4cSJordan Brown 
21734163af6aSjose borrego 	smb_llist_enter(ll, RW_READER);
21741fcced4cSJordan Brown 
2175811599a4SMatt Barden 	for (sn = smb_llist_head(ll);
2176811599a4SMatt Barden 	    sn != NULL;
2177811599a4SMatt Barden 	    sn = smb_llist_next(ll, sn)) {
21784163af6aSjose borrego 		SMB_SESSION_VALID(sn);
21791fcced4cSJordan Brown 
2180811599a4SMatt Barden 		if (*client != '\0' && !smb_session_isclient(sn, client))
21811fcced4cSJordan Brown 			continue;
21821fcced4cSJordan Brown 
21831fcced4cSJordan Brown 		ulist = &sn->s_user_list;
21841fcced4cSJordan Brown 		smb_llist_enter(ulist, RW_READER);
21851fcced4cSJordan Brown 
2186811599a4SMatt Barden 		for (user = smb_llist_head(ulist);
2187811599a4SMatt Barden 		    user != NULL;
2188811599a4SMatt Barden 		    user = smb_llist_next(ulist, user)) {
21891fcced4cSJordan Brown 
2190811599a4SMatt Barden 			if (smb_user_hold(user)) {
2191896d9552SGordon Ross 
2192896d9552SGordon Ross 				if (*name == '\0' ||
2193896d9552SGordon Ross 				    smb_user_namecmp(user, name)) {
2194811599a4SMatt Barden 					smb_user_logoff(user);
2195811599a4SMatt Barden 					count++;
21961fcced4cSJordan Brown 				}
2197896d9552SGordon Ross 
2198896d9552SGordon Ross 				smb_user_release(user);
2199896d9552SGordon Ross 			}
22001fcced4cSJordan Brown 		}
22011fcced4cSJordan Brown 
2202faa1795aSjb150015 		smb_llist_exit(ulist);
2203faa1795aSjb150015 	}
22041fcced4cSJordan Brown 
22054163af6aSjose borrego 	smb_llist_exit(ll);
22061fcced4cSJordan Brown 	return (count);
22071fcced4cSJordan Brown }
22081fcced4cSJordan Brown 
22091fcced4cSJordan Brown /*
22101fcced4cSJordan Brown  * Close a file by its unique id.
22111fcced4cSJordan Brown  */
22121fcced4cSJordan Brown static int
22138d94f651SGordon Ross smb_server_fclose(smb_server_t *sv, uint32_t uniqid)
22141fcced4cSJordan Brown {
22158d94f651SGordon Ross 	smb_llist_t	*ll;
22161fcced4cSJordan Brown 	smb_session_t	*sn;
22173b13a1efSThomas Keiser 	smb_llist_t	*tlist;
22183b13a1efSThomas Keiser 	smb_tree_t	*tree;
22191fcced4cSJordan Brown 	int		rc = ENOENT;
22201fcced4cSJordan Brown 
22218d94f651SGordon Ross 	ll = &sv->sv_session_list;
22224163af6aSjose borrego 	smb_llist_enter(ll, RW_READER);
22234163af6aSjose borrego 	sn = smb_llist_head(ll);
22241fcced4cSJordan Brown 
22251fcced4cSJordan Brown 	while ((sn != NULL) && (rc == ENOENT)) {
22264163af6aSjose borrego 		SMB_SESSION_VALID(sn);
22273b13a1efSThomas Keiser 		tlist = &sn->s_tree_list;
22283b13a1efSThomas Keiser 		smb_llist_enter(tlist, RW_READER);
22293b13a1efSThomas Keiser 		tree = smb_llist_head(tlist);
22301fcced4cSJordan Brown 
22313b13a1efSThomas Keiser 		while ((tree != NULL) && (rc == ENOENT)) {
22323b13a1efSThomas Keiser 			if (smb_tree_hold(tree)) {
22333b13a1efSThomas Keiser 				rc = smb_tree_fclose(tree, uniqid);
22343b13a1efSThomas Keiser 				smb_tree_release(tree);
22351fcced4cSJordan Brown 			}
22361fcced4cSJordan Brown 
22373b13a1efSThomas Keiser 			tree = smb_llist_next(tlist, tree);
22381fcced4cSJordan Brown 		}
22391fcced4cSJordan Brown 
22403b13a1efSThomas Keiser 		smb_llist_exit(tlist);
22414163af6aSjose borrego 		sn = smb_llist_next(ll, sn);
22421fcced4cSJordan Brown 	}
22431fcced4cSJordan Brown 
22444163af6aSjose borrego 	smb_llist_exit(ll);
22451fcced4cSJordan Brown 	return (rc);
2246faa1795aSjb150015 }
2247faa1795aSjb150015 
2248811599a4SMatt Barden /*
2249811599a4SMatt Barden  * This is used by SMB2 session setup to logoff a previous session,
2250811599a4SMatt Barden  * so it can force a logoff that we haven't noticed yet.
2251811599a4SMatt Barden  * This is not called frequently, so we just walk the list of
2252811599a4SMatt Barden  * connections searching for the user.
22531baeef30SPrashanth Badari  *
22541baeef30SPrashanth Badari  * Note that this must wait for any durable handles (ofiles)
22551baeef30SPrashanth Badari  * owned by this user to become "orphaned", so that a reconnect
22561baeef30SPrashanth Badari  * that may immediately follow can find and use such ofiles.
2257811599a4SMatt Barden  */
2258811599a4SMatt Barden void
2259811599a4SMatt Barden smb_server_logoff_ssnid(smb_request_t *sr, uint64_t ssnid)
2260811599a4SMatt Barden {
2261811599a4SMatt Barden 	smb_server_t	*sv = sr->sr_server;
2262811599a4SMatt Barden 	smb_llist_t	*sess_list;
2263811599a4SMatt Barden 	smb_session_t	*sess;
22641baeef30SPrashanth Badari 	smb_user_t	*user = NULL;
22650c5f22c1SGordon Ross 	boolean_t	do_logoff = B_FALSE;
22661baeef30SPrashanth Badari 
22671baeef30SPrashanth Badari 	SMB_SERVER_VALID(sv);
2268811599a4SMatt Barden 
2269811599a4SMatt Barden 	if (sv->sv_state != SMB_SERVER_STATE_RUNNING)
2270811599a4SMatt Barden 		return;
2271811599a4SMatt Barden 
2272811599a4SMatt Barden 	sess_list = &sv->sv_session_list;
2273811599a4SMatt Barden 	smb_llist_enter(sess_list, RW_READER);
2274811599a4SMatt Barden 
2275811599a4SMatt Barden 	for (sess = smb_llist_head(sess_list);
2276811599a4SMatt Barden 	    sess != NULL;
2277811599a4SMatt Barden 	    sess = smb_llist_next(sess_list, sess)) {
2278811599a4SMatt Barden 
2279811599a4SMatt Barden 		SMB_SESSION_VALID(sess);
2280811599a4SMatt Barden 
2281811599a4SMatt Barden 		if (sess->dialect < SMB_VERS_2_BASE)
2282811599a4SMatt Barden 			continue;
2283811599a4SMatt Barden 
22841baeef30SPrashanth Badari 		switch (sess->s_state) {
22851baeef30SPrashanth Badari 		case SMB_SESSION_STATE_NEGOTIATED:
22861baeef30SPrashanth Badari 		case SMB_SESSION_STATE_TERMINATED:
22871baeef30SPrashanth Badari 		case SMB_SESSION_STATE_DISCONNECTED:
22881baeef30SPrashanth Badari 			break;
22891baeef30SPrashanth Badari 		default:
2290811599a4SMatt Barden 			continue;
2291811599a4SMatt Barden 		}
2292811599a4SMatt Barden 
22931baeef30SPrashanth Badari 		/*
22941baeef30SPrashanth Badari 		 * Normal situation is to find a LOGGED_ON user.
22951baeef30SPrashanth Badari 		 */
22961baeef30SPrashanth Badari 		user = smb_session_lookup_uid_st(sess, ssnid, 0,
22971baeef30SPrashanth Badari 		    SMB_USER_STATE_LOGGED_ON);
22981baeef30SPrashanth Badari 		if (user != NULL) {
22991baeef30SPrashanth Badari 			if (smb_is_same_user(user->u_cred, sr->user_cr)) {
23000c5f22c1SGordon Ross 				do_logoff = B_TRUE;
23011baeef30SPrashanth Badari 				break;
23021baeef30SPrashanth Badari 			}
2303811599a4SMatt Barden 			smb_user_release(user);
23041baeef30SPrashanth Badari 			user = NULL;
23051baeef30SPrashanth Badari 		}
2306811599a4SMatt Barden 
2307811599a4SMatt Barden 		/*
23081baeef30SPrashanth Badari 		 * If we raced with disconnect, may find LOGGING_OFF,
23091baeef30SPrashanth Badari 		 * in which case we want to just wait for it.
2310811599a4SMatt Barden 		 */
23111baeef30SPrashanth Badari 		user = smb_session_lookup_uid_st(sess, ssnid, 0,
23121baeef30SPrashanth Badari 		    SMB_USER_STATE_LOGGING_OFF);
23131baeef30SPrashanth Badari 		if (user != NULL) {
23141baeef30SPrashanth Badari 			if (smb_is_same_user(user->u_cred, sr->user_cr))
23151baeef30SPrashanth Badari 				break;
23161baeef30SPrashanth Badari 			smb_user_release(user);
23171baeef30SPrashanth Badari 			user = NULL;
23181baeef30SPrashanth Badari 		}
2319811599a4SMatt Barden 	}
2320811599a4SMatt Barden 
2321811599a4SMatt Barden 	smb_llist_exit(sess_list);
23221baeef30SPrashanth Badari 
23230c5f22c1SGordon Ross 	/*
23240c5f22c1SGordon Ross 	 * Note that smb_user_logoff() can block for a while if
23250c5f22c1SGordon Ross 	 * smb_session_disconnect_owned_trees, smb_ofile_close_all
23260c5f22c1SGordon Ross 	 * ends up blocked on locks held by running requests.
23270c5f22c1SGordon Ross 	 * Do that while not holding the session list rwlock.
23280c5f22c1SGordon Ross 	 */
23291baeef30SPrashanth Badari 	if (user != NULL) {
23300c5f22c1SGordon Ross 		if (do_logoff) {
23310c5f22c1SGordon Ross 			/* Treat this as if we lost the connection */
23320c5f22c1SGordon Ross 			user->preserve_opens = SMB2_DH_PRESERVE_SOME;
23330c5f22c1SGordon Ross 			smb_user_logoff(user);
23340c5f22c1SGordon Ross 		}
23350c5f22c1SGordon Ross 
23361baeef30SPrashanth Badari 		/*
23371baeef30SPrashanth Badari 		 * Wait for durable handles to be orphaned.
23381baeef30SPrashanth Badari 		 * Note: not holding the sess list rwlock.
23391baeef30SPrashanth Badari 		 */
23401baeef30SPrashanth Badari 		smb_user_wait_trees(user);
23411baeef30SPrashanth Badari 
23421baeef30SPrashanth Badari 		/*
23431baeef30SPrashanth Badari 		 * Could be doing the last release on a user below,
23441baeef30SPrashanth Badari 		 * which can leave work on the delete queues for
23451baeef30SPrashanth Badari 		 * s_user_list or s_tree_list so flush those.
23461baeef30SPrashanth Badari 		 * Must hold the session list after the user release
23471baeef30SPrashanth Badari 		 * so that the session can't go away while we flush.
23481baeef30SPrashanth Badari 		 */
23491baeef30SPrashanth Badari 		smb_llist_enter(sess_list, RW_READER);
23501baeef30SPrashanth Badari 
23511baeef30SPrashanth Badari 		sess = user->u_session;
23521baeef30SPrashanth Badari 		smb_user_release(user);
23531baeef30SPrashanth Badari 
23541baeef30SPrashanth Badari 		smb_llist_flush(&sess->s_tree_list);
23551baeef30SPrashanth Badari 		smb_llist_flush(&sess->s_user_list);
23561baeef30SPrashanth Badari 
23571baeef30SPrashanth Badari 		smb_llist_exit(sess_list);
23581baeef30SPrashanth Badari 	}
2359811599a4SMatt Barden }
2360811599a4SMatt Barden 
236112b65585SGordon Ross /* See also: libsmb smb_kmod_setcfg */
2362faa1795aSjb150015 static void
236329bd2886SAlan Wright smb_server_store_cfg(smb_server_t *sv, smb_ioc_cfg_t *ioc)
2364faa1795aSjb150015 {
236529bd2886SAlan Wright 	if (ioc->maxconnections == 0)
236629bd2886SAlan Wright 		ioc->maxconnections = 0xFFFFFFFF;
2367faa1795aSjb150015 
23681160dcf7SMatt Barden 	if (ioc->encrypt == SMB_CONFIG_REQUIRED &&
23691160dcf7SMatt Barden 	    ioc->max_protocol < SMB_VERS_3_0) {
23701160dcf7SMatt Barden 		cmn_err(CE_WARN, "Server set to require encryption; "
23711160dcf7SMatt Barden 		    "forcing max_protocol to 3.0");
23721160dcf7SMatt Barden 		ioc->max_protocol = SMB_VERS_3_0;
23731160dcf7SMatt Barden 	}
237429bd2886SAlan Wright 	sv->sv_cfg.skc_maxworkers = ioc->maxworkers;
237529bd2886SAlan Wright 	sv->sv_cfg.skc_maxconnections = ioc->maxconnections;
237629bd2886SAlan Wright 	sv->sv_cfg.skc_keepalive = ioc->keepalive;
237729bd2886SAlan Wright 	sv->sv_cfg.skc_restrict_anon = ioc->restrict_anon;
237829bd2886SAlan Wright 	sv->sv_cfg.skc_signing_enable = ioc->signing_enable;
237929bd2886SAlan Wright 	sv->sv_cfg.skc_signing_required = ioc->signing_required;
238029bd2886SAlan Wright 	sv->sv_cfg.skc_oplock_enable = ioc->oplock_enable;
238129bd2886SAlan Wright 	sv->sv_cfg.skc_sync_enable = ioc->sync_enable;
238229bd2886SAlan Wright 	sv->sv_cfg.skc_secmode = ioc->secmode;
238312b65585SGordon Ross 	sv->sv_cfg.skc_netbios_enable = ioc->netbios_enable;
238429bd2886SAlan Wright 	sv->sv_cfg.skc_ipv6_enable = ioc->ipv6_enable;
2385cb174861Sjoyce mcintosh 	sv->sv_cfg.skc_print_enable = ioc->print_enable;
23865f1ef25cSAram Hăvărneanu 	sv->sv_cfg.skc_traverse_mounts = ioc->traverse_mounts;
2387814e0daaSGordon Ross 	sv->sv_cfg.skc_short_names = ioc->short_names;
2388a90cf9f2SGordon Ross 	sv->sv_cfg.skc_max_protocol = ioc->max_protocol;
23893e2c0c09SMatt Barden 	sv->sv_cfg.skc_min_protocol = ioc->min_protocol;
23901160dcf7SMatt Barden 	sv->sv_cfg.skc_encrypt = ioc->encrypt;
2391b0bb0d63SGordon Ross 	sv->sv_cfg.skc_encrypt_ciphers = ioc->encrypt_ciphers;
2392148c5f43SAlan Wright 	sv->sv_cfg.skc_execflags = ioc->exec_flags;
239312b65585SGordon Ross 	sv->sv_cfg.skc_negtok_len = ioc->negtok_len;
23942cf6b79fSGordon Ross 	sv->sv_cfg.skc_max_opens = ioc->max_opens;
2395148c5f43SAlan Wright 	sv->sv_cfg.skc_version = ioc->version;
2396a90cf9f2SGordon Ross 	sv->sv_cfg.skc_initial_credits = ioc->initial_credits;
2397a90cf9f2SGordon Ross 	sv->sv_cfg.skc_maximum_credits = ioc->maximum_credits;
2398a90cf9f2SGordon Ross 
239912b65585SGordon Ross 	(void) memcpy(sv->sv_cfg.skc_machine_uuid, ioc->machine_uuid,
240012b65585SGordon Ross 	    sizeof (uuid_t));
240112b65585SGordon Ross 	(void) memcpy(sv->sv_cfg.skc_negtok, ioc->negtok,
240212b65585SGordon Ross 	    sizeof (sv->sv_cfg.skc_negtok));
240312b65585SGordon Ross 	(void) memcpy(sv->sv_cfg.skc_native_os, ioc->native_os,
240412b65585SGordon Ross 	    sizeof (sv->sv_cfg.skc_native_os));
240512b65585SGordon Ross 	(void) memcpy(sv->sv_cfg.skc_native_lm, ioc->native_lm,
240612b65585SGordon Ross 	    sizeof (sv->sv_cfg.skc_native_lm));
240712b65585SGordon Ross 
240829bd2886SAlan Wright 	(void) strlcpy(sv->sv_cfg.skc_nbdomain, ioc->nbdomain,
240929bd2886SAlan Wright 	    sizeof (sv->sv_cfg.skc_nbdomain));
241029bd2886SAlan Wright 	(void) strlcpy(sv->sv_cfg.skc_fqdn, ioc->fqdn,
241129bd2886SAlan Wright 	    sizeof (sv->sv_cfg.skc_fqdn));
241229bd2886SAlan Wright 	(void) strlcpy(sv->sv_cfg.skc_hostname, ioc->hostname,
241329bd2886SAlan Wright 	    sizeof (sv->sv_cfg.skc_hostname));
241429bd2886SAlan Wright 	(void) strlcpy(sv->sv_cfg.skc_system_comment, ioc->system_comment,
241529bd2886SAlan Wright 	    sizeof (sv->sv_cfg.skc_system_comment));
2416faa1795aSjb150015 }
2417faa1795aSjb150015 
2418faa1795aSjb150015 static int
2419faa1795aSjb150015 smb_server_fsop_start(smb_server_t *sv)
2420faa1795aSjb150015 {
2421faa1795aSjb150015 	int	error;
2422faa1795aSjb150015 
24238622ec45SGordon Ross 	error = smb_node_root_init(sv, &sv->si_root_smb_node);
2424faa1795aSjb150015 	if (error != 0)
2425faa1795aSjb150015 		sv->si_root_smb_node = NULL;
2426faa1795aSjb150015 
2427faa1795aSjb150015 	return (error);
2428faa1795aSjb150015 }
2429faa1795aSjb150015 
2430faa1795aSjb150015 static void
2431faa1795aSjb150015 smb_server_fsop_stop(smb_server_t *sv)
2432faa1795aSjb150015 {
2433faa1795aSjb150015 	if (sv->si_root_smb_node != NULL) {
2434faa1795aSjb150015 		smb_node_release(sv->si_root_smb_node);
2435faa1795aSjb150015 		sv->si_root_smb_node = NULL;
2436faa1795aSjb150015 	}
2437faa1795aSjb150015 }
24389fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
24399fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_event_t *
24408622ec45SGordon Ross smb_event_create(smb_server_t *sv, int timeout)
24419fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
24429fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_event_t	*event;
24439fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
24448622ec45SGordon Ross 	if (smb_server_is_stopping(sv))
24459fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (NULL);
24469fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
24478622ec45SGordon Ross 	event = kmem_cache_alloc(smb_cache_event, KM_SLEEP);
24489fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
24499fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	bzero(event, sizeof (smb_event_t));
24509fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_init(&event->se_mutex, NULL, MUTEX_DEFAULT, NULL);
24519fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	cv_init(&event->se_cv, NULL, CV_DEFAULT, NULL);
24529fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event->se_magic = SMB_EVENT_MAGIC;
24539fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event->se_txid = smb_event_alloc_txid();
24549fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event->se_server = sv;
2455cb174861Sjoyce mcintosh 	event->se_timeout = timeout;
24569fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
24579fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_enter(&sv->sv_event_list, RW_WRITER);
24589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_insert_tail(&sv->sv_event_list, event);
24599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_exit(&sv->sv_event_list);
24609fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
24619fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	return (event);
24629fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
24639fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
24649fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States void
24659fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_event_destroy(smb_event_t *event)
24669fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
24679fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_server_t	*sv;
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;
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 	ASSERT(event->se_waittime == 0);
24748622ec45SGordon Ross 	sv = event->se_server;
24758622ec45SGordon Ross 	SMB_SERVER_VALID(sv);
24769fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
24779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_enter(&sv->sv_event_list, RW_WRITER);
24789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_remove(&sv->sv_event_list, event);
24799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_exit(&sv->sv_event_list);
24809fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
24819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event->se_magic = (uint32_t)~SMB_EVENT_MAGIC;
24829fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	cv_destroy(&event->se_cv);
24839fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_destroy(&event->se_mutex);
24849fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
24858622ec45SGordon Ross 	kmem_cache_free(smb_cache_event, event);
24869fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
24879fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
24889fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
24899fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Get the txid for the specified event.
24909fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  */
24919fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States uint32_t
24929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_event_txid(smb_event_t *event)
24939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
24949fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (event != NULL) {
24959fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_EVENT_VALID(event);
24969fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (event->se_txid);
24979fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
24989fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
24999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	cmn_err(CE_NOTE, "smb_event_txid failed");
25009fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	return ((uint32_t)-1);
25019fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
25029fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
25039fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
25049fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Wait for event notification.
25059fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  */
25069fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States int
25079fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_event_wait(smb_event_t *event)
25089fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
25099fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	int	seconds = 1;
25109fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	int	ticks;
2511856399cfSGordon Ross 	int	err;
25129fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
25139fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (event == NULL)
25149fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (EINVAL);
25159fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
25169fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	SMB_EVENT_VALID(event);
25179fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
25189fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_enter(&event->se_mutex);
25199fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event->se_waittime = 1;
25209fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event->se_errno = 0;
25219fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
25229fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	while (!(event->se_notified)) {
2523c5866007SKeyur Desai 		if (smb_event_debug && ((event->se_waittime % 30) == 0))
25249fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			cmn_err(CE_NOTE, "smb_event_wait[%d] (%d sec)",
25259fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			    event->se_txid, event->se_waittime);
25269fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
25279fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		if (event->se_errno != 0)
25289fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			break;
25299fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
2530cb174861Sjoyce mcintosh 		if (event->se_waittime > event->se_timeout) {
25319fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			event->se_errno = ETIME;
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 		ticks = SEC_TO_TICK(seconds);
25369fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		(void) cv_reltimedwait(&event->se_cv,
25379fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		    &event->se_mutex, (clock_t)ticks, TR_CLOCK_TICK);
25389fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		++event->se_waittime;
25399fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
25409fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
2541856399cfSGordon Ross 	err = event->se_errno;
25429fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event->se_waittime = 0;
25439fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event->se_notified = B_FALSE;
25449fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	cv_signal(&event->se_cv);
25459fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_exit(&event->se_mutex);
2546856399cfSGordon Ross 	return (err);
25479fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
25489fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
25499fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
25509fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * If txid is non-zero, cancel the specified event.
25519fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Otherwise, cancel all events.
25529fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  */
25539fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void
25549fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_event_cancel(smb_server_t *sv, uint32_t txid)
25559fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
25569fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_event_t	*event;
25579fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_t	*event_list;
25589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
25599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	SMB_SERVER_VALID(sv);
25609fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
25619fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event_list = &sv->sv_event_list;
25629fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_enter(event_list, RW_WRITER);
25639fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
25649fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event = smb_llist_head(event_list);
25659fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	while (event) {
25669fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_EVENT_VALID(event);
25679fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
25689fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		if (txid == 0 || event->se_txid == txid) {
25699fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			mutex_enter(&event->se_mutex);
25709fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			event->se_errno = ECANCELED;
25719fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			event->se_notified = B_TRUE;
25729fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			cv_signal(&event->se_cv);
25739fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			mutex_exit(&event->se_mutex);
25749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
25759fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			if (txid != 0)
25769fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 				break;
25779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		}
25789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
25799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		event = smb_llist_next(event_list, event);
25809fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
25819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
25829fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_exit(event_list);
25839fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
25849fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
25859fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
25869fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * If txid is non-zero, notify the specified event.
25879fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Otherwise, notify all events.
25889fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  */
2589cb174861Sjoyce mcintosh void
25909fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_event_notify(smb_server_t *sv, uint32_t txid)
25919fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
25929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_event_t	*event;
25939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_t	*event_list;
25949fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
25959fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	SMB_SERVER_VALID(sv);
25969fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
25979fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event_list = &sv->sv_event_list;
25989fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_enter(event_list, RW_READER);
25999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
26009fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event = smb_llist_head(event_list);
26019fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	while (event) {
26029fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_EVENT_VALID(event);
26039fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
26049fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		if (txid == 0 || event->se_txid == txid) {
26059fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			mutex_enter(&event->se_mutex);
26069fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			event->se_notified = B_TRUE;
26079fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			cv_signal(&event->se_cv);
26089fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			mutex_exit(&event->se_mutex);
26099fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
26109fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			if (txid != 0)
26119fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 				break;
26129fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		}
26139fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
26149fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		event = smb_llist_next(event_list, event);
26159fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
26169fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
26179fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_exit(event_list);
26189fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
26199fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
26209fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
26219fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Allocate a new transaction id (txid).
26229fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  *
26239fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * 0 or -1 are not assigned because they are used to detect invalid
26249fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * conditions or to indicate all open id's.
26259fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  */
26269fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static uint32_t
26279fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_event_alloc_txid(void)
26289fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
26299fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	static kmutex_t	txmutex;
26309fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	static uint32_t	txid;
26319fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	uint32_t	txid_ret;
26329fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
26339fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_enter(&txmutex);
26349fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
26359fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (txid == 0)
26369fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		txid = ddi_get_lbolt() << 11;
26379fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
26389fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	do {
26399fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		++txid;
26409fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	} while (txid == 0 || txid == (uint32_t)-1);
26419fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
26429fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	txid_ret = txid;
26439fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_exit(&txmutex);
26449fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
26459fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	return (txid_ret);
26469fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
2647cb174861Sjoyce mcintosh 
2648cb174861Sjoyce mcintosh /*
2649cb174861Sjoyce mcintosh  * Called by the ioctl to find the corresponding
2650cb174861Sjoyce mcintosh  * spooldoc node.  removes node on success
2651cb174861Sjoyce mcintosh  *
2652cb174861Sjoyce mcintosh  * Return values
2653cb174861Sjoyce mcintosh  * rc
2654cb174861Sjoyce mcintosh  * B_FALSE - not found
2655cb174861Sjoyce mcintosh  * B_TRUE  - found
2656cb174861Sjoyce mcintosh  *
2657cb174861Sjoyce mcintosh  */
2658cb174861Sjoyce mcintosh 
265923a9c295SGordon Ross static boolean_t
266023a9c295SGordon Ross smb_spool_lookup_doc_byfid(smb_server_t *sv, uint16_t fid,
266123a9c295SGordon Ross     smb_kspooldoc_t *spdoc)
2662cb174861Sjoyce mcintosh {
2663cb174861Sjoyce mcintosh 	smb_kspooldoc_t *sp;
2664cb174861Sjoyce mcintosh 	smb_llist_t	*splist;
2665cb174861Sjoyce mcintosh 
2666cb174861Sjoyce mcintosh 	splist = &sv->sp_info.sp_list;
2667cb174861Sjoyce mcintosh 	smb_llist_enter(splist, RW_WRITER);
2668cb174861Sjoyce mcintosh 	sp = smb_llist_head(splist);
2669cb174861Sjoyce mcintosh 	while (sp != NULL) {
2670cb174861Sjoyce mcintosh 		/*
2671cb174861Sjoyce mcintosh 		 * check for a matching fid
2672cb174861Sjoyce mcintosh 		 */
2673cb174861Sjoyce mcintosh 		if (sp->sd_fid == fid) {
2674cb174861Sjoyce mcintosh 			*spdoc = *sp;
2675cb174861Sjoyce mcintosh 			smb_llist_remove(splist, sp);
2676cb174861Sjoyce mcintosh 			smb_llist_exit(splist);
2677cb174861Sjoyce mcintosh 			kmem_free(sp, sizeof (smb_kspooldoc_t));
2678cb174861Sjoyce mcintosh 			return (B_TRUE);
2679cb174861Sjoyce mcintosh 		}
2680cb174861Sjoyce mcintosh 		sp = smb_llist_next(splist, sp);
2681cb174861Sjoyce mcintosh 	}
2682cb174861Sjoyce mcintosh 	cmn_err(CE_WARN, "smb_spool_lookup_user_byfid: no fid:%d", fid);
2683cb174861Sjoyce mcintosh 	smb_llist_exit(splist);
2684cb174861Sjoyce mcintosh 	return (B_FALSE);
2685cb174861Sjoyce mcintosh }
2686cb174861Sjoyce mcintosh 
2687cb174861Sjoyce mcintosh /*
2688cb174861Sjoyce mcintosh  * Adds the spool fid to a linked list to be used
2689cb174861Sjoyce mcintosh  * as a search key in the spooldoc queue
2690cb174861Sjoyce mcintosh  *
2691cb174861Sjoyce mcintosh  * Return values
2692cb174861Sjoyce mcintosh  *      rc non-zero error
2693cb174861Sjoyce mcintosh  *	rc zero success
2694cb174861Sjoyce mcintosh  *
2695cb174861Sjoyce mcintosh  */
2696cb174861Sjoyce mcintosh 
269786d7016bSGordon Ross void
269886d7016bSGordon Ross smb_spool_add_fid(smb_server_t *sv, uint16_t fid)
2699cb174861Sjoyce mcintosh {
2700cb174861Sjoyce mcintosh 	smb_llist_t	*fidlist;
2701cb174861Sjoyce mcintosh 	smb_spoolfid_t  *sf;
2702cb174861Sjoyce mcintosh 
270386d7016bSGordon Ross 	if (sv->sv_cfg.skc_print_enable == 0)
270486d7016bSGordon Ross 		return;
2705cb174861Sjoyce mcintosh 
2706cb174861Sjoyce mcintosh 	sf = kmem_zalloc(sizeof (smb_spoolfid_t), KM_SLEEP);
2707cb174861Sjoyce mcintosh 	fidlist = &sv->sp_info.sp_fidlist;
2708cb174861Sjoyce mcintosh 	smb_llist_enter(fidlist, RW_WRITER);
2709cb174861Sjoyce mcintosh 	sf->sf_fid = fid;
2710cb174861Sjoyce mcintosh 	smb_llist_insert_tail(fidlist, sf);
2711cb174861Sjoyce mcintosh 	smb_llist_exit(fidlist);
271286d7016bSGordon Ross 	cv_broadcast(&sv->sp_info.sp_cv);
2713cb174861Sjoyce mcintosh }
2714cb174861Sjoyce mcintosh 
2715cb174861Sjoyce mcintosh /*
2716cb174861Sjoyce mcintosh  * Called by the ioctl to get and remove the head of the fid list
2717cb174861Sjoyce mcintosh  *
2718cb174861Sjoyce mcintosh  * Return values
2719cb174861Sjoyce mcintosh  * int fd
2720cb174861Sjoyce mcintosh  * greater than 0 success
2721cb174861Sjoyce mcintosh  * 0 - error
2722cb174861Sjoyce mcintosh  *
2723cb174861Sjoyce mcintosh  */
2724cb174861Sjoyce mcintosh 
272523a9c295SGordon Ross static uint16_t
272623a9c295SGordon Ross smb_spool_get_fid(smb_server_t *sv)
2727cb174861Sjoyce mcintosh {
2728cb174861Sjoyce mcintosh 	smb_spoolfid_t	*spfid;
2729cb174861Sjoyce mcintosh 	smb_llist_t	*splist;
2730cb174861Sjoyce mcintosh 	uint16_t	fid;
2731cb174861Sjoyce mcintosh 
2732cb174861Sjoyce mcintosh 	splist = &sv->sp_info.sp_fidlist;
2733cb174861Sjoyce mcintosh 	smb_llist_enter(splist, RW_WRITER);
2734cb174861Sjoyce mcintosh 	spfid = smb_llist_head(splist);
2735cb174861Sjoyce mcintosh 	if (spfid != NULL) {
2736cb174861Sjoyce mcintosh 		fid = spfid->sf_fid;
2737cb174861Sjoyce mcintosh 		smb_llist_remove(&sv->sp_info.sp_fidlist, spfid);
2738cb174861Sjoyce mcintosh 		kmem_free(spfid, sizeof (smb_spoolfid_t));
2739cb174861Sjoyce mcintosh 	} else {
2740cb174861Sjoyce mcintosh 		fid = 0;
2741cb174861Sjoyce mcintosh 	}
2742cb174861Sjoyce mcintosh 	smb_llist_exit(splist);
2743cb174861Sjoyce mcintosh 	return (fid);
2744cb174861Sjoyce mcintosh }
2745cb174861Sjoyce mcintosh 
2746cb174861Sjoyce mcintosh /*
2747cb174861Sjoyce mcintosh  * Adds the spooldoc to the tail of the spooldoc list
2748cb174861Sjoyce mcintosh  *
2749cb174861Sjoyce mcintosh  * Return values
2750cb174861Sjoyce mcintosh  *      rc non-zero error
2751cb174861Sjoyce mcintosh  *	rc zero success
2752cb174861Sjoyce mcintosh  */
2753cb174861Sjoyce mcintosh int
27548622ec45SGordon Ross smb_spool_add_doc(smb_tree_t *tree, smb_kspooldoc_t *sp)
2755cb174861Sjoyce mcintosh {
2756cb174861Sjoyce mcintosh 	smb_llist_t	*splist;
27578622ec45SGordon Ross 	smb_server_t	*sv = tree->t_server;
2758cb174861Sjoyce mcintosh 	int rc = 0;
2759cb174861Sjoyce mcintosh 
2760cb174861Sjoyce mcintosh 	splist = &sv->sp_info.sp_list;
2761cb174861Sjoyce mcintosh 	smb_llist_enter(splist, RW_WRITER);
276223a9c295SGordon Ross 	sp->sd_spool_num = atomic_inc_32_nv(&sv->sp_info.sp_cnt);
2763cb174861Sjoyce mcintosh 	smb_llist_insert_tail(splist, sp);
2764cb174861Sjoyce mcintosh 	smb_llist_exit(splist);
27658622ec45SGordon Ross 
2766cb174861Sjoyce mcintosh 	return (rc);
2767cb174861Sjoyce mcintosh }
27684163af6aSjose borrego 
27694163af6aSjose borrego /*
27704163af6aSjose borrego  * smb_server_create_session
27714163af6aSjose borrego  */
27724163af6aSjose borrego static void
27734163af6aSjose borrego smb_server_create_session(smb_listener_daemon_t *ld, ksocket_t s_so)
27744163af6aSjose borrego {
2775811599a4SMatt Barden 	smb_server_t		*sv = ld->ld_sv;
277661b20185SGordon Ross 	smb_session_t		*session;
277761b20185SGordon Ross 	smb_llist_t		*sl;
277861b20185SGordon Ross 	taskqid_t		tqid;
277961b20185SGordon Ross 	clock_t			now;
27804163af6aSjose borrego 
2781811599a4SMatt Barden 	session = smb_session_create(s_so, ld->ld_port, sv,
27824163af6aSjose borrego 	    ld->ld_family);
27834163af6aSjose borrego 
27848622ec45SGordon Ross 	if (session == NULL) {
278561b20185SGordon Ross 		/* This should be rare (create sleeps) */
27868622ec45SGordon Ross 		smb_soshutdown(s_so);
27878622ec45SGordon Ross 		smb_sodestroy(s_so);
27888622ec45SGordon Ross 		cmn_err(CE_WARN, "SMB Session: alloc failed");
27898622ec45SGordon Ross 		return;
27908622ec45SGordon Ross 	}
27918622ec45SGordon Ross 
2792811599a4SMatt Barden 	sl = &sv->sv_session_list;
2793811599a4SMatt Barden 	smb_llist_enter(sl, RW_WRITER);
279461b20185SGordon Ross 	if (smb_llist_get_count(sl) >= sv->sv_cfg.skc_maxconnections) {
279561b20185SGordon Ross 		/*
279661b20185SGordon Ross 		 * New session not in sv_session_list, so we can just
279761b20185SGordon Ross 		 * delete it directly.
279861b20185SGordon Ross 		 */
279961b20185SGordon Ross 		smb_llist_exit(sl);
280061b20185SGordon Ross 		DTRACE_PROBE1(maxconn, smb_session_t *, session);
280161b20185SGordon Ross 		smb_soshutdown(session->sock);
280261b20185SGordon Ross 		smb_session_delete(session);
280361b20185SGordon Ross 		goto logmaxconn;
280461b20185SGordon Ross 	}
2805811599a4SMatt Barden 	smb_llist_insert_tail(sl, session);
2806811599a4SMatt Barden 	smb_llist_exit(sl);
28074163af6aSjose borrego 
28088622ec45SGordon Ross 	/*
28098622ec45SGordon Ross 	 * These taskq entries must run independently of one another,
28108622ec45SGordon Ross 	 * so TQ_NOQUEUE.  TQ_SLEEP (==0) just for clarity.
28118622ec45SGordon Ross 	 */
2812811599a4SMatt Barden 	tqid = taskq_dispatch(sv->sv_receiver_pool,
2813811599a4SMatt Barden 	    smb_server_receiver, session, TQ_NOQUEUE | TQ_SLEEP);
28149788d6deSGordon Ross 	if (tqid != TASKQID_INVALID) {
28159788d6deSGordon Ross 		/* Success */
28169788d6deSGordon Ross 		return;
28179788d6deSGordon Ross 	}
28189788d6deSGordon Ross 
281961b20185SGordon Ross 	/*
28209788d6deSGordon Ross 	 * Have: tqid == TASKQID_INVALID
282161b20185SGordon Ross 	 * We never entered smb_server_receiver()
28229788d6deSGordon Ross 	 * so need to do its return cleanup
282361b20185SGordon Ross 	 */
282461b20185SGordon Ross 	DTRACE_PROBE1(maxconn, smb_session_t *, session);
28254163af6aSjose borrego 	smb_session_disconnect(session);
282661b20185SGordon Ross 	smb_session_logoff(session);
2827811599a4SMatt Barden 	smb_server_destroy_session(session);
282861b20185SGordon Ross 
282961b20185SGordon Ross logmaxconn:
283061b20185SGordon Ross 	/*
283161b20185SGordon Ross 	 * If we hit max_connections, log something so an admin
283261b20185SGordon Ross 	 * can find out why new connections are failing, but
283361b20185SGordon Ross 	 * log this no more than once a minute.
283461b20185SGordon Ross 	 */
283561b20185SGordon Ross 	now = ddi_get_lbolt();
283661b20185SGordon Ross 	if (now > ld->ld_quiet) {
283761b20185SGordon Ross 		ld->ld_quiet = now + SEC_TO_TICK(60);
283861b20185SGordon Ross 		cmn_err(CE_WARN, "SMB can't create session: "
283961b20185SGordon Ross 		    "Would exceed max_connections.");
284061b20185SGordon Ross 	}
28414163af6aSjose borrego }
28424163af6aSjose borrego 
28434163af6aSjose borrego static void
2844811599a4SMatt Barden smb_server_destroy_session(smb_session_t *session)
28454163af6aSjose borrego {
2846811599a4SMatt Barden 	smb_server_t *sv;
2847811599a4SMatt Barden 	smb_llist_t *ll;
2848811599a4SMatt Barden 	uint32_t count;
2849811599a4SMatt Barden 
2850811599a4SMatt Barden 	ASSERT(session->s_server != NULL);
2851811599a4SMatt Barden 	sv = session->s_server;
2852811599a4SMatt Barden 	ll = &sv->sv_session_list;
2853811599a4SMatt Barden 
2854811599a4SMatt Barden 	smb_llist_flush(&session->s_tree_list);
2855811599a4SMatt Barden 	smb_llist_flush(&session->s_user_list);
2856811599a4SMatt Barden 
2857811599a4SMatt Barden 	smb_llist_enter(ll, RW_WRITER);
2858811599a4SMatt Barden 	smb_llist_remove(ll, session);
2859811599a4SMatt Barden 	count = ll->ll_count;
2860811599a4SMatt Barden 	smb_llist_exit(ll);
2861811599a4SMatt Barden 
28627f5d80fdSGordon Ross 	/*
28637f5d80fdSGordon Ross 	 * Normally, the session should have state SHUTDOWN here.
28647f5d80fdSGordon Ross 	 * If the session has any ofiles remaining, eg. due to
28657f5d80fdSGordon Ross 	 * forgotten ofile references or something, the state
28667f5d80fdSGordon Ross 	 * will be _DISCONNECTED or _TERMINATED.  Keep such
28677f5d80fdSGordon Ross 	 * sessions in the list of zombies (for debugging).
28687f5d80fdSGordon Ross 	 */
28697f5d80fdSGordon Ross 	if (session->s_state == SMB_SESSION_STATE_SHUTDOWN) {
28704163af6aSjose borrego 		smb_session_delete(session);
28717f5d80fdSGordon Ross 	} else {
287286184067SGordon Ross 		cmn_err(CE_NOTE, "!Leaked session: 0x%p", (void *)session);
287386184067SGordon Ross 		DTRACE_PROBE1(new__zombie, smb_session_t *, session);
28747f5d80fdSGordon Ross 		smb_llist_enter(&smb_server_session_zombies, RW_WRITER);
28757f5d80fdSGordon Ross 		smb_llist_insert_head(&smb_server_session_zombies, session);
28767f5d80fdSGordon Ross 		smb_llist_exit(&smb_server_session_zombies);
28777f5d80fdSGordon Ross 	}
28787f5d80fdSGordon Ross 
2879811599a4SMatt Barden 	if (count == 0) {
2880811599a4SMatt Barden 		/* See smb_server_shutdown */
2881811599a4SMatt Barden 		cv_signal(&sv->sv_cv);
2882811599a4SMatt Barden 	}
28834163af6aSjose borrego }
2884