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