xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_server.c (revision 7f5d80fd842f21a48514cca6718c3bbdaf592316)
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.
2561b20185SGordon Ross  * Copyright 2022 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>
209bbf6f00cSJordan Brown #include <netinet/in.h>
210bbf6f00cSJordan Brown #include <netinet/in_systm.h>
211bbf6f00cSJordan Brown #include <netinet/ip.h>
212bbf6f00cSJordan Brown #include <netinet/ip_icmp.h>
213bbf6f00cSJordan Brown #include <netinet/ip_var.h>
214bbf6f00cSJordan Brown #include <netinet/tcp.h>
215a90cf9f2SGordon Ross #include <smbsrv/smb2_kproto.h>
216bbf6f00cSJordan Brown #include <smbsrv/string.h>
217faa1795aSjb150015 #include <smbsrv/netbios.h>
218faa1795aSjb150015 #include <smbsrv/smb_fsops.h>
2193db3f65cSamw #include <smbsrv/smb_share.h>
2209fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States #include <smbsrv/smb_door.h>
2216537f381Sas200622 #include <smbsrv/smb_kstat.h>
222faa1795aSjb150015 
223148c5f43SAlan Wright static void smb_server_kstat_init(smb_server_t *);
224faa1795aSjb150015 static void smb_server_kstat_fini(smb_server_t *);
225faa1795aSjb150015 static void smb_server_timers(smb_thread_t *, void *);
22629bd2886SAlan Wright static void smb_server_store_cfg(smb_server_t *, smb_ioc_cfg_t *);
2279fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void smb_server_shutdown(smb_server_t *);
228faa1795aSjb150015 static int smb_server_fsop_start(smb_server_t *);
229faa1795aSjb150015 static void smb_server_fsop_stop(smb_server_t *);
2309fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void smb_event_cancel(smb_server_t *, uint32_t);
2319fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static uint32_t smb_event_alloc_txid(void);
232faa1795aSjb150015 
2338d94f651SGordon Ross static void smb_server_disconnect_share(smb_server_t *, const char *);
2348d94f651SGordon Ross static void smb_server_enum_users(smb_server_t *, smb_svcenum_t *);
2358d94f651SGordon Ross static void smb_server_enum_trees(smb_server_t *, smb_svcenum_t *);
2368d94f651SGordon Ross static int smb_server_session_disconnect(smb_server_t *, const char *,
2371fcced4cSJordan Brown     const char *);
2388d94f651SGordon Ross static int smb_server_fclose(smb_server_t *, uint32_t);
239148c5f43SAlan Wright static int smb_server_kstat_update(kstat_t *, int);
240cb174861Sjoyce mcintosh static int smb_server_legacy_kstat_update(kstat_t *, int);
2414163af6aSjose borrego static void smb_server_listener_init(smb_server_t *, smb_listener_daemon_t *,
2424163af6aSjose borrego     char *, in_port_t, int);
2434163af6aSjose borrego static void smb_server_listener_destroy(smb_listener_daemon_t *);
2444163af6aSjose borrego static int smb_server_listener_start(smb_listener_daemon_t *);
2454163af6aSjose borrego static void smb_server_listener_stop(smb_listener_daemon_t *);
2464163af6aSjose borrego static void smb_server_listener(smb_thread_t *, void *);
2474163af6aSjose borrego static void smb_server_receiver(void *);
2484163af6aSjose borrego static void smb_server_create_session(smb_listener_daemon_t *, ksocket_t);
249811599a4SMatt Barden static void smb_server_destroy_session(smb_session_t *);
25023a9c295SGordon Ross static uint16_t smb_spool_get_fid(smb_server_t *);
25123a9c295SGordon Ross static boolean_t smb_spool_lookup_doc_byfid(smb_server_t *, uint16_t,
25223a9c295SGordon Ross     smb_kspooldoc_t *);
2531fcced4cSJordan Brown 
254811599a4SMatt Barden /*
255811599a4SMatt Barden  * How many "buckets" should our hash tables use?  On a "real" server,
256811599a4SMatt Barden  * make them much larger than the number of CPUs we're likely to have.
257811599a4SMatt Barden  * On "fksmbd" make it smaller so dtrace logs are shorter.
258811599a4SMatt Barden  * These must be powers of two.
259811599a4SMatt Barden  */
260811599a4SMatt Barden #ifdef	_KERNEL
261811599a4SMatt Barden #define	DEFAULT_HASH_NBUCKETS	256	/* real server */
262811599a4SMatt Barden #else
263811599a4SMatt Barden #define	DEFAULT_HASH_NBUCKETS	16	/* for "fksmbd" */
264811599a4SMatt Barden #endif
265811599a4SMatt Barden uint32_t SMB_OFILE_HASH_NBUCKETS = DEFAULT_HASH_NBUCKETS;
266811599a4SMatt Barden uint32_t SMB_LEASE_HASH_NBUCKETS = DEFAULT_HASH_NBUCKETS;
267811599a4SMatt Barden 
2689fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States int smb_event_debug = 0;
2699fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
270faa1795aSjb150015 static smb_llist_t	smb_servers;
271faa1795aSjb150015 
272*7f5d80fdSGordon Ross /* for smb_server_destroy_session() */
273*7f5d80fdSGordon Ross static smb_llist_t smb_server_session_zombies;
274*7f5d80fdSGordon Ross 
2758622ec45SGordon Ross kmem_cache_t		*smb_cache_request;
2768622ec45SGordon Ross kmem_cache_t		*smb_cache_session;
2778622ec45SGordon Ross kmem_cache_t		*smb_cache_user;
2788622ec45SGordon Ross kmem_cache_t		*smb_cache_tree;
2798622ec45SGordon Ross kmem_cache_t		*smb_cache_ofile;
2808622ec45SGordon Ross kmem_cache_t		*smb_cache_odir;
2818622ec45SGordon Ross kmem_cache_t		*smb_cache_opipe;
2828622ec45SGordon Ross kmem_cache_t		*smb_cache_event;
2830897f7fbSGordon Ross kmem_cache_t		*smb_cache_lock;
2848622ec45SGordon Ross 
285faa1795aSjb150015 /*
286faa1795aSjb150015  * *****************************************************************************
287faa1795aSjb150015  * **************** Functions called from the device interface *****************
288faa1795aSjb150015  * *****************************************************************************
289faa1795aSjb150015  *
2901fcced4cSJordan Brown  * These functions typically have to determine the relevant smb server
2911fcced4cSJordan Brown  * to which the call applies.
292faa1795aSjb150015  */
293faa1795aSjb150015 
294faa1795aSjb150015 /*
295a90cf9f2SGordon Ross  * How many zones have an SMB server active?
296a90cf9f2SGordon Ross  */
297a90cf9f2SGordon Ross int
298a90cf9f2SGordon Ross smb_server_get_count(void)
299a90cf9f2SGordon Ross {
300a90cf9f2SGordon Ross 	return (smb_llist_get_count(&smb_servers));
301a90cf9f2SGordon Ross }
302a90cf9f2SGordon Ross 
303a90cf9f2SGordon Ross /*
3048622ec45SGordon Ross  * smb_server_g_init
305faa1795aSjb150015  *
306c8ec8eeaSjose borrego  * This function must be called from smb_drv_attach().
307faa1795aSjb150015  */
308faa1795aSjb150015 int
3098622ec45SGordon Ross smb_server_g_init(void)
310faa1795aSjb150015 {
3118622ec45SGordon Ross 	int rc;
312faa1795aSjb150015 
3138622ec45SGordon Ross 	if ((rc = smb_vop_init()) != 0)
3148622ec45SGordon Ross 		goto errout;
3158622ec45SGordon Ross 	if ((rc = smb_fem_init()) != 0)
3168622ec45SGordon Ross 		goto errout;
3178622ec45SGordon Ross 
3188622ec45SGordon Ross 	smb_kshare_g_init();
3198622ec45SGordon Ross 	smb_codepage_init();
3208622ec45SGordon Ross 	smb_mbc_init();		/* smb_mbc_cache */
3218622ec45SGordon Ross 	smb_node_init();	/* smb_node_cache, lists */
32294047d49SGordon Ross 	smb2_lease_init();
3238622ec45SGordon Ross 
3248622ec45SGordon Ross 	smb_cache_request = kmem_cache_create("smb_request_cache",
3258622ec45SGordon Ross 	    sizeof (smb_request_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
3268622ec45SGordon Ross 	smb_cache_session = kmem_cache_create("smb_session_cache",
3278622ec45SGordon Ross 	    sizeof (smb_session_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
3288622ec45SGordon Ross 	smb_cache_user = kmem_cache_create("smb_user_cache",
3298622ec45SGordon Ross 	    sizeof (smb_user_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
3308622ec45SGordon Ross 	smb_cache_tree = kmem_cache_create("smb_tree_cache",
3318622ec45SGordon Ross 	    sizeof (smb_tree_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
3328622ec45SGordon Ross 	smb_cache_ofile = kmem_cache_create("smb_ofile_cache",
3338622ec45SGordon Ross 	    sizeof (smb_ofile_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
3348622ec45SGordon Ross 	smb_cache_odir = kmem_cache_create("smb_odir_cache",
3358622ec45SGordon Ross 	    sizeof (smb_odir_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
3368622ec45SGordon Ross 	smb_cache_opipe = kmem_cache_create("smb_opipe_cache",
3378622ec45SGordon Ross 	    sizeof (smb_opipe_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
3388622ec45SGordon Ross 	smb_cache_event = kmem_cache_create("smb_event_cache",
3398622ec45SGordon Ross 	    sizeof (smb_event_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
3400897f7fbSGordon Ross 	smb_cache_lock = kmem_cache_create("smb_lock_cache",
3410897f7fbSGordon Ross 	    sizeof (smb_lock_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
3428622ec45SGordon Ross 
3439fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_init();
344faa1795aSjb150015 	smb_llist_constructor(&smb_servers, sizeof (smb_server_t),
345faa1795aSjb150015 	    offsetof(smb_server_t, sv_lnd));
3469fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
347*7f5d80fdSGordon Ross 	smb_llist_constructor(&smb_server_session_zombies,
348*7f5d80fdSGordon Ross 	    sizeof (smb_session_t), offsetof(smb_session_t, s_lnd));
349*7f5d80fdSGordon Ross 
3508622ec45SGordon Ross 	return (0);
3518622ec45SGordon Ross 
3528622ec45SGordon Ross errout:
353faa1795aSjb150015 	smb_fem_fini();
354faa1795aSjb150015 	smb_vop_fini();
355faa1795aSjb150015 	return (rc);
356faa1795aSjb150015 }
357faa1795aSjb150015 
358faa1795aSjb150015 /*
3598622ec45SGordon Ross  * smb_server_g_fini
360faa1795aSjb150015  *
361faa1795aSjb150015  * This function must called from smb_drv_detach(). It will fail if servers
362faa1795aSjb150015  * still exist.
363faa1795aSjb150015  */
364a90cf9f2SGordon Ross void
3658622ec45SGordon Ross smb_server_g_fini(void)
366faa1795aSjb150015 {
367faa1795aSjb150015 
368a90cf9f2SGordon Ross 	ASSERT(smb_llist_get_count(&smb_servers) == 0);
369a90cf9f2SGordon Ross 
3709fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_fini();
3718622ec45SGordon Ross 
3728622ec45SGordon Ross 	kmem_cache_destroy(smb_cache_request);
3738622ec45SGordon Ross 	kmem_cache_destroy(smb_cache_session);
3748622ec45SGordon Ross 	kmem_cache_destroy(smb_cache_user);
3758622ec45SGordon Ross 	kmem_cache_destroy(smb_cache_tree);
3768622ec45SGordon Ross 	kmem_cache_destroy(smb_cache_ofile);
3778622ec45SGordon Ross 	kmem_cache_destroy(smb_cache_odir);
3788622ec45SGordon Ross 	kmem_cache_destroy(smb_cache_opipe);
3798622ec45SGordon Ross 	kmem_cache_destroy(smb_cache_event);
3800897f7fbSGordon Ross 	kmem_cache_destroy(smb_cache_lock);
3818622ec45SGordon Ross 
38294047d49SGordon Ross 	smb2_lease_fini();
383faa1795aSjb150015 	smb_node_fini();
3842c2961f8Sjose borrego 	smb_mbc_fini();
385adc68ba9SPavel Zakharov 	smb_codepage_fini();
3868622ec45SGordon Ross 	smb_kshare_g_fini();
3878622ec45SGordon Ross 
3888622ec45SGordon Ross 	smb_fem_fini();
3898622ec45SGordon Ross 	smb_vop_fini();
3908622ec45SGordon Ross 
391faa1795aSjb150015 	smb_llist_destructor(&smb_servers);
392faa1795aSjb150015 }
393faa1795aSjb150015 
394faa1795aSjb150015 /*
395faa1795aSjb150015  * smb_server_create
396faa1795aSjb150015  *
397faa1795aSjb150015  * This function will fail if there's already a server associated with the
398faa1795aSjb150015  * caller's zone.
399faa1795aSjb150015  */
400faa1795aSjb150015 int
401faa1795aSjb150015 smb_server_create(void)
402faa1795aSjb150015 {
403faa1795aSjb150015 	zoneid_t	zid;
404faa1795aSjb150015 	smb_server_t	*sv;
405faa1795aSjb150015 
406faa1795aSjb150015 	zid = getzoneid();
407faa1795aSjb150015 
408faa1795aSjb150015 	smb_llist_enter(&smb_servers, RW_WRITER);
409faa1795aSjb150015 	sv = smb_llist_head(&smb_servers);
410faa1795aSjb150015 	while (sv) {
4119fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_SERVER_VALID(sv);
412faa1795aSjb150015 		if (sv->sv_zid == zid) {
413faa1795aSjb150015 			smb_llist_exit(&smb_servers);
41494fff790SAlan Wright 			return (EPERM);
415faa1795aSjb150015 		}
416faa1795aSjb150015 		sv = smb_llist_next(&smb_servers, sv);
417faa1795aSjb150015 	}
418faa1795aSjb150015 
4198622ec45SGordon Ross 	sv = kmem_zalloc(sizeof (smb_server_t), KM_SLEEP);
4208622ec45SGordon Ross 
4218622ec45SGordon Ross 	sv->sv_magic = SMB_SERVER_MAGIC;
4228622ec45SGordon Ross 	sv->sv_state = SMB_SERVER_STATE_CREATED;
4238622ec45SGordon Ross 	sv->sv_zid = zid;
424b819cea2SGordon Ross 	sv->sv_pid = ddi_get_pid();
4258622ec45SGordon Ross 
4268622ec45SGordon Ross 	mutex_init(&sv->sv_mutex, NULL, MUTEX_DEFAULT, NULL);
4278622ec45SGordon Ross 	cv_init(&sv->sv_cv, NULL, CV_DEFAULT, NULL);
4288622ec45SGordon Ross 	cv_init(&sv->sp_info.sp_cv, NULL, CV_DEFAULT, NULL);
429faa1795aSjb150015 
430811599a4SMatt Barden 	sv->sv_persistid_ht = smb_hash_create(sizeof (smb_ofile_t),
431811599a4SMatt Barden 	    offsetof(smb_ofile_t, f_dh_lnd), SMB_OFILE_HASH_NBUCKETS);
432811599a4SMatt Barden 
43394047d49SGordon Ross 	sv->sv_lease_ht = smb_hash_create(sizeof (smb_lease_t),
43494047d49SGordon Ross 	    offsetof(smb_lease_t, ls_lnd), SMB_LEASE_HASH_NBUCKETS);
43594047d49SGordon Ross 
436811599a4SMatt Barden 	smb_llist_constructor(&sv->sv_session_list, sizeof (smb_session_t),
437811599a4SMatt Barden 	    offsetof(smb_session_t, s_lnd));
438811599a4SMatt Barden 
4399fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_constructor(&sv->sv_event_list, sizeof (smb_event_t),
4409fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	    offsetof(smb_event_t, se_lnd));
4419fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
442cb174861Sjoyce mcintosh 	smb_llist_constructor(&sv->sp_info.sp_list, sizeof (smb_kspooldoc_t),
443cb174861Sjoyce mcintosh 	    offsetof(smb_kspooldoc_t, sd_lnd));
444cb174861Sjoyce mcintosh 
445cb174861Sjoyce mcintosh 	smb_llist_constructor(&sv->sp_info.sp_fidlist,
446cb174861Sjoyce mcintosh 	    sizeof (smb_spoolfid_t), offsetof(smb_spoolfid_t, sf_lnd));
447cb174861Sjoyce mcintosh 
448a90cf9f2SGordon Ross 	sv->sv_disp_stats1 = kmem_zalloc(SMB_COM_NUM *
449a90cf9f2SGordon Ross 	    sizeof (smb_disp_stats_t), KM_SLEEP);
450a90cf9f2SGordon Ross 
451a90cf9f2SGordon Ross 	sv->sv_disp_stats2 = kmem_zalloc(SMB2__NCMDS *
4528622ec45SGordon Ross 	    sizeof (smb_disp_stats_t), KM_SLEEP);
453faa1795aSjb150015 
45408344b29SGordon Ross 	smb_thread_init(&sv->si_thread_timers, "smb_timers",
45508344b29SGordon Ross 	    smb_server_timers, sv, smbsrv_timer_pri);
456faa1795aSjb150015 
457148c5f43SAlan Wright 	smb_srqueue_init(&sv->sv_srqueue);
458faa1795aSjb150015 
4598622ec45SGordon Ross 	smb_kdoor_init(sv);
4608622ec45SGordon Ross 	smb_kshare_init(sv);
461148c5f43SAlan Wright 	smb_server_kstat_init(sv);
462faa1795aSjb150015 
463856399cfSGordon Ross 	smb_threshold_init(&sv->sv_ssetup_ct, SMB_SSETUP_CMD,
464856399cfSGordon Ross 	    smb_ssetup_threshold, smb_ssetup_timeout);
465856399cfSGordon Ross 	smb_threshold_init(&sv->sv_tcon_ct, SMB_TCON_CMD,
466856399cfSGordon Ross 	    smb_tcon_threshold, smb_tcon_timeout);
467856399cfSGordon Ross 	smb_threshold_init(&sv->sv_opipe_ct, SMB_OPIPE_CMD,
468856399cfSGordon Ross 	    smb_opipe_threshold, smb_opipe_timeout);
469856399cfSGordon Ross 
470faa1795aSjb150015 	smb_llist_insert_tail(&smb_servers, sv);
471faa1795aSjb150015 	smb_llist_exit(&smb_servers);
472cb174861Sjoyce mcintosh 
473faa1795aSjb150015 	return (0);
474faa1795aSjb150015 }
475faa1795aSjb150015 
476faa1795aSjb150015 /*
477faa1795aSjb150015  * smb_server_delete
478faa1795aSjb150015  *
479faa1795aSjb150015  * This function will delete the server passed in. It will make sure that all
480faa1795aSjb150015  * activity associated that server has ceased before destroying it.
481faa1795aSjb150015  */
482faa1795aSjb150015 int
4838d94f651SGordon Ross smb_server_delete(smb_server_t	*sv)
484faa1795aSjb150015 {
485faa1795aSjb150015 
486faa1795aSjb150015 	mutex_enter(&sv->sv_mutex);
487faa1795aSjb150015 	switch (sv->sv_state) {
488faa1795aSjb150015 	case SMB_SERVER_STATE_RUNNING:
4899fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		sv->sv_state = SMB_SERVER_STATE_STOPPING;
490faa1795aSjb150015 		mutex_exit(&sv->sv_mutex);
4914163af6aSjose borrego 		smb_server_shutdown(sv);
492faa1795aSjb150015 		mutex_enter(&sv->sv_mutex);
4934163af6aSjose borrego 		cv_broadcast(&sv->sp_info.sp_cv);
4944163af6aSjose borrego 		sv->sv_state = SMB_SERVER_STATE_DELETING;
4954163af6aSjose borrego 		break;
4964163af6aSjose borrego 	case SMB_SERVER_STATE_STOPPING:
4974163af6aSjose borrego 		sv->sv_state = SMB_SERVER_STATE_DELETING;
498faa1795aSjb150015 		break;
499faa1795aSjb150015 	case SMB_SERVER_STATE_CONFIGURED:
500faa1795aSjb150015 	case SMB_SERVER_STATE_CREATED:
501faa1795aSjb150015 		sv->sv_state = SMB_SERVER_STATE_DELETING;
502faa1795aSjb150015 		break;
503faa1795aSjb150015 	default:
5049fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_SERVER_STATE_VALID(sv->sv_state);
505faa1795aSjb150015 		mutex_exit(&sv->sv_mutex);
506faa1795aSjb150015 		smb_server_release(sv);
507faa1795aSjb150015 		return (ENOTTY);
508faa1795aSjb150015 	}
509faa1795aSjb150015 
510faa1795aSjb150015 	ASSERT(sv->sv_state == SMB_SERVER_STATE_DELETING);
511faa1795aSjb150015 
512faa1795aSjb150015 	sv->sv_refcnt--;
513faa1795aSjb150015 	while (sv->sv_refcnt)
514faa1795aSjb150015 		cv_wait(&sv->sv_cv, &sv->sv_mutex);
515faa1795aSjb150015 
516faa1795aSjb150015 	mutex_exit(&sv->sv_mutex);
517faa1795aSjb150015 
518faa1795aSjb150015 	smb_llist_enter(&smb_servers, RW_WRITER);
519faa1795aSjb150015 	smb_llist_remove(&smb_servers, sv);
520faa1795aSjb150015 	smb_llist_exit(&smb_servers);
521faa1795aSjb150015 
522856399cfSGordon Ross 	smb_threshold_fini(&sv->sv_ssetup_ct);
523856399cfSGordon Ross 	smb_threshold_fini(&sv->sv_tcon_ct);
524856399cfSGordon Ross 	smb_threshold_fini(&sv->sv_opipe_ct);
525856399cfSGordon Ross 
5264163af6aSjose borrego 	smb_server_listener_destroy(&sv->sv_nbt_daemon);
5274163af6aSjose borrego 	smb_server_listener_destroy(&sv->sv_tcp_daemon);
528faa1795aSjb150015 	rw_destroy(&sv->sv_cfg_lock);
529faa1795aSjb150015 	smb_server_kstat_fini(sv);
5308622ec45SGordon Ross 	smb_kshare_fini(sv);
5318622ec45SGordon Ross 	smb_kdoor_fini(sv);
5329fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_destructor(&sv->sv_event_list);
533811599a4SMatt Barden 	smb_llist_destructor(&sv->sv_session_list);
5342c1b14e5Sjose borrego 
535a90cf9f2SGordon Ross 	kmem_free(sv->sv_disp_stats1,
5368622ec45SGordon Ross 	    SMB_COM_NUM * sizeof (smb_disp_stats_t));
537faa1795aSjb150015 
538a90cf9f2SGordon Ross 	kmem_free(sv->sv_disp_stats2,
539a90cf9f2SGordon Ross 	    SMB2__NCMDS * sizeof (smb_disp_stats_t));
540a90cf9f2SGordon Ross 
541148c5f43SAlan Wright 	smb_srqueue_destroy(&sv->sv_srqueue);
542faa1795aSjb150015 	smb_thread_destroy(&sv->si_thread_timers);
5438622ec45SGordon Ross 
544faa1795aSjb150015 	mutex_destroy(&sv->sv_mutex);
54594047d49SGordon Ross 	smb_hash_destroy(sv->sv_lease_ht);
546811599a4SMatt Barden 	smb_hash_destroy(sv->sv_persistid_ht);
547faa1795aSjb150015 	cv_destroy(&sv->sv_cv);
548faa1795aSjb150015 	sv->sv_magic = 0;
549faa1795aSjb150015 	kmem_free(sv, sizeof (smb_server_t));
550faa1795aSjb150015 
551faa1795aSjb150015 	return (0);
552faa1795aSjb150015 }
553faa1795aSjb150015 
554faa1795aSjb150015 /*
555faa1795aSjb150015  * smb_server_configure
556faa1795aSjb150015  */
557faa1795aSjb150015 int
55829bd2886SAlan Wright smb_server_configure(smb_ioc_cfg_t *ioc)
559faa1795aSjb150015 {
560faa1795aSjb150015 	int		rc = 0;
561faa1795aSjb150015 	smb_server_t	*sv;
562faa1795aSjb150015 
5631d443a93SDan McDonald 	/*
5641d443a93SDan McDonald 	 * Reality check negotiation token length vs. #define'd maximum.
5651d443a93SDan McDonald 	 */
5661d443a93SDan McDonald 	if (ioc->negtok_len > SMB_PI_MAX_NEGTOK)
5671d443a93SDan McDonald 		return (EINVAL);
5681d443a93SDan McDonald 
569faa1795aSjb150015 	rc = smb_server_lookup(&sv);
570faa1795aSjb150015 	if (rc)
571faa1795aSjb150015 		return (rc);
572faa1795aSjb150015 
573faa1795aSjb150015 	mutex_enter(&sv->sv_mutex);
574faa1795aSjb150015 	switch (sv->sv_state) {
575faa1795aSjb150015 	case SMB_SERVER_STATE_CREATED:
57629bd2886SAlan Wright 		smb_server_store_cfg(sv, ioc);
577faa1795aSjb150015 		sv->sv_state = SMB_SERVER_STATE_CONFIGURED;
578faa1795aSjb150015 		break;
579faa1795aSjb150015 
580faa1795aSjb150015 	case SMB_SERVER_STATE_CONFIGURED:
58129bd2886SAlan Wright 		smb_server_store_cfg(sv, ioc);
582faa1795aSjb150015 		break;
583faa1795aSjb150015 
584faa1795aSjb150015 	case SMB_SERVER_STATE_RUNNING:
5859fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	case SMB_SERVER_STATE_STOPPING:
586faa1795aSjb150015 		rw_enter(&sv->sv_cfg_lock, RW_WRITER);
58729bd2886SAlan Wright 		smb_server_store_cfg(sv, ioc);
588faa1795aSjb150015 		rw_exit(&sv->sv_cfg_lock);
589faa1795aSjb150015 		break;
590faa1795aSjb150015 
591faa1795aSjb150015 	default:
5929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_SERVER_STATE_VALID(sv->sv_state);
593faa1795aSjb150015 		rc = EFAULT;
594faa1795aSjb150015 		break;
595faa1795aSjb150015 	}
596faa1795aSjb150015 	mutex_exit(&sv->sv_mutex);
597faa1795aSjb150015 
598faa1795aSjb150015 	smb_server_release(sv);
599faa1795aSjb150015 
600faa1795aSjb150015 	return (rc);
601faa1795aSjb150015 }
602faa1795aSjb150015 
603faa1795aSjb150015 /*
604faa1795aSjb150015  * smb_server_start
605faa1795aSjb150015  */
606faa1795aSjb150015 int
60729bd2886SAlan Wright smb_server_start(smb_ioc_start_t *ioc)
608faa1795aSjb150015 {
609faa1795aSjb150015 	int		rc = 0;
6104163af6aSjose borrego 	int		family;
611faa1795aSjb150015 	smb_server_t	*sv;
6128d94f651SGordon Ross 	cred_t		*ucr;
613faa1795aSjb150015 
614faa1795aSjb150015 	rc = smb_server_lookup(&sv);
615faa1795aSjb150015 	if (rc)
616faa1795aSjb150015 		return (rc);
617faa1795aSjb150015 
618faa1795aSjb150015 	mutex_enter(&sv->sv_mutex);
619faa1795aSjb150015 	switch (sv->sv_state) {
620faa1795aSjb150015 	case SMB_SERVER_STATE_CONFIGURED:
621faa1795aSjb150015 
6228622ec45SGordon Ross 		if ((rc = smb_server_fsop_start(sv)) != 0)
6238622ec45SGordon Ross 			break;
6248622ec45SGordon Ross 
6258d94f651SGordon Ross 		/*
6268d94f651SGordon Ross 		 * Note: smb_kshare_start needs sv_session.
6278d94f651SGordon Ross 		 */
6288d94f651SGordon Ross 		sv->sv_session = smb_session_create(NULL, 0, sv, 0);
6298d94f651SGordon Ross 		if (sv->sv_session == NULL) {
6308d94f651SGordon Ross 			rc = ENOMEM;
6318d94f651SGordon Ross 			break;
6328d94f651SGordon Ross 		}
6338d94f651SGordon Ross 
6348d94f651SGordon Ross 		/*
6358d94f651SGordon Ross 		 * Create a logon on the server session,
6368d94f651SGordon Ross 		 * used when importing CA shares.
6378d94f651SGordon Ross 		 */
6388d94f651SGordon Ross 		sv->sv_rootuser = smb_user_new(sv->sv_session);
6398d94f651SGordon Ross 		ucr = smb_kcred_create();
6408d94f651SGordon Ross 		rc = smb_user_logon(sv->sv_rootuser, ucr, "", "root",
6418d94f651SGordon Ross 		    SMB_USER_FLAG_ADMIN, 0, 0);
6428d94f651SGordon Ross 		crfree(ucr);
6438d94f651SGordon Ross 		ucr = NULL;
6448d94f651SGordon Ross 		if (rc != 0) {
6458d94f651SGordon Ross 			cmn_err(CE_NOTE, "smb_server_start: "
6468d94f651SGordon Ross 			    "failed to create root user");
6478d94f651SGordon Ross 			break;
6488d94f651SGordon Ross 		}
6498d94f651SGordon Ross 
6508622ec45SGordon Ross 		if ((rc = smb_kshare_start(sv)) != 0)
6518622ec45SGordon Ross 			break;
6528622ec45SGordon Ross 
653b819cea2SGordon Ross 		/*
654b819cea2SGordon Ross 		 * NB: the proc passed here has to be a "system" one.
655b819cea2SGordon Ross 		 * Normally that's p0, or the NGZ eqivalent.
656b819cea2SGordon Ross 		 */
6578622ec45SGordon Ross 		sv->sv_worker_pool = taskq_create_proc("smb_workers",
65808344b29SGordon Ross 		    sv->sv_cfg.skc_maxworkers, smbsrv_worker_pri,
659faa1795aSjb150015 		    sv->sv_cfg.skc_maxworkers, INT_MAX,
6608622ec45SGordon Ross 		    curzone->zone_zsched, TASKQ_DYNAMIC);
661faa1795aSjb150015 
6628622ec45SGordon Ross 		sv->sv_receiver_pool = taskq_create_proc("smb_receivers",
66308344b29SGordon Ross 		    sv->sv_cfg.skc_maxconnections, smbsrv_receive_pri,
6644163af6aSjose borrego 		    sv->sv_cfg.skc_maxconnections, INT_MAX,
6658622ec45SGordon Ross 		    curzone->zone_zsched, TASKQ_DYNAMIC);
6664163af6aSjose borrego 
6678d94f651SGordon Ross 		if (sv->sv_worker_pool == NULL ||
6688d94f651SGordon Ross 		    sv->sv_receiver_pool == NULL) {
669faa1795aSjb150015 			rc = ENOMEM;
670faa1795aSjb150015 			break;
671faa1795aSjb150015 		}
672faa1795aSjb150015 
673b819cea2SGordon Ross #ifdef	_KERNEL
674faa1795aSjb150015 		ASSERT(sv->sv_lmshrd == NULL);
675148c5f43SAlan Wright 		sv->sv_lmshrd = smb_kshare_door_init(ioc->lmshrd);
676faa1795aSjb150015 		if (sv->sv_lmshrd == NULL)
677faa1795aSjb150015 			break;
67854026d5aSGordon Ross 		if ((rc = smb_kdoor_open(sv, ioc->udoor)) != 0) {
6799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			cmn_err(CE_WARN, "Cannot open smbd door");
680faa1795aSjb150015 			break;
6819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		}
682b819cea2SGordon Ross #else	/* _KERNEL */
683b819cea2SGordon Ross 		/* Fake kernel does not use the kshare_door */
684b819cea2SGordon Ross 		fksmb_kdoor_open(sv, ioc->udoor_func);
685b819cea2SGordon Ross #endif	/* _KERNEL */
686b819cea2SGordon Ross 
68754026d5aSGordon Ross 		if ((rc = smb_thread_start(&sv->si_thread_timers)) != 0)
6889fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			break;
6894163af6aSjose borrego 
6904163af6aSjose borrego 		family = AF_INET;
6914163af6aSjose borrego 		smb_server_listener_init(sv, &sv->sv_nbt_daemon,
6924163af6aSjose borrego 		    "smb_nbt_listener", IPPORT_NETBIOS_SSN, family);
6934163af6aSjose borrego 		if (sv->sv_cfg.skc_ipv6_enable)
6944163af6aSjose borrego 			family = AF_INET6;
6954163af6aSjose borrego 		smb_server_listener_init(sv, &sv->sv_tcp_daemon,
6964163af6aSjose borrego 		    "smb_tcp_listener", IPPORT_SMB, family);
6974163af6aSjose borrego 		rc = smb_server_listener_start(&sv->sv_tcp_daemon);
6984163af6aSjose borrego 		if (rc != 0)
6994163af6aSjose borrego 			break;
70083d2dfe6SGordon Ross 		if (sv->sv_cfg.skc_netbios_enable)
70183d2dfe6SGordon Ross 			(void) smb_server_listener_start(&sv->sv_nbt_daemon);
7024163af6aSjose borrego 
703faa1795aSjb150015 		sv->sv_state = SMB_SERVER_STATE_RUNNING;
704148c5f43SAlan Wright 		sv->sv_start_time = gethrtime();
705faa1795aSjb150015 		mutex_exit(&sv->sv_mutex);
706faa1795aSjb150015 		smb_server_release(sv);
7078622ec45SGordon Ross 		smb_export_start(sv);
708faa1795aSjb150015 		return (0);
709faa1795aSjb150015 	default:
7109fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_SERVER_STATE_VALID(sv->sv_state);
711faa1795aSjb150015 		mutex_exit(&sv->sv_mutex);
712faa1795aSjb150015 		smb_server_release(sv);
713faa1795aSjb150015 		return (ENOTTY);
714faa1795aSjb150015 	}
715faa1795aSjb150015 
716faa1795aSjb150015 	mutex_exit(&sv->sv_mutex);
7174163af6aSjose borrego 	smb_server_shutdown(sv);
718faa1795aSjb150015 	smb_server_release(sv);
719faa1795aSjb150015 	return (rc);
720faa1795aSjb150015 }
721faa1795aSjb150015 
722faa1795aSjb150015 /*
7239fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * An smbd is shutting down.
7249fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  */
7259fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States int
7269fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_server_stop(void)
7279fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
7289fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_server_t	*sv;
7299fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	int		rc;
7309fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7319fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if ((rc = smb_server_lookup(&sv)) != 0)
7329fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (rc);
7339fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7349fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_enter(&sv->sv_mutex);
7359fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	switch (sv->sv_state) {
7369fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	case SMB_SERVER_STATE_RUNNING:
7379fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		sv->sv_state = SMB_SERVER_STATE_STOPPING;
7384163af6aSjose borrego 		mutex_exit(&sv->sv_mutex);
7394163af6aSjose borrego 		smb_server_shutdown(sv);
7404163af6aSjose borrego 		mutex_enter(&sv->sv_mutex);
741cb174861Sjoyce mcintosh 		cv_broadcast(&sv->sp_info.sp_cv);
7429fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		break;
7439fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	default:
7449fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_SERVER_STATE_VALID(sv->sv_state);
7459fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		break;
7469fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
7479fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_exit(&sv->sv_mutex);
7489fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7499fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_server_release(sv);
7509fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	return (0);
7519fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
7529fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7539fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States boolean_t
7548622ec45SGordon Ross smb_server_is_stopping(smb_server_t *sv)
7559fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
7569fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	boolean_t	status;
7579fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	SMB_SERVER_VALID(sv);
7599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7609fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_enter(&sv->sv_mutex);
7619fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7629fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	switch (sv->sv_state) {
7639fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	case SMB_SERVER_STATE_STOPPING:
7649fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	case SMB_SERVER_STATE_DELETING:
7659fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		status = B_TRUE;
7669fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		break;
7679fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	default:
7689fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		status = B_FALSE;
7699fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		break;
7709fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
7719fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7729fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_exit(&sv->sv_mutex);
7739fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	return (status);
7749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
7759fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7768622ec45SGordon Ross void
7778622ec45SGordon Ross smb_server_cancel_event(smb_server_t *sv, uint32_t txid)
7789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
7799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_event_cancel(sv, txid);
7809fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
7819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7829fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States int
7839fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_server_notify_event(smb_ioc_event_t *ioc)
7849fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
7859fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_server_t	*sv;
7869fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	int		rc;
7879fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7889fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if ((rc = smb_server_lookup(&sv)) == 0) {
7899fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		smb_event_notify(sv, ioc->txid);
7909fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		smb_server_release(sv);
7919fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
7929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	return (rc);
7949fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
7959fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7969fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
797cb174861Sjoyce mcintosh  * smb_server_spooldoc
798cb174861Sjoyce mcintosh  *
799cb174861Sjoyce mcintosh  * Waits for print file close broadcast.
800cb174861Sjoyce mcintosh  * Gets the head of the fid list,
801cb174861Sjoyce mcintosh  * then searches the spooldoc list and returns
802cb174861Sjoyce mcintosh  * this info via the ioctl to user land.
803cb174861Sjoyce mcintosh  *
804cb174861Sjoyce mcintosh  * rc - 0 success
805cb174861Sjoyce mcintosh  */
806cb174861Sjoyce mcintosh 
807cb174861Sjoyce mcintosh int
808cb174861Sjoyce mcintosh smb_server_spooldoc(smb_ioc_spooldoc_t *ioc)
809cb174861Sjoyce mcintosh {
810cb174861Sjoyce mcintosh 	smb_server_t	*sv;
811cb174861Sjoyce mcintosh 	int		rc;
812cb174861Sjoyce mcintosh 	smb_kspooldoc_t *spdoc;
813cb174861Sjoyce mcintosh 	uint16_t	fid;
814cb174861Sjoyce mcintosh 
81523a9c295SGordon Ross 	if ((rc = smb_server_lookup(&sv)) != 0)
81623a9c295SGordon Ross 		return (rc);
81723a9c295SGordon Ross 
818b7301bf5SGordon Ross 	if (sv->sv_cfg.skc_print_enable == 0) {
819b7301bf5SGordon Ross 		rc = ENOTTY;
820b7301bf5SGordon Ross 		goto out;
821b7301bf5SGordon Ross 	}
822b7301bf5SGordon Ross 
82323a9c295SGordon Ross 	mutex_enter(&sv->sv_mutex);
82423a9c295SGordon Ross 	for (;;) {
825cb174861Sjoyce mcintosh 		if (sv->sv_state != SMB_SERVER_STATE_RUNNING) {
826cb174861Sjoyce mcintosh 			rc = ECANCELED;
82723a9c295SGordon Ross 			break;
82823a9c295SGordon Ross 		}
82923a9c295SGordon Ross 		if ((fid = smb_spool_get_fid(sv)) != 0) {
83023a9c295SGordon Ross 			rc = 0;
83123a9c295SGordon Ross 			break;
83223a9c295SGordon Ross 		}
83323a9c295SGordon Ross 		if (cv_wait_sig(&sv->sp_info.sp_cv, &sv->sv_mutex) == 0) {
83423a9c295SGordon Ross 			rc = EINTR;
83523a9c295SGordon Ross 			break;
83623a9c295SGordon Ross 		}
83723a9c295SGordon Ross 	}
83823a9c295SGordon Ross 	mutex_exit(&sv->sv_mutex);
839b7301bf5SGordon Ross 	if (rc != 0)
840b7301bf5SGordon Ross 		goto out;
841b7301bf5SGordon Ross 
84223a9c295SGordon Ross 	spdoc = kmem_zalloc(sizeof (*spdoc), KM_SLEEP);
84323a9c295SGordon Ross 	if (smb_spool_lookup_doc_byfid(sv, fid, spdoc)) {
844cb174861Sjoyce mcintosh 		ioc->spool_num = spdoc->sd_spool_num;
845cb174861Sjoyce mcintosh 		ioc->ipaddr = spdoc->sd_ipaddr;
846cb174861Sjoyce mcintosh 		(void) strlcpy(ioc->path, spdoc->sd_path,
847cb174861Sjoyce mcintosh 		    MAXPATHLEN);
848cb174861Sjoyce mcintosh 		(void) strlcpy(ioc->username,
849cb174861Sjoyce mcintosh 		    spdoc->sd_username, MAXNAMELEN);
85023a9c295SGordon Ross 	} else {
85123a9c295SGordon Ross 		/* Did not find that print job. */
85223a9c295SGordon Ross 		rc = EAGAIN;
853cb174861Sjoyce mcintosh 	}
85423a9c295SGordon Ross 	kmem_free(spdoc, sizeof (*spdoc));
85523a9c295SGordon Ross 
856b7301bf5SGordon Ross out:
857cb174861Sjoyce mcintosh 	smb_server_release(sv);
858cb174861Sjoyce mcintosh 	return (rc);
859cb174861Sjoyce mcintosh }
860cb174861Sjoyce mcintosh 
861faa1795aSjb150015 int
86229bd2886SAlan Wright smb_server_set_gmtoff(smb_ioc_gmt_t *ioc)
863faa1795aSjb150015 {
864faa1795aSjb150015 	int		rc;
865faa1795aSjb150015 	smb_server_t	*sv;
866faa1795aSjb150015 
86708f0d8daSafshin salek ardakani - Sun Microsystems - Irvine United States 	if ((rc = smb_server_lookup(&sv)) == 0) {
86829bd2886SAlan Wright 		sv->si_gmtoff = ioc->offset;
869faa1795aSjb150015 		smb_server_release(sv);
87008f0d8daSafshin salek ardakani - Sun Microsystems - Irvine United States 	}
871faa1795aSjb150015 
872faa1795aSjb150015 	return (rc);
873faa1795aSjb150015 }
874faa1795aSjb150015 
87529bd2886SAlan Wright int
8761fcced4cSJordan Brown smb_server_numopen(smb_ioc_opennum_t *ioc)
87729bd2886SAlan Wright {
87829bd2886SAlan Wright 	smb_server_t	*sv;
87929bd2886SAlan Wright 	int		rc;
88029bd2886SAlan Wright 
88129bd2886SAlan Wright 	if ((rc = smb_server_lookup(&sv)) == 0) {
882148c5f43SAlan Wright 		ioc->open_users = sv->sv_users;
883148c5f43SAlan Wright 		ioc->open_trees = sv->sv_trees;
884148c5f43SAlan Wright 		ioc->open_files = sv->sv_files + sv->sv_pipes;
88529bd2886SAlan Wright 		smb_server_release(sv);
88629bd2886SAlan Wright 	}
88729bd2886SAlan Wright 	return (rc);
88829bd2886SAlan Wright }
88929bd2886SAlan Wright 
890faa1795aSjb150015 /*
8911fcced4cSJordan Brown  * Enumerate objects within the server.  The svcenum provides the
8921fcced4cSJordan Brown  * enumeration context, i.e. what the caller want to get back.
8931fcced4cSJordan Brown  */
8941fcced4cSJordan Brown int
8951fcced4cSJordan Brown smb_server_enum(smb_ioc_svcenum_t *ioc)
8961fcced4cSJordan Brown {
8971fcced4cSJordan Brown 	smb_svcenum_t	*svcenum = &ioc->svcenum;
8981fcced4cSJordan Brown 	smb_server_t	*sv;
8991fcced4cSJordan Brown 	int		rc;
9001fcced4cSJordan Brown 
9011d443a93SDan McDonald 	/*
9021d443a93SDan McDonald 	 * Reality check that the buffer-length insize the enum doesn't
9031d443a93SDan McDonald 	 * overrun the ioctl's total length.
9041d443a93SDan McDonald 	 */
9051d443a93SDan McDonald 	if (svcenum->se_buflen + sizeof (*ioc) > ioc->hdr.len)
9061d443a93SDan McDonald 		return (EINVAL);
9071d443a93SDan McDonald 
9081fcced4cSJordan Brown 	if ((rc = smb_server_lookup(&sv)) != 0)
9091fcced4cSJordan Brown 		return (rc);
9101fcced4cSJordan Brown 
9111fcced4cSJordan Brown 	svcenum->se_bavail = svcenum->se_buflen;
9121fcced4cSJordan Brown 	svcenum->se_bused = 0;
9131fcced4cSJordan Brown 	svcenum->se_nitems = 0;
9141fcced4cSJordan Brown 
9153b13a1efSThomas Keiser 	switch (svcenum->se_type) {
9163b13a1efSThomas Keiser 	case SMB_SVCENUM_TYPE_USER:
9178d94f651SGordon Ross 		smb_server_enum_users(sv, svcenum);
9183b13a1efSThomas Keiser 		break;
9193b13a1efSThomas Keiser 	case SMB_SVCENUM_TYPE_TREE:
9203b13a1efSThomas Keiser 	case SMB_SVCENUM_TYPE_FILE:
9218d94f651SGordon Ross 		smb_server_enum_trees(sv, svcenum);
9223b13a1efSThomas Keiser 		break;
9233b13a1efSThomas Keiser 	default:
9243b13a1efSThomas Keiser 		rc = EINVAL;
9253b13a1efSThomas Keiser 	}
9261fcced4cSJordan Brown 
9271fcced4cSJordan Brown 	smb_server_release(sv);
9283b13a1efSThomas Keiser 	return (rc);
9291fcced4cSJordan Brown }
9301fcced4cSJordan Brown 
9311fcced4cSJordan Brown /*
9321fcced4cSJordan Brown  * Look for sessions to disconnect by client and user name.
9331fcced4cSJordan Brown  */
9341fcced4cSJordan Brown int
9351fcced4cSJordan Brown smb_server_session_close(smb_ioc_session_t *ioc)
9361fcced4cSJordan Brown {
9371fcced4cSJordan Brown 	smb_server_t	*sv;
938811599a4SMatt Barden 	int		cnt;
9391fcced4cSJordan Brown 	int		rc;
9401fcced4cSJordan Brown 
9411fcced4cSJordan Brown 	if ((rc = smb_server_lookup(&sv)) != 0)
9421fcced4cSJordan Brown 		return (rc);
9431fcced4cSJordan Brown 
9448d94f651SGordon Ross 	cnt = smb_server_session_disconnect(sv, ioc->client, ioc->username);
9451fcced4cSJordan Brown 
9461fcced4cSJordan Brown 	smb_server_release(sv);
9471fcced4cSJordan Brown 
948811599a4SMatt Barden 	if (cnt == 0)
9491fcced4cSJordan Brown 		return (ENOENT);
9501fcced4cSJordan Brown 	return (0);
9511fcced4cSJordan Brown }
9521fcced4cSJordan Brown 
9531fcced4cSJordan Brown /*
9541fcced4cSJordan Brown  * Close a file by uniqid.
9551fcced4cSJordan Brown  */
9561fcced4cSJordan Brown int
9571fcced4cSJordan Brown smb_server_file_close(smb_ioc_fileid_t *ioc)
9581fcced4cSJordan Brown {
9591fcced4cSJordan Brown 	uint32_t	uniqid = ioc->uniqid;
9601fcced4cSJordan Brown 	smb_server_t	*sv;
9611fcced4cSJordan Brown 	int		rc;
9621fcced4cSJordan Brown 
9631fcced4cSJordan Brown 	if ((rc = smb_server_lookup(&sv)) != 0)
9641fcced4cSJordan Brown 		return (rc);
9651fcced4cSJordan Brown 
9668d94f651SGordon Ross 	rc = smb_server_fclose(sv, uniqid);
9671fcced4cSJordan Brown 
9681fcced4cSJordan Brown 	smb_server_release(sv);
9691fcced4cSJordan Brown 	return (rc);
9701fcced4cSJordan Brown }
9711fcced4cSJordan Brown 
9721fcced4cSJordan Brown /*
973faa1795aSjb150015  * These functions determine the relevant smb server to which the call apply.
974faa1795aSjb150015  */
975faa1795aSjb150015 
976faa1795aSjb150015 uint32_t
9778622ec45SGordon Ross smb_server_get_session_count(smb_server_t *sv)
978faa1795aSjb150015 {
979faa1795aSjb150015 	uint32_t	counter = 0;
980faa1795aSjb150015 
981811599a4SMatt Barden 	counter = smb_llist_get_count(&sv->sv_session_list);
982faa1795aSjb150015 
983faa1795aSjb150015 	return (counter);
984faa1795aSjb150015 }
985faa1795aSjb150015 
986faa1795aSjb150015 /*
9878d94f651SGordon Ross  * Gets the smb_node of the specified share path.
9888d94f651SGordon Ross  * Node is returned held (caller must rele.)
989148c5f43SAlan Wright  */
990148c5f43SAlan Wright int
9918d94f651SGordon Ross smb_server_share_lookup(smb_server_t *sv, const char *shr_path,
9928d94f651SGordon Ross     smb_node_t **nodepp)
993148c5f43SAlan Wright {
994148c5f43SAlan Wright 	smb_request_t	*sr;
995148c5f43SAlan Wright 	smb_node_t	*fnode = NULL;
9968d94f651SGordon Ross 	smb_node_t	*dnode = NULL;
997148c5f43SAlan Wright 	char		last_comp[MAXNAMELEN];
998148c5f43SAlan Wright 	int		rc = 0;
999148c5f43SAlan Wright 
1000148c5f43SAlan Wright 	ASSERT(shr_path);
1001148c5f43SAlan Wright 
1002148c5f43SAlan Wright 	mutex_enter(&sv->sv_mutex);
1003148c5f43SAlan Wright 	switch (sv->sv_state) {
1004148c5f43SAlan Wright 	case SMB_SERVER_STATE_RUNNING:
1005148c5f43SAlan Wright 		break;
1006148c5f43SAlan Wright 	default:
1007148c5f43SAlan Wright 		mutex_exit(&sv->sv_mutex);
1008148c5f43SAlan Wright 		return (ENOTACTIVE);
1009148c5f43SAlan Wright 	}
1010148c5f43SAlan Wright 	mutex_exit(&sv->sv_mutex);
1011148c5f43SAlan Wright 
1012148c5f43SAlan Wright 	if ((sr = smb_request_alloc(sv->sv_session, 0)) == NULL) {
1013811599a4SMatt Barden 		return (ENOTCONN);
1014148c5f43SAlan Wright 	}
10158622ec45SGordon Ross 	sr->user_cr = zone_kcred();
1016148c5f43SAlan Wright 
1017148c5f43SAlan Wright 	rc = smb_pathname_reduce(sr, sr->user_cr, shr_path,
1018148c5f43SAlan Wright 	    NULL, NULL, &dnode, last_comp);
1019148c5f43SAlan Wright 
1020148c5f43SAlan Wright 	if (rc == 0) {
1021148c5f43SAlan Wright 		rc = smb_fsop_lookup(sr, sr->user_cr, SMB_FOLLOW_LINKS,
1022148c5f43SAlan Wright 		    sv->si_root_smb_node, dnode, last_comp, &fnode);
1023148c5f43SAlan Wright 		smb_node_release(dnode);
1024148c5f43SAlan Wright 	}
1025148c5f43SAlan Wright 
1026148c5f43SAlan Wright 	smb_request_free(sr);
1027148c5f43SAlan Wright 
1028148c5f43SAlan Wright 	if (rc != 0)
1029148c5f43SAlan Wright 		return (rc);
1030148c5f43SAlan Wright 
1031148c5f43SAlan Wright 	ASSERT(fnode->vp && fnode->vp->v_vfsp);
1032148c5f43SAlan Wright 
10338d94f651SGordon Ross 	*nodepp = fnode;
1034148c5f43SAlan Wright 
1035148c5f43SAlan Wright 	return (0);
1036148c5f43SAlan Wright }
1037148c5f43SAlan Wright 
1038b819cea2SGordon Ross #ifdef	_KERNEL
1039148c5f43SAlan Wright /*
1040148c5f43SAlan Wright  * This is a special interface that will be utilized by ZFS to cause a share to
1041148c5f43SAlan Wright  * be added/removed.
1042148c5f43SAlan Wright  *
1043148c5f43SAlan Wright  * arg is either a lmshare_info_t or share_name from userspace.
1044148c5f43SAlan Wright  * It will need to be copied into the kernel.   It is lmshare_info_t
1045148c5f43SAlan Wright  * for add operations and share_name for delete operations.
1046148c5f43SAlan Wright  */
1047148c5f43SAlan Wright int
1048148c5f43SAlan Wright smb_server_share(void *arg, boolean_t add_share)
1049148c5f43SAlan Wright {
1050148c5f43SAlan Wright 	smb_server_t	*sv;
1051148c5f43SAlan Wright 	int		rc;
1052148c5f43SAlan Wright 
1053148c5f43SAlan Wright 	if ((rc = smb_server_lookup(&sv)) == 0) {
1054148c5f43SAlan Wright 		mutex_enter(&sv->sv_mutex);
1055148c5f43SAlan Wright 		switch (sv->sv_state) {
1056148c5f43SAlan Wright 		case SMB_SERVER_STATE_RUNNING:
1057148c5f43SAlan Wright 			mutex_exit(&sv->sv_mutex);
1058148c5f43SAlan Wright 			(void) smb_kshare_upcall(sv->sv_lmshrd, arg, add_share);
1059148c5f43SAlan Wright 			break;
1060148c5f43SAlan Wright 		default:
1061148c5f43SAlan Wright 			mutex_exit(&sv->sv_mutex);
1062148c5f43SAlan Wright 			break;
1063148c5f43SAlan Wright 		}
1064148c5f43SAlan Wright 		smb_server_release(sv);
1065148c5f43SAlan Wright 	}
1066148c5f43SAlan Wright 
1067148c5f43SAlan Wright 	return (rc);
1068148c5f43SAlan Wright }
1069b819cea2SGordon Ross #endif	/* _KERNEL */
1070148c5f43SAlan Wright 
1071148c5f43SAlan Wright int
1072148c5f43SAlan Wright smb_server_unshare(const char *sharename)
1073148c5f43SAlan Wright {
1074148c5f43SAlan Wright 	smb_server_t	*sv;
1075148c5f43SAlan Wright 	int		rc;
1076148c5f43SAlan Wright 
1077148c5f43SAlan Wright 	if ((rc = smb_server_lookup(&sv)))
1078148c5f43SAlan Wright 		return (rc);
1079148c5f43SAlan Wright 
1080148c5f43SAlan Wright 	mutex_enter(&sv->sv_mutex);
1081148c5f43SAlan Wright 	switch (sv->sv_state) {
1082148c5f43SAlan Wright 	case SMB_SERVER_STATE_RUNNING:
1083148c5f43SAlan Wright 	case SMB_SERVER_STATE_STOPPING:
1084148c5f43SAlan Wright 		break;
1085148c5f43SAlan Wright 	default:
1086148c5f43SAlan Wright 		mutex_exit(&sv->sv_mutex);
1087148c5f43SAlan Wright 		smb_server_release(sv);
1088148c5f43SAlan Wright 		return (ENOTACTIVE);
1089148c5f43SAlan Wright 	}
1090148c5f43SAlan Wright 	mutex_exit(&sv->sv_mutex);
1091148c5f43SAlan Wright 
10928d94f651SGordon Ross 	smb_server_disconnect_share(sv, sharename);
1093148c5f43SAlan Wright 
1094148c5f43SAlan Wright 	smb_server_release(sv);
1095148c5f43SAlan Wright 	return (0);
1096148c5f43SAlan Wright }
1097148c5f43SAlan Wright 
1098148c5f43SAlan Wright /*
10999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Disconnect the specified share.
11009fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Typically called when a share has been removed.
1101faa1795aSjb150015  */
11022c1b14e5Sjose borrego static void
11038d94f651SGordon Ross smb_server_disconnect_share(smb_server_t *sv, const char *sharename)
1104faa1795aSjb150015 {
11058d94f651SGordon Ross 	smb_llist_t	*ll;
11069fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_session_t	*session;
11079fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
11088d94f651SGordon Ross 	ll = &sv->sv_session_list;
11094163af6aSjose borrego 	smb_llist_enter(ll, RW_READER);
11109fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
11114163af6aSjose borrego 	session = smb_llist_head(ll);
11129fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	while (session) {
11134163af6aSjose borrego 		SMB_SESSION_VALID(session);
11149fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		smb_rwx_rwenter(&session->s_lock, RW_READER);
11159fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		switch (session->s_state) {
11169fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		case SMB_SESSION_STATE_NEGOTIATED:
1117811599a4SMatt Barden 			smb_rwx_rwexit(&session->s_lock);
11189fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			smb_session_disconnect_share(session, sharename);
11199fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			break;
11209fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		default:
1121811599a4SMatt Barden 			smb_rwx_rwexit(&session->s_lock);
11229fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			break;
11239fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		}
11244163af6aSjose borrego 		session = smb_llist_next(ll, session);
11259fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
11269fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
11274163af6aSjose borrego 	smb_llist_exit(ll);
1128faa1795aSjb150015 }
1129faa1795aSjb150015 
1130faa1795aSjb150015 /*
1131faa1795aSjb150015  * *****************************************************************************
1132faa1795aSjb150015  * **************** Functions called from the internal layers ******************
1133faa1795aSjb150015  * *****************************************************************************
1134faa1795aSjb150015  *
1135faa1795aSjb150015  * These functions are provided the relevant smb server by the caller.
1136faa1795aSjb150015  */
1137faa1795aSjb150015 
1138faa1795aSjb150015 void
1139faa1795aSjb150015 smb_server_get_cfg(smb_server_t *sv, smb_kmod_cfg_t *cfg)
1140faa1795aSjb150015 {
1141faa1795aSjb150015 	rw_enter(&sv->sv_cfg_lock, RW_READER);
1142faa1795aSjb150015 	bcopy(&sv->sv_cfg, cfg, sizeof (*cfg));
1143faa1795aSjb150015 	rw_exit(&sv->sv_cfg_lock);
1144faa1795aSjb150015 }
1145faa1795aSjb150015 
1146faa1795aSjb150015 /*
1147148c5f43SAlan Wright  *
1148148c5f43SAlan Wright  */
1149148c5f43SAlan Wright void
1150148c5f43SAlan Wright smb_server_inc_nbt_sess(smb_server_t *sv)
1151148c5f43SAlan Wright {
1152148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1153148c5f43SAlan Wright 	atomic_inc_32(&sv->sv_nbt_sess);
1154148c5f43SAlan Wright }
1155148c5f43SAlan Wright 
1156148c5f43SAlan Wright void
1157148c5f43SAlan Wright smb_server_dec_nbt_sess(smb_server_t *sv)
1158148c5f43SAlan Wright {
1159148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1160148c5f43SAlan Wright 	atomic_dec_32(&sv->sv_nbt_sess);
1161148c5f43SAlan Wright }
1162148c5f43SAlan Wright 
1163148c5f43SAlan Wright void
1164148c5f43SAlan Wright smb_server_inc_tcp_sess(smb_server_t *sv)
1165148c5f43SAlan Wright {
1166148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1167148c5f43SAlan Wright 	atomic_inc_32(&sv->sv_tcp_sess);
1168148c5f43SAlan Wright }
1169148c5f43SAlan Wright 
1170148c5f43SAlan Wright void
1171148c5f43SAlan Wright smb_server_dec_tcp_sess(smb_server_t *sv)
1172148c5f43SAlan Wright {
1173148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1174148c5f43SAlan Wright 	atomic_dec_32(&sv->sv_tcp_sess);
1175148c5f43SAlan Wright }
1176148c5f43SAlan Wright 
1177148c5f43SAlan Wright void
1178148c5f43SAlan Wright smb_server_inc_users(smb_server_t *sv)
1179148c5f43SAlan Wright {
1180148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1181148c5f43SAlan Wright 	atomic_inc_32(&sv->sv_users);
1182148c5f43SAlan Wright }
1183148c5f43SAlan Wright 
1184148c5f43SAlan Wright void
1185148c5f43SAlan Wright smb_server_dec_users(smb_server_t *sv)
1186148c5f43SAlan Wright {
1187148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1188148c5f43SAlan Wright 	atomic_dec_32(&sv->sv_users);
1189148c5f43SAlan Wright }
1190148c5f43SAlan Wright 
1191148c5f43SAlan Wright void
1192148c5f43SAlan Wright smb_server_inc_trees(smb_server_t *sv)
1193148c5f43SAlan Wright {
1194148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1195148c5f43SAlan Wright 	atomic_inc_32(&sv->sv_trees);
1196148c5f43SAlan Wright }
1197148c5f43SAlan Wright 
1198148c5f43SAlan Wright void
1199148c5f43SAlan Wright smb_server_dec_trees(smb_server_t *sv)
1200148c5f43SAlan Wright {
1201148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1202148c5f43SAlan Wright 	atomic_dec_32(&sv->sv_trees);
1203148c5f43SAlan Wright }
1204148c5f43SAlan Wright 
1205148c5f43SAlan Wright void
1206148c5f43SAlan Wright smb_server_inc_files(smb_server_t *sv)
1207148c5f43SAlan Wright {
1208148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1209148c5f43SAlan Wright 	atomic_inc_32(&sv->sv_files);
1210148c5f43SAlan Wright }
1211148c5f43SAlan Wright 
1212148c5f43SAlan Wright void
1213148c5f43SAlan Wright smb_server_dec_files(smb_server_t *sv)
1214148c5f43SAlan Wright {
1215148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1216148c5f43SAlan Wright 	atomic_dec_32(&sv->sv_files);
1217148c5f43SAlan Wright }
1218148c5f43SAlan Wright 
1219148c5f43SAlan Wright void
1220148c5f43SAlan Wright smb_server_inc_pipes(smb_server_t *sv)
1221148c5f43SAlan Wright {
1222148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1223148c5f43SAlan Wright 	atomic_inc_32(&sv->sv_pipes);
1224148c5f43SAlan Wright }
1225148c5f43SAlan Wright 
1226148c5f43SAlan Wright void
1227148c5f43SAlan Wright smb_server_dec_pipes(smb_server_t *sv)
1228148c5f43SAlan Wright {
1229148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1230148c5f43SAlan Wright 	atomic_dec_32(&sv->sv_pipes);
1231148c5f43SAlan Wright }
1232148c5f43SAlan Wright 
1233148c5f43SAlan Wright void
1234148c5f43SAlan Wright smb_server_add_rxb(smb_server_t *sv, int64_t value)
1235148c5f43SAlan Wright {
1236148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1237148c5f43SAlan Wright 	atomic_add_64(&sv->sv_rxb, value);
1238148c5f43SAlan Wright }
1239148c5f43SAlan Wright 
1240148c5f43SAlan Wright void
1241148c5f43SAlan Wright smb_server_add_txb(smb_server_t *sv, int64_t value)
1242148c5f43SAlan Wright {
1243148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1244148c5f43SAlan Wright 	atomic_add_64(&sv->sv_txb, value);
1245148c5f43SAlan Wright }
1246148c5f43SAlan Wright 
1247148c5f43SAlan Wright void
1248148c5f43SAlan Wright smb_server_inc_req(smb_server_t *sv)
1249148c5f43SAlan Wright {
1250148c5f43SAlan Wright 	SMB_SERVER_VALID(sv);
1251148c5f43SAlan Wright 	atomic_inc_64(&sv->sv_nreq);
1252148c5f43SAlan Wright }
1253148c5f43SAlan Wright 
1254148c5f43SAlan Wright /*
1255faa1795aSjb150015  * *****************************************************************************
1256faa1795aSjb150015  * *************************** Static Functions ********************************
1257faa1795aSjb150015  * *****************************************************************************
1258faa1795aSjb150015  */
1259faa1795aSjb150015 
1260faa1795aSjb150015 static void
1261faa1795aSjb150015 smb_server_timers(smb_thread_t *thread, void *arg)
1262faa1795aSjb150015 {
1263faa1795aSjb150015 	smb_server_t	*sv = (smb_server_t *)arg;
1264faa1795aSjb150015 
1265faa1795aSjb150015 	ASSERT(sv != NULL);
1266faa1795aSjb150015 
1267b819cea2SGordon Ross 	/*
1268811599a4SMatt Barden 	 * This kills old inactive sessions and expired durable
1269811599a4SMatt Barden 	 * handles. The session code expects one call per minute.
1270b819cea2SGordon Ross 	 */
1271b819cea2SGordon Ross 	while (smb_thread_continue_timedwait(thread, 60 /* Seconds */)) {
1272811599a4SMatt Barden 		if (sv->sv_cfg.skc_keepalive != 0)
1273811599a4SMatt Barden 			smb_session_timers(sv);
1274811599a4SMatt Barden 		smb2_durable_timers(sv);
1275faa1795aSjb150015 	}
1276faa1795aSjb150015 }
1277faa1795aSjb150015 
1278faa1795aSjb150015 /*
1279faa1795aSjb150015  * smb_server_kstat_init
1280faa1795aSjb150015  */
1281148c5f43SAlan Wright static void
1282faa1795aSjb150015 smb_server_kstat_init(smb_server_t *sv)
1283faa1795aSjb150015 {
1284cb174861Sjoyce mcintosh 
12858622ec45SGordon Ross 	sv->sv_ksp = kstat_create_zone(SMBSRV_KSTAT_MODULE, 0,
1286148c5f43SAlan Wright 	    SMBSRV_KSTAT_STATISTICS, SMBSRV_KSTAT_CLASS, KSTAT_TYPE_RAW,
1287148c5f43SAlan Wright 	    sizeof (smbsrv_kstats_t), 0, sv->sv_zid);
1288faa1795aSjb150015 
1289148c5f43SAlan Wright 	if (sv->sv_ksp != NULL) {
1290148c5f43SAlan Wright 		sv->sv_ksp->ks_update = smb_server_kstat_update;
1291148c5f43SAlan Wright 		sv->sv_ksp->ks_private = sv;
1292148c5f43SAlan Wright 		((smbsrv_kstats_t *)sv->sv_ksp->ks_data)->ks_start_time =
1293148c5f43SAlan Wright 		    sv->sv_start_time;
12948622ec45SGordon Ross 		smb_dispatch_stats_init(sv);
1295a90cf9f2SGordon Ross 		smb2_dispatch_stats_init(sv);
1296faa1795aSjb150015 		kstat_install(sv->sv_ksp);
1297148c5f43SAlan Wright 	} else {
1298148c5f43SAlan Wright 		cmn_err(CE_WARN, "SMB Server: Statistics unavailable");
1299faa1795aSjb150015 	}
1300cb174861Sjoyce mcintosh 
13018622ec45SGordon Ross 	sv->sv_legacy_ksp = kstat_create_zone(SMBSRV_KSTAT_MODULE, 0,
13028622ec45SGordon Ross 	    SMBSRV_KSTAT_NAME, SMBSRV_KSTAT_CLASS, KSTAT_TYPE_NAMED,
13038622ec45SGordon Ross 	    sizeof (smb_server_legacy_kstat_t) / sizeof (kstat_named_t),
13048622ec45SGordon Ross 	    0, sv->sv_zid);
1305cb174861Sjoyce mcintosh 
1306cb174861Sjoyce mcintosh 	if (sv->sv_legacy_ksp != NULL) {
1307cb174861Sjoyce mcintosh 		smb_server_legacy_kstat_t *ksd;
1308cb174861Sjoyce mcintosh 
1309cb174861Sjoyce mcintosh 		ksd = sv->sv_legacy_ksp->ks_data;
1310cb174861Sjoyce mcintosh 
1311cb174861Sjoyce mcintosh 		(void) strlcpy(ksd->ls_files.name, "open_files",
1312cb174861Sjoyce mcintosh 		    sizeof (ksd->ls_files.name));
1313cb174861Sjoyce mcintosh 		ksd->ls_files.data_type = KSTAT_DATA_UINT32;
1314cb174861Sjoyce mcintosh 
1315cb174861Sjoyce mcintosh 		(void) strlcpy(ksd->ls_trees.name, "connections",
1316cb174861Sjoyce mcintosh 		    sizeof (ksd->ls_trees.name));
1317cb174861Sjoyce mcintosh 		ksd->ls_trees.data_type = KSTAT_DATA_UINT32;
1318cb174861Sjoyce mcintosh 
1319cb174861Sjoyce mcintosh 		(void) strlcpy(ksd->ls_users.name, "connections",
1320cb174861Sjoyce mcintosh 		    sizeof (ksd->ls_users.name));
1321cb174861Sjoyce mcintosh 		ksd->ls_users.data_type = KSTAT_DATA_UINT32;
1322cb174861Sjoyce mcintosh 
1323cb174861Sjoyce mcintosh 		mutex_init(&sv->sv_legacy_ksmtx, NULL, MUTEX_DEFAULT, NULL);
1324cb174861Sjoyce mcintosh 		sv->sv_legacy_ksp->ks_lock = &sv->sv_legacy_ksmtx;
1325cb174861Sjoyce mcintosh 		sv->sv_legacy_ksp->ks_update = smb_server_legacy_kstat_update;
1326cb174861Sjoyce mcintosh 		kstat_install(sv->sv_legacy_ksp);
1327cb174861Sjoyce mcintosh 	}
1328faa1795aSjb150015 }
1329faa1795aSjb150015 
1330faa1795aSjb150015 /*
1331faa1795aSjb150015  * smb_server_kstat_fini
1332faa1795aSjb150015  */
1333faa1795aSjb150015 static void
1334faa1795aSjb150015 smb_server_kstat_fini(smb_server_t *sv)
1335faa1795aSjb150015 {
1336cb174861Sjoyce mcintosh 	if (sv->sv_legacy_ksp != NULL) {
1337cb174861Sjoyce mcintosh 		kstat_delete(sv->sv_legacy_ksp);
1338cb174861Sjoyce mcintosh 		mutex_destroy(&sv->sv_legacy_ksmtx);
1339cb174861Sjoyce mcintosh 		sv->sv_legacy_ksp = NULL;
1340cb174861Sjoyce mcintosh 	}
1341cb174861Sjoyce mcintosh 
1342148c5f43SAlan Wright 	if (sv->sv_ksp != NULL) {
1343faa1795aSjb150015 		kstat_delete(sv->sv_ksp);
1344faa1795aSjb150015 		sv->sv_ksp = NULL;
13458622ec45SGordon Ross 		smb_dispatch_stats_fini(sv);
1346a90cf9f2SGordon Ross 		smb2_dispatch_stats_fini(sv);
1347faa1795aSjb150015 	}
1348faa1795aSjb150015 }
1349faa1795aSjb150015 
1350148c5f43SAlan Wright /*
1351148c5f43SAlan Wright  * smb_server_kstat_update
1352148c5f43SAlan Wright  */
1353faa1795aSjb150015 static int
1354148c5f43SAlan Wright smb_server_kstat_update(kstat_t *ksp, int rw)
1355faa1795aSjb150015 {
1356faa1795aSjb150015 	smb_server_t	*sv;
1357148c5f43SAlan Wright 	smbsrv_kstats_t	*ksd;
1358faa1795aSjb150015 
1359148c5f43SAlan Wright 	if (rw == KSTAT_READ) {
1360148c5f43SAlan Wright 		sv = ksp->ks_private;
13619fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_SERVER_VALID(sv);
1362148c5f43SAlan Wright 		ksd = (smbsrv_kstats_t *)ksp->ks_data;
1363148c5f43SAlan Wright 		/*
1364148c5f43SAlan Wright 		 * Counters
1365148c5f43SAlan Wright 		 */
1366148c5f43SAlan Wright 		ksd->ks_nbt_sess = sv->sv_nbt_sess;
1367148c5f43SAlan Wright 		ksd->ks_tcp_sess = sv->sv_tcp_sess;
1368148c5f43SAlan Wright 		ksd->ks_users = sv->sv_users;
1369148c5f43SAlan Wright 		ksd->ks_trees = sv->sv_trees;
1370148c5f43SAlan Wright 		ksd->ks_files = sv->sv_files;
1371148c5f43SAlan Wright 		ksd->ks_pipes = sv->sv_pipes;
1372148c5f43SAlan Wright 		/*
1373148c5f43SAlan Wright 		 * Throughput
1374148c5f43SAlan Wright 		 */
1375148c5f43SAlan Wright 		ksd->ks_txb = sv->sv_txb;
1376148c5f43SAlan Wright 		ksd->ks_rxb = sv->sv_rxb;
1377148c5f43SAlan Wright 		ksd->ks_nreq = sv->sv_nreq;
1378148c5f43SAlan Wright 		/*
1379148c5f43SAlan Wright 		 * Busyness
1380148c5f43SAlan Wright 		 */
1381148c5f43SAlan Wright 		ksd->ks_maxreqs = sv->sv_cfg.skc_maxworkers;
1382148c5f43SAlan Wright 		smb_srqueue_update(&sv->sv_srqueue,
1383148c5f43SAlan Wright 		    &ksd->ks_utilization);
1384148c5f43SAlan Wright 		/*
1385148c5f43SAlan Wright 		 * Latency & Throughput of the requests
1386148c5f43SAlan Wright 		 */
1387a90cf9f2SGordon Ross 		smb_dispatch_stats_update(sv, ksd->ks_reqs1, 0, SMB_COM_NUM);
1388a90cf9f2SGordon Ross 		smb2_dispatch_stats_update(sv, ksd->ks_reqs2, 0, SMB2__NCMDS);
1389faa1795aSjb150015 		return (0);
1390faa1795aSjb150015 	}
1391148c5f43SAlan Wright 	if (rw == KSTAT_WRITE)
1392148c5f43SAlan Wright 		return (EACCES);
1393148c5f43SAlan Wright 
1394148c5f43SAlan Wright 	return (EIO);
1395148c5f43SAlan Wright }
1396faa1795aSjb150015 
1397cb174861Sjoyce mcintosh static int
1398cb174861Sjoyce mcintosh smb_server_legacy_kstat_update(kstat_t *ksp, int rw)
1399cb174861Sjoyce mcintosh {
1400cb174861Sjoyce mcintosh 	smb_server_t			*sv;
1401cb174861Sjoyce mcintosh 	smb_server_legacy_kstat_t	*ksd;
1402cb174861Sjoyce mcintosh 	int				rc;
1403cb174861Sjoyce mcintosh 
1404cb174861Sjoyce mcintosh 	switch (rw) {
1405cb174861Sjoyce mcintosh 	case KSTAT_WRITE:
1406cb174861Sjoyce mcintosh 		rc = EACCES;
1407cb174861Sjoyce mcintosh 		break;
1408cb174861Sjoyce mcintosh 	case KSTAT_READ:
1409cb174861Sjoyce mcintosh 		if (!smb_server_lookup(&sv)) {
1410cb174861Sjoyce mcintosh 			ASSERT(MUTEX_HELD(ksp->ks_lock));
1411cb174861Sjoyce mcintosh 			ASSERT(sv->sv_legacy_ksp == ksp);
1412cb174861Sjoyce mcintosh 			ksd = (smb_server_legacy_kstat_t *)ksp->ks_data;
1413cb174861Sjoyce mcintosh 			ksd->ls_files.value.ui32 = sv->sv_files + sv->sv_pipes;
1414cb174861Sjoyce mcintosh 			ksd->ls_trees.value.ui32 = sv->sv_trees;
1415cb174861Sjoyce mcintosh 			ksd->ls_users.value.ui32 = sv->sv_users;
1416cb174861Sjoyce mcintosh 			smb_server_release(sv);
1417cb174861Sjoyce mcintosh 			rc = 0;
1418cb174861Sjoyce mcintosh 			break;
1419cb174861Sjoyce mcintosh 		}
14202d63d7e2SToomas Soome 		/* FALLTHROUGH */
1421cb174861Sjoyce mcintosh 	default:
1422cb174861Sjoyce mcintosh 		rc = EIO;
1423cb174861Sjoyce mcintosh 		break;
1424cb174861Sjoyce mcintosh 	}
1425cb174861Sjoyce mcintosh 	return (rc);
1426cb174861Sjoyce mcintosh 
1427cb174861Sjoyce mcintosh }
1428cb174861Sjoyce mcintosh 
1429faa1795aSjb150015 /*
14304163af6aSjose borrego  * smb_server_shutdown
1431faa1795aSjb150015  */
1432faa1795aSjb150015 static void
14339fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_server_shutdown(smb_server_t *sv)
1434faa1795aSjb150015 {
1435811599a4SMatt Barden 	smb_llist_t *sl = &sv->sv_session_list;
1436811599a4SMatt Barden 	smb_session_t *session;
1437811599a4SMatt Barden 	clock_t	time;
1438811599a4SMatt Barden 
14399fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	SMB_SERVER_VALID(sv);
1440faa1795aSjb150015 
1441856399cfSGordon Ross 	/*
1442856399cfSGordon Ross 	 * Stop the listeners first, so we don't get any more
1443856399cfSGordon Ross 	 * new work while we're trying to shut down.
1444856399cfSGordon Ross 	 */
1445856399cfSGordon Ross 	smb_server_listener_stop(&sv->sv_nbt_daemon);
1446856399cfSGordon Ross 	smb_server_listener_stop(&sv->sv_tcp_daemon);
1447faa1795aSjb150015 	smb_thread_stop(&sv->si_thread_timers);
1448856399cfSGordon Ross 
1449811599a4SMatt Barden 	/* Disconnect all of the sessions */
1450811599a4SMatt Barden 	smb_llist_enter(sl, RW_READER);
1451811599a4SMatt Barden 	session = smb_llist_head(sl);
1452811599a4SMatt Barden 	while (session != NULL) {
1453811599a4SMatt Barden 		smb_session_disconnect(session);
1454811599a4SMatt Barden 		session = smb_llist_next(sl, session);
1455811599a4SMatt Barden 	}
1456811599a4SMatt Barden 	smb_llist_exit(sl);
1457811599a4SMatt Barden 
1458856399cfSGordon Ross 	/*
1459856399cfSGordon Ross 	 * Wake up any threads we might have blocked.
1460856399cfSGordon Ross 	 * Must precede kdoor_close etc. because those will
1461856399cfSGordon Ross 	 * wait for such threads to get out.
1462856399cfSGordon Ross 	 */
1463856399cfSGordon Ross 	smb_event_cancel(sv, 0);
1464856399cfSGordon Ross 	smb_threshold_wake_all(&sv->sv_ssetup_ct);
1465856399cfSGordon Ross 	smb_threshold_wake_all(&sv->sv_tcon_ct);
1466856399cfSGordon Ross 	smb_threshold_wake_all(&sv->sv_opipe_ct);
1467856399cfSGordon Ross 
1468811599a4SMatt Barden 	/*
1469811599a4SMatt Barden 	 * Wait for the session list to empty.
1470811599a4SMatt Barden 	 * (cv_signal in smb_server_destroy_session)
1471811599a4SMatt Barden 	 *
1472811599a4SMatt Barden 	 * This should not take long, but if there are any leaked
1473811599a4SMatt Barden 	 * references to ofiles, trees, or users, there could be a
1474811599a4SMatt Barden 	 * session hanging around.  If that happens, the ll_count
1475811599a4SMatt Barden 	 * never gets to zero and we'll never get the sv_signal.
1476811599a4SMatt Barden 	 * Defend against that problem using timed wait, then
1477811599a4SMatt Barden 	 * complain if we find sessions left over and continue
1478811599a4SMatt Barden 	 * with shutdown in spite of any leaked sessions.
1479811599a4SMatt Barden 	 * That's better than a server that won't reboot.
1480811599a4SMatt Barden 	 */
1481*7f5d80fdSGordon Ross 	time = SEC_TO_TICK(5) + ddi_get_lbolt();
1482811599a4SMatt Barden 	mutex_enter(&sv->sv_mutex);
1483811599a4SMatt Barden 	while (sv->sv_session_list.ll_count != 0) {
1484811599a4SMatt Barden 		if (cv_timedwait(&sv->sv_cv, &sv->sv_mutex, time) < 0)
1485811599a4SMatt Barden 			break;
1486811599a4SMatt Barden 	}
1487811599a4SMatt Barden 	mutex_exit(&sv->sv_mutex);
1488811599a4SMatt Barden #ifdef	DEBUG
1489811599a4SMatt Barden 	if (sv->sv_session_list.ll_count != 0) {
1490811599a4SMatt Barden 		cmn_err(CE_NOTE, "shutdown leaked sessions");
1491811599a4SMatt Barden 		debug_enter("shutdown leaked sessions");
1492811599a4SMatt Barden 	}
1493811599a4SMatt Barden #endif
1494811599a4SMatt Barden 
1495811599a4SMatt Barden 	/*
1496811599a4SMatt Barden 	 * Clean out any durable handles.  After this we should
1497811599a4SMatt Barden 	 * have no ofiles remaining (and no more oplock breaks).
1498811599a4SMatt Barden 	 */
1499811599a4SMatt Barden 	smb2_dh_shutdown(sv);
1500811599a4SMatt Barden 
15018622ec45SGordon Ross 	smb_kdoor_close(sv);
1502b819cea2SGordon Ross #ifdef	_KERNEL
1503148c5f43SAlan Wright 	smb_kshare_door_fini(sv->sv_lmshrd);
1504b819cea2SGordon Ross #endif	/* _KERNEL */
15050dcb3379Sjb150015 	sv->sv_lmshrd = NULL;
1506b819cea2SGordon Ross 
15078622ec45SGordon Ross 	smb_export_stop(sv);
1508811599a4SMatt Barden 	smb_kshare_stop(sv);
15098d96b23eSAlan Wright 
15104846df9bSKevin Crowe 	/*
1511811599a4SMatt Barden 	 * Both kshare and the oplock break sub-systems may have
1512811599a4SMatt Barden 	 * taskq jobs on the spcial "server" session, until we've
1513811599a4SMatt Barden 	 * closed all ofiles and stopped the kshare exporter.
1514811599a4SMatt Barden 	 * Now it's safe to destroy the server session, but first
1515811599a4SMatt Barden 	 * wait for any requests on it to finish.  Note that for
1516811599a4SMatt Barden 	 * normal sessions, this happens in smb_session_cancel,
1517811599a4SMatt Barden 	 * but that's not called for the server session.
15184846df9bSKevin Crowe 	 */
15198d94f651SGordon Ross 	if (sv->sv_rootuser != NULL) {
15208d94f651SGordon Ross 		smb_user_logoff(sv->sv_rootuser);
15218d94f651SGordon Ross 		smb_user_release(sv->sv_rootuser);
15228d94f651SGordon Ross 		sv->sv_rootuser = NULL;
15238d94f651SGordon Ross 	}
1524811599a4SMatt Barden 	if (sv->sv_session != NULL) {
1525525641e8SGordon Ross 		smb_session_cancel_requests(sv->sv_session, NULL, NULL);
15264846df9bSKevin Crowe 		smb_slist_wait_for_empty(&sv->sv_session->s_req_list);
15274846df9bSKevin Crowe 
15288d94f651SGordon Ross 		/* Just in case import left users and trees */
15298d94f651SGordon Ross 		smb_session_logoff(sv->sv_session);
15308d94f651SGordon Ross 
1531faa1795aSjb150015 		smb_session_delete(sv->sv_session);
1532faa1795aSjb150015 		sv->sv_session = NULL;
1533faa1795aSjb150015 	}
15348d96b23eSAlan Wright 
15354163af6aSjose borrego 	if (sv->sv_receiver_pool != NULL) {
15364163af6aSjose borrego 		taskq_destroy(sv->sv_receiver_pool);
15374163af6aSjose borrego 		sv->sv_receiver_pool = NULL;
15384163af6aSjose borrego 	}
15394163af6aSjose borrego 
15404163af6aSjose borrego 	if (sv->sv_worker_pool != NULL) {
15414163af6aSjose borrego 		taskq_destroy(sv->sv_worker_pool);
15424163af6aSjose borrego 		sv->sv_worker_pool = NULL;
15438d96b23eSAlan Wright 	}
15448622ec45SGordon Ross 
15458622ec45SGordon Ross 	smb_server_fsop_stop(sv);
1546faa1795aSjb150015 }
1547faa1795aSjb150015 
15484163af6aSjose borrego /*
15494163af6aSjose borrego  * smb_server_listener_init
15504163af6aSjose borrego  *
15514163af6aSjose borrego  * Initializes listener contexts.
15524163af6aSjose borrego  */
15534163af6aSjose borrego static void
15544163af6aSjose borrego smb_server_listener_init(
1555faa1795aSjb150015     smb_server_t		*sv,
1556faa1795aSjb150015     smb_listener_daemon_t	*ld,
15574163af6aSjose borrego     char			*name,
1558faa1795aSjb150015     in_port_t			port,
15594163af6aSjose borrego     int				family)
1560faa1795aSjb150015 {
15614163af6aSjose borrego 	ASSERT(ld->ld_magic != SMB_LISTENER_MAGIC);
1562faa1795aSjb150015 
15634163af6aSjose borrego 	bzero(ld, sizeof (*ld));
1564faa1795aSjb150015 
15654163af6aSjose borrego 	ld->ld_sv = sv;
15664163af6aSjose borrego 	ld->ld_family = family;
15674163af6aSjose borrego 	ld->ld_port = port;
15684163af6aSjose borrego 
15697f667e74Sjose borrego 	if (family == AF_INET) {
15707f667e74Sjose borrego 		ld->ld_sin.sin_family = (uint32_t)family;
1571faa1795aSjb150015 		ld->ld_sin.sin_port = htons(port);
1572faa1795aSjb150015 		ld->ld_sin.sin_addr.s_addr = htonl(INADDR_ANY);
15737f667e74Sjose borrego 	} else {
15747f667e74Sjose borrego 		ld->ld_sin6.sin6_family = (uint32_t)family;
15757f667e74Sjose borrego 		ld->ld_sin6.sin6_port = htons(port);
15767f667e74Sjose borrego 		(void) memset(&ld->ld_sin6.sin6_addr.s6_addr, 0,
15777f667e74Sjose borrego 		    sizeof (ld->ld_sin6.sin6_addr.s6_addr));
15787f667e74Sjose borrego 	}
1579faa1795aSjb150015 
158008344b29SGordon Ross 	smb_thread_init(&ld->ld_thread, name, smb_server_listener, ld,
158108344b29SGordon Ross 	    smbsrv_listen_pri);
15824163af6aSjose borrego 	ld->ld_magic = SMB_LISTENER_MAGIC;
15834163af6aSjose borrego }
15844163af6aSjose borrego 
15854163af6aSjose borrego /*
15864163af6aSjose borrego  * smb_server_listener_destroy
15874163af6aSjose borrego  *
15884163af6aSjose borrego  * Destroyes listener contexts.
15894163af6aSjose borrego  */
15904163af6aSjose borrego static void
15914163af6aSjose borrego smb_server_listener_destroy(smb_listener_daemon_t *ld)
15924163af6aSjose borrego {
159383d2dfe6SGordon Ross 	/*
159483d2dfe6SGordon Ross 	 * Note that if startup fails early, we can legitimately
159583d2dfe6SGordon Ross 	 * get here with an all-zeros object.
159683d2dfe6SGordon Ross 	 */
159783d2dfe6SGordon Ross 	if (ld->ld_magic == 0)
159883d2dfe6SGordon Ross 		return;
159983d2dfe6SGordon Ross 
16004163af6aSjose borrego 	SMB_LISTENER_VALID(ld);
16014163af6aSjose borrego 	ASSERT(ld->ld_so == NULL);
16024163af6aSjose borrego 	smb_thread_destroy(&ld->ld_thread);
16034163af6aSjose borrego 	ld->ld_magic = 0;
16044163af6aSjose borrego }
16054163af6aSjose borrego 
16064163af6aSjose borrego /*
16074163af6aSjose borrego  * smb_server_listener_start
16084163af6aSjose borrego  *
16094163af6aSjose borrego  * Starts the listener associated with the context passed in.
16104163af6aSjose borrego  *
16114163af6aSjose borrego  * Return:	0	Success
16124163af6aSjose borrego  *		not 0	Failure
16134163af6aSjose borrego  */
16144163af6aSjose borrego static int
16154163af6aSjose borrego smb_server_listener_start(smb_listener_daemon_t *ld)
16164163af6aSjose borrego {
16174163af6aSjose borrego 	int		rc;
16184163af6aSjose borrego 	uint32_t	on;
16194163af6aSjose borrego 	uint32_t	off;
16204163af6aSjose borrego 
16214163af6aSjose borrego 	SMB_LISTENER_VALID(ld);
16224163af6aSjose borrego 
16234163af6aSjose borrego 	if (ld->ld_so != NULL)
16244163af6aSjose borrego 		return (EINVAL);
16254163af6aSjose borrego 
16264163af6aSjose borrego 	ld->ld_so = smb_socreate(ld->ld_family, SOCK_STREAM, 0);
16279fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (ld->ld_so == NULL) {
16284163af6aSjose borrego 		cmn_err(CE_WARN, "port %d: socket create failed", ld->ld_port);
16299fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (ENOMEM);
16309fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
16319fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
16329fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	off = 0;
16330f1702c5SYu Xiangning 	(void) ksocket_setsockopt(ld->ld_so, SOL_SOCKET,
1634fc724630SAlan Wright 	    SO_MAC_EXEMPT, &off, sizeof (off), CRED());
16359fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
16369fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	on = 1;
1637fc724630SAlan Wright 	(void) ksocket_setsockopt(ld->ld_so, SOL_SOCKET,
1638fc724630SAlan Wright 	    SO_REUSEADDR, &on, sizeof (on), CRED());
1639fc724630SAlan Wright 
16404163af6aSjose borrego 	if (ld->ld_family == AF_INET) {
16410f1702c5SYu Xiangning 		rc = ksocket_bind(ld->ld_so,
16420f1702c5SYu Xiangning 		    (struct sockaddr *)&ld->ld_sin,
16430f1702c5SYu Xiangning 		    sizeof (ld->ld_sin), CRED());
16447f667e74Sjose borrego 	} else {
16457f667e74Sjose borrego 		rc = ksocket_bind(ld->ld_so,
16467f667e74Sjose borrego 		    (struct sockaddr *)&ld->ld_sin6,
16477f667e74Sjose borrego 		    sizeof (ld->ld_sin6), CRED());
16487f667e74Sjose borrego 	}
16499fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
16509fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (rc != 0) {
16514163af6aSjose borrego 		cmn_err(CE_WARN, "port %d: bind failed", ld->ld_port);
16529fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (rc);
16539fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
16549fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
16550f1702c5SYu Xiangning 	rc =  ksocket_listen(ld->ld_so, 20, CRED());
1656faa1795aSjb150015 	if (rc < 0) {
16574163af6aSjose borrego 		cmn_err(CE_WARN, "port %d: listen failed", ld->ld_port);
1658faa1795aSjb150015 		return (rc);
1659faa1795aSjb150015 	}
16604163af6aSjose borrego 
16614163af6aSjose borrego 	ksocket_hold(ld->ld_so);
16624163af6aSjose borrego 	rc = smb_thread_start(&ld->ld_thread);
16634163af6aSjose borrego 	if (rc != 0) {
16644163af6aSjose borrego 		ksocket_rele(ld->ld_so);
16654163af6aSjose borrego 		cmn_err(CE_WARN, "port %d: listener failed to start",
16664163af6aSjose borrego 		    ld->ld_port);
16674163af6aSjose borrego 		return (rc);
1668faa1795aSjb150015 	}
16694163af6aSjose borrego 	return (0);
16704163af6aSjose borrego }
16714163af6aSjose borrego 
16724163af6aSjose borrego /*
16734163af6aSjose borrego  * smb_server_listener_stop
16744163af6aSjose borrego  *
16754163af6aSjose borrego  * Stops the listener associated with the context passed in.
16764163af6aSjose borrego  */
16774163af6aSjose borrego static void
16784163af6aSjose borrego smb_server_listener_stop(smb_listener_daemon_t *ld)
16794163af6aSjose borrego {
16804163af6aSjose borrego 	SMB_LISTENER_VALID(ld);
16814163af6aSjose borrego 
16824163af6aSjose borrego 	if (ld->ld_so != NULL) {
16834163af6aSjose borrego 		smb_soshutdown(ld->ld_so);
16844163af6aSjose borrego 		smb_sodestroy(ld->ld_so);
16854163af6aSjose borrego 		smb_thread_stop(&ld->ld_thread);
16864163af6aSjose borrego 		ld->ld_so = NULL;
16874163af6aSjose borrego 	}
16884163af6aSjose borrego }
16894163af6aSjose borrego 
16904163af6aSjose borrego /*
16914163af6aSjose borrego  * smb_server_listener
16924163af6aSjose borrego  *
16934163af6aSjose borrego  * Entry point of the listeners.
16944163af6aSjose borrego  */
16954163af6aSjose borrego static void
16964163af6aSjose borrego smb_server_listener(smb_thread_t *thread, void *arg)
16974163af6aSjose borrego {
16984163af6aSjose borrego 	_NOTE(ARGUNUSED(thread))
16994163af6aSjose borrego 	smb_listener_daemon_t	*ld;
17004163af6aSjose borrego 	ksocket_t		s_so;
17014163af6aSjose borrego 	int			on;
17024163af6aSjose borrego 	int			txbuf_size;
17034163af6aSjose borrego 
17044163af6aSjose borrego 	ld = (smb_listener_daemon_t *)arg;
17054163af6aSjose borrego 
17064163af6aSjose borrego 	SMB_LISTENER_VALID(ld);
1707faa1795aSjb150015 
1708faa1795aSjb150015 	DTRACE_PROBE1(so__wait__accept, struct sonode *, ld->ld_so);
1709faa1795aSjb150015 
171041bd8510Skcrowenex 	for (;;) {
171141bd8510Skcrowenex 		int ret = ksocket_accept(ld->ld_so, NULL, NULL, &s_so, CRED());
171241bd8510Skcrowenex 
171341bd8510Skcrowenex 		switch (ret) {
171441bd8510Skcrowenex 		case 0:
171541bd8510Skcrowenex 			break;
171641bd8510Skcrowenex 		case ECONNABORTED:
171741bd8510Skcrowenex 			continue;
171841bd8510Skcrowenex 		case EINTR:
171941bd8510Skcrowenex 		case EBADF:	/* libfakekernel */
172041bd8510Skcrowenex 			goto out;
172141bd8510Skcrowenex 		default:
172241bd8510Skcrowenex 			cmn_err(CE_WARN,
172341bd8510Skcrowenex 			    "smb_server_listener: ksocket_accept(%d)",
172441bd8510Skcrowenex 			    ret);
172541bd8510Skcrowenex 			goto out;
172641bd8510Skcrowenex 		}
172741bd8510Skcrowenex 
1728faa1795aSjb150015 		DTRACE_PROBE1(so__accept, struct sonode *, s_so);
1729faa1795aSjb150015 
17309fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		on = 1;
17319fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		(void) ksocket_setsockopt(s_so, IPPROTO_TCP, TCP_NODELAY,
17329fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		    &on, sizeof (on), CRED());
17339fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
17349fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		on = 1;
17359fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		(void) ksocket_setsockopt(s_so, SOL_SOCKET, SO_KEEPALIVE,
17369fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		    &on, sizeof (on), CRED());
17379fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
17389fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		txbuf_size = 128*1024;
17390f1702c5SYu Xiangning 		(void) ksocket_setsockopt(s_so, SOL_SOCKET, SO_SNDBUF,
17409fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		    (const void *)&txbuf_size, sizeof (txbuf_size), CRED());
17419fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
1742faa1795aSjb150015 		/*
1743faa1795aSjb150015 		 * Create a session for this connection.
1744faa1795aSjb150015 		 */
17454163af6aSjose borrego 		smb_server_create_session(ld, s_so);
1746faa1795aSjb150015 	}
174741bd8510Skcrowenex out:
17484163af6aSjose borrego 	ksocket_rele(ld->ld_so);
1749faa1795aSjb150015 }
17509fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
17514163af6aSjose borrego /*
17524163af6aSjose borrego  * smb_server_receiver
17534163af6aSjose borrego  *
17544163af6aSjose borrego  * Entry point of the receiver threads.
1755811599a4SMatt Barden  * Also does cleanup when socket disconnected.
17564163af6aSjose borrego  */
17579fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void
17584163af6aSjose borrego smb_server_receiver(void *arg)
17599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
17604163af6aSjose borrego 	smb_session_t	*session;
1761faa1795aSjb150015 
1762811599a4SMatt Barden 	session = (smb_session_t *)arg;
1763811599a4SMatt Barden 
1764811599a4SMatt Barden 	/* We stay in here until socket disconnect. */
17654163af6aSjose borrego 	smb_session_receiver(session);
1766811599a4SMatt Barden 
1767811599a4SMatt Barden 	smb_server_destroy_session(session);
1768faa1795aSjb150015 }
1769faa1795aSjb150015 
1770faa1795aSjb150015 /*
1771faa1795aSjb150015  * smb_server_lookup
1772faa1795aSjb150015  *
17738622ec45SGordon Ross  * This function finds the server associated with the zone of the
17748622ec45SGordon Ross  * caller.  Note: requires a fix in the dynamic taskq code:
17758622ec45SGordon Ross  * 1501 taskq_create_proc ... TQ_DYNAMIC puts tasks in p0
1776faa1795aSjb150015  */
17774846df9bSKevin Crowe int
1778faa1795aSjb150015 smb_server_lookup(smb_server_t **psv)
1779faa1795aSjb150015 {
1780faa1795aSjb150015 	zoneid_t	zid;
1781faa1795aSjb150015 	smb_server_t	*sv;
1782faa1795aSjb150015 
1783faa1795aSjb150015 	zid = getzoneid();
1784faa1795aSjb150015 
1785faa1795aSjb150015 	smb_llist_enter(&smb_servers, RW_READER);
1786faa1795aSjb150015 	sv = smb_llist_head(&smb_servers);
1787faa1795aSjb150015 	while (sv) {
17889fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_SERVER_VALID(sv);
1789faa1795aSjb150015 		if (sv->sv_zid == zid) {
1790faa1795aSjb150015 			mutex_enter(&sv->sv_mutex);
1791faa1795aSjb150015 			if (sv->sv_state != SMB_SERVER_STATE_DELETING) {
1792faa1795aSjb150015 				sv->sv_refcnt++;
1793faa1795aSjb150015 				mutex_exit(&sv->sv_mutex);
1794faa1795aSjb150015 				smb_llist_exit(&smb_servers);
1795faa1795aSjb150015 				*psv = sv;
1796faa1795aSjb150015 				return (0);
1797faa1795aSjb150015 			}
1798faa1795aSjb150015 			mutex_exit(&sv->sv_mutex);
1799faa1795aSjb150015 			break;
1800faa1795aSjb150015 		}
1801faa1795aSjb150015 		sv = smb_llist_next(&smb_servers, sv);
1802faa1795aSjb150015 	}
1803faa1795aSjb150015 	smb_llist_exit(&smb_servers);
1804faa1795aSjb150015 	return (EPERM);
1805faa1795aSjb150015 }
1806faa1795aSjb150015 
1807faa1795aSjb150015 /*
1808faa1795aSjb150015  * smb_server_release
1809faa1795aSjb150015  *
1810faa1795aSjb150015  * This function decrements the reference count of the server and signals its
1811faa1795aSjb150015  * condition variable if the state of the server is SMB_SERVER_STATE_DELETING.
1812faa1795aSjb150015  */
18134846df9bSKevin Crowe void
1814faa1795aSjb150015 smb_server_release(smb_server_t *sv)
1815faa1795aSjb150015 {
18169fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	SMB_SERVER_VALID(sv);
1817faa1795aSjb150015 
1818faa1795aSjb150015 	mutex_enter(&sv->sv_mutex);
1819faa1795aSjb150015 	ASSERT(sv->sv_refcnt);
1820faa1795aSjb150015 	sv->sv_refcnt--;
1821faa1795aSjb150015 	if ((sv->sv_refcnt == 0) && (sv->sv_state == SMB_SERVER_STATE_DELETING))
1822faa1795aSjb150015 		cv_signal(&sv->sv_cv);
1823faa1795aSjb150015 	mutex_exit(&sv->sv_mutex);
1824faa1795aSjb150015 }
1825faa1795aSjb150015 
18261fcced4cSJordan Brown /*
18271fcced4cSJordan Brown  * Enumerate the users associated with a session list.
18281fcced4cSJordan Brown  */
18291fcced4cSJordan Brown static void
18308d94f651SGordon Ross smb_server_enum_users(smb_server_t *sv, smb_svcenum_t *svcenum)
1831faa1795aSjb150015 {
18328d94f651SGordon Ross 	smb_llist_t	*ll = &sv->sv_session_list;
18331fcced4cSJordan Brown 	smb_session_t	*sn;
1834faa1795aSjb150015 	smb_llist_t	*ulist;
18351fcced4cSJordan Brown 	smb_user_t	*user;
183629bd2886SAlan Wright 	int		rc = 0;
1837faa1795aSjb150015 
18384163af6aSjose borrego 	smb_llist_enter(ll, RW_READER);
18394163af6aSjose borrego 	sn = smb_llist_head(ll);
18401fcced4cSJordan Brown 
18411fcced4cSJordan Brown 	while (sn != NULL) {
18424163af6aSjose borrego 		SMB_SESSION_VALID(sn);
1843faa1795aSjb150015 		ulist = &sn->s_user_list;
1844faa1795aSjb150015 		smb_llist_enter(ulist, RW_READER);
1845faa1795aSjb150015 		user = smb_llist_head(ulist);
18461fcced4cSJordan Brown 
18471fcced4cSJordan Brown 		while (user != NULL) {
18481fcced4cSJordan Brown 			if (smb_user_hold(user)) {
18491fcced4cSJordan Brown 				rc = smb_user_enum(user, svcenum);
18501fcced4cSJordan Brown 				smb_user_release(user);
18513b13a1efSThomas Keiser 				if (rc != 0)
18523b13a1efSThomas Keiser 					break;
1853faa1795aSjb150015 			}
18541fcced4cSJordan Brown 
1855faa1795aSjb150015 			user = smb_llist_next(ulist, user);
1856faa1795aSjb150015 		}
18571fcced4cSJordan Brown 
18581fcced4cSJordan Brown 		smb_llist_exit(ulist);
18591fcced4cSJordan Brown 
18601fcced4cSJordan Brown 		if (rc != 0)
18611fcced4cSJordan Brown 			break;
18621fcced4cSJordan Brown 
18634163af6aSjose borrego 		sn = smb_llist_next(ll, sn);
18641fcced4cSJordan Brown 	}
18651fcced4cSJordan Brown 
18664163af6aSjose borrego 	smb_llist_exit(ll);
18671fcced4cSJordan Brown }
18681fcced4cSJordan Brown 
18691fcced4cSJordan Brown /*
18703b13a1efSThomas Keiser  * Enumerate the trees/files associated with a session list.
18713b13a1efSThomas Keiser  */
18723b13a1efSThomas Keiser static void
18738d94f651SGordon Ross smb_server_enum_trees(smb_server_t *sv, smb_svcenum_t *svcenum)
18743b13a1efSThomas Keiser {
18758d94f651SGordon Ross 	smb_llist_t	*ll = &sv->sv_session_list;
18763b13a1efSThomas Keiser 	smb_session_t	*sn;
18773b13a1efSThomas Keiser 	smb_llist_t	*tlist;
18783b13a1efSThomas Keiser 	smb_tree_t	*tree;
18793b13a1efSThomas Keiser 	int		rc = 0;
18803b13a1efSThomas Keiser 
18813b13a1efSThomas Keiser 	smb_llist_enter(ll, RW_READER);
18823b13a1efSThomas Keiser 	sn = smb_llist_head(ll);
18833b13a1efSThomas Keiser 
18843b13a1efSThomas Keiser 	while (sn != NULL) {
18853b13a1efSThomas Keiser 		SMB_SESSION_VALID(sn);
18863b13a1efSThomas Keiser 		tlist = &sn->s_tree_list;
18873b13a1efSThomas Keiser 		smb_llist_enter(tlist, RW_READER);
18883b13a1efSThomas Keiser 		tree = smb_llist_head(tlist);
18893b13a1efSThomas Keiser 
18903b13a1efSThomas Keiser 		while (tree != NULL) {
18913b13a1efSThomas Keiser 			if (smb_tree_hold(tree)) {
18923b13a1efSThomas Keiser 				rc = smb_tree_enum(tree, svcenum);
18933b13a1efSThomas Keiser 				smb_tree_release(tree);
18943b13a1efSThomas Keiser 				if (rc != 0)
18953b13a1efSThomas Keiser 					break;
18963b13a1efSThomas Keiser 			}
18973b13a1efSThomas Keiser 
18983b13a1efSThomas Keiser 			tree = smb_llist_next(tlist, tree);
18993b13a1efSThomas Keiser 		}
19003b13a1efSThomas Keiser 
19013b13a1efSThomas Keiser 		smb_llist_exit(tlist);
19023b13a1efSThomas Keiser 
19033b13a1efSThomas Keiser 		if (rc != 0)
19043b13a1efSThomas Keiser 			break;
19053b13a1efSThomas Keiser 
19063b13a1efSThomas Keiser 		sn = smb_llist_next(ll, sn);
19073b13a1efSThomas Keiser 	}
19083b13a1efSThomas Keiser 
19093b13a1efSThomas Keiser 	smb_llist_exit(ll);
19103b13a1efSThomas Keiser }
19113b13a1efSThomas Keiser 
19123b13a1efSThomas Keiser /*
19131fcced4cSJordan Brown  * Disconnect sessions associated with the specified client and username.
19141fcced4cSJordan Brown  * Empty strings are treated as wildcards.
19151fcced4cSJordan Brown  */
19161fcced4cSJordan Brown static int
19178d94f651SGordon Ross smb_server_session_disconnect(smb_server_t *sv,
19181fcced4cSJordan Brown     const char *client, const char *name)
19191fcced4cSJordan Brown {
19208d94f651SGordon Ross 	smb_llist_t	*ll = &sv->sv_session_list;
19211fcced4cSJordan Brown 	smb_session_t	*sn;
19221fcced4cSJordan Brown 	smb_llist_t	*ulist;
19231fcced4cSJordan Brown 	smb_user_t	*user;
19241fcced4cSJordan Brown 	int		count = 0;
19251fcced4cSJordan Brown 
19264163af6aSjose borrego 	smb_llist_enter(ll, RW_READER);
19271fcced4cSJordan Brown 
1928811599a4SMatt Barden 	for (sn = smb_llist_head(ll);
1929811599a4SMatt Barden 	    sn != NULL;
1930811599a4SMatt Barden 	    sn = smb_llist_next(ll, sn)) {
19314163af6aSjose borrego 		SMB_SESSION_VALID(sn);
19321fcced4cSJordan Brown 
1933811599a4SMatt Barden 		if (*client != '\0' && !smb_session_isclient(sn, client))
19341fcced4cSJordan Brown 			continue;
19351fcced4cSJordan Brown 
19361fcced4cSJordan Brown 		ulist = &sn->s_user_list;
19371fcced4cSJordan Brown 		smb_llist_enter(ulist, RW_READER);
19381fcced4cSJordan Brown 
1939811599a4SMatt Barden 		for (user = smb_llist_head(ulist);
1940811599a4SMatt Barden 		    user != NULL;
1941811599a4SMatt Barden 		    user = smb_llist_next(ulist, user)) {
19421fcced4cSJordan Brown 
1943811599a4SMatt Barden 			if (smb_user_hold(user)) {
1944896d9552SGordon Ross 
1945896d9552SGordon Ross 				if (*name == '\0' ||
1946896d9552SGordon Ross 				    smb_user_namecmp(user, name)) {
1947811599a4SMatt Barden 					smb_user_logoff(user);
1948811599a4SMatt Barden 					count++;
19491fcced4cSJordan Brown 				}
1950896d9552SGordon Ross 
1951896d9552SGordon Ross 				smb_user_release(user);
1952896d9552SGordon Ross 			}
19531fcced4cSJordan Brown 		}
19541fcced4cSJordan Brown 
1955faa1795aSjb150015 		smb_llist_exit(ulist);
1956faa1795aSjb150015 	}
19571fcced4cSJordan Brown 
19584163af6aSjose borrego 	smb_llist_exit(ll);
19591fcced4cSJordan Brown 	return (count);
19601fcced4cSJordan Brown }
19611fcced4cSJordan Brown 
19621fcced4cSJordan Brown /*
19631fcced4cSJordan Brown  * Close a file by its unique id.
19641fcced4cSJordan Brown  */
19651fcced4cSJordan Brown static int
19668d94f651SGordon Ross smb_server_fclose(smb_server_t *sv, uint32_t uniqid)
19671fcced4cSJordan Brown {
19688d94f651SGordon Ross 	smb_llist_t	*ll;
19691fcced4cSJordan Brown 	smb_session_t	*sn;
19703b13a1efSThomas Keiser 	smb_llist_t	*tlist;
19713b13a1efSThomas Keiser 	smb_tree_t	*tree;
19721fcced4cSJordan Brown 	int		rc = ENOENT;
19731fcced4cSJordan Brown 
19748d94f651SGordon Ross 	ll = &sv->sv_session_list;
19754163af6aSjose borrego 	smb_llist_enter(ll, RW_READER);
19764163af6aSjose borrego 	sn = smb_llist_head(ll);
19771fcced4cSJordan Brown 
19781fcced4cSJordan Brown 	while ((sn != NULL) && (rc == ENOENT)) {
19794163af6aSjose borrego 		SMB_SESSION_VALID(sn);
19803b13a1efSThomas Keiser 		tlist = &sn->s_tree_list;
19813b13a1efSThomas Keiser 		smb_llist_enter(tlist, RW_READER);
19823b13a1efSThomas Keiser 		tree = smb_llist_head(tlist);
19831fcced4cSJordan Brown 
19843b13a1efSThomas Keiser 		while ((tree != NULL) && (rc == ENOENT)) {
19853b13a1efSThomas Keiser 			if (smb_tree_hold(tree)) {
19863b13a1efSThomas Keiser 				rc = smb_tree_fclose(tree, uniqid);
19873b13a1efSThomas Keiser 				smb_tree_release(tree);
19881fcced4cSJordan Brown 			}
19891fcced4cSJordan Brown 
19903b13a1efSThomas Keiser 			tree = smb_llist_next(tlist, tree);
19911fcced4cSJordan Brown 		}
19921fcced4cSJordan Brown 
19933b13a1efSThomas Keiser 		smb_llist_exit(tlist);
19944163af6aSjose borrego 		sn = smb_llist_next(ll, sn);
19951fcced4cSJordan Brown 	}
19961fcced4cSJordan Brown 
19974163af6aSjose borrego 	smb_llist_exit(ll);
19981fcced4cSJordan Brown 	return (rc);
1999faa1795aSjb150015 }
2000faa1795aSjb150015 
2001811599a4SMatt Barden /*
2002811599a4SMatt Barden  * This is used by SMB2 session setup to logoff a previous session,
2003811599a4SMatt Barden  * so it can force a logoff that we haven't noticed yet.
2004811599a4SMatt Barden  * This is not called frequently, so we just walk the list of
2005811599a4SMatt Barden  * connections searching for the user.
20061baeef30SPrashanth Badari  *
20071baeef30SPrashanth Badari  * Note that this must wait for any durable handles (ofiles)
20081baeef30SPrashanth Badari  * owned by this user to become "orphaned", so that a reconnect
20091baeef30SPrashanth Badari  * that may immediately follow can find and use such ofiles.
2010811599a4SMatt Barden  */
2011811599a4SMatt Barden void
2012811599a4SMatt Barden smb_server_logoff_ssnid(smb_request_t *sr, uint64_t ssnid)
2013811599a4SMatt Barden {
2014811599a4SMatt Barden 	smb_server_t	*sv = sr->sr_server;
2015811599a4SMatt Barden 	smb_llist_t	*sess_list;
2016811599a4SMatt Barden 	smb_session_t	*sess;
20171baeef30SPrashanth Badari 	smb_user_t	*user = NULL;
20181baeef30SPrashanth Badari 
20191baeef30SPrashanth Badari 	SMB_SERVER_VALID(sv);
2020811599a4SMatt Barden 
2021811599a4SMatt Barden 	if (sv->sv_state != SMB_SERVER_STATE_RUNNING)
2022811599a4SMatt Barden 		return;
2023811599a4SMatt Barden 
2024811599a4SMatt Barden 	sess_list = &sv->sv_session_list;
2025811599a4SMatt Barden 	smb_llist_enter(sess_list, RW_READER);
2026811599a4SMatt Barden 
2027811599a4SMatt Barden 	for (sess = smb_llist_head(sess_list);
2028811599a4SMatt Barden 	    sess != NULL;
2029811599a4SMatt Barden 	    sess = smb_llist_next(sess_list, sess)) {
2030811599a4SMatt Barden 
2031811599a4SMatt Barden 		SMB_SESSION_VALID(sess);
2032811599a4SMatt Barden 
2033811599a4SMatt Barden 		if (sess->dialect < SMB_VERS_2_BASE)
2034811599a4SMatt Barden 			continue;
2035811599a4SMatt Barden 
20361baeef30SPrashanth Badari 		switch (sess->s_state) {
20371baeef30SPrashanth Badari 		case SMB_SESSION_STATE_NEGOTIATED:
20381baeef30SPrashanth Badari 		case SMB_SESSION_STATE_TERMINATED:
20391baeef30SPrashanth Badari 		case SMB_SESSION_STATE_DISCONNECTED:
20401baeef30SPrashanth Badari 			break;
20411baeef30SPrashanth Badari 		default:
2042811599a4SMatt Barden 			continue;
2043811599a4SMatt Barden 		}
2044811599a4SMatt Barden 
20451baeef30SPrashanth Badari 		/*
20461baeef30SPrashanth Badari 		 * Normal situation is to find a LOGGED_ON user.
20471baeef30SPrashanth Badari 		 */
20481baeef30SPrashanth Badari 		user = smb_session_lookup_uid_st(sess, ssnid, 0,
20491baeef30SPrashanth Badari 		    SMB_USER_STATE_LOGGED_ON);
20501baeef30SPrashanth Badari 		if (user != NULL) {
20511baeef30SPrashanth Badari 
20521baeef30SPrashanth Badari 			if (smb_is_same_user(user->u_cred, sr->user_cr)) {
2053811599a4SMatt Barden 				/* Treat this as if we lost the connection */
2054811599a4SMatt Barden 				user->preserve_opens = SMB2_DH_PRESERVE_SOME;
2055811599a4SMatt Barden 				smb_user_logoff(user);
20561baeef30SPrashanth Badari 				break;
20571baeef30SPrashanth Badari 			}
2058811599a4SMatt Barden 			smb_user_release(user);
20591baeef30SPrashanth Badari 			user = NULL;
20601baeef30SPrashanth Badari 		}
2061811599a4SMatt Barden 
2062811599a4SMatt Barden 		/*
20631baeef30SPrashanth Badari 		 * If we raced with disconnect, may find LOGGING_OFF,
20641baeef30SPrashanth Badari 		 * in which case we want to just wait for it.
2065811599a4SMatt Barden 		 */
20661baeef30SPrashanth Badari 		user = smb_session_lookup_uid_st(sess, ssnid, 0,
20671baeef30SPrashanth Badari 		    SMB_USER_STATE_LOGGING_OFF);
20681baeef30SPrashanth Badari 		if (user != NULL) {
20691baeef30SPrashanth Badari 			if (smb_is_same_user(user->u_cred, sr->user_cr))
20701baeef30SPrashanth Badari 				break;
20711baeef30SPrashanth Badari 			smb_user_release(user);
20721baeef30SPrashanth Badari 			user = NULL;
20731baeef30SPrashanth Badari 		}
2074811599a4SMatt Barden 	}
2075811599a4SMatt Barden 
2076811599a4SMatt Barden 	smb_llist_exit(sess_list);
20771baeef30SPrashanth Badari 
20781baeef30SPrashanth Badari 	if (user != NULL) {
20791baeef30SPrashanth Badari 		/*
20801baeef30SPrashanth Badari 		 * Wait for durable handles to be orphaned.
20811baeef30SPrashanth Badari 		 * Note: not holding the sess list rwlock.
20821baeef30SPrashanth Badari 		 */
20831baeef30SPrashanth Badari 		smb_user_wait_trees(user);
20841baeef30SPrashanth Badari 
20851baeef30SPrashanth Badari 		/*
20861baeef30SPrashanth Badari 		 * Could be doing the last release on a user below,
20871baeef30SPrashanth Badari 		 * which can leave work on the delete queues for
20881baeef30SPrashanth Badari 		 * s_user_list or s_tree_list so flush those.
20891baeef30SPrashanth Badari 		 * Must hold the session list after the user release
20901baeef30SPrashanth Badari 		 * so that the session can't go away while we flush.
20911baeef30SPrashanth Badari 		 */
20921baeef30SPrashanth Badari 		smb_llist_enter(sess_list, RW_READER);
20931baeef30SPrashanth Badari 
20941baeef30SPrashanth Badari 		sess = user->u_session;
20951baeef30SPrashanth Badari 		smb_user_release(user);
20961baeef30SPrashanth Badari 
20971baeef30SPrashanth Badari 		smb_llist_flush(&sess->s_tree_list);
20981baeef30SPrashanth Badari 		smb_llist_flush(&sess->s_user_list);
20991baeef30SPrashanth Badari 
21001baeef30SPrashanth Badari 		smb_llist_exit(sess_list);
21011baeef30SPrashanth Badari 	}
2102811599a4SMatt Barden }
2103811599a4SMatt Barden 
210412b65585SGordon Ross /* See also: libsmb smb_kmod_setcfg */
2105faa1795aSjb150015 static void
210629bd2886SAlan Wright smb_server_store_cfg(smb_server_t *sv, smb_ioc_cfg_t *ioc)
2107faa1795aSjb150015 {
210829bd2886SAlan Wright 	if (ioc->maxconnections == 0)
210929bd2886SAlan Wright 		ioc->maxconnections = 0xFFFFFFFF;
2110faa1795aSjb150015 
21111160dcf7SMatt Barden 	if (ioc->encrypt == SMB_CONFIG_REQUIRED &&
21121160dcf7SMatt Barden 	    ioc->max_protocol < SMB_VERS_3_0) {
21131160dcf7SMatt Barden 		cmn_err(CE_WARN, "Server set to require encryption; "
21141160dcf7SMatt Barden 		    "forcing max_protocol to 3.0");
21151160dcf7SMatt Barden 		ioc->max_protocol = SMB_VERS_3_0;
21161160dcf7SMatt Barden 	}
21171160dcf7SMatt Barden 
211829bd2886SAlan Wright 	sv->sv_cfg.skc_maxworkers = ioc->maxworkers;
211929bd2886SAlan Wright 	sv->sv_cfg.skc_maxconnections = ioc->maxconnections;
212029bd2886SAlan Wright 	sv->sv_cfg.skc_keepalive = ioc->keepalive;
212129bd2886SAlan Wright 	sv->sv_cfg.skc_restrict_anon = ioc->restrict_anon;
212229bd2886SAlan Wright 	sv->sv_cfg.skc_signing_enable = ioc->signing_enable;
212329bd2886SAlan Wright 	sv->sv_cfg.skc_signing_required = ioc->signing_required;
212429bd2886SAlan Wright 	sv->sv_cfg.skc_oplock_enable = ioc->oplock_enable;
212529bd2886SAlan Wright 	sv->sv_cfg.skc_sync_enable = ioc->sync_enable;
212629bd2886SAlan Wright 	sv->sv_cfg.skc_secmode = ioc->secmode;
212712b65585SGordon Ross 	sv->sv_cfg.skc_netbios_enable = ioc->netbios_enable;
212829bd2886SAlan Wright 	sv->sv_cfg.skc_ipv6_enable = ioc->ipv6_enable;
2129cb174861Sjoyce mcintosh 	sv->sv_cfg.skc_print_enable = ioc->print_enable;
21305f1ef25cSAram Hăvărneanu 	sv->sv_cfg.skc_traverse_mounts = ioc->traverse_mounts;
2131814e0daaSGordon Ross 	sv->sv_cfg.skc_short_names = ioc->short_names;
2132a90cf9f2SGordon Ross 	sv->sv_cfg.skc_max_protocol = ioc->max_protocol;
21333e2c0c09SMatt Barden 	sv->sv_cfg.skc_min_protocol = ioc->min_protocol;
21341160dcf7SMatt Barden 	sv->sv_cfg.skc_encrypt = ioc->encrypt;
21354e065a9fSAlexander Stetsenko 	sv->sv_cfg.skc_encrypt_cipher = ioc->encrypt_cipher;
2136148c5f43SAlan Wright 	sv->sv_cfg.skc_execflags = ioc->exec_flags;
213712b65585SGordon Ross 	sv->sv_cfg.skc_negtok_len = ioc->negtok_len;
2138148c5f43SAlan Wright 	sv->sv_cfg.skc_version = ioc->version;
2139a90cf9f2SGordon Ross 	sv->sv_cfg.skc_initial_credits = ioc->initial_credits;
2140a90cf9f2SGordon Ross 	sv->sv_cfg.skc_maximum_credits = ioc->maximum_credits;
2141a90cf9f2SGordon Ross 
214212b65585SGordon Ross 	(void) memcpy(sv->sv_cfg.skc_machine_uuid, ioc->machine_uuid,
214312b65585SGordon Ross 	    sizeof (uuid_t));
214412b65585SGordon Ross 	(void) memcpy(sv->sv_cfg.skc_negtok, ioc->negtok,
214512b65585SGordon Ross 	    sizeof (sv->sv_cfg.skc_negtok));
214612b65585SGordon Ross 	(void) memcpy(sv->sv_cfg.skc_native_os, ioc->native_os,
214712b65585SGordon Ross 	    sizeof (sv->sv_cfg.skc_native_os));
214812b65585SGordon Ross 	(void) memcpy(sv->sv_cfg.skc_native_lm, ioc->native_lm,
214912b65585SGordon Ross 	    sizeof (sv->sv_cfg.skc_native_lm));
215012b65585SGordon Ross 
215129bd2886SAlan Wright 	(void) strlcpy(sv->sv_cfg.skc_nbdomain, ioc->nbdomain,
215229bd2886SAlan Wright 	    sizeof (sv->sv_cfg.skc_nbdomain));
215329bd2886SAlan Wright 	(void) strlcpy(sv->sv_cfg.skc_fqdn, ioc->fqdn,
215429bd2886SAlan Wright 	    sizeof (sv->sv_cfg.skc_fqdn));
215529bd2886SAlan Wright 	(void) strlcpy(sv->sv_cfg.skc_hostname, ioc->hostname,
215629bd2886SAlan Wright 	    sizeof (sv->sv_cfg.skc_hostname));
215729bd2886SAlan Wright 	(void) strlcpy(sv->sv_cfg.skc_system_comment, ioc->system_comment,
215829bd2886SAlan Wright 	    sizeof (sv->sv_cfg.skc_system_comment));
2159faa1795aSjb150015 }
2160faa1795aSjb150015 
2161faa1795aSjb150015 static int
2162faa1795aSjb150015 smb_server_fsop_start(smb_server_t *sv)
2163faa1795aSjb150015 {
2164faa1795aSjb150015 	int	error;
2165faa1795aSjb150015 
21668622ec45SGordon Ross 	error = smb_node_root_init(sv, &sv->si_root_smb_node);
2167faa1795aSjb150015 	if (error != 0)
2168faa1795aSjb150015 		sv->si_root_smb_node = NULL;
2169faa1795aSjb150015 
2170faa1795aSjb150015 	return (error);
2171faa1795aSjb150015 }
2172faa1795aSjb150015 
2173faa1795aSjb150015 static void
2174faa1795aSjb150015 smb_server_fsop_stop(smb_server_t *sv)
2175faa1795aSjb150015 {
2176faa1795aSjb150015 	if (sv->si_root_smb_node != NULL) {
2177faa1795aSjb150015 		smb_node_release(sv->si_root_smb_node);
2178faa1795aSjb150015 		sv->si_root_smb_node = NULL;
2179faa1795aSjb150015 	}
2180faa1795aSjb150015 }
21819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
21829fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_event_t *
21838622ec45SGordon Ross smb_event_create(smb_server_t *sv, int timeout)
21849fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
21859fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_event_t	*event;
21869fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
21878622ec45SGordon Ross 	if (smb_server_is_stopping(sv))
21889fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (NULL);
21899fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
21908622ec45SGordon Ross 	event = kmem_cache_alloc(smb_cache_event, KM_SLEEP);
21919fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
21929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	bzero(event, sizeof (smb_event_t));
21939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_init(&event->se_mutex, NULL, MUTEX_DEFAULT, NULL);
21949fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	cv_init(&event->se_cv, NULL, CV_DEFAULT, NULL);
21959fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event->se_magic = SMB_EVENT_MAGIC;
21969fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event->se_txid = smb_event_alloc_txid();
21979fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event->se_server = sv;
2198cb174861Sjoyce mcintosh 	event->se_timeout = timeout;
21999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
22009fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_enter(&sv->sv_event_list, RW_WRITER);
22019fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_insert_tail(&sv->sv_event_list, event);
22029fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_exit(&sv->sv_event_list);
22039fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
22049fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	return (event);
22059fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
22069fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
22079fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States void
22089fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_event_destroy(smb_event_t *event)
22099fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
22109fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_server_t	*sv;
22119fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
22129fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (event == NULL)
22139fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return;
22149fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
22159fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	SMB_EVENT_VALID(event);
22169fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	ASSERT(event->se_waittime == 0);
22178622ec45SGordon Ross 	sv = event->se_server;
22188622ec45SGordon Ross 	SMB_SERVER_VALID(sv);
22199fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
22209fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_enter(&sv->sv_event_list, RW_WRITER);
22219fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_remove(&sv->sv_event_list, event);
22229fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_exit(&sv->sv_event_list);
22239fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
22249fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event->se_magic = (uint32_t)~SMB_EVENT_MAGIC;
22259fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	cv_destroy(&event->se_cv);
22269fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_destroy(&event->se_mutex);
22279fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
22288622ec45SGordon Ross 	kmem_cache_free(smb_cache_event, event);
22299fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
22309fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
22319fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
22329fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Get the txid for the specified event.
22339fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  */
22349fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States uint32_t
22359fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_event_txid(smb_event_t *event)
22369fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
22379fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (event != NULL) {
22389fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_EVENT_VALID(event);
22399fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (event->se_txid);
22409fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
22419fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
22429fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	cmn_err(CE_NOTE, "smb_event_txid failed");
22439fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	return ((uint32_t)-1);
22449fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
22459fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
22469fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
22479fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Wait for event notification.
22489fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  */
22499fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States int
22509fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_event_wait(smb_event_t *event)
22519fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
22529fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	int	seconds = 1;
22539fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	int	ticks;
2254856399cfSGordon Ross 	int	err;
22559fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
22569fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (event == NULL)
22579fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (EINVAL);
22589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
22599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	SMB_EVENT_VALID(event);
22609fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
22619fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_enter(&event->se_mutex);
22629fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event->se_waittime = 1;
22639fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event->se_errno = 0;
22649fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
22659fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	while (!(event->se_notified)) {
2266c5866007SKeyur Desai 		if (smb_event_debug && ((event->se_waittime % 30) == 0))
22679fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			cmn_err(CE_NOTE, "smb_event_wait[%d] (%d sec)",
22689fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			    event->se_txid, event->se_waittime);
22699fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
22709fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		if (event->se_errno != 0)
22719fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			break;
22729fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
2273cb174861Sjoyce mcintosh 		if (event->se_waittime > event->se_timeout) {
22749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			event->se_errno = ETIME;
22759fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			break;
22769fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		}
22779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
22789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		ticks = SEC_TO_TICK(seconds);
22799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		(void) cv_reltimedwait(&event->se_cv,
22809fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		    &event->se_mutex, (clock_t)ticks, TR_CLOCK_TICK);
22819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		++event->se_waittime;
22829fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
22839fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
2284856399cfSGordon Ross 	err = event->se_errno;
22859fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event->se_waittime = 0;
22869fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event->se_notified = B_FALSE;
22879fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	cv_signal(&event->se_cv);
22889fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_exit(&event->se_mutex);
2289856399cfSGordon Ross 	return (err);
22909fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
22919fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
22929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
22939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * If txid is non-zero, cancel the specified event.
22949fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Otherwise, cancel all events.
22959fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  */
22969fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void
22979fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_event_cancel(smb_server_t *sv, uint32_t txid)
22989fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
22999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_event_t	*event;
23009fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_t	*event_list;
23019fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
23029fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	SMB_SERVER_VALID(sv);
23039fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
23049fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event_list = &sv->sv_event_list;
23059fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_enter(event_list, RW_WRITER);
23069fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
23079fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event = smb_llist_head(event_list);
23089fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	while (event) {
23099fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_EVENT_VALID(event);
23109fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
23119fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		if (txid == 0 || event->se_txid == txid) {
23129fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			mutex_enter(&event->se_mutex);
23139fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			event->se_errno = ECANCELED;
23149fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			event->se_notified = B_TRUE;
23159fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			cv_signal(&event->se_cv);
23169fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			mutex_exit(&event->se_mutex);
23179fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
23189fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			if (txid != 0)
23199fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 				break;
23209fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		}
23219fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
23229fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		event = smb_llist_next(event_list, event);
23239fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
23249fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
23259fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_exit(event_list);
23269fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
23279fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
23289fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
23299fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * If txid is non-zero, notify the specified event.
23309fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Otherwise, notify all events.
23319fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  */
2332cb174861Sjoyce mcintosh void
23339fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_event_notify(smb_server_t *sv, uint32_t txid)
23349fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
23359fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_event_t	*event;
23369fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_t	*event_list;
23379fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
23389fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	SMB_SERVER_VALID(sv);
23399fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
23409fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event_list = &sv->sv_event_list;
23419fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_enter(event_list, RW_READER);
23429fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
23439fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	event = smb_llist_head(event_list);
23449fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	while (event) {
23459fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		SMB_EVENT_VALID(event);
23469fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
23479fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		if (txid == 0 || event->se_txid == txid) {
23489fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			mutex_enter(&event->se_mutex);
23499fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			event->se_notified = B_TRUE;
23509fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			cv_signal(&event->se_cv);
23519fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			mutex_exit(&event->se_mutex);
23529fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
23539fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			if (txid != 0)
23549fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 				break;
23559fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		}
23569fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
23579fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		event = smb_llist_next(event_list, event);
23589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
23599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
23609fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_llist_exit(event_list);
23619fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
23629fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
23639fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
23649fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Allocate a new transaction id (txid).
23659fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  *
23669fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * 0 or -1 are not assigned because they are used to detect invalid
23679fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * conditions or to indicate all open id's.
23689fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  */
23699fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static uint32_t
23709fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_event_alloc_txid(void)
23719fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
23729fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	static kmutex_t	txmutex;
23739fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	static uint32_t	txid;
23749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	uint32_t	txid_ret;
23759fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
23769fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_enter(&txmutex);
23779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
23789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (txid == 0)
23799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		txid = ddi_get_lbolt() << 11;
23809fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
23819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	do {
23829fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		++txid;
23839fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	} while (txid == 0 || txid == (uint32_t)-1);
23849fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
23859fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	txid_ret = txid;
23869fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_exit(&txmutex);
23879fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
23889fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	return (txid_ret);
23899fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
2390cb174861Sjoyce mcintosh 
2391cb174861Sjoyce mcintosh /*
2392cb174861Sjoyce mcintosh  * Called by the ioctl to find the corresponding
2393cb174861Sjoyce mcintosh  * spooldoc node.  removes node on success
2394cb174861Sjoyce mcintosh  *
2395cb174861Sjoyce mcintosh  * Return values
2396cb174861Sjoyce mcintosh  * rc
2397cb174861Sjoyce mcintosh  * B_FALSE - not found
2398cb174861Sjoyce mcintosh  * B_TRUE  - found
2399cb174861Sjoyce mcintosh  *
2400cb174861Sjoyce mcintosh  */
2401cb174861Sjoyce mcintosh 
240223a9c295SGordon Ross static boolean_t
240323a9c295SGordon Ross smb_spool_lookup_doc_byfid(smb_server_t *sv, uint16_t fid,
240423a9c295SGordon Ross     smb_kspooldoc_t *spdoc)
2405cb174861Sjoyce mcintosh {
2406cb174861Sjoyce mcintosh 	smb_kspooldoc_t *sp;
2407cb174861Sjoyce mcintosh 	smb_llist_t	*splist;
2408cb174861Sjoyce mcintosh 
2409cb174861Sjoyce mcintosh 	splist = &sv->sp_info.sp_list;
2410cb174861Sjoyce mcintosh 	smb_llist_enter(splist, RW_WRITER);
2411cb174861Sjoyce mcintosh 	sp = smb_llist_head(splist);
2412cb174861Sjoyce mcintosh 	while (sp != NULL) {
2413cb174861Sjoyce mcintosh 		/*
2414cb174861Sjoyce mcintosh 		 * check for a matching fid
2415cb174861Sjoyce mcintosh 		 */
2416cb174861Sjoyce mcintosh 		if (sp->sd_fid == fid) {
2417cb174861Sjoyce mcintosh 			*spdoc = *sp;
2418cb174861Sjoyce mcintosh 			smb_llist_remove(splist, sp);
2419cb174861Sjoyce mcintosh 			smb_llist_exit(splist);
2420cb174861Sjoyce mcintosh 			kmem_free(sp, sizeof (smb_kspooldoc_t));
2421cb174861Sjoyce mcintosh 			return (B_TRUE);
2422cb174861Sjoyce mcintosh 		}
2423cb174861Sjoyce mcintosh 		sp = smb_llist_next(splist, sp);
2424cb174861Sjoyce mcintosh 	}
2425cb174861Sjoyce mcintosh 	cmn_err(CE_WARN, "smb_spool_lookup_user_byfid: no fid:%d", fid);
2426cb174861Sjoyce mcintosh 	smb_llist_exit(splist);
2427cb174861Sjoyce mcintosh 	return (B_FALSE);
2428cb174861Sjoyce mcintosh }
2429cb174861Sjoyce mcintosh 
2430cb174861Sjoyce mcintosh /*
2431cb174861Sjoyce mcintosh  * Adds the spool fid to a linked list to be used
2432cb174861Sjoyce mcintosh  * as a search key in the spooldoc queue
2433cb174861Sjoyce mcintosh  *
2434cb174861Sjoyce mcintosh  * Return values
2435cb174861Sjoyce mcintosh  *      rc non-zero error
2436cb174861Sjoyce mcintosh  *	rc zero success
2437cb174861Sjoyce mcintosh  *
2438cb174861Sjoyce mcintosh  */
2439cb174861Sjoyce mcintosh 
244086d7016bSGordon Ross void
244186d7016bSGordon Ross smb_spool_add_fid(smb_server_t *sv, uint16_t fid)
2442cb174861Sjoyce mcintosh {
2443cb174861Sjoyce mcintosh 	smb_llist_t	*fidlist;
2444cb174861Sjoyce mcintosh 	smb_spoolfid_t  *sf;
2445cb174861Sjoyce mcintosh 
244686d7016bSGordon Ross 	if (sv->sv_cfg.skc_print_enable == 0)
244786d7016bSGordon Ross 		return;
2448cb174861Sjoyce mcintosh 
2449cb174861Sjoyce mcintosh 	sf = kmem_zalloc(sizeof (smb_spoolfid_t), KM_SLEEP);
2450cb174861Sjoyce mcintosh 	fidlist = &sv->sp_info.sp_fidlist;
2451cb174861Sjoyce mcintosh 	smb_llist_enter(fidlist, RW_WRITER);
2452cb174861Sjoyce mcintosh 	sf->sf_fid = fid;
2453cb174861Sjoyce mcintosh 	smb_llist_insert_tail(fidlist, sf);
2454cb174861Sjoyce mcintosh 	smb_llist_exit(fidlist);
245586d7016bSGordon Ross 	cv_broadcast(&sv->sp_info.sp_cv);
2456cb174861Sjoyce mcintosh }
2457cb174861Sjoyce mcintosh 
2458cb174861Sjoyce mcintosh /*
2459cb174861Sjoyce mcintosh  * Called by the ioctl to get and remove the head of the fid list
2460cb174861Sjoyce mcintosh  *
2461cb174861Sjoyce mcintosh  * Return values
2462cb174861Sjoyce mcintosh  * int fd
2463cb174861Sjoyce mcintosh  * greater than 0 success
2464cb174861Sjoyce mcintosh  * 0 - error
2465cb174861Sjoyce mcintosh  *
2466cb174861Sjoyce mcintosh  */
2467cb174861Sjoyce mcintosh 
246823a9c295SGordon Ross static uint16_t
246923a9c295SGordon Ross smb_spool_get_fid(smb_server_t *sv)
2470cb174861Sjoyce mcintosh {
2471cb174861Sjoyce mcintosh 	smb_spoolfid_t	*spfid;
2472cb174861Sjoyce mcintosh 	smb_llist_t	*splist;
2473cb174861Sjoyce mcintosh 	uint16_t	fid;
2474cb174861Sjoyce mcintosh 
2475cb174861Sjoyce mcintosh 	splist = &sv->sp_info.sp_fidlist;
2476cb174861Sjoyce mcintosh 	smb_llist_enter(splist, RW_WRITER);
2477cb174861Sjoyce mcintosh 	spfid = smb_llist_head(splist);
2478cb174861Sjoyce mcintosh 	if (spfid != NULL) {
2479cb174861Sjoyce mcintosh 		fid = spfid->sf_fid;
2480cb174861Sjoyce mcintosh 		smb_llist_remove(&sv->sp_info.sp_fidlist, spfid);
2481cb174861Sjoyce mcintosh 		kmem_free(spfid, sizeof (smb_spoolfid_t));
2482cb174861Sjoyce mcintosh 	} else {
2483cb174861Sjoyce mcintosh 		fid = 0;
2484cb174861Sjoyce mcintosh 	}
2485cb174861Sjoyce mcintosh 	smb_llist_exit(splist);
2486cb174861Sjoyce mcintosh 	return (fid);
2487cb174861Sjoyce mcintosh }
2488cb174861Sjoyce mcintosh 
2489cb174861Sjoyce mcintosh /*
2490cb174861Sjoyce mcintosh  * Adds the spooldoc to the tail of the spooldoc list
2491cb174861Sjoyce mcintosh  *
2492cb174861Sjoyce mcintosh  * Return values
2493cb174861Sjoyce mcintosh  *      rc non-zero error
2494cb174861Sjoyce mcintosh  *	rc zero success
2495cb174861Sjoyce mcintosh  */
2496cb174861Sjoyce mcintosh int
24978622ec45SGordon Ross smb_spool_add_doc(smb_tree_t *tree, smb_kspooldoc_t *sp)
2498cb174861Sjoyce mcintosh {
2499cb174861Sjoyce mcintosh 	smb_llist_t	*splist;
25008622ec45SGordon Ross 	smb_server_t	*sv = tree->t_server;
2501cb174861Sjoyce mcintosh 	int rc = 0;
2502cb174861Sjoyce mcintosh 
2503cb174861Sjoyce mcintosh 	splist = &sv->sp_info.sp_list;
2504cb174861Sjoyce mcintosh 	smb_llist_enter(splist, RW_WRITER);
250523a9c295SGordon Ross 	sp->sd_spool_num = atomic_inc_32_nv(&sv->sp_info.sp_cnt);
2506cb174861Sjoyce mcintosh 	smb_llist_insert_tail(splist, sp);
2507cb174861Sjoyce mcintosh 	smb_llist_exit(splist);
25088622ec45SGordon Ross 
2509cb174861Sjoyce mcintosh 	return (rc);
2510cb174861Sjoyce mcintosh }
25114163af6aSjose borrego 
25124163af6aSjose borrego /*
25134163af6aSjose borrego  * smb_server_create_session
25144163af6aSjose borrego  */
25154163af6aSjose borrego static void
25164163af6aSjose borrego smb_server_create_session(smb_listener_daemon_t *ld, ksocket_t s_so)
25174163af6aSjose borrego {
2518811599a4SMatt Barden 	smb_server_t		*sv = ld->ld_sv;
251961b20185SGordon Ross 	smb_session_t		*session;
252061b20185SGordon Ross 	smb_llist_t		*sl;
252161b20185SGordon Ross 	taskqid_t		tqid;
252261b20185SGordon Ross 	clock_t			now;
25234163af6aSjose borrego 
2524811599a4SMatt Barden 	session = smb_session_create(s_so, ld->ld_port, sv,
25254163af6aSjose borrego 	    ld->ld_family);
25264163af6aSjose borrego 
25278622ec45SGordon Ross 	if (session == NULL) {
252861b20185SGordon Ross 		/* This should be rare (create sleeps) */
25298622ec45SGordon Ross 		smb_soshutdown(s_so);
25308622ec45SGordon Ross 		smb_sodestroy(s_so);
25318622ec45SGordon Ross 		cmn_err(CE_WARN, "SMB Session: alloc failed");
25328622ec45SGordon Ross 		return;
25338622ec45SGordon Ross 	}
25348622ec45SGordon Ross 
2535811599a4SMatt Barden 	sl = &sv->sv_session_list;
2536811599a4SMatt Barden 	smb_llist_enter(sl, RW_WRITER);
253761b20185SGordon Ross 	if (smb_llist_get_count(sl) >= sv->sv_cfg.skc_maxconnections) {
253861b20185SGordon Ross 		/*
253961b20185SGordon Ross 		 * New session not in sv_session_list, so we can just
254061b20185SGordon Ross 		 * delete it directly.
254161b20185SGordon Ross 		 */
254261b20185SGordon Ross 		smb_llist_exit(sl);
254361b20185SGordon Ross 		DTRACE_PROBE1(maxconn, smb_session_t *, session);
254461b20185SGordon Ross 		smb_soshutdown(session->sock);
254561b20185SGordon Ross 		smb_session_delete(session);
254661b20185SGordon Ross 		goto logmaxconn;
254761b20185SGordon Ross 	}
2548811599a4SMatt Barden 	smb_llist_insert_tail(sl, session);
2549811599a4SMatt Barden 	smb_llist_exit(sl);
25504163af6aSjose borrego 
25518622ec45SGordon Ross 	/*
25528622ec45SGordon Ross 	 * These taskq entries must run independently of one another,
25538622ec45SGordon Ross 	 * so TQ_NOQUEUE.  TQ_SLEEP (==0) just for clarity.
25548622ec45SGordon Ross 	 */
2555811599a4SMatt Barden 	tqid = taskq_dispatch(sv->sv_receiver_pool,
2556811599a4SMatt Barden 	    smb_server_receiver, session, TQ_NOQUEUE | TQ_SLEEP);
2557fc8ae2ecSToomas Soome 	if (tqid == TASKQID_INVALID) {
255861b20185SGordon Ross 		/*
255961b20185SGordon Ross 		 * We never entered smb_server_receiver()
256061b20185SGordon Ross 		 * so need to do it's return cleanup
256161b20185SGordon Ross 		 */
256261b20185SGordon Ross 		DTRACE_PROBE1(maxconn, smb_session_t *, session);
25634163af6aSjose borrego 		smb_session_disconnect(session);
256461b20185SGordon Ross 		smb_session_logoff(session);
2565811599a4SMatt Barden 		smb_server_destroy_session(session);
256661b20185SGordon Ross 		goto logmaxconn;
25674163af6aSjose borrego 	}
256861b20185SGordon Ross 
256961b20185SGordon Ross 	/* Success */
25708622ec45SGordon Ross 	session->s_receiver_tqid = tqid;
257161b20185SGordon Ross 	return;
257261b20185SGordon Ross 
257361b20185SGordon Ross logmaxconn:
257461b20185SGordon Ross 	/*
257561b20185SGordon Ross 	 * If we hit max_connections, log something so an admin
257661b20185SGordon Ross 	 * can find out why new connections are failing, but
257761b20185SGordon Ross 	 * log this no more than once a minute.
257861b20185SGordon Ross 	 */
257961b20185SGordon Ross 	now = ddi_get_lbolt();
258061b20185SGordon Ross 	if (now > ld->ld_quiet) {
258161b20185SGordon Ross 		ld->ld_quiet = now + SEC_TO_TICK(60);
258261b20185SGordon Ross 		cmn_err(CE_WARN, "SMB can't create session: "
258361b20185SGordon Ross 		    "Would exceed max_connections.");
258461b20185SGordon Ross 	}
25854163af6aSjose borrego }
25864163af6aSjose borrego 
25874163af6aSjose borrego static void
2588811599a4SMatt Barden smb_server_destroy_session(smb_session_t *session)
25894163af6aSjose borrego {
2590811599a4SMatt Barden 	smb_server_t *sv;
2591811599a4SMatt Barden 	smb_llist_t *ll;
2592811599a4SMatt Barden 	uint32_t count;
2593811599a4SMatt Barden 
2594811599a4SMatt Barden 	ASSERT(session->s_server != NULL);
2595811599a4SMatt Barden 	sv = session->s_server;
2596811599a4SMatt Barden 	ll = &sv->sv_session_list;
2597811599a4SMatt Barden 
2598811599a4SMatt Barden 	smb_llist_flush(&session->s_tree_list);
2599811599a4SMatt Barden 	smb_llist_flush(&session->s_user_list);
2600811599a4SMatt Barden 
2601811599a4SMatt Barden 	/*
2602811599a4SMatt Barden 	 * The user and tree lists should be empty now.
2603811599a4SMatt Barden 	 */
2604811599a4SMatt Barden #ifdef DEBUG
2605811599a4SMatt Barden 	if (session->s_user_list.ll_count != 0) {
2606811599a4SMatt Barden 		cmn_err(CE_WARN, "user list not empty?");
2607811599a4SMatt Barden 		debug_enter("s_user_list");
2608811599a4SMatt Barden 	}
2609811599a4SMatt Barden 	if (session->s_tree_list.ll_count != 0) {
2610811599a4SMatt Barden 		cmn_err(CE_WARN, "tree list not empty?");
2611811599a4SMatt Barden 		debug_enter("s_tree_list");
2612811599a4SMatt Barden 	}
2613811599a4SMatt Barden #endif
2614811599a4SMatt Barden 
2615811599a4SMatt Barden 	smb_llist_enter(ll, RW_WRITER);
2616811599a4SMatt Barden 	smb_llist_remove(ll, session);
2617811599a4SMatt Barden 	count = ll->ll_count;
2618811599a4SMatt Barden 	smb_llist_exit(ll);
2619811599a4SMatt Barden 
2620*7f5d80fdSGordon Ross 	/*
2621*7f5d80fdSGordon Ross 	 * Normally, the session should have state SHUTDOWN here.
2622*7f5d80fdSGordon Ross 	 * If the session has any ofiles remaining, eg. due to
2623*7f5d80fdSGordon Ross 	 * forgotten ofile references or something, the state
2624*7f5d80fdSGordon Ross 	 * will be _DISCONNECTED or _TERMINATED.  Keep such
2625*7f5d80fdSGordon Ross 	 * sessions in the list of zombies (for debugging).
2626*7f5d80fdSGordon Ross 	 */
2627*7f5d80fdSGordon Ross 	if (session->s_state == SMB_SESSION_STATE_SHUTDOWN) {
26284163af6aSjose borrego 		smb_session_delete(session);
2629*7f5d80fdSGordon Ross 	} else {
2630*7f5d80fdSGordon Ross #ifdef	DEBUG
2631*7f5d80fdSGordon Ross 		cmn_err(CE_NOTE, "Leaked session: 0x%p", (void *)session);
2632*7f5d80fdSGordon Ross 		debug_enter("leaked session");
2633*7f5d80fdSGordon Ross #endif
2634*7f5d80fdSGordon Ross 		smb_llist_enter(&smb_server_session_zombies, RW_WRITER);
2635*7f5d80fdSGordon Ross 		smb_llist_insert_head(&smb_server_session_zombies, session);
2636*7f5d80fdSGordon Ross 		smb_llist_exit(&smb_server_session_zombies);
2637*7f5d80fdSGordon Ross 	}
2638*7f5d80fdSGordon Ross 
2639811599a4SMatt Barden 	if (count == 0) {
2640811599a4SMatt Barden 		/* See smb_server_shutdown */
2641811599a4SMatt Barden 		cv_signal(&sv->sv_cv);
2642811599a4SMatt Barden 	}
26434163af6aSjose borrego }
2644