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