xref: /titanic_50/usr/src/uts/common/fs/smbsrv/smb_server.c (revision 17a2b317610f531d565bf4e940433aab2d9e6985)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
23  */
24 
25 /*
26  * General Structures Layout
27  * -------------------------
28  *
29  * This is a simplified diagram showing the relationship between most of the
30  * main structures.
31  *
32  * +-------------------+
33  * |     SMB_SERVER    |
34  * +-------------------+
35  *          |
36  *          |
37  *          v
38  * +-------------------+       +-------------------+      +-------------------+
39  * |     SESSION       |<----->|     SESSION       |......|      SESSION      |
40  * +-------------------+       +-------------------+      +-------------------+
41  *          |
42  *          |
43  *          v
44  * +-------------------+       +-------------------+      +-------------------+
45  * |       USER        |<----->|       USER        |......|       USER        |
46  * +-------------------+       +-------------------+      +-------------------+
47  *          |
48  *          |
49  *          v
50  * +-------------------+       +-------------------+      +-------------------+
51  * |       TREE        |<----->|       TREE        |......|       TREE        |
52  * +-------------------+       +-------------------+      +-------------------+
53  *      |         |
54  *      |         |
55  *      |         v
56  *      |     +-------+       +-------+      +-------+
57  *      |     | OFILE |<----->| OFILE |......| OFILE |
58  *      |     +-------+       +-------+      +-------+
59  *      |
60  *      |
61  *      v
62  *  +-------+       +------+      +------+
63  *  | ODIR  |<----->| ODIR |......| ODIR |
64  *  +-------+       +------+      +------+
65  *
66  *
67  * Module Interface Overview
68  * -------------------------
69  *
70  *
71  *	    +===================================+
72  *	    |		 smbd daemon		|
73  *	    +===================================+
74  *	      |		     |		      ^
75  *	      |		     |		      |
76  * User	      |		     |		      |
77  * -----------|--------------|----------------|--------------------------------
78  * Kernel     |		     |		      |
79  *            |		     |		      |
80  *	      |		     |		      |
81  *  +=========|==============|================|=================+
82  *  |	      v		     v		      |			|
83  *  | +-----------+ +--------------------+ +------------------+ |
84  *  | |     IO    | | Kernel Door Server | | User Door Servers|	|
85  *  | | Interface | |     Interface      | |   Interface      | |
86  *  | +-----------+ +--------------------+ +------------------+ |
87  *  |		|	     |		      ^		^	|
88  *  |		v	     v		      |		|	|    +=========+
89  *  |	     +-----------------------------------+	|	|    |	       |
90  *  |	     + SMB Server Management (this file) |<------------------|	 ZFS   |
91  *  |	     +-----------------------------------+	|	|    |	       |
92  *  |							|	|    |  Module |
93  *  |	     +-----------------------------------+	|	|    |	       |
94  *  |	     +     SMB Server Internal Layers    |------+	|    +=========+
95  *  |	     +-----------------------------------+		|
96  *  |								|
97  *  |								|
98  *  +===========================================================+
99  *
100  *
101  * Server State Machine
102  * --------------------
103  *                                  |
104  *                                  | T0
105  *                                  |
106  *                                  v
107  *                    +-----------------------------+
108  *		      |   SMB_SERVER_STATE_CREATED  |
109  *		      +-----------------------------+
110  *				    |
111  *				    | T1
112  *				    |
113  *				    v
114  *		      +-----------------------------+
115  *		      | SMB_SERVER_STATE_CONFIGURED |
116  *		      +-----------------------------+
117  *				    |
118  *				    | T2
119  *				    |
120  *				    v
121  *		      +-----------------------------+
122  *		      |  SMB_SERVER_STATE_RUNNING / |
123  *		      |  SMB_SERVER_STATE_STOPPING  |
124  *		      +-----------------------------+
125  *				    |
126  *				    | T3
127  *				    |
128  *				    v
129  *		      +-----------------------------+
130  *		      |  SMB_SERVER_STATE_DELETING  |
131  *                    +-----------------------------+
132  *				    |
133  *				    |
134  *				    |
135  *				    v
136  *
137  * States
138  * ------
139  *
140  * SMB_SERVER_STATE_CREATED
141  *
142  *    This is the state of the server just after creation.
143  *
144  * SMB_SERVER_STATE_CONFIGURED
145  *
146  *    The server has been configured.
147  *
148  * SMB_SERVER_STATE_RUNNING
149  *
150  *    The server has been started. While in this state the threads listening on
151  *    the sockets car be started. The smbd daemon does so through an Ioctl:
152  *
153  *	smb_drv_ioctl(SMB_IOC_NBT_LISTEN) --> smb_server_nbt_listen()
154  *	smb_drv_ioctl(SMB_IOC_TCP_LISTEN) --> smb_server_nbt_listen()
155  *
156  *    When a client establishes a connection the thread listening leaves
157  *    temporarily the kernel. While in user space it creates a thread for the
158  *    new session. It then returns to kernel with the result of the thread
159  *    creation. If the creation failed the new session context is destroyed
160  *    before returning listening.
161  *
162  *    The new created thread enters the kernel though an Ioctl:
163  *
164  *	smb_drv_ioctl(SMB_IOC_NBT_RECEIVE) --> smb_server_nbt_receive()
165  *	smb_drv_ioctl(SMB_IOC_TCP_RECEIVE) --> smb_server_tcp_receive()
166  *
167  * SMB_SERVER_STATE_STOPPING
168  *
169  *    The threads listening on the NBT and TCP sockets are being terminated.
170  *
171  *
172  * Transitions
173  * -----------
174  *
175  * Transition T0
176  *
177  *    The daemon smbd triggers its creation by opening the smbsrv device. If
178  *    the zone where the daemon lives doesn't have an smb server yet it is
179  *    created.
180  *
181  *		smb_drv_open() --> smb_server_create()
182  *
183  * Transition T1
184  *
185  *    This transition occurs in smb_server_configure(). It is triggered by the
186  *    daemon through an Ioctl.
187  *
188  *	smb_drv_ioctl(SMB_IOC_CONFIG) --> smb_server_configure()
189  *
190  * Transition T2
191  *
192  *    This transition occurs in smb_server_start(). It is triggered by the
193  *    daemon through an Ioctl.
194  *
195  *	smb_drv_ioctl(SMB_IOC_START) --> smb_server_start()
196  *
197  * Transition T3
198  *
199  *    This transition occurs in smb_server_delete(). It is triggered by the
200  *    daemon when closing the smbsrv device
201  *
202  *		smb_drv_close() --> smb_server_delete()
203  *
204  * Comments
205  * --------
206  *
207  * This files assumes that there will one SMB server per zone. For now the
208  * smb server works only in global zone. There's nothing in this file preventing
209  * an smb server from being created in a non global zone. That limitation is
210  * enforced in user space.
211  */
212 
213 #include <sys/strsubr.h>
214 #include <sys/cmn_err.h>
215 #include <sys/priv.h>
216 #include <sys/socketvar.h>
217 #include <sys/zone.h>
218 #include <netinet/in.h>
219 #include <netinet/in_systm.h>
220 #include <netinet/ip.h>
221 #include <netinet/ip_icmp.h>
222 #include <netinet/ip_var.h>
223 #include <netinet/tcp.h>
224 #include <smbsrv/smb_kproto.h>
225 #include <smbsrv/string.h>
226 #include <smbsrv/netbios.h>
227 #include <smbsrv/smb_fsops.h>
228 #include <smbsrv/smb_share.h>
229 #include <smbsrv/smb_door.h>
230 #include <smbsrv/smb_kstat.h>
231 
232 extern void smb_reply_notify_change_request(smb_request_t *);
233 
234 static void smb_server_kstat_init(smb_server_t *);
235 static void smb_server_kstat_fini(smb_server_t *);
236 static void smb_server_timers(smb_thread_t *, void *);
237 static int smb_server_listen(smb_server_t *, smb_listener_daemon_t *,
238     in_port_t, int, int);
239 static void smb_server_listen_fini(smb_listener_daemon_t *);
240 static kt_did_t smb_server_listener_tid(smb_listener_daemon_t *);
241 static int smb_server_lookup(smb_server_t **);
242 static void smb_server_release(smb_server_t *);
243 static void smb_server_store_cfg(smb_server_t *, smb_ioc_cfg_t *);
244 static void smb_server_shutdown(smb_server_t *);
245 static int smb_server_fsop_start(smb_server_t *);
246 static void smb_server_fsop_stop(smb_server_t *);
247 static void smb_server_signal_listeners(smb_server_t *);
248 static void smb_event_cancel(smb_server_t *, uint32_t);
249 static uint32_t smb_event_alloc_txid(void);
250 
251 static void smb_server_disconnect_share(smb_session_list_t *, const char *);
252 static void smb_server_enum_private(smb_session_list_t *, smb_svcenum_t *);
253 static int smb_server_sesion_disconnect(smb_session_list_t *, const char *,
254     const char *);
255 static int smb_server_fclose(smb_session_list_t *, uint32_t);
256 static int smb_server_kstat_update(kstat_t *, int);
257 static int smb_server_legacy_kstat_update(kstat_t *, int);
258 
259 int smb_event_debug = 0;
260 
261 static smb_llist_t	smb_servers;
262 
263 /*
264  * *****************************************************************************
265  * **************** Functions called from the device interface *****************
266  * *****************************************************************************
267  *
268  * These functions typically have to determine the relevant smb server
269  * to which the call applies.
270  */
271 
272 /*
273  * smb_server_svc_init
274  *
275  * This function must be called from smb_drv_attach().
276  */
277 int
278 smb_server_svc_init(void)
279 {
280 	int	rc = 0;
281 
282 	while (rc == 0) {
283 		if (rc = smb_mbc_init())
284 			continue;
285 		if (rc = smb_vop_init())
286 			continue;
287 		if (rc = smb_node_init())
288 			continue;
289 		if (rc = smb_oplock_init())
290 			continue;
291 		if (rc = smb_fem_init())
292 			continue;
293 		if (rc = smb_notify_init())
294 			continue;
295 		if (rc = smb_net_init())
296 			continue;
297 		smb_llist_init();
298 		smb_llist_constructor(&smb_servers, sizeof (smb_server_t),
299 		    offsetof(smb_server_t, sv_lnd));
300 		return (0);
301 	}
302 
303 	smb_llist_fini();
304 	smb_net_fini();
305 	smb_notify_fini();
306 	smb_fem_fini();
307 	smb_node_fini();
308 	smb_vop_fini();
309 	smb_mbc_fini();
310 	return (rc);
311 }
312 
313 /*
314  * smb_server_svc_fini
315  *
316  * This function must called from smb_drv_detach(). It will fail if servers
317  * still exist.
318  */
319 int
320 smb_server_svc_fini(void)
321 {
322 	int	rc = EBUSY;
323 
324 	if (smb_llist_get_count(&smb_servers) == 0) {
325 		smb_llist_fini();
326 		smb_net_fini();
327 		smb_notify_fini();
328 		smb_fem_fini();
329 		smb_node_fini();
330 		smb_oplock_fini();
331 		smb_vop_fini();
332 		smb_mbc_fini();
333 		smb_llist_destructor(&smb_servers);
334 		rc = 0;
335 	}
336 	return (rc);
337 }
338 
339 /*
340  * smb_server_create
341  *
342  * This function will fail if there's already a server associated with the
343  * caller's zone.
344  */
345 int
346 smb_server_create(void)
347 {
348 	zoneid_t	zid;
349 	smb_server_t	*sv;
350 
351 	zid = getzoneid();
352 
353 	smb_llist_enter(&smb_servers, RW_WRITER);
354 	sv = smb_llist_head(&smb_servers);
355 	while (sv) {
356 		SMB_SERVER_VALID(sv);
357 		if (sv->sv_zid == zid) {
358 			smb_llist_exit(&smb_servers);
359 			return (EPERM);
360 		}
361 		sv = smb_llist_next(&smb_servers, sv);
362 	}
363 
364 	sv = kmem_zalloc(sizeof (smb_server_t), KM_NOSLEEP);
365 	if (sv == NULL) {
366 		smb_llist_exit(&smb_servers);
367 		return (ENOMEM);
368 	}
369 
370 	smb_llist_constructor(&sv->sv_opipe_list, sizeof (smb_opipe_t),
371 	    offsetof(smb_opipe_t, p_lnd));
372 
373 	smb_llist_constructor(&sv->sv_event_list, sizeof (smb_event_t),
374 	    offsetof(smb_event_t, se_lnd));
375 
376 	smb_llist_constructor(&sv->sp_info.sp_list, sizeof (smb_kspooldoc_t),
377 	    offsetof(smb_kspooldoc_t, sd_lnd));
378 
379 	smb_llist_constructor(&sv->sp_info.sp_fidlist,
380 	    sizeof (smb_spoolfid_t), offsetof(smb_spoolfid_t, sf_lnd));
381 
382 	smb_session_list_constructor(&sv->sv_nbt_daemon.ld_session_list);
383 	smb_session_list_constructor(&sv->sv_tcp_daemon.ld_session_list);
384 
385 	sv->si_cache_request = kmem_cache_create("smb_request_cache",
386 	    sizeof (smb_request_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
387 	sv->si_cache_session = kmem_cache_create("smb_session_cache",
388 	    sizeof (smb_session_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
389 	sv->si_cache_user = kmem_cache_create("smb_user_cache",
390 	    sizeof (smb_user_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
391 	sv->si_cache_tree = kmem_cache_create("smb_tree_cache",
392 	    sizeof (smb_tree_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
393 	sv->si_cache_ofile = kmem_cache_create("smb_ofile_cache",
394 	    sizeof (smb_ofile_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
395 	sv->si_cache_odir = kmem_cache_create("smb_odir_cache",
396 	    sizeof (smb_odir_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
397 	sv->si_cache_opipe = kmem_cache_create("smb_opipe_cache",
398 	    sizeof (smb_opipe_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
399 	sv->si_cache_event = kmem_cache_create("smb_event_cache",
400 	    sizeof (smb_event_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
401 
402 	smb_thread_init(&sv->si_thread_timers,
403 	    "smb_timers", smb_server_timers, sv,
404 	    NULL, NULL);
405 
406 	sv->sv_pid = curproc->p_pid;
407 	smb_srqueue_init(&sv->sv_srqueue);
408 
409 	smb_kdoor_init();
410 	smb_opipe_door_init();
411 	smb_server_kstat_init(sv);
412 
413 	mutex_init(&sv->sv_mutex, NULL, MUTEX_DEFAULT, NULL);
414 	mutex_init(&sv->sp_info.sp_mutex, NULL, MUTEX_DEFAULT, NULL);
415 	cv_init(&sv->sv_cv, NULL, CV_DEFAULT, NULL);
416 	cv_init(&sv->sp_info.sp_cv, NULL, CV_DEFAULT, NULL);
417 
418 	sv->sv_state = SMB_SERVER_STATE_CREATED;
419 	sv->sv_magic = SMB_SERVER_MAGIC;
420 	sv->sv_zid = zid;
421 
422 	smb_llist_insert_tail(&smb_servers, sv);
423 	smb_llist_exit(&smb_servers);
424 
425 	smb_threshold_init(&sv->sv_ssetup_ct, SMB_SSETUP_CMD,
426 	    smb_ssetup_threshold, smb_ssetup_timeout);
427 	smb_threshold_init(&sv->sv_tcon_ct, SMB_TCON_CMD, smb_tcon_threshold,
428 	    smb_tcon_timeout);
429 	smb_threshold_init(&sv->sv_opipe_ct, SMB_OPIPE_CMD, smb_opipe_threshold,
430 	    smb_opipe_timeout);
431 
432 	return (0);
433 }
434 
435 /*
436  * smb_server_delete
437  *
438  * This function will delete the server passed in. It will make sure that all
439  * activity associated that server has ceased before destroying it.
440  */
441 int
442 smb_server_delete(void)
443 {
444 	smb_server_t	*sv;
445 	kt_did_t	nbt_tid;
446 	kt_did_t	tcp_tid;
447 	int		rc;
448 
449 	rc = smb_server_lookup(&sv);
450 	if (rc != 0)
451 		return (rc);
452 
453 	smb_threshold_fini(&sv->sv_ssetup_ct);
454 	smb_threshold_fini(&sv->sv_tcon_ct);
455 	smb_threshold_fini(&sv->sv_opipe_ct);
456 
457 	mutex_enter(&sv->sv_mutex);
458 	switch (sv->sv_state) {
459 	case SMB_SERVER_STATE_RUNNING:
460 	case SMB_SERVER_STATE_STOPPING:
461 		sv->sv_state = SMB_SERVER_STATE_STOPPING;
462 		smb_server_signal_listeners(sv);
463 		nbt_tid = smb_server_listener_tid(&sv->sv_nbt_daemon);
464 		tcp_tid = smb_server_listener_tid(&sv->sv_tcp_daemon);
465 		cv_broadcast(&sv->sp_info.sp_cv);
466 
467 		sv->sv_state = SMB_SERVER_STATE_DELETING;
468 		mutex_exit(&sv->sv_mutex);
469 
470 		if (nbt_tid != 0)
471 			thread_join(nbt_tid);
472 		if (tcp_tid != 0)
473 			thread_join(tcp_tid);
474 
475 		smb_server_listen_fini(&sv->sv_nbt_daemon);
476 		smb_server_listen_fini(&sv->sv_tcp_daemon);
477 		mutex_enter(&sv->sv_mutex);
478 		break;
479 	case SMB_SERVER_STATE_CONFIGURED:
480 	case SMB_SERVER_STATE_CREATED:
481 		sv->sv_state = SMB_SERVER_STATE_DELETING;
482 		break;
483 	default:
484 		SMB_SERVER_STATE_VALID(sv->sv_state);
485 		mutex_exit(&sv->sv_mutex);
486 		smb_server_release(sv);
487 		return (ENOTTY);
488 	}
489 
490 	ASSERT(sv->sv_state == SMB_SERVER_STATE_DELETING);
491 
492 	sv->sv_refcnt--;
493 	while (sv->sv_refcnt)
494 		cv_wait(&sv->sv_cv, &sv->sv_mutex);
495 
496 	mutex_exit(&sv->sv_mutex);
497 
498 	smb_llist_enter(&smb_servers, RW_WRITER);
499 	smb_llist_remove(&smb_servers, sv);
500 	smb_llist_exit(&smb_servers);
501 
502 	smb_server_shutdown(sv);
503 	rw_destroy(&sv->sv_cfg_lock);
504 	smb_opipe_door_fini();
505 	smb_kdoor_fini();
506 	smb_server_kstat_fini(sv);
507 	smb_llist_destructor(&sv->sv_opipe_list);
508 	smb_llist_destructor(&sv->sv_event_list);
509 
510 	kmem_cache_destroy(sv->si_cache_request);
511 	kmem_cache_destroy(sv->si_cache_session);
512 	kmem_cache_destroy(sv->si_cache_user);
513 	kmem_cache_destroy(sv->si_cache_tree);
514 	kmem_cache_destroy(sv->si_cache_ofile);
515 	kmem_cache_destroy(sv->si_cache_odir);
516 	kmem_cache_destroy(sv->si_cache_opipe);
517 	kmem_cache_destroy(sv->si_cache_event);
518 
519 	smb_srqueue_destroy(&sv->sv_srqueue);
520 
521 	smb_thread_destroy(&sv->si_thread_timers);
522 	mutex_destroy(&sv->sv_mutex);
523 	cv_destroy(&sv->sv_cv);
524 	sv->sv_magic = 0;
525 	kmem_free(sv, sizeof (smb_server_t));
526 
527 	return (0);
528 }
529 
530 /*
531  * smb_server_configure
532  */
533 int
534 smb_server_configure(smb_ioc_cfg_t *ioc)
535 {
536 	int		rc = 0;
537 	smb_server_t	*sv;
538 
539 	rc = smb_server_lookup(&sv);
540 	if (rc)
541 		return (rc);
542 
543 	mutex_enter(&sv->sv_mutex);
544 	switch (sv->sv_state) {
545 	case SMB_SERVER_STATE_CREATED:
546 		smb_server_store_cfg(sv, ioc);
547 		sv->sv_state = SMB_SERVER_STATE_CONFIGURED;
548 		break;
549 
550 	case SMB_SERVER_STATE_CONFIGURED:
551 		smb_server_store_cfg(sv, ioc);
552 		break;
553 
554 	case SMB_SERVER_STATE_RUNNING:
555 	case SMB_SERVER_STATE_STOPPING:
556 		rw_enter(&sv->sv_cfg_lock, RW_WRITER);
557 		smb_server_store_cfg(sv, ioc);
558 		rw_exit(&sv->sv_cfg_lock);
559 		break;
560 
561 	default:
562 		SMB_SERVER_STATE_VALID(sv->sv_state);
563 		rc = EFAULT;
564 		break;
565 	}
566 	mutex_exit(&sv->sv_mutex);
567 
568 	smb_server_release(sv);
569 
570 	return (rc);
571 }
572 
573 /*
574  * smb_server_start
575  */
576 int
577 smb_server_start(smb_ioc_start_t *ioc)
578 {
579 	int		rc = 0;
580 	smb_server_t	*sv;
581 
582 	rc = smb_server_lookup(&sv);
583 	if (rc)
584 		return (rc);
585 
586 	mutex_enter(&sv->sv_mutex);
587 	switch (sv->sv_state) {
588 	case SMB_SERVER_STATE_CONFIGURED:
589 		smb_codepage_init();
590 
591 		sv->sv_thread_pool = taskq_create("smb_workers",
592 		    sv->sv_cfg.skc_maxworkers, SMB_WORKER_PRIORITY,
593 		    sv->sv_cfg.skc_maxworkers, INT_MAX,
594 		    TASKQ_DYNAMIC|TASKQ_PREPOPULATE);
595 
596 		sv->sv_session = smb_session_create(NULL, 0, sv, 0);
597 
598 		if (sv->sv_thread_pool == NULL || sv->sv_session == NULL) {
599 			rc = ENOMEM;
600 			break;
601 		}
602 
603 		if (rc = smb_server_fsop_start(sv))
604 			break;
605 		ASSERT(sv->sv_lmshrd == NULL);
606 		sv->sv_lmshrd = smb_kshare_door_init(ioc->lmshrd);
607 		if (sv->sv_lmshrd == NULL)
608 			break;
609 		if (rc = smb_kdoor_open(ioc->udoor)) {
610 			cmn_err(CE_WARN, "Cannot open smbd door");
611 			break;
612 		}
613 		if (rc = smb_opipe_door_open(ioc->opipe)) {
614 			cmn_err(CE_WARN, "Cannot open opipe door");
615 			break;
616 		}
617 		if (rc = smb_thread_start(&sv->si_thread_timers))
618 			break;
619 		sv->sv_state = SMB_SERVER_STATE_RUNNING;
620 		sv->sv_start_time = gethrtime();
621 		mutex_exit(&sv->sv_mutex);
622 		smb_server_release(sv);
623 
624 		smb_export_start();
625 		return (0);
626 	default:
627 		SMB_SERVER_STATE_VALID(sv->sv_state);
628 		mutex_exit(&sv->sv_mutex);
629 		smb_server_release(sv);
630 		return (ENOTTY);
631 	}
632 
633 	smb_server_shutdown(sv);
634 	mutex_exit(&sv->sv_mutex);
635 	smb_server_release(sv);
636 	return (rc);
637 }
638 
639 /*
640  * An smbd is shutting down.
641  */
642 int
643 smb_server_stop(void)
644 {
645 	smb_server_t	*sv;
646 	int		rc;
647 
648 	if ((rc = smb_server_lookup(&sv)) != 0)
649 		return (rc);
650 
651 	mutex_enter(&sv->sv_mutex);
652 	switch (sv->sv_state) {
653 	case SMB_SERVER_STATE_RUNNING:
654 		sv->sv_state = SMB_SERVER_STATE_STOPPING;
655 		smb_server_signal_listeners(sv);
656 		cv_broadcast(&sv->sp_info.sp_cv);
657 		break;
658 	default:
659 		SMB_SERVER_STATE_VALID(sv->sv_state);
660 		break;
661 	}
662 	mutex_exit(&sv->sv_mutex);
663 
664 	smb_server_release(sv);
665 	return (0);
666 }
667 
668 boolean_t
669 smb_server_is_stopping(void)
670 {
671 	smb_server_t    *sv;
672 	boolean_t	status;
673 
674 	if (smb_server_lookup(&sv) != 0)
675 		return (B_TRUE);
676 
677 	SMB_SERVER_VALID(sv);
678 
679 	mutex_enter(&sv->sv_mutex);
680 
681 	switch (sv->sv_state) {
682 	case SMB_SERVER_STATE_STOPPING:
683 	case SMB_SERVER_STATE_DELETING:
684 		status = B_TRUE;
685 		break;
686 	default:
687 		status = B_FALSE;
688 		break;
689 	}
690 
691 	mutex_exit(&sv->sv_mutex);
692 	smb_server_release(sv);
693 	return (status);
694 }
695 
696 int
697 smb_server_cancel_event(uint32_t txid)
698 {
699 	smb_server_t	*sv;
700 	int		rc;
701 
702 	if ((rc = smb_server_lookup(&sv)) == 0) {
703 		smb_event_cancel(sv, txid);
704 		smb_server_release(sv);
705 	}
706 
707 	return (rc);
708 }
709 
710 int
711 smb_server_notify_event(smb_ioc_event_t *ioc)
712 {
713 	smb_server_t	*sv;
714 	int		rc;
715 
716 	if ((rc = smb_server_lookup(&sv)) == 0) {
717 		smb_event_notify(sv, ioc->txid);
718 		smb_server_release(sv);
719 	}
720 
721 	return (rc);
722 }
723 
724 /*
725  * SMB-over-NetBIOS (port 139)
726  *
727  * Traditional SMB service over NetBIOS, which requires that a NetBIOS
728  * session be established.
729  */
730 int
731 smb_server_nbt_listen(smb_ioc_listen_t *ioc)
732 {
733 	smb_server_t	*sv;
734 	int		rc;
735 
736 	rc = smb_server_lookup(&sv);
737 	if (rc)
738 		return (rc);
739 
740 	mutex_enter(&sv->sv_mutex);
741 	switch (sv->sv_state) {
742 	case SMB_SERVER_STATE_RUNNING:
743 		if ((sv->sv_nbt_daemon.ld_kth != NULL) &&
744 		    (sv->sv_nbt_daemon.ld_kth != curthread)) {
745 			mutex_exit(&sv->sv_mutex);
746 			smb_server_release(sv);
747 			return (EACCES);
748 		} else {
749 			sv->sv_nbt_daemon.ld_kth = curthread;
750 			sv->sv_nbt_daemon.ld_ktdid = curthread->t_did;
751 		}
752 		break;
753 	case SMB_SERVER_STATE_STOPPING:
754 		mutex_exit(&sv->sv_mutex);
755 		smb_server_release(sv);
756 		return (ECANCELED);
757 	default:
758 		SMB_SERVER_STATE_VALID(sv->sv_state);
759 		mutex_exit(&sv->sv_mutex);
760 		smb_server_release(sv);
761 		return (EFAULT);
762 	}
763 	mutex_exit(&sv->sv_mutex);
764 
765 	/*
766 	 * netbios must be ipv4
767 	 */
768 	rc = smb_server_listen(sv, &sv->sv_nbt_daemon, IPPORT_NETBIOS_SSN,
769 	    AF_INET, ioc->error);
770 
771 	mutex_enter(&sv->sv_mutex);
772 	sv->sv_nbt_daemon.ld_kth = NULL;
773 	mutex_exit(&sv->sv_mutex);
774 
775 	smb_server_release(sv);
776 	return (rc);
777 }
778 
779 /*
780  *  SMB-over-TCP (port 445)
781  */
782 int
783 smb_server_tcp_listen(smb_ioc_listen_t *ioc)
784 {
785 	smb_server_t	*sv;
786 	int		rc;
787 
788 	rc = smb_server_lookup(&sv);
789 	if (rc)
790 		return (rc);
791 
792 	mutex_enter(&sv->sv_mutex);
793 	switch (sv->sv_state) {
794 	case SMB_SERVER_STATE_RUNNING:
795 		if ((sv->sv_tcp_daemon.ld_kth != NULL) &&
796 		    (sv->sv_tcp_daemon.ld_kth != curthread)) {
797 			mutex_exit(&sv->sv_mutex);
798 			smb_server_release(sv);
799 			return (EACCES);
800 		} else {
801 			sv->sv_tcp_daemon.ld_kth = curthread;
802 			sv->sv_tcp_daemon.ld_ktdid = curthread->t_did;
803 		}
804 		break;
805 	case SMB_SERVER_STATE_STOPPING:
806 		mutex_exit(&sv->sv_mutex);
807 		smb_server_release(sv);
808 		return (ECANCELED);
809 	default:
810 		SMB_SERVER_STATE_VALID(sv->sv_state);
811 		mutex_exit(&sv->sv_mutex);
812 		smb_server_release(sv);
813 		return (EFAULT);
814 	}
815 	mutex_exit(&sv->sv_mutex);
816 
817 	if (sv->sv_cfg.skc_ipv6_enable)
818 		rc = smb_server_listen(sv, &sv->sv_tcp_daemon,
819 		    IPPORT_SMB, AF_INET6, ioc->error);
820 	else
821 		rc = smb_server_listen(sv, &sv->sv_tcp_daemon,
822 		    IPPORT_SMB, AF_INET, ioc->error);
823 
824 	mutex_enter(&sv->sv_mutex);
825 	sv->sv_tcp_daemon.ld_kth = NULL;
826 	mutex_exit(&sv->sv_mutex);
827 
828 	smb_server_release(sv);
829 	return (rc);
830 }
831 
832 /*
833  * smb_server_nbt_receive
834  */
835 int
836 smb_server_nbt_receive(void)
837 {
838 	int		rc;
839 	smb_server_t	*sv;
840 
841 	if ((rc = smb_server_lookup(&sv)) == 0) {
842 		rc = smb_session_daemon(&sv->sv_nbt_daemon.ld_session_list);
843 		smb_server_release(sv);
844 	}
845 
846 	return (rc);
847 }
848 
849 /*
850  * smb_server_tcp_receive
851  */
852 int
853 smb_server_tcp_receive(void)
854 {
855 	int		rc;
856 	smb_server_t	*sv;
857 
858 	if ((rc = smb_server_lookup(&sv)) == 0) {
859 		rc = smb_session_daemon(&sv->sv_tcp_daemon.ld_session_list);
860 		smb_server_release(sv);
861 	}
862 
863 	return (rc);
864 }
865 
866 /*
867  * smb_server_spooldoc
868  *
869  * Waits for print file close broadcast.
870  * Gets the head of the fid list,
871  * then searches the spooldoc list and returns
872  * this info via the ioctl to user land.
873  *
874  * rc - 0 success
875  */
876 
877 int
878 smb_server_spooldoc(smb_ioc_spooldoc_t *ioc)
879 {
880 	smb_server_t	*sv;
881 	int		rc;
882 	smb_kspooldoc_t *spdoc;
883 	uint16_t	fid;
884 
885 	if ((rc = smb_server_lookup(&sv)) == 0) {
886 		if (sv->sv_state != SMB_SERVER_STATE_RUNNING) {
887 			smb_server_release(sv);
888 			return (ECANCELED);
889 		}
890 		mutex_enter(&sv->sp_info.sp_mutex);
891 		spdoc = kmem_zalloc(sizeof (smb_kspooldoc_t), KM_SLEEP);
892 		cv_wait(&sv->sp_info.sp_cv, &sv->sp_info.sp_mutex);
893 		if (sv->sv_state != SMB_SERVER_STATE_RUNNING)
894 			rc = ECANCELED;
895 		else {
896 			fid = smb_spool_get_fid();
897 			atomic_inc_32(&sv->sp_info.sp_cnt);
898 			if (smb_spool_lookup_doc_byfid(fid, spdoc)) {
899 				ioc->spool_num = spdoc->sd_spool_num;
900 				ioc->ipaddr = spdoc->sd_ipaddr;
901 				(void) strlcpy(ioc->path, spdoc->sd_path,
902 				    MAXPATHLEN);
903 				(void) strlcpy(ioc->username,
904 				    spdoc->sd_username, MAXNAMELEN);
905 			}
906 		}
907 		kmem_free(spdoc, sizeof (smb_kspooldoc_t));
908 		mutex_exit(&sv->sp_info.sp_mutex);
909 		smb_server_release(sv);
910 	}
911 	return (rc);
912 }
913 
914 int
915 smb_server_set_gmtoff(smb_ioc_gmt_t *ioc)
916 {
917 	int		rc;
918 	smb_server_t	*sv;
919 
920 	if ((rc = smb_server_lookup(&sv)) == 0) {
921 		sv->si_gmtoff = ioc->offset;
922 		smb_server_release(sv);
923 	}
924 
925 	return (rc);
926 }
927 
928 int
929 smb_server_numopen(smb_ioc_opennum_t *ioc)
930 {
931 	smb_server_t	*sv;
932 	int		rc;
933 
934 	if ((rc = smb_server_lookup(&sv)) == 0) {
935 		ioc->open_users = sv->sv_users;
936 		ioc->open_trees = sv->sv_trees;
937 		ioc->open_files = sv->sv_files + sv->sv_pipes;
938 		smb_server_release(sv);
939 	}
940 	return (rc);
941 }
942 
943 /*
944  * Enumerate objects within the server.  The svcenum provides the
945  * enumeration context, i.e. what the caller want to get back.
946  */
947 int
948 smb_server_enum(smb_ioc_svcenum_t *ioc)
949 {
950 	smb_svcenum_t		*svcenum = &ioc->svcenum;
951 	smb_server_t		*sv;
952 	smb_session_list_t	*se;
953 	int			rc;
954 
955 	switch (svcenum->se_type) {
956 	case SMB_SVCENUM_TYPE_USER:
957 	case SMB_SVCENUM_TYPE_TREE:
958 	case SMB_SVCENUM_TYPE_FILE:
959 		break;
960 	default:
961 		return (EINVAL);
962 	}
963 
964 	if ((rc = smb_server_lookup(&sv)) != 0)
965 		return (rc);
966 
967 	svcenum->se_bavail = svcenum->se_buflen;
968 	svcenum->se_bused = 0;
969 	svcenum->se_nitems = 0;
970 
971 	se = &sv->sv_nbt_daemon.ld_session_list;
972 	smb_server_enum_private(se, svcenum);
973 
974 	se = &sv->sv_tcp_daemon.ld_session_list;
975 	smb_server_enum_private(se, svcenum);
976 
977 	smb_server_release(sv);
978 	return (0);
979 }
980 
981 /*
982  * Look for sessions to disconnect by client and user name.
983  */
984 int
985 smb_server_session_close(smb_ioc_session_t *ioc)
986 {
987 	smb_session_list_t	*se;
988 	smb_server_t		*sv;
989 	int			nbt_cnt;
990 	int			tcp_cnt;
991 	int			rc;
992 
993 	if ((rc = smb_server_lookup(&sv)) != 0)
994 		return (rc);
995 
996 	se = &sv->sv_nbt_daemon.ld_session_list;
997 	nbt_cnt = smb_server_sesion_disconnect(se, ioc->client, ioc->username);
998 
999 	se = &sv->sv_tcp_daemon.ld_session_list;
1000 	tcp_cnt = smb_server_sesion_disconnect(se, ioc->client, ioc->username);
1001 
1002 	smb_server_release(sv);
1003 
1004 	if ((nbt_cnt == 0) && (tcp_cnt == 0))
1005 		return (ENOENT);
1006 	return (0);
1007 }
1008 
1009 /*
1010  * Close a file by uniqid.
1011  */
1012 int
1013 smb_server_file_close(smb_ioc_fileid_t *ioc)
1014 {
1015 	uint32_t		uniqid = ioc->uniqid;
1016 	smb_session_list_t	*se;
1017 	smb_server_t		*sv;
1018 	int			rc;
1019 
1020 	if ((rc = smb_server_lookup(&sv)) != 0)
1021 		return (rc);
1022 
1023 	se = &sv->sv_nbt_daemon.ld_session_list;
1024 	rc = smb_server_fclose(se, uniqid);
1025 
1026 	if (rc == ENOENT) {
1027 		se = &sv->sv_tcp_daemon.ld_session_list;
1028 		rc = smb_server_fclose(se, uniqid);
1029 	}
1030 
1031 	smb_server_release(sv);
1032 	return (rc);
1033 }
1034 
1035 /*
1036  * These functions determine the relevant smb server to which the call apply.
1037  */
1038 
1039 uint32_t
1040 smb_server_get_session_count(void)
1041 {
1042 	smb_server_t	*sv;
1043 	uint32_t	counter = 0;
1044 
1045 	if (smb_server_lookup(&sv))
1046 		return (0);
1047 
1048 	rw_enter(&sv->sv_nbt_daemon.ld_session_list.se_lock, RW_READER);
1049 	counter = sv->sv_nbt_daemon.ld_session_list.se_act.count;
1050 	rw_exit(&sv->sv_nbt_daemon.ld_session_list.se_lock);
1051 	rw_enter(&sv->sv_tcp_daemon.ld_session_list.se_lock, RW_READER);
1052 	counter += sv->sv_tcp_daemon.ld_session_list.se_act.count;
1053 	rw_exit(&sv->sv_tcp_daemon.ld_session_list.se_lock);
1054 
1055 	smb_server_release(sv);
1056 
1057 	return (counter);
1058 }
1059 
1060 /*
1061  * Gets the vnode of the specified share path.
1062  *
1063  * A hold on the returned vnode pointer is taken so the caller
1064  * must call VN_RELE.
1065  */
1066 int
1067 smb_server_sharevp(const char *shr_path, vnode_t **vp)
1068 {
1069 	smb_server_t	*sv;
1070 	smb_request_t	*sr;
1071 	smb_node_t	*fnode = NULL;
1072 	smb_node_t	*dnode;
1073 	char		last_comp[MAXNAMELEN];
1074 	int		rc = 0;
1075 
1076 	ASSERT(shr_path);
1077 
1078 	if ((rc = smb_server_lookup(&sv)))
1079 		return (rc);
1080 
1081 	mutex_enter(&sv->sv_mutex);
1082 	switch (sv->sv_state) {
1083 	case SMB_SERVER_STATE_RUNNING:
1084 		break;
1085 	default:
1086 		mutex_exit(&sv->sv_mutex);
1087 		smb_server_release(sv);
1088 		return (ENOTACTIVE);
1089 	}
1090 	mutex_exit(&sv->sv_mutex);
1091 
1092 	if ((sr = smb_request_alloc(sv->sv_session, 0)) == NULL) {
1093 		smb_server_release(sv);
1094 		return (ENOMEM);
1095 	}
1096 	sr->user_cr = kcred;
1097 
1098 	rc = smb_pathname_reduce(sr, sr->user_cr, shr_path,
1099 	    NULL, NULL, &dnode, last_comp);
1100 
1101 	if (rc == 0) {
1102 		rc = smb_fsop_lookup(sr, sr->user_cr, SMB_FOLLOW_LINKS,
1103 		    sv->si_root_smb_node, dnode, last_comp, &fnode);
1104 		smb_node_release(dnode);
1105 	}
1106 
1107 	smb_request_free(sr);
1108 	smb_server_release(sv);
1109 
1110 	if (rc != 0)
1111 		return (rc);
1112 
1113 	ASSERT(fnode->vp && fnode->vp->v_vfsp);
1114 
1115 	VN_HOLD(fnode->vp);
1116 	*vp = fnode->vp;
1117 
1118 	smb_node_release(fnode);
1119 
1120 	return (0);
1121 }
1122 
1123 
1124 /*
1125  * This is a special interface that will be utilized by ZFS to cause a share to
1126  * be added/removed.
1127  *
1128  * arg is either a lmshare_info_t or share_name from userspace.
1129  * It will need to be copied into the kernel.   It is lmshare_info_t
1130  * for add operations and share_name for delete operations.
1131  */
1132 int
1133 smb_server_share(void *arg, boolean_t add_share)
1134 {
1135 	smb_server_t	*sv;
1136 	int		rc;
1137 
1138 	if ((rc = smb_server_lookup(&sv)) == 0) {
1139 		mutex_enter(&sv->sv_mutex);
1140 		switch (sv->sv_state) {
1141 		case SMB_SERVER_STATE_RUNNING:
1142 			mutex_exit(&sv->sv_mutex);
1143 			(void) smb_kshare_upcall(sv->sv_lmshrd, arg, add_share);
1144 			break;
1145 		default:
1146 			mutex_exit(&sv->sv_mutex);
1147 			break;
1148 		}
1149 		smb_server_release(sv);
1150 	}
1151 
1152 	return (rc);
1153 }
1154 
1155 int
1156 smb_server_unshare(const char *sharename)
1157 {
1158 	smb_server_t		*sv;
1159 	smb_session_list_t	*slist;
1160 	int			rc;
1161 
1162 	if ((rc = smb_server_lookup(&sv)))
1163 		return (rc);
1164 
1165 	mutex_enter(&sv->sv_mutex);
1166 	switch (sv->sv_state) {
1167 	case SMB_SERVER_STATE_RUNNING:
1168 	case SMB_SERVER_STATE_STOPPING:
1169 		break;
1170 	default:
1171 		mutex_exit(&sv->sv_mutex);
1172 		smb_server_release(sv);
1173 		return (ENOTACTIVE);
1174 	}
1175 	mutex_exit(&sv->sv_mutex);
1176 
1177 	slist = &sv->sv_nbt_daemon.ld_session_list;
1178 	smb_server_disconnect_share(slist, sharename);
1179 
1180 	slist = &sv->sv_tcp_daemon.ld_session_list;
1181 	smb_server_disconnect_share(slist, sharename);
1182 
1183 	smb_server_release(sv);
1184 	return (0);
1185 }
1186 
1187 /*
1188  * Disconnect the specified share.
1189  * Typically called when a share has been removed.
1190  */
1191 static void
1192 smb_server_disconnect_share(smb_session_list_t *slist, const char *sharename)
1193 {
1194 	smb_session_t		*session;
1195 
1196 	rw_enter(&slist->se_lock, RW_READER);
1197 
1198 	session = list_head(&slist->se_act.lst);
1199 	while (session) {
1200 		ASSERT(session->s_magic == SMB_SESSION_MAGIC);
1201 		smb_rwx_rwenter(&session->s_lock, RW_READER);
1202 		switch (session->s_state) {
1203 		case SMB_SESSION_STATE_NEGOTIATED:
1204 		case SMB_SESSION_STATE_OPLOCK_BREAKING:
1205 		case SMB_SESSION_STATE_WRITE_RAW_ACTIVE:
1206 			smb_session_disconnect_share(session, sharename);
1207 			break;
1208 		default:
1209 			break;
1210 		}
1211 		smb_rwx_rwexit(&session->s_lock);
1212 		session = list_next(&slist->se_act.lst, session);
1213 	}
1214 
1215 	rw_exit(&slist->se_lock);
1216 }
1217 
1218 /*
1219  * *****************************************************************************
1220  * **************** Functions called from the internal layers ******************
1221  * *****************************************************************************
1222  *
1223  * These functions are provided the relevant smb server by the caller.
1224  */
1225 
1226 void
1227 smb_server_reconnection_check(smb_server_t *sv, smb_session_t *session)
1228 {
1229 	ASSERT(sv == session->s_server);
1230 
1231 	smb_session_reconnection_check(&sv->sv_nbt_daemon.ld_session_list,
1232 	    session);
1233 	smb_session_reconnection_check(&sv->sv_tcp_daemon.ld_session_list,
1234 	    session);
1235 }
1236 
1237 void
1238 smb_server_get_cfg(smb_server_t *sv, smb_kmod_cfg_t *cfg)
1239 {
1240 	rw_enter(&sv->sv_cfg_lock, RW_READER);
1241 	bcopy(&sv->sv_cfg, cfg, sizeof (*cfg));
1242 	rw_exit(&sv->sv_cfg_lock);
1243 }
1244 
1245 /*
1246  *
1247  */
1248 void
1249 smb_server_inc_nbt_sess(smb_server_t *sv)
1250 {
1251 	SMB_SERVER_VALID(sv);
1252 	atomic_inc_32(&sv->sv_nbt_sess);
1253 }
1254 
1255 void
1256 smb_server_dec_nbt_sess(smb_server_t *sv)
1257 {
1258 	SMB_SERVER_VALID(sv);
1259 	atomic_dec_32(&sv->sv_nbt_sess);
1260 }
1261 
1262 void
1263 smb_server_inc_tcp_sess(smb_server_t *sv)
1264 {
1265 	SMB_SERVER_VALID(sv);
1266 	atomic_inc_32(&sv->sv_tcp_sess);
1267 }
1268 
1269 void
1270 smb_server_dec_tcp_sess(smb_server_t *sv)
1271 {
1272 	SMB_SERVER_VALID(sv);
1273 	atomic_dec_32(&sv->sv_tcp_sess);
1274 }
1275 
1276 void
1277 smb_server_inc_users(smb_server_t *sv)
1278 {
1279 	SMB_SERVER_VALID(sv);
1280 	atomic_inc_32(&sv->sv_users);
1281 }
1282 
1283 void
1284 smb_server_dec_users(smb_server_t *sv)
1285 {
1286 	SMB_SERVER_VALID(sv);
1287 	atomic_dec_32(&sv->sv_users);
1288 }
1289 
1290 void
1291 smb_server_inc_trees(smb_server_t *sv)
1292 {
1293 	SMB_SERVER_VALID(sv);
1294 	atomic_inc_32(&sv->sv_trees);
1295 }
1296 
1297 void
1298 smb_server_dec_trees(smb_server_t *sv)
1299 {
1300 	SMB_SERVER_VALID(sv);
1301 	atomic_dec_32(&sv->sv_trees);
1302 }
1303 
1304 void
1305 smb_server_inc_files(smb_server_t *sv)
1306 {
1307 	SMB_SERVER_VALID(sv);
1308 	atomic_inc_32(&sv->sv_files);
1309 }
1310 
1311 void
1312 smb_server_dec_files(smb_server_t *sv)
1313 {
1314 	SMB_SERVER_VALID(sv);
1315 	atomic_dec_32(&sv->sv_files);
1316 }
1317 
1318 void
1319 smb_server_inc_pipes(smb_server_t *sv)
1320 {
1321 	SMB_SERVER_VALID(sv);
1322 	atomic_inc_32(&sv->sv_pipes);
1323 }
1324 
1325 void
1326 smb_server_dec_pipes(smb_server_t *sv)
1327 {
1328 	SMB_SERVER_VALID(sv);
1329 	atomic_dec_32(&sv->sv_pipes);
1330 }
1331 
1332 void
1333 smb_server_add_rxb(smb_server_t *sv, int64_t value)
1334 {
1335 	SMB_SERVER_VALID(sv);
1336 	atomic_add_64(&sv->sv_rxb, value);
1337 }
1338 
1339 void
1340 smb_server_add_txb(smb_server_t *sv, int64_t value)
1341 {
1342 	SMB_SERVER_VALID(sv);
1343 	atomic_add_64(&sv->sv_txb, value);
1344 }
1345 
1346 void
1347 smb_server_inc_req(smb_server_t *sv)
1348 {
1349 	SMB_SERVER_VALID(sv);
1350 	atomic_inc_64(&sv->sv_nreq);
1351 }
1352 
1353 /*
1354  * *****************************************************************************
1355  * *************************** Static Functions ********************************
1356  * *****************************************************************************
1357  */
1358 
1359 static void
1360 smb_server_timers(smb_thread_t *thread, void *arg)
1361 {
1362 	smb_server_t	*sv = (smb_server_t *)arg;
1363 
1364 	ASSERT(sv != NULL);
1365 
1366 	while (smb_thread_continue_timedwait(thread, 1 /* Seconds */)) {
1367 		smb_session_timers(&sv->sv_nbt_daemon.ld_session_list);
1368 		smb_session_timers(&sv->sv_tcp_daemon.ld_session_list);
1369 	}
1370 }
1371 
1372 /*
1373  * smb_server_kstat_init
1374  */
1375 static void
1376 smb_server_kstat_init(smb_server_t *sv)
1377 {
1378 	char	name[KSTAT_STRLEN];
1379 
1380 	sv->sv_ksp = kstat_create_zone(SMBSRV_KSTAT_MODULE, sv->sv_zid,
1381 	    SMBSRV_KSTAT_STATISTICS, SMBSRV_KSTAT_CLASS, KSTAT_TYPE_RAW,
1382 	    sizeof (smbsrv_kstats_t), 0, sv->sv_zid);
1383 
1384 	if (sv->sv_ksp != NULL) {
1385 		sv->sv_ksp->ks_update = smb_server_kstat_update;
1386 		sv->sv_ksp->ks_private = sv;
1387 		((smbsrv_kstats_t *)sv->sv_ksp->ks_data)->ks_start_time =
1388 		    sv->sv_start_time;
1389 		smb_dispatch_stats_init(
1390 		    ((smbsrv_kstats_t *)sv->sv_ksp->ks_data)->ks_reqs);
1391 		kstat_install(sv->sv_ksp);
1392 	} else {
1393 		cmn_err(CE_WARN, "SMB Server: Statistics unavailable");
1394 	}
1395 
1396 	(void) snprintf(name, sizeof (name), "%s%d",
1397 	    SMBSRV_KSTAT_NAME, sv->sv_zid);
1398 
1399 	sv->sv_legacy_ksp = kstat_create(SMBSRV_KSTAT_MODULE, sv->sv_zid,
1400 	    name, SMBSRV_KSTAT_CLASS, KSTAT_TYPE_NAMED,
1401 	    sizeof (smb_server_legacy_kstat_t) / sizeof (kstat_named_t), 0);
1402 
1403 	if (sv->sv_legacy_ksp != NULL) {
1404 		smb_server_legacy_kstat_t *ksd;
1405 
1406 		ksd = sv->sv_legacy_ksp->ks_data;
1407 
1408 		(void) strlcpy(ksd->ls_files.name, "open_files",
1409 		    sizeof (ksd->ls_files.name));
1410 		ksd->ls_files.data_type = KSTAT_DATA_UINT32;
1411 
1412 		(void) strlcpy(ksd->ls_trees.name, "connections",
1413 		    sizeof (ksd->ls_trees.name));
1414 		ksd->ls_trees.data_type = KSTAT_DATA_UINT32;
1415 
1416 		(void) strlcpy(ksd->ls_users.name, "connections",
1417 		    sizeof (ksd->ls_users.name));
1418 		ksd->ls_users.data_type = KSTAT_DATA_UINT32;
1419 
1420 		mutex_init(&sv->sv_legacy_ksmtx, NULL, MUTEX_DEFAULT, NULL);
1421 		sv->sv_legacy_ksp->ks_lock = &sv->sv_legacy_ksmtx;
1422 		sv->sv_legacy_ksp->ks_update = smb_server_legacy_kstat_update;
1423 		kstat_install(sv->sv_legacy_ksp);
1424 	}
1425 }
1426 
1427 /*
1428  * smb_server_kstat_fini
1429  */
1430 static void
1431 smb_server_kstat_fini(smb_server_t *sv)
1432 {
1433 	if (sv->sv_legacy_ksp != NULL) {
1434 		kstat_delete(sv->sv_legacy_ksp);
1435 		mutex_destroy(&sv->sv_legacy_ksmtx);
1436 		sv->sv_legacy_ksp = NULL;
1437 	}
1438 
1439 	if (sv->sv_ksp != NULL) {
1440 		kstat_delete(sv->sv_ksp);
1441 		sv->sv_ksp = NULL;
1442 		smb_dispatch_stats_fini();
1443 	}
1444 }
1445 
1446 /*
1447  * smb_server_kstat_update
1448  */
1449 static int
1450 smb_server_kstat_update(kstat_t *ksp, int rw)
1451 {
1452 	smb_server_t	*sv;
1453 	smbsrv_kstats_t	*ksd;
1454 
1455 	if (rw == KSTAT_READ) {
1456 		sv = ksp->ks_private;
1457 		SMB_SERVER_VALID(sv);
1458 		ksd = (smbsrv_kstats_t *)ksp->ks_data;
1459 		/*
1460 		 * Counters
1461 		 */
1462 		ksd->ks_nbt_sess = sv->sv_nbt_sess;
1463 		ksd->ks_tcp_sess = sv->sv_tcp_sess;
1464 		ksd->ks_users = sv->sv_users;
1465 		ksd->ks_trees = sv->sv_trees;
1466 		ksd->ks_files = sv->sv_files;
1467 		ksd->ks_pipes = sv->sv_pipes;
1468 		/*
1469 		 * Throughput
1470 		 */
1471 		ksd->ks_txb = sv->sv_txb;
1472 		ksd->ks_rxb = sv->sv_rxb;
1473 		ksd->ks_nreq = sv->sv_nreq;
1474 		/*
1475 		 * Busyness
1476 		 */
1477 		ksd->ks_maxreqs = sv->sv_cfg.skc_maxworkers;
1478 		smb_srqueue_update(&sv->sv_srqueue,
1479 		    &ksd->ks_utilization);
1480 		/*
1481 		 * Latency & Throughput of the requests
1482 		 */
1483 		smb_dispatch_stats_update(ksd->ks_reqs, 0, SMB_COM_NUM);
1484 		return (0);
1485 	}
1486 	if (rw == KSTAT_WRITE)
1487 		return (EACCES);
1488 
1489 	return (EIO);
1490 }
1491 
1492 static int
1493 smb_server_legacy_kstat_update(kstat_t *ksp, int rw)
1494 {
1495 	smb_server_t			*sv;
1496 	smb_server_legacy_kstat_t	*ksd;
1497 	int				rc;
1498 
1499 	switch (rw) {
1500 	case KSTAT_WRITE:
1501 		rc = EACCES;
1502 		break;
1503 	case KSTAT_READ:
1504 		if (!smb_server_lookup(&sv)) {
1505 			ASSERT(MUTEX_HELD(ksp->ks_lock));
1506 			ASSERT(sv->sv_legacy_ksp == ksp);
1507 			ksd = (smb_server_legacy_kstat_t *)ksp->ks_data;
1508 			ksd->ls_files.value.ui32 = sv->sv_files + sv->sv_pipes;
1509 			ksd->ls_trees.value.ui32 = sv->sv_trees;
1510 			ksd->ls_users.value.ui32 = sv->sv_users;
1511 			smb_server_release(sv);
1512 			rc = 0;
1513 			break;
1514 		}
1515 		_NOTE(FALLTHRU)
1516 	default:
1517 		rc = EIO;
1518 		break;
1519 	}
1520 	return (rc);
1521 
1522 }
1523 
1524 /*
1525  * The mutex of the server must have been entered before calling this function.
1526  */
1527 static void
1528 smb_server_shutdown(smb_server_t *sv)
1529 {
1530 	SMB_SERVER_VALID(sv);
1531 
1532 	smb_opipe_door_close();
1533 	smb_thread_stop(&sv->si_thread_timers);
1534 	smb_kdoor_close();
1535 	smb_kshare_door_fini(sv->sv_lmshrd);
1536 	sv->sv_lmshrd = NULL;
1537 	smb_export_stop();
1538 	smb_server_fsop_stop(sv);
1539 
1540 	if (sv->sv_session) {
1541 		smb_session_delete(sv->sv_session);
1542 		sv->sv_session = NULL;
1543 	}
1544 
1545 	if (sv->sv_thread_pool) {
1546 		taskq_destroy(sv->sv_thread_pool);
1547 		sv->sv_thread_pool = NULL;
1548 	}
1549 }
1550 
1551 static int
1552 smb_server_listen(
1553     smb_server_t		*sv,
1554     smb_listener_daemon_t	*ld,
1555     in_port_t			port,
1556     int				family,
1557     int				pthread_create_error)
1558 {
1559 	int			rc = 0;
1560 	ksocket_t		s_so;
1561 	uint32_t		on;
1562 	uint32_t		off;
1563 	uint32_t		txbuf_size;
1564 	smb_session_t		*session;
1565 
1566 	if (pthread_create_error) {
1567 		/*
1568 		 * Delete the last session created. The user space thread
1569 		 * creation failed.
1570 		 */
1571 		smb_session_list_delete_tail(&ld->ld_session_list);
1572 	}
1573 
1574 	if (ld->ld_so == NULL) {
1575 		/* First time listener */
1576 		if (family == AF_INET) {
1577 			ld->ld_sin.sin_family = (uint32_t)family;
1578 			ld->ld_sin.sin_port = htons(port);
1579 			ld->ld_sin.sin_addr.s_addr = htonl(INADDR_ANY);
1580 		} else {
1581 			ld->ld_sin6.sin6_family = (uint32_t)family;
1582 			ld->ld_sin6.sin6_port = htons(port);
1583 			(void) memset(&ld->ld_sin6.sin6_addr.s6_addr, 0,
1584 			    sizeof (ld->ld_sin6.sin6_addr.s6_addr));
1585 		}
1586 
1587 		ld->ld_so = smb_socreate(family, SOCK_STREAM, 0);
1588 		if (ld->ld_so == NULL) {
1589 			cmn_err(CE_WARN, "port %d: socket create failed", port);
1590 			return (ENOMEM);
1591 		}
1592 
1593 		off = 0;
1594 		(void) ksocket_setsockopt(ld->ld_so, SOL_SOCKET,
1595 		    SO_MAC_EXEMPT, &off, sizeof (off), CRED());
1596 
1597 		on = 1;
1598 		(void) ksocket_setsockopt(ld->ld_so, SOL_SOCKET,
1599 		    SO_REUSEADDR, &on, sizeof (on), CRED());
1600 
1601 		if (family == AF_INET) {
1602 			rc = ksocket_bind(ld->ld_so,
1603 			    (struct sockaddr *)&ld->ld_sin,
1604 			    sizeof (ld->ld_sin), CRED());
1605 		} else {
1606 			rc = ksocket_bind(ld->ld_so,
1607 			    (struct sockaddr *)&ld->ld_sin6,
1608 			    sizeof (ld->ld_sin6), CRED());
1609 		}
1610 
1611 		if (rc != 0) {
1612 			cmn_err(CE_WARN, "port %d: bind failed (%d)", port, rc);
1613 			smb_server_listen_fini(ld);
1614 			return (rc);
1615 		}
1616 
1617 		rc =  ksocket_listen(ld->ld_so, 20, CRED());
1618 		if (rc < 0) {
1619 			cmn_err(CE_WARN, "port %d: listen failed", port);
1620 			smb_server_listen_fini(ld);
1621 			return (rc);
1622 		}
1623 	}
1624 
1625 	DTRACE_PROBE1(so__wait__accept, struct sonode *, ld->ld_so);
1626 
1627 	for (;;) {
1628 		if (smb_server_is_stopping()) {
1629 			rc = ECANCELED;
1630 			break;
1631 		}
1632 
1633 		rc = ksocket_accept(ld->ld_so, NULL, NULL, &s_so, CRED());
1634 		if (rc != 0)
1635 			break;
1636 
1637 		if (smb_server_is_stopping()) {
1638 			smb_soshutdown(s_so);
1639 			smb_sodestroy(s_so);
1640 			rc = ECANCELED;
1641 			break;
1642 		}
1643 
1644 		DTRACE_PROBE1(so__accept, struct sonode *, s_so);
1645 
1646 		on = 1;
1647 		(void) ksocket_setsockopt(s_so, IPPROTO_TCP, TCP_NODELAY,
1648 		    &on, sizeof (on), CRED());
1649 
1650 		on = 1;
1651 		(void) ksocket_setsockopt(s_so, SOL_SOCKET, SO_KEEPALIVE,
1652 		    &on, sizeof (on), CRED());
1653 
1654 		txbuf_size = 128*1024;
1655 		(void) ksocket_setsockopt(s_so, SOL_SOCKET, SO_SNDBUF,
1656 		    (const void *)&txbuf_size, sizeof (txbuf_size), CRED());
1657 
1658 		/*
1659 		 * Create a session for this connection.
1660 		 */
1661 		session = smb_session_create(s_so, port, sv, family);
1662 		if (session) {
1663 			smb_session_list_append(&ld->ld_session_list, session);
1664 			rc = 0;
1665 			break;
1666 		} else {
1667 			smb_soshutdown(s_so);
1668 			smb_sodestroy(s_so);
1669 		}
1670 	}
1671 
1672 	if (rc != 0)
1673 		smb_server_listen_fini(ld);
1674 
1675 	return (rc);
1676 }
1677 
1678 static void
1679 smb_server_listen_fini(smb_listener_daemon_t *ld)
1680 {
1681 	if (ld->ld_so != NULL) {
1682 		smb_session_list_signal(&ld->ld_session_list);
1683 		smb_soshutdown(ld->ld_so);
1684 		smb_sodestroy(ld->ld_so);
1685 		ld->ld_so = NULL;
1686 	}
1687 }
1688 
1689 static kt_did_t
1690 smb_server_listener_tid(smb_listener_daemon_t *ld)
1691 {
1692 	kt_did_t	tid = 0;
1693 
1694 	if (ld->ld_ktdid != 0) {
1695 		tid = ld->ld_ktdid;
1696 		ld->ld_ktdid = 0;
1697 	}
1698 
1699 	return (tid);
1700 }
1701 
1702 /*
1703  * smb_server_lookup
1704  *
1705  * This function tries to find the server associated with the zone of the
1706  * caller.
1707  */
1708 static int
1709 smb_server_lookup(smb_server_t **psv)
1710 {
1711 	zoneid_t	zid;
1712 	smb_server_t	*sv;
1713 
1714 	zid = getzoneid();
1715 
1716 	smb_llist_enter(&smb_servers, RW_READER);
1717 	sv = smb_llist_head(&smb_servers);
1718 	while (sv) {
1719 		SMB_SERVER_VALID(sv);
1720 		if (sv->sv_zid == zid) {
1721 			mutex_enter(&sv->sv_mutex);
1722 			if (sv->sv_state != SMB_SERVER_STATE_DELETING) {
1723 				sv->sv_refcnt++;
1724 				mutex_exit(&sv->sv_mutex);
1725 				smb_llist_exit(&smb_servers);
1726 				*psv = sv;
1727 				return (0);
1728 			}
1729 			mutex_exit(&sv->sv_mutex);
1730 			break;
1731 		}
1732 		sv = smb_llist_next(&smb_servers, sv);
1733 	}
1734 	smb_llist_exit(&smb_servers);
1735 	return (EPERM);
1736 }
1737 
1738 /*
1739  * smb_server_release
1740  *
1741  * This function decrements the reference count of the server and signals its
1742  * condition variable if the state of the server is SMB_SERVER_STATE_DELETING.
1743  */
1744 static void
1745 smb_server_release(smb_server_t *sv)
1746 {
1747 	SMB_SERVER_VALID(sv);
1748 
1749 	mutex_enter(&sv->sv_mutex);
1750 	ASSERT(sv->sv_refcnt);
1751 	sv->sv_refcnt--;
1752 	if ((sv->sv_refcnt == 0) && (sv->sv_state == SMB_SERVER_STATE_DELETING))
1753 		cv_signal(&sv->sv_cv);
1754 	mutex_exit(&sv->sv_mutex);
1755 }
1756 
1757 /*
1758  * Enumerate the users associated with a session list.
1759  */
1760 static void
1761 smb_server_enum_private(smb_session_list_t *se, smb_svcenum_t *svcenum)
1762 {
1763 	smb_session_t	*sn;
1764 	smb_llist_t	*ulist;
1765 	smb_user_t	*user;
1766 	int		rc = 0;
1767 
1768 	rw_enter(&se->se_lock, RW_READER);
1769 	sn = list_head(&se->se_act.lst);
1770 
1771 	while (sn != NULL) {
1772 		ASSERT(sn->s_magic == SMB_SESSION_MAGIC);
1773 		ulist = &sn->s_user_list;
1774 		smb_llist_enter(ulist, RW_READER);
1775 		user = smb_llist_head(ulist);
1776 
1777 		while (user != NULL) {
1778 			if (smb_user_hold(user)) {
1779 				rc = smb_user_enum(user, svcenum);
1780 				smb_user_release(user);
1781 			}
1782 
1783 			user = smb_llist_next(ulist, user);
1784 		}
1785 
1786 		smb_llist_exit(ulist);
1787 
1788 		if (rc != 0)
1789 			break;
1790 
1791 		sn = list_next(&se->se_act.lst, sn);
1792 	}
1793 
1794 	rw_exit(&se->se_lock);
1795 }
1796 
1797 /*
1798  * Disconnect sessions associated with the specified client and username.
1799  * Empty strings are treated as wildcards.
1800  */
1801 static int
1802 smb_server_sesion_disconnect(smb_session_list_t *se,
1803     const char *client, const char *name)
1804 {
1805 	smb_session_t	*sn;
1806 	smb_llist_t	*ulist;
1807 	smb_user_t	*user;
1808 	boolean_t	match;
1809 	int		count = 0;
1810 
1811 	rw_enter(&se->se_lock, RW_READER);
1812 	sn = list_head(&se->se_act.lst);
1813 
1814 	while (sn != NULL) {
1815 		ASSERT(sn->s_magic == SMB_SESSION_MAGIC);
1816 
1817 		if ((*client != '\0') && (!smb_session_isclient(sn, client))) {
1818 			sn = list_next(&se->se_act.lst, sn);
1819 			continue;
1820 		}
1821 
1822 		ulist = &sn->s_user_list;
1823 		smb_llist_enter(ulist, RW_READER);
1824 		user = smb_llist_head(ulist);
1825 
1826 		while (user != NULL) {
1827 			if (smb_user_hold(user)) {
1828 				match = (*name == '\0');
1829 				if (!match)
1830 					match = smb_user_namecmp(user, name);
1831 
1832 				if (match) {
1833 					smb_llist_exit(ulist);
1834 					smb_user_logoff(user);
1835 					++count;
1836 					smb_user_release(user);
1837 					smb_llist_enter(ulist, RW_READER);
1838 					user = smb_llist_head(ulist);
1839 					continue;
1840 				}
1841 
1842 				smb_user_release(user);
1843 			}
1844 
1845 			user = smb_llist_next(ulist, user);
1846 		}
1847 
1848 		smb_llist_exit(ulist);
1849 		sn = list_next(&se->se_act.lst, sn);
1850 	}
1851 
1852 	rw_exit(&se->se_lock);
1853 	return (count);
1854 }
1855 
1856 /*
1857  * Close a file by its unique id.
1858  */
1859 static int
1860 smb_server_fclose(smb_session_list_t *se, uint32_t uniqid)
1861 {
1862 	smb_session_t	*sn;
1863 	smb_llist_t	*ulist;
1864 	smb_user_t	*user;
1865 	int		rc = ENOENT;
1866 
1867 	rw_enter(&se->se_lock, RW_READER);
1868 	sn = list_head(&se->se_act.lst);
1869 
1870 	while ((sn != NULL) && (rc == ENOENT)) {
1871 		ASSERT(sn->s_magic == SMB_SESSION_MAGIC);
1872 		ulist = &sn->s_user_list;
1873 		smb_llist_enter(ulist, RW_READER);
1874 		user = smb_llist_head(ulist);
1875 
1876 		while ((user != NULL) && (rc == ENOENT)) {
1877 			if (smb_user_hold(user)) {
1878 				rc = smb_user_fclose(user, uniqid);
1879 				smb_user_release(user);
1880 			}
1881 
1882 			user = smb_llist_next(ulist, user);
1883 		}
1884 
1885 		smb_llist_exit(ulist);
1886 		sn = list_next(&se->se_act.lst, sn);
1887 	}
1888 
1889 	rw_exit(&se->se_lock);
1890 	return (rc);
1891 }
1892 
1893 static void
1894 smb_server_store_cfg(smb_server_t *sv, smb_ioc_cfg_t *ioc)
1895 {
1896 	if (ioc->maxconnections == 0)
1897 		ioc->maxconnections = 0xFFFFFFFF;
1898 
1899 	smb_session_correct_keep_alive_values(
1900 	    &sv->sv_nbt_daemon.ld_session_list, ioc->keepalive);
1901 	smb_session_correct_keep_alive_values(
1902 	    &sv->sv_tcp_daemon.ld_session_list, ioc->keepalive);
1903 
1904 	sv->sv_cfg.skc_maxworkers = ioc->maxworkers;
1905 	sv->sv_cfg.skc_maxconnections = ioc->maxconnections;
1906 	sv->sv_cfg.skc_keepalive = ioc->keepalive;
1907 	sv->sv_cfg.skc_restrict_anon = ioc->restrict_anon;
1908 	sv->sv_cfg.skc_signing_enable = ioc->signing_enable;
1909 	sv->sv_cfg.skc_signing_required = ioc->signing_required;
1910 	sv->sv_cfg.skc_oplock_enable = ioc->oplock_enable;
1911 	sv->sv_cfg.skc_sync_enable = ioc->sync_enable;
1912 	sv->sv_cfg.skc_secmode = ioc->secmode;
1913 	sv->sv_cfg.skc_ipv6_enable = ioc->ipv6_enable;
1914 	sv->sv_cfg.skc_print_enable = ioc->print_enable;
1915 	sv->sv_cfg.skc_execflags = ioc->exec_flags;
1916 	sv->sv_cfg.skc_version = ioc->version;
1917 	(void) strlcpy(sv->sv_cfg.skc_nbdomain, ioc->nbdomain,
1918 	    sizeof (sv->sv_cfg.skc_nbdomain));
1919 	(void) strlcpy(sv->sv_cfg.skc_fqdn, ioc->fqdn,
1920 	    sizeof (sv->sv_cfg.skc_fqdn));
1921 	(void) strlcpy(sv->sv_cfg.skc_hostname, ioc->hostname,
1922 	    sizeof (sv->sv_cfg.skc_hostname));
1923 	(void) strlcpy(sv->sv_cfg.skc_system_comment, ioc->system_comment,
1924 	    sizeof (sv->sv_cfg.skc_system_comment));
1925 }
1926 
1927 static int
1928 smb_server_fsop_start(smb_server_t *sv)
1929 {
1930 	int	error;
1931 
1932 	error = smb_node_root_init(rootdir, sv, &sv->si_root_smb_node);
1933 	if (error != 0)
1934 		sv->si_root_smb_node = NULL;
1935 
1936 	return (error);
1937 }
1938 
1939 static void
1940 smb_server_fsop_stop(smb_server_t *sv)
1941 {
1942 	if (sv->si_root_smb_node != NULL) {
1943 		smb_node_release(sv->si_root_smb_node);
1944 		sv->si_root_smb_node = NULL;
1945 	}
1946 }
1947 
1948 static void
1949 smb_server_signal_listeners(smb_server_t *sv)
1950 {
1951 	SMB_SERVER_VALID(sv);
1952 	ASSERT(sv->sv_state == SMB_SERVER_STATE_STOPPING);
1953 	ASSERT(MUTEX_HELD(&sv->sv_mutex));
1954 
1955 	smb_event_cancel(sv, 0);
1956 
1957 	if (sv->sv_nbt_daemon.ld_kth != NULL) {
1958 		tsignal(sv->sv_nbt_daemon.ld_kth, SIGINT);
1959 		sv->sv_nbt_daemon.ld_kth = NULL;
1960 	}
1961 
1962 	if (sv->sv_tcp_daemon.ld_kth != NULL) {
1963 		tsignal(sv->sv_tcp_daemon.ld_kth, SIGINT);
1964 		sv->sv_tcp_daemon.ld_kth = NULL;
1965 	}
1966 }
1967 
1968 smb_event_t *
1969 smb_event_create(int timeout)
1970 {
1971 	smb_server_t	*sv;
1972 	smb_event_t	*event;
1973 
1974 	if (smb_server_is_stopping())
1975 		return (NULL);
1976 
1977 	if (smb_server_lookup(&sv) != 0) {
1978 		cmn_err(CE_NOTE, "smb_event_create failed");
1979 		return (NULL);
1980 	}
1981 
1982 	event = kmem_cache_alloc(sv->si_cache_event, KM_SLEEP);
1983 
1984 	bzero(event, sizeof (smb_event_t));
1985 	mutex_init(&event->se_mutex, NULL, MUTEX_DEFAULT, NULL);
1986 	cv_init(&event->se_cv, NULL, CV_DEFAULT, NULL);
1987 	event->se_magic = SMB_EVENT_MAGIC;
1988 	event->se_txid = smb_event_alloc_txid();
1989 	event->se_server = sv;
1990 	event->se_timeout = timeout;
1991 
1992 	smb_llist_enter(&sv->sv_event_list, RW_WRITER);
1993 	smb_llist_insert_tail(&sv->sv_event_list, event);
1994 	smb_llist_exit(&sv->sv_event_list);
1995 
1996 	smb_server_release(sv);
1997 	return (event);
1998 }
1999 
2000 void
2001 smb_event_destroy(smb_event_t *event)
2002 {
2003 	smb_server_t	*sv;
2004 
2005 	if (event == NULL)
2006 		return;
2007 
2008 	SMB_EVENT_VALID(event);
2009 	ASSERT(event->se_waittime == 0);
2010 
2011 	if (smb_server_lookup(&sv) != 0)
2012 		return;
2013 
2014 	smb_llist_enter(&sv->sv_event_list, RW_WRITER);
2015 	smb_llist_remove(&sv->sv_event_list, event);
2016 	smb_llist_exit(&sv->sv_event_list);
2017 
2018 	event->se_magic = (uint32_t)~SMB_EVENT_MAGIC;
2019 	cv_destroy(&event->se_cv);
2020 	mutex_destroy(&event->se_mutex);
2021 
2022 	kmem_cache_free(sv->si_cache_event, event);
2023 	smb_server_release(sv);
2024 }
2025 
2026 /*
2027  * Get the txid for the specified event.
2028  */
2029 uint32_t
2030 smb_event_txid(smb_event_t *event)
2031 {
2032 	if (event != NULL) {
2033 		SMB_EVENT_VALID(event);
2034 		return (event->se_txid);
2035 	}
2036 
2037 	cmn_err(CE_NOTE, "smb_event_txid failed");
2038 	return ((uint32_t)-1);
2039 }
2040 
2041 /*
2042  * Wait for event notification.
2043  */
2044 int
2045 smb_event_wait(smb_event_t *event)
2046 {
2047 	int	seconds = 1;
2048 	int	ticks;
2049 
2050 	if (event == NULL)
2051 		return (EINVAL);
2052 
2053 	SMB_EVENT_VALID(event);
2054 
2055 	mutex_enter(&event->se_mutex);
2056 	event->se_waittime = 1;
2057 	event->se_errno = 0;
2058 
2059 	while (!(event->se_notified)) {
2060 		if (smb_event_debug && ((event->se_waittime % 30) == 0))
2061 			cmn_err(CE_NOTE, "smb_event_wait[%d] (%d sec)",
2062 			    event->se_txid, event->se_waittime);
2063 
2064 		if (event->se_errno != 0)
2065 			break;
2066 
2067 		if (event->se_waittime > event->se_timeout) {
2068 			event->se_errno = ETIME;
2069 			break;
2070 		}
2071 
2072 		ticks = SEC_TO_TICK(seconds);
2073 		(void) cv_reltimedwait(&event->se_cv,
2074 		    &event->se_mutex, (clock_t)ticks, TR_CLOCK_TICK);
2075 		++event->se_waittime;
2076 	}
2077 
2078 	event->se_waittime = 0;
2079 	event->se_notified = B_FALSE;
2080 	cv_signal(&event->se_cv);
2081 	mutex_exit(&event->se_mutex);
2082 	return (event->se_errno);
2083 }
2084 
2085 /*
2086  * If txid is non-zero, cancel the specified event.
2087  * Otherwise, cancel all events.
2088  */
2089 static void
2090 smb_event_cancel(smb_server_t *sv, uint32_t txid)
2091 {
2092 	smb_event_t	*event;
2093 	smb_llist_t	*event_list;
2094 
2095 	SMB_SERVER_VALID(sv);
2096 
2097 	event_list = &sv->sv_event_list;
2098 	smb_llist_enter(event_list, RW_WRITER);
2099 
2100 	event = smb_llist_head(event_list);
2101 	while (event) {
2102 		SMB_EVENT_VALID(event);
2103 
2104 		if (txid == 0 || event->se_txid == txid) {
2105 			mutex_enter(&event->se_mutex);
2106 			event->se_errno = ECANCELED;
2107 			event->se_notified = B_TRUE;
2108 			cv_signal(&event->se_cv);
2109 			mutex_exit(&event->se_mutex);
2110 
2111 			if (txid != 0)
2112 				break;
2113 		}
2114 
2115 		event = smb_llist_next(event_list, event);
2116 	}
2117 
2118 	smb_llist_exit(event_list);
2119 }
2120 
2121 /*
2122  * If txid is non-zero, notify the specified event.
2123  * Otherwise, notify all events.
2124  */
2125 void
2126 smb_event_notify(smb_server_t *sv, uint32_t txid)
2127 {
2128 	smb_event_t	*event;
2129 	smb_llist_t	*event_list;
2130 
2131 	SMB_SERVER_VALID(sv);
2132 
2133 	event_list = &sv->sv_event_list;
2134 	smb_llist_enter(event_list, RW_READER);
2135 
2136 	event = smb_llist_head(event_list);
2137 	while (event) {
2138 		SMB_EVENT_VALID(event);
2139 
2140 		if (txid == 0 || event->se_txid == txid) {
2141 			mutex_enter(&event->se_mutex);
2142 			event->se_notified = B_TRUE;
2143 			cv_signal(&event->se_cv);
2144 			mutex_exit(&event->se_mutex);
2145 
2146 			if (txid != 0)
2147 				break;
2148 		}
2149 
2150 		event = smb_llist_next(event_list, event);
2151 	}
2152 
2153 	smb_llist_exit(event_list);
2154 }
2155 
2156 /*
2157  * Allocate a new transaction id (txid).
2158  *
2159  * 0 or -1 are not assigned because they are used to detect invalid
2160  * conditions or to indicate all open id's.
2161  */
2162 static uint32_t
2163 smb_event_alloc_txid(void)
2164 {
2165 	static kmutex_t	txmutex;
2166 	static uint32_t	txid;
2167 	uint32_t	txid_ret;
2168 
2169 	mutex_enter(&txmutex);
2170 
2171 	if (txid == 0)
2172 		txid = ddi_get_lbolt() << 11;
2173 
2174 	do {
2175 		++txid;
2176 	} while (txid == 0 || txid == (uint32_t)-1);
2177 
2178 	txid_ret = txid;
2179 	mutex_exit(&txmutex);
2180 
2181 	return (txid_ret);
2182 }
2183 
2184 /*
2185  * Called by the ioctl to find the corresponding
2186  * spooldoc node.  removes node on success
2187  *
2188  * Return values
2189  * rc
2190  * B_FALSE - not found
2191  * B_TRUE  - found
2192  *
2193  */
2194 
2195 boolean_t
2196 smb_spool_lookup_doc_byfid(uint16_t fid, smb_kspooldoc_t *spdoc)
2197 {
2198 	smb_kspooldoc_t *sp;
2199 	smb_llist_t	*splist;
2200 	smb_server_t	*sv;
2201 	int		rc;
2202 
2203 	rc = smb_server_lookup(&sv);
2204 	if (rc)
2205 		return (B_FALSE);
2206 
2207 	splist = &sv->sp_info.sp_list;
2208 	smb_llist_enter(splist, RW_WRITER);
2209 	sp = smb_llist_head(splist);
2210 	while (sp != NULL) {
2211 		/*
2212 		 * check for a matching fid
2213 		 */
2214 		if (sp->sd_fid == fid) {
2215 			*spdoc = *sp;
2216 			smb_llist_remove(splist, sp);
2217 			smb_llist_exit(splist);
2218 			kmem_free(sp, sizeof (smb_kspooldoc_t));
2219 			smb_server_release(sv);
2220 			return (B_TRUE);
2221 		}
2222 		sp = smb_llist_next(splist, sp);
2223 	}
2224 	cmn_err(CE_WARN, "smb_spool_lookup_user_byfid: no fid:%d", fid);
2225 	smb_llist_exit(splist);
2226 	smb_server_release(sv);
2227 	return (B_FALSE);
2228 }
2229 
2230 /*
2231  * Adds the spool fid to a linked list to be used
2232  * as a search key in the spooldoc queue
2233  *
2234  * Return values
2235  *      rc non-zero error
2236  *	rc zero success
2237  *
2238  */
2239 
2240 int
2241 smb_spool_add_fid(uint16_t fid)
2242 {
2243 	smb_llist_t	*fidlist;
2244 	smb_server_t	*sv;
2245 	smb_spoolfid_t  *sf;
2246 	int rc = 0;
2247 
2248 	rc = smb_server_lookup(&sv);
2249 	if (rc)
2250 		return (rc);
2251 
2252 	sf = kmem_zalloc(sizeof (smb_spoolfid_t), KM_SLEEP);
2253 	fidlist = &sv->sp_info.sp_fidlist;
2254 	smb_llist_enter(fidlist, RW_WRITER);
2255 	sf->sf_fid = fid;
2256 	smb_llist_insert_tail(fidlist, sf);
2257 	smb_llist_exit(fidlist);
2258 	smb_server_release(sv);
2259 	return (rc);
2260 }
2261 
2262 /*
2263  * Called by the ioctl to get and remove the head of the fid list
2264  *
2265  * Return values
2266  * int fd
2267  * greater than 0 success
2268  * 0 - error
2269  *
2270  */
2271 
2272 uint16_t
2273 smb_spool_get_fid()
2274 {
2275 	smb_spoolfid_t	*spfid;
2276 	smb_llist_t	*splist;
2277 	smb_server_t	*sv;
2278 	int 		rc = 0;
2279 	uint16_t	fid;
2280 
2281 	rc = smb_server_lookup(&sv);
2282 	if (rc)
2283 		return (0);
2284 
2285 	splist = &sv->sp_info.sp_fidlist;
2286 	smb_llist_enter(splist, RW_WRITER);
2287 	spfid = smb_llist_head(splist);
2288 	if (spfid != NULL) {
2289 		fid = spfid->sf_fid;
2290 		smb_llist_remove(&sv->sp_info.sp_fidlist, spfid);
2291 		kmem_free(spfid, sizeof (smb_spoolfid_t));
2292 	} else {
2293 		fid = 0;
2294 	}
2295 	smb_llist_exit(splist);
2296 	smb_server_release(sv);
2297 	return (fid);
2298 }
2299 
2300 /*
2301  * Adds the spooldoc to the tail of the spooldoc list
2302  *
2303  * Return values
2304  *      rc non-zero error
2305  *	rc zero success
2306  */
2307 int
2308 smb_spool_add_doc(smb_kspooldoc_t *sp)
2309 {
2310 	smb_llist_t	*splist;
2311 	smb_server_t	*sv;
2312 	int rc = 0;
2313 
2314 	rc = smb_server_lookup(&sv);
2315 	if (rc)
2316 		return (rc);
2317 
2318 	splist = &sv->sp_info.sp_list;
2319 	smb_llist_enter(splist, RW_WRITER);
2320 	sp->sd_spool_num = sv->sp_info.sp_cnt;
2321 	smb_llist_insert_tail(splist, sp);
2322 	smb_llist_exit(splist);
2323 	smb_server_release(sv);
2324 	return (rc);
2325 }
2326