xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_tree.c (revision 609febc9a48c79a089214cb5d882759a72a38513)
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 /*
23  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Copyright (c) 2016 by Delphix. All rights reserved.
25  * Copyright 2021 Tintri by DDN, Inc. All rights reserved.
26  */
27 
28 /*
29  * General Structures Layout
30  * -------------------------
31  *
32  * This is a simplified diagram showing the relationship between most of the
33  * main structures.
34  *
35  * +-------------------+
36  * |     SMB_INFO      |
37  * +-------------------+
38  *          |
39  *          |
40  *          v
41  * +-------------------+       +-------------------+      +-------------------+
42  * |     SESSION       |<----->|     SESSION       |......|      SESSION      |
43  * +-------------------+       +-------------------+      +-------------------+
44  *   |          |
45  *   |          |
46  *   |          v
47  *   |  +-------------------+     +-------------------+   +-------------------+
48  *   |  |       USER        |<--->|       USER        |...|       USER        |
49  *   |  +-------------------+     +-------------------+   +-------------------+
50  *   |
51  *   |
52  *   v
53  * +-------------------+       +-------------------+      +-------------------+
54  * |       TREE        |<----->|       TREE        |......|       TREE        |
55  * +-------------------+       +-------------------+      +-------------------+
56  *      |         |
57  *      |         |
58  *      |         v
59  *      |     +-------+       +-------+      +-------+
60  *      |     | OFILE |<----->| OFILE |......| OFILE |
61  *      |     +-------+       +-------+      +-------+
62  *      |
63  *      |
64  *      v
65  *  +-------+       +------+      +------+
66  *  | ODIR  |<----->| ODIR |......| ODIR |
67  *  +-------+       +------+      +------+
68  *
69  *
70  * Tree State Machine
71  * ------------------
72  *
73  *    +-----------------------------+	 T0
74  *    |  SMB_TREE_STATE_CONNECTED   |<----------- Creation/Allocation
75  *    +-----------------------------+
76  *		    |
77  *		    | T1
78  *		    |
79  *		    v
80  *    +------------------------------+
81  *    | SMB_TREE_STATE_DISCONNECTING |
82  *    +------------------------------+
83  *		    |
84  *		    | T2
85  *		    |
86  *		    v
87  *    +-----------------------------+    T3
88  *    | SMB_TREE_STATE_DISCONNECTED |----------> Deletion/Free
89  *    +-----------------------------+
90  *
91  * SMB_TREE_STATE_CONNECTED
92  *
93  *    While in this state:
94  *      - The tree is queued in the list of trees of its user.
95  *      - References will be given out if the tree is looked up.
96  *      - Files under that tree can be accessed.
97  *
98  * SMB_TREE_STATE_DISCONNECTING
99  *
100  *    While in this state:
101  *      - The tree is queued in the list of trees of its user.
102  *      - References will not be given out if the tree is looked up.
103  *      - The files and directories open under the tree are being closed.
104  *      - The resources associated with the tree remain.
105  *
106  * SMB_TREE_STATE_DISCONNECTED
107  *
108  *    While in this state:
109  *      - The tree is queued in the list of trees of its user.
110  *      - References will not be given out if the tree is looked up.
111  *      - The tree has no more files and directories opened.
112  *      - The resources associated with the tree remain.
113  *
114  * Transition T0
115  *
116  *    This transition occurs in smb_tree_connect(). A new tree is created and
117  *    added to the list of trees of a user.
118  *
119  * Transition T1
120  *
121  *    This transition occurs in smb_tree_disconnect().
122  *
123  * Transition T2
124  *
125  *    This transition occurs in smb_tree_disconnect()
126  *
127  * Transition T3
128  *
129  *    This transition occurs in smb_tree_release(). The resources associated
130  *    with the tree are freed as well as the tree structure. For the transition
131  *    to occur, the tree must be in the SMB_TREE_STATE_DISCONNECTED and the
132  *    reference count must be zero.
133  *
134  * Comments
135  * --------
136  *
137  *    The state machine of the tree structures is controlled by 3 elements:
138  *      - The list of trees of the user it belongs to.
139  *      - The mutex embedded in the structure itself.
140  *      - The reference count.
141  *
142  *    There's a mutex embedded in the tree structure used to protect its fields
143  *    and there's a lock embedded in the list of trees of a user. To
144  *    increment or to decrement the reference count the mutex must be entered.
145  *    To insert the tree into the list of trees of the user and to remove
146  *    the tree from it, the lock must be entered in RW_WRITER mode.
147  *
148  *    Rules of access to a tree structure:
149  *
150  *    1) In order to avoid deadlocks, when both (mutex and lock of the user
151  *       list) have to be entered, the lock must be entered first. Additionally,
152  *       when both the (mutex and lock of the ofile list) have to be entered,
153  *       the mutex must be entered first. However, the ofile list lock must NOT
154  *       be dropped while the mutex is held in such a way that the ofile deleteq
155  *       is flushed.
156  *
157  *    2) All actions applied to a tree require a reference count.
158  *
159  *    3) There are 2 ways of getting a reference count: when a tree is
160  *       connected and when a tree is looked up.
161  *
162  *    It should be noted that the reference count of a tree registers the
163  *    number of references to the tree in other structures (such as an smb
164  *    request). The reference count is not incremented in these 2 instances:
165  *
166  *    1) The tree is connected. An tree is anchored by its state. If there's
167  *       no activity involving a tree currently connected, the reference
168  *       count of that tree is zero.
169  *
170  *    2) The tree is queued in the list of trees of the user. The fact of
171  *       being queued in that list is NOT registered by incrementing the
172  *       reference count.
173  */
174 
175 #include <sys/refstr_impl.h>
176 #include <smbsrv/smb_kproto.h>
177 #include <smbsrv/smb_ktypes.h>
178 #include <smbsrv/smb_fsops.h>
179 #include <smbsrv/smb_share.h>
180 
181 int smb_tcon_mute = 0;
182 
183 uint32_t	smb_tree_connect_core(smb_request_t *);
184 uint32_t	smb_tree_connect_disk(smb_request_t *, smb_arg_tcon_t *);
185 uint32_t	smb_tree_connect_printq(smb_request_t *, smb_arg_tcon_t *);
186 uint32_t	smb_tree_connect_ipc(smb_request_t *, smb_arg_tcon_t *);
187 static void smb_tree_dealloc(void *);
188 static boolean_t smb_tree_is_connected_locked(smb_tree_t *);
189 static char *smb_tree_get_sharename(char *);
190 static int smb_tree_getattr(const smb_kshare_t *, smb_node_t *, smb_tree_t *);
191 static void smb_tree_get_creation(smb_node_t *, smb_tree_t *);
192 static void smb_tree_get_volname(vfs_t *, smb_tree_t *);
193 static void smb_tree_get_flags(const smb_kshare_t *, vfs_t *, smb_tree_t *);
194 static void smb_tree_log(smb_request_t *, const char *, const char *, ...);
195 static void smb_tree_close_odirs(smb_tree_t *, uint32_t);
196 static void smb_tree_set_execinfo(smb_tree_t *, smb_shr_execinfo_t *, int);
197 static int smb_tree_enum_private(smb_tree_t *, smb_svcenum_t *);
198 static int smb_tree_netinfo_encode(smb_tree_t *, uint8_t *, size_t, uint32_t *);
199 static void smb_tree_netinfo_init(smb_tree_t *tree, smb_netconnectinfo_t *);
200 static void smb_tree_netinfo_fini(smb_netconnectinfo_t *);
201 
202 uint32_t
203 smb_tree_connect(smb_request_t *sr)
204 {
205 	smb_server_t	*sv = sr->sr_server;
206 	uint32_t status;
207 
208 	if (smb_threshold_enter(&sv->sv_tcon_ct) != 0) {
209 		return (NT_STATUS_INSUFF_SERVER_RESOURCES);
210 	}
211 
212 	status = smb_tree_connect_core(sr);
213 	smb_threshold_exit(&sv->sv_tcon_ct);
214 	return (status);
215 }
216 
217 /*
218  * Lookup the share name dispatch the appropriate stype handler.
219  * Share names are case insensitive so we map the share name to
220  * lower-case as a convenience for internal processing.
221  *
222  * Valid service values are:
223  *	A:      Disk share
224  *	LPT1:   Printer
225  *	IPC     Named pipe (IPC$ is reserved as the named pipe share).
226  *	COMM    Communications device
227  *	?????   Any type of device (wildcard)
228  */
229 uint32_t
230 smb_tree_connect_core(smb_request_t *sr)
231 {
232 	smb_arg_tcon_t	*tcon = &sr->sr_tcon;
233 	smb_kshare_t	*si;
234 	char		*name;
235 	uint32_t	status;
236 
237 	(void) smb_strlwr(tcon->path);
238 
239 	if ((name = smb_tree_get_sharename(tcon->path)) == NULL) {
240 		smb_tree_log(sr, tcon->path, "invalid UNC path");
241 		return (NT_STATUS_BAD_NETWORK_NAME);
242 	}
243 
244 	si = smb_kshare_lookup(sr->sr_server, name);
245 	if (si == NULL) {
246 		smb_tree_log(sr, name, "share not found");
247 		return (NT_STATUS_BAD_NETWORK_NAME);
248 	}
249 
250 	if (!strcasecmp(SMB_SHARE_PRINT, name)) {
251 		smb_kshare_release(sr->sr_server, si);
252 		smb_tree_log(sr, name, "access not permitted");
253 		return (NT_STATUS_ACCESS_DENIED);
254 	}
255 
256 	/* NB: name points into tcon->path - don't free it. */
257 	tcon->name = name;
258 	sr->sr_tcon.si = si;
259 
260 	/*
261 	 * [MS-SMB2] 3.3.5.7 Receiving an SMB2 TREE_CONNECT Request
262 	 *
263 	 * If we support 3.x, RejectUnencryptedAccess is TRUE,
264 	 * if Tcon.EncryptData is TRUE or global EncryptData is TRUE,
265 	 * and the connection doesn't support encryption,
266 	 * return ACCESS_DENIED.
267 	 *
268 	 * If RejectUnencryptedAccess is TRUE, we force max_protocol
269 	 * to at least 3.0. Additionally, if the tree requires encryption,
270 	 * we don't care what we support, we still enforce encryption.
271 	 */
272 	if ((sr->sr_server->sv_cfg.skc_encrypt == SMB_CONFIG_REQUIRED ||
273 	    si->shr_encrypt == SMB_CONFIG_REQUIRED) &&
274 	    (sr->session->srv_cap & SMB2_CAP_ENCRYPTION) == 0) {
275 		status = NT_STATUS_ACCESS_DENIED;
276 		goto out;
277 	}
278 
279 	switch (si->shr_type & STYPE_MASK) {
280 	case STYPE_DISKTREE:
281 		status = smb_tree_connect_disk(sr, &sr->sr_tcon);
282 		break;
283 	case STYPE_IPC:
284 		status = smb_tree_connect_ipc(sr, &sr->sr_tcon);
285 		break;
286 	case STYPE_PRINTQ:
287 		status = smb_tree_connect_printq(sr, &sr->sr_tcon);
288 		break;
289 	default:
290 		status = NT_STATUS_BAD_DEVICE_TYPE;
291 		break;
292 	}
293 
294 out:
295 	smb_kshare_release(sr->sr_server, si);
296 	sr->sr_tcon.si = NULL;
297 
298 	return (status);
299 }
300 
301 /*
302  * Disconnect a tree.
303  *
304  * The "do_exec" arg is obsolete and ignored.
305  */
306 void
307 smb_tree_disconnect(smb_tree_t *tree, boolean_t do_exec)
308 {
309 	_NOTE(ARGUNUSED(do_exec))
310 	smb_shr_execinfo_t execinfo;
311 
312 	ASSERT(tree->t_magic == SMB_TREE_MAGIC);
313 
314 	mutex_enter(&tree->t_mutex);
315 	ASSERT(tree->t_refcnt);
316 
317 	if (!smb_tree_is_connected_locked(tree)) {
318 		mutex_exit(&tree->t_mutex);
319 		return;
320 	}
321 
322 	/*
323 	 * Indicate that the disconnect process has started.
324 	 */
325 	tree->t_state = SMB_TREE_STATE_DISCONNECTING;
326 	mutex_exit(&tree->t_mutex);
327 
328 	/*
329 	 * The files opened under this tree are closed.
330 	 */
331 	smb_ofile_close_all(tree, 0);
332 	/*
333 	 * The directories opened under this tree are closed.
334 	 */
335 	smb_tree_close_odirs(tree, 0);
336 
337 	if ((tree->t_execflags & SMB_EXEC_UNMAP) != 0) {
338 		smb_tree_set_execinfo(tree, &execinfo, SMB_EXEC_UNMAP);
339 		(void) smb_kshare_exec(tree->t_server, &execinfo);
340 	}
341 }
342 
343 /*
344  * Take a reference on a tree.
345  */
346 boolean_t
347 smb_tree_hold(
348     smb_tree_t		*tree)
349 {
350 	SMB_TREE_VALID(tree);
351 
352 	mutex_enter(&tree->t_mutex);
353 
354 	if (smb_tree_is_connected_locked(tree)) {
355 		tree->t_refcnt++;
356 		mutex_exit(&tree->t_mutex);
357 		return (B_TRUE);
358 	}
359 
360 	mutex_exit(&tree->t_mutex);
361 	return (B_FALSE);
362 }
363 
364 /*
365  * Bump the hold count regardless of the tree state.  This is used in
366  * some internal code paths where we've already checked that we had a
367  * valid tree connection, and don't want to deal with the possiblity
368  * that the tree state might have changed to disconnecting after our
369  * original hold was taken.  It's correct to continue processing a
370  * request even when new requests cannot lookup that tree anymore.
371  */
372 void
373 smb_tree_hold_internal(
374     smb_tree_t		*tree)
375 {
376 	SMB_TREE_VALID(tree);
377 
378 	mutex_enter(&tree->t_mutex);
379 	tree->t_refcnt++;
380 	mutex_exit(&tree->t_mutex);
381 }
382 
383 /*
384  * Release a reference on a tree.  If the tree is disconnected and the
385  * reference count falls to zero, post the object for deletion.
386  * Object deletion is deferred to avoid modifying a list while an
387  * iteration may be in progress.
388  */
389 void
390 smb_tree_release(
391     smb_tree_t		*tree)
392 {
393 	SMB_TREE_VALID(tree);
394 
395 	/* flush the ofile and odir lists' delete queues */
396 	smb_llist_flush(&tree->t_ofile_list);
397 	smb_llist_flush(&tree->t_odir_list);
398 
399 	mutex_enter(&tree->t_mutex);
400 	ASSERT(tree->t_refcnt);
401 	tree->t_refcnt--;
402 
403 	switch (tree->t_state) {
404 	case SMB_TREE_STATE_DISCONNECTING:
405 		if (tree->t_refcnt == 0) {
406 			smb_session_t *ssn = tree->t_session;
407 			tree->t_state = SMB_TREE_STATE_DISCONNECTED;
408 			smb_llist_post(&ssn->s_tree_list, tree,
409 			    smb_tree_dealloc);
410 		}
411 		break;
412 	case SMB_TREE_STATE_CONNECTED:
413 		break;
414 	default:
415 		ASSERT(0);
416 		break;
417 	}
418 
419 	mutex_exit(&tree->t_mutex);
420 }
421 
422 /*
423  * Close ofiles and odirs that match pid.
424  */
425 void
426 smb_tree_close_pid(
427     smb_tree_t		*tree,
428     uint32_t		pid)
429 {
430 	ASSERT(tree);
431 	ASSERT(tree->t_magic == SMB_TREE_MAGIC);
432 
433 	smb_ofile_close_all(tree, pid);
434 	smb_tree_close_odirs(tree, pid);
435 }
436 
437 /*
438  * Check whether or not a tree supports the features identified by flags.
439  */
440 boolean_t
441 smb_tree_has_feature(smb_tree_t *tree, uint32_t flags)
442 {
443 	ASSERT(tree);
444 	ASSERT(tree->t_magic == SMB_TREE_MAGIC);
445 
446 	return ((tree->t_flags & flags) == flags);
447 }
448 
449 /*
450  * If the enumeration request is for tree data, handle the request
451  * here.  Otherwise, pass it on to the ofiles.
452  *
453  * This function should be called with a hold on the tree.
454  */
455 int
456 smb_tree_enum(smb_tree_t *tree, smb_svcenum_t *svcenum)
457 {
458 	smb_llist_t	*of_list;
459 	smb_ofile_t	*of;
460 	int		rc = 0;
461 
462 	if (svcenum->se_type == SMB_SVCENUM_TYPE_TREE)
463 		return (smb_tree_enum_private(tree, svcenum));
464 
465 	of_list = &tree->t_ofile_list;
466 	smb_llist_enter(of_list, RW_READER);
467 
468 	of = smb_llist_head(of_list);
469 	while (of) {
470 		if (smb_ofile_hold(of)) {
471 			rc = smb_ofile_enum(of, svcenum);
472 			smb_ofile_release(of);
473 		}
474 		if (rc != 0)
475 			break;
476 		of = smb_llist_next(of_list, of);
477 	}
478 
479 	smb_llist_exit(of_list);
480 
481 	return (rc);
482 }
483 
484 /*
485  * Close a file by its unique id.
486  */
487 int
488 smb_tree_fclose(smb_tree_t *tree, uint32_t uniqid)
489 {
490 	smb_ofile_t	*of;
491 
492 	ASSERT(tree);
493 	ASSERT(tree->t_magic == SMB_TREE_MAGIC);
494 
495 	/*
496 	 * Note that ORPHANED ofiles aren't fclosable, as they have
497 	 * no session, user, or tree by which they might be found.
498 	 * They will eventually expire.
499 	 */
500 	if ((of = smb_ofile_lookup_by_uniqid(tree, uniqid)) == NULL)
501 		return (ENOENT);
502 
503 	if (smb_ofile_disallow_fclose(of)) {
504 		smb_ofile_release(of);
505 		return (EACCES);
506 	}
507 
508 	smb_ofile_close(of, 0);
509 	smb_ofile_release(of);
510 	return (0);
511 }
512 
513 /* *************************** Static Functions ***************************** */
514 
515 #define	SHARES_DIR	".zfs/shares/"
516 
517 /*
518  * Calculates permissions given by the share's ACL to the
519  * user in the passed request.  The default is full access.
520  * If any error occurs, full access is granted.
521  *
522  * Using the vnode of the share path find the root directory
523  * of the mounted file system. Then look to see if there is a
524  * .zfs/shares directory and if there is, lookup the file with
525  * the same name as the share name in it. The ACL set for this
526  * file is the share's ACL which is used for access check here.
527  */
528 static uint32_t
529 smb_tree_acl_access(smb_request_t *sr, const smb_kshare_t *si, vnode_t *pathvp)
530 {
531 	smb_user_t	*user;
532 	cred_t		*cred;
533 	int		rc;
534 	vfs_t		*vfsp;
535 	vnode_t		*root = NULL;
536 	vnode_t		*sharevp = NULL;
537 	char		*sharepath;
538 	struct pathname	pnp;
539 	size_t		size;
540 	uint32_t	access;
541 
542 	user = sr->uid_user;
543 	cred = user->u_cred;
544 	access = ACE_ALL_PERMS;
545 
546 	if (si->shr_flags & SMB_SHRF_AUTOHOME) {
547 		/*
548 		 * An autohome share owner gets full access to the share.
549 		 * Everyone else is denied access.
550 		 */
551 		if (si->shr_uid != crgetuid(cred))
552 			access = 0;
553 
554 		return (access);
555 	}
556 
557 	/*
558 	 * The hold on 'root' is released by the lookuppnvp() that follows
559 	 */
560 	vfsp = pathvp->v_vfsp;
561 	if (vfsp != NULL)
562 		rc = VFS_ROOT(vfsp, &root);
563 	else
564 		rc = ENOENT;
565 
566 	if (rc != 0)
567 		return (access);
568 
569 
570 	size = sizeof (SHARES_DIR) + strlen(si->shr_name) + 1;
571 	sharepath = smb_srm_alloc(sr, size);
572 	(void) snprintf(sharepath, size, "%s%s", SHARES_DIR, si->shr_name);
573 
574 	pn_alloc(&pnp);
575 	(void) pn_set(&pnp, sharepath);
576 	rc = lookuppnvp(&pnp, NULL, NO_FOLLOW, NULL, &sharevp, rootdir, root,
577 	    zone_kcred());
578 	pn_free(&pnp);
579 
580 	/*
581 	 * Now get the effective access value based on cred and ACL values.
582 	 */
583 	if (rc == 0) {
584 		smb_vop_eaccess(sharevp, (int *)&access, V_ACE_MASK, NULL,
585 		    cred);
586 		VN_RELE(sharevp);
587 	}
588 
589 	return (access);
590 }
591 
592 /*
593  * Performs the following access checks for a disk share:
594  *
595  *  - No IPC/anonymous user is allowed
596  *
597  *  - If user is Guest, guestok property of the share should be
598  *    enabled
599  *
600  *  - If this is an Admin share, the user should have administrative
601  *    privileges
602  *
603  *  - Host based access control lists
604  *
605  *  - Share ACL
606  *
607  *  Returns the access allowed or 0 if access is denied.
608  */
609 static uint32_t
610 smb_tree_chkaccess(smb_request_t *sr, smb_kshare_t *shr, vnode_t *vp)
611 {
612 	smb_user_t *user = sr->uid_user;
613 	char *sharename = shr->shr_name;
614 	uint32_t host_access;
615 	uint32_t acl_access;
616 	uint32_t access;
617 
618 	if (user->u_flags & SMB_USER_FLAG_ANON) {
619 		smb_tree_log(sr, sharename, "access denied: IPC only");
620 		return (0);
621 	}
622 
623 	if ((user->u_flags & SMB_USER_FLAG_GUEST) &&
624 	    ((shr->shr_flags & SMB_SHRF_GUEST_OK) == 0)) {
625 		smb_tree_log(sr, sharename, "access denied: guest disabled");
626 		return (0);
627 	}
628 
629 	if ((shr->shr_flags & SMB_SHRF_ADMIN) && !smb_user_is_admin(user)) {
630 		smb_tree_log(sr, sharename, "access denied: not admin");
631 		return (0);
632 	}
633 
634 	host_access = smb_kshare_hostaccess(shr, sr->session);
635 	if ((host_access & ACE_ALL_PERMS) == 0) {
636 		smb_tree_log(sr, sharename, "access denied: host access");
637 		return (0);
638 	}
639 
640 	acl_access = smb_tree_acl_access(sr, shr, vp);
641 	if ((acl_access & ACE_ALL_PERMS) == 0) {
642 		smb_tree_log(sr, sharename, "access denied: share ACL");
643 		return (0);
644 	}
645 
646 	access = host_access & acl_access;
647 	if ((access & ACE_ALL_PERMS) == 0) {
648 		smb_tree_log(sr, sharename, "access denied");
649 		return (0);
650 	}
651 
652 	return (access);
653 }
654 
655 /* How long should tree connect wait for DH import to complete? */
656 int smb_tcon_import_wait = 20; /* sec. */
657 
658 /*
659  * Connect a share for use with files and directories.
660  */
661 uint32_t
662 smb_tree_connect_disk(smb_request_t *sr, smb_arg_tcon_t *tcon)
663 {
664 	char			*sharename = tcon->path;
665 	const char		*any = "?????";
666 	smb_user_t		*user = sr->uid_user;
667 	smb_node_t		*snode = NULL;
668 	smb_kshare_t		*si = tcon->si;
669 	char			*service = tcon->service;
670 	smb_tree_t		*tree;
671 	int			rc;
672 	uint32_t		access;
673 	smb_shr_execinfo_t	execinfo;
674 	clock_t	time;
675 
676 	ASSERT(user);
677 	ASSERT(user->u_cred);
678 
679 	if (service != NULL &&
680 	    strcmp(service, any) != 0 &&
681 	    strcasecmp(service, "A:") != 0) {
682 		smb_tree_log(sr, sharename, "invalid service (%s)", service);
683 		return (NT_STATUS_BAD_DEVICE_TYPE);
684 	}
685 
686 	/*
687 	 * Check that the shared directory exists.
688 	 */
689 	snode = si->shr_root_node;
690 	if (snode == NULL) {
691 		smb_tree_log(sr, sharename, "bad path: %s", si->shr_path);
692 		return (NT_STATUS_BAD_NETWORK_NAME);
693 	}
694 
695 	if ((access = smb_tree_chkaccess(sr, si, snode->vp)) == 0) {
696 		return (NT_STATUS_ACCESS_DENIED);
697 	}
698 
699 	/*
700 	 * Wait for DH import of persistent handles to finish.
701 	 * If we timeout, it's not clear what status to return,
702 	 * but as the share is not really available yet, let's
703 	 * return the status for "no such share".
704 	 */
705 	time = SEC_TO_TICK(smb_tcon_import_wait) + ddi_get_lbolt();
706 	mutex_enter(&si->shr_mutex);
707 	while (si->shr_import_busy != NULL) {
708 		if (cv_timedwait(&si->shr_cv, &si->shr_mutex, time) < 0) {
709 			mutex_exit(&si->shr_mutex);
710 			return (NT_STATUS_BAD_NETWORK_NAME);
711 		}
712 	}
713 	mutex_exit(&si->shr_mutex);
714 
715 	/*
716 	 * Set up the OptionalSupport for this share.
717 	 */
718 	tcon->optional_support = SMB_SUPPORT_SEARCH_BITS;
719 
720 	switch (si->shr_flags & SMB_SHRF_CSC_MASK) {
721 	case SMB_SHRF_CSC_DISABLED:
722 		tcon->optional_support |= SMB_CSC_CACHE_NONE;
723 		break;
724 	case SMB_SHRF_CSC_AUTO:
725 		tcon->optional_support |= SMB_CSC_CACHE_AUTO_REINT;
726 		break;
727 	case SMB_SHRF_CSC_VDO:
728 		tcon->optional_support |= SMB_CSC_CACHE_VDO;
729 		break;
730 	case SMB_SHRF_CSC_MANUAL:
731 	default:
732 		/*
733 		 * Default to SMB_CSC_CACHE_MANUAL_REINT.
734 		 */
735 		break;
736 	}
737 
738 	/* ABE support */
739 	if (si->shr_flags & SMB_SHRF_ABE)
740 		tcon->optional_support |=
741 		    SHI1005_FLAGS_ACCESS_BASED_DIRECTORY_ENUM;
742 
743 	if (si->shr_flags & SMB_SHRF_DFSROOT)
744 		tcon->optional_support |= SMB_SHARE_IS_IN_DFS;
745 
746 	/* if 'smb' zfs property: shortnames=disabled */
747 	if (!smb_shortnames)
748 		sr->arg.tcon.optional_support |= SMB_UNIQUE_FILE_NAME;
749 
750 	tree = smb_tree_alloc(sr, si, snode, access, sr->sr_cfg->skc_execflags);
751 
752 	if (tree == NULL)
753 		return (NT_STATUS_INSUFF_SERVER_RESOURCES);
754 
755 	if (tree->t_execflags & SMB_EXEC_MAP) {
756 		smb_tree_set_execinfo(tree, &execinfo, SMB_EXEC_MAP);
757 
758 		rc = smb_kshare_exec(tree->t_server, &execinfo);
759 
760 		if ((rc != 0) && (tree->t_execflags & SMB_EXEC_TERM)) {
761 			/*
762 			 * Inline parts of: smb_tree_disconnect()
763 			 * Not using smb_tree_disconnect() for cleanup
764 			 * here because: we don't want an exec up-call,
765 			 * and there can't be any opens as we never
766 			 * returned this TID to the client.
767 			 */
768 			mutex_enter(&tree->t_mutex);
769 			tree->t_state = SMB_TREE_STATE_DISCONNECTING;
770 			mutex_exit(&tree->t_mutex);
771 
772 			smb_tree_release(tree);
773 			return (NT_STATUS_ACCESS_DENIED);
774 		}
775 	}
776 
777 	sr->tid_tree = tree;
778 	sr->smb_tid  = tree->t_tid;
779 
780 	return (0);
781 }
782 
783 /*
784  * Shares have both a share and host based access control.  The access
785  * granted will be minimum permissions based on both hostaccess
786  * (permissions allowed by host based access) and aclaccess (from the
787  * share ACL).
788  */
789 uint32_t
790 smb_tree_connect_printq(smb_request_t *sr, smb_arg_tcon_t *tcon)
791 {
792 	char			*sharename = tcon->path;
793 	const char		*any = "?????";
794 	smb_user_t		*user = sr->uid_user;
795 	smb_node_t		*dnode = NULL;
796 	smb_node_t		*snode = NULL;
797 	smb_kshare_t		*si = tcon->si;
798 	char			*service = tcon->service;
799 	char			last_component[MAXNAMELEN];
800 	smb_tree_t		*tree;
801 	int			rc;
802 	uint32_t		access;
803 
804 	ASSERT(user);
805 	ASSERT(user->u_cred);
806 
807 	if (sr->sr_server->sv_cfg.skc_print_enable == 0) {
808 		smb_tree_log(sr, sharename, "printing disabled");
809 		return (NT_STATUS_BAD_NETWORK_NAME);
810 	}
811 
812 	if (service != NULL &&
813 	    strcmp(service, any) != 0 &&
814 	    strcasecmp(service, "LPT1:") != 0) {
815 		smb_tree_log(sr, sharename, "invalid service (%s)", service);
816 		return (NT_STATUS_BAD_DEVICE_TYPE);
817 	}
818 
819 	/*
820 	 * Check that the shared directory exists.
821 	 */
822 	rc = smb_pathname_reduce(sr, user->u_cred, si->shr_path, 0, 0, &dnode,
823 	    last_component);
824 	if (rc == 0) {
825 		rc = smb_fsop_lookup(sr, user->u_cred, SMB_FOLLOW_LINKS,
826 		    sr->sr_server->si_root_smb_node, dnode, last_component,
827 		    &snode);
828 
829 		smb_node_release(dnode);
830 	}
831 
832 	if (rc) {
833 		if (snode)
834 			smb_node_release(snode);
835 
836 		smb_tree_log(sr, sharename, "bad path: %s", si->shr_path);
837 		return (NT_STATUS_BAD_NETWORK_NAME);
838 	}
839 
840 	if ((access = smb_tree_chkaccess(sr, si, snode->vp)) == 0) {
841 		smb_node_release(snode);
842 		return (NT_STATUS_ACCESS_DENIED);
843 	}
844 
845 	tcon->optional_support = SMB_SUPPORT_SEARCH_BITS;
846 
847 	tree = smb_tree_alloc(sr, si, snode, access, sr->sr_cfg->skc_execflags);
848 
849 	smb_node_release(snode);
850 
851 	if (tree == NULL)
852 		return (NT_STATUS_INSUFF_SERVER_RESOURCES);
853 
854 	sr->tid_tree = tree;
855 	sr->smb_tid  = tree->t_tid;
856 
857 	return (0);
858 }
859 
860 /*
861  * Connect an IPC share for use with named pipes.
862  */
863 uint32_t
864 smb_tree_connect_ipc(smb_request_t *sr, smb_arg_tcon_t *tcon)
865 {
866 	char		*name = tcon->path;
867 	const char	*any = "?????";
868 	smb_user_t	*user = sr->uid_user;
869 	smb_tree_t	*tree;
870 	smb_kshare_t	*si = tcon->si;
871 	char		*service = tcon->service;
872 
873 	ASSERT(user);
874 
875 	if (service != NULL &&
876 	    strcmp(service, any) != 0 &&
877 	    strcasecmp(service, "IPC") != 0) {
878 		smb_tree_log(sr, name, "invalid service (%s)", service);
879 		return (NT_STATUS_BAD_DEVICE_TYPE);
880 	}
881 
882 	if ((user->u_flags & SMB_USER_FLAG_ANON) &&
883 	    sr->sr_cfg->skc_restrict_anon) {
884 		smb_tree_log(sr, name, "access denied: restrict anonymous");
885 		return (NT_STATUS_ACCESS_DENIED);
886 	}
887 
888 	tcon->optional_support = SMB_SUPPORT_SEARCH_BITS;
889 
890 	tree = smb_tree_alloc(sr, si, NULL, ACE_ALL_PERMS, 0);
891 	if (tree == NULL)
892 		return (NT_STATUS_INSUFF_SERVER_RESOURCES);
893 
894 	sr->tid_tree = tree;
895 	sr->smb_tid  = tree->t_tid;
896 
897 	return (0);
898 }
899 
900 /*
901  * Allocate a tree.
902  */
903 smb_tree_t *
904 smb_tree_alloc(smb_request_t *sr, const smb_kshare_t *si,
905     smb_node_t *snode, uint32_t access, uint32_t execflags)
906 {
907 	smb_session_t	*session = sr->session;
908 	smb_tree_t	*tree;
909 	uint32_t	stype = si->shr_type;
910 	uint16_t	tid;
911 
912 	if (smb_idpool_alloc(&session->s_tid_pool, &tid))
913 		return (NULL);
914 
915 	tree = kmem_cache_alloc(smb_cache_tree, KM_SLEEP);
916 	bzero(tree, sizeof (smb_tree_t));
917 
918 	tree->t_session = session;
919 	tree->t_server = session->s_server;
920 
921 	if (STYPE_ISDSK(stype) || STYPE_ISPRN(stype)) {
922 		if (smb_tree_getattr(si, snode, tree) != 0) {
923 			smb_idpool_free(&session->s_tid_pool, tid);
924 			kmem_cache_free(smb_cache_tree, tree);
925 			return (NULL);
926 		}
927 	}
928 
929 	if (smb_idpool_constructor(&tree->t_fid_pool)) {
930 		smb_idpool_free(&session->s_tid_pool, tid);
931 		kmem_cache_free(smb_cache_tree, tree);
932 		return (NULL);
933 	}
934 
935 	if (smb_idpool_constructor(&tree->t_odid_pool)) {
936 		smb_idpool_destructor(&tree->t_fid_pool);
937 		smb_idpool_free(&session->s_tid_pool, tid);
938 		kmem_cache_free(smb_cache_tree, tree);
939 		return (NULL);
940 	}
941 
942 	smb_llist_constructor(&tree->t_ofile_list, sizeof (smb_ofile_t),
943 	    offsetof(smb_ofile_t, f_tree_lnd));
944 
945 	smb_llist_constructor(&tree->t_odir_list, sizeof (smb_odir_t),
946 	    offsetof(smb_odir_t, d_lnd));
947 
948 	(void) strlcpy(tree->t_sharename, si->shr_name,
949 	    sizeof (tree->t_sharename));
950 	(void) strlcpy(tree->t_resource, si->shr_path,
951 	    sizeof (tree->t_resource));
952 
953 	mutex_init(&tree->t_mutex, NULL, MUTEX_DEFAULT, NULL);
954 
955 	tree->t_refcnt = 1;
956 	tree->t_tid = tid;
957 	tree->t_res_type = stype;
958 	tree->t_state = SMB_TREE_STATE_CONNECTED;
959 	tree->t_magic = SMB_TREE_MAGIC;
960 	tree->t_access = access;
961 	tree->t_connect_time = gethrestime_sec();
962 	tree->t_execflags = execflags;
963 
964 	/* grab a ref for tree->t_owner */
965 	smb_user_hold_internal(sr->uid_user);
966 	smb_user_inc_trees(sr->uid_user);
967 	tree->t_owner = sr->uid_user;
968 
969 	/* if FS is readonly, enforce that here */
970 	if (tree->t_flags & SMB_TREE_READONLY)
971 		tree->t_access &= ~ACE_ALL_WRITE_PERMS;
972 
973 	if (STYPE_ISDSK(stype) || STYPE_ISPRN(stype)) {
974 		smb_node_ref(snode);
975 		tree->t_snode = snode;
976 		tree->t_acltype = smb_fsop_acltype(snode);
977 	}
978 
979 	smb_llist_enter(&session->s_tree_list, RW_WRITER);
980 	smb_llist_insert_head(&session->s_tree_list, tree);
981 	smb_llist_exit(&session->s_tree_list);
982 	atomic_inc_32(&session->s_tree_cnt);
983 	smb_server_inc_trees(session->s_server);
984 	return (tree);
985 }
986 
987 /*
988  * Deallocate a tree.  The open file and open directory lists should be
989  * empty.
990  *
991  * Remove the tree from the user's tree list before freeing resources
992  * associated with the tree.
993  */
994 static void
995 smb_tree_dealloc(void *arg)
996 {
997 	smb_session_t	*session;
998 	smb_tree_t	*tree = (smb_tree_t *)arg;
999 
1000 	SMB_TREE_VALID(tree);
1001 	ASSERT(tree->t_state == SMB_TREE_STATE_DISCONNECTED);
1002 	ASSERT(tree->t_refcnt == 0);
1003 
1004 	smb_server_dec_trees(tree->t_server);
1005 
1006 	session = tree->t_session;
1007 	smb_llist_enter(&session->s_tree_list, RW_WRITER);
1008 	smb_llist_remove(&session->s_tree_list, tree);
1009 	smb_idpool_free(&session->s_tid_pool, tree->t_tid);
1010 	atomic_dec_32(&session->s_tree_cnt);
1011 	smb_llist_exit(&session->s_tree_list);
1012 
1013 	/*
1014 	 * This tree is no longer on s_tree_list, however...
1015 	 *
1016 	 * This is called via smb_llist_post, which means it may run
1017 	 * BEFORE smb_tree_release drops t_mutex (if another thread
1018 	 * flushes the delete queue before we do).  Synchronize.
1019 	 */
1020 	mutex_enter(&tree->t_mutex);
1021 	mutex_exit(&tree->t_mutex);
1022 
1023 	tree->t_magic = (uint32_t)~SMB_TREE_MAGIC;
1024 
1025 	if (tree->t_snode)
1026 		smb_node_release(tree->t_snode);
1027 
1028 	mutex_destroy(&tree->t_mutex);
1029 	smb_llist_destructor(&tree->t_ofile_list);
1030 	smb_llist_destructor(&tree->t_odir_list);
1031 	smb_idpool_destructor(&tree->t_fid_pool);
1032 	smb_idpool_destructor(&tree->t_odid_pool);
1033 
1034 	SMB_USER_VALID(tree->t_owner);
1035 	smb_user_dec_trees(tree->t_owner);
1036 	smb_user_release(tree->t_owner);
1037 
1038 	kmem_cache_free(smb_cache_tree, tree);
1039 }
1040 
1041 /*
1042  * Determine whether or not a tree is connected.
1043  * This function must be called with the tree mutex held.
1044  */
1045 static boolean_t
1046 smb_tree_is_connected_locked(smb_tree_t *tree)
1047 {
1048 	switch (tree->t_state) {
1049 	case SMB_TREE_STATE_CONNECTED:
1050 		return (B_TRUE);
1051 
1052 	case SMB_TREE_STATE_DISCONNECTING:
1053 	case SMB_TREE_STATE_DISCONNECTED:
1054 		/*
1055 		 * The tree exists but is being disconnected or destroyed.
1056 		 */
1057 		return (B_FALSE);
1058 
1059 	default:
1060 		ASSERT(0);
1061 		return (B_FALSE);
1062 	}
1063 }
1064 
1065 /*
1066  * Return a pointer to the share name within a share resource path.
1067  *
1068  * The share path may be a Uniform Naming Convention (UNC) string
1069  * (\\server\share) or simply the share name.  We validate the UNC
1070  * format but we don't look at the server name.
1071  */
1072 static char *
1073 smb_tree_get_sharename(char *unc_path)
1074 {
1075 	char *sharename = unc_path;
1076 
1077 	if (sharename[0] == '\\') {
1078 		/*
1079 		 * Looks like a UNC path, validate the format.
1080 		 */
1081 		if (sharename[1] != '\\')
1082 			return (NULL);
1083 
1084 		if ((sharename = strchr(sharename+2, '\\')) == NULL)
1085 			return (NULL);
1086 
1087 		++sharename;
1088 	} else if (strchr(sharename, '\\') != NULL) {
1089 		/*
1090 		 * This should be a share name (no embedded \'s).
1091 		 */
1092 		return (NULL);
1093 	}
1094 
1095 	return (sharename);
1096 }
1097 
1098 /*
1099  * Obtain the tree attributes: volume name, typename and flags.
1100  */
1101 static int
1102 smb_tree_getattr(const smb_kshare_t *si, smb_node_t *node, smb_tree_t *tree)
1103 {
1104 	vfs_t *vfsp = SMB_NODE_VFS(node);
1105 	vfs_t *realvfsp;
1106 	smb_cfg_val_t srv_encrypt;
1107 
1108 	ASSERT(vfsp);
1109 
1110 	smb_tree_get_creation(node, tree);
1111 	smb_tree_get_volname(vfsp, tree);
1112 
1113 	/*
1114 	 * In the case of an lofs mount, we need to ask the (real)
1115 	 * underlying filesystem about capabilities, where the
1116 	 * passed in vfs_t will be from lofs.
1117 	 */
1118 	realvfsp = getvfs(&vfsp->vfs_fsid);
1119 	if (realvfsp != NULL) {
1120 		smb_tree_get_flags(si, realvfsp, tree);
1121 		VFS_RELE(realvfsp);
1122 	} else {
1123 		cmn_err(CE_NOTE, "Failed getting info for share: %s",
1124 		    si->shr_name);
1125 		/* do the best we can without realvfsp */
1126 		smb_tree_get_flags(si, vfsp, tree);
1127 	}
1128 
1129 	srv_encrypt = tree->t_session->s_server->sv_cfg.skc_encrypt;
1130 	if (tree->t_session->dialect >= SMB_VERS_3_0) {
1131 		if (si->shr_encrypt == SMB_CONFIG_REQUIRED ||
1132 		    srv_encrypt == SMB_CONFIG_REQUIRED)
1133 			tree->t_encrypt = SMB_CONFIG_REQUIRED;
1134 		else if (si->shr_encrypt == SMB_CONFIG_ENABLED ||
1135 		    srv_encrypt == SMB_CONFIG_ENABLED)
1136 			tree->t_encrypt = SMB_CONFIG_ENABLED;
1137 		else
1138 			tree->t_encrypt = SMB_CONFIG_DISABLED;
1139 	} else
1140 		tree->t_encrypt = SMB_CONFIG_DISABLED;
1141 
1142 	return (0);
1143 }
1144 
1145 /*
1146  * File volume creation time
1147  */
1148 static void
1149 smb_tree_get_creation(smb_node_t *node, smb_tree_t *tree)
1150 {
1151 	smb_attr_t	attr;
1152 	cred_t		*kcr = zone_kcred();
1153 
1154 	bzero(&attr, sizeof (attr));
1155 	attr.sa_mask = SMB_AT_CRTIME;
1156 	(void) smb_node_getattr(NULL, node, kcr, NULL, &attr);
1157 	/* On failure we'll have time zero, which is OK */
1158 
1159 	tree->t_create_time = attr.sa_crtime;
1160 }
1161 
1162 /*
1163  * Extract the volume name.
1164  */
1165 static void
1166 smb_tree_get_volname(vfs_t *vfsp, smb_tree_t *tree)
1167 {
1168 #ifdef	_FAKE_KERNEL
1169 	_NOTE(ARGUNUSED(vfsp))
1170 	(void) strlcpy(tree->t_volume, "fake", SMB_VOLNAMELEN);
1171 #else	/* _FAKE_KERNEL */
1172 	refstr_t *vfs_mntpoint;
1173 	const char *s;
1174 	char *name;
1175 
1176 	vfs_mntpoint = vfs_getmntpoint(vfsp);
1177 
1178 	s = refstr_value(vfs_mntpoint);
1179 	s += strspn(s, "/");
1180 	(void) strlcpy(tree->t_volume, s, SMB_VOLNAMELEN);
1181 
1182 	refstr_rele(vfs_mntpoint);
1183 
1184 	name = tree->t_volume;
1185 	(void) strsep((char **)&name, "/");
1186 #endif	/* _FAKE_KERNEL */
1187 }
1188 
1189 /*
1190  * Always set "unicode on disk" because we always use utf8 names locally.
1191  * Always set ACL support because the VFS will fake ACLs for file systems
1192  * that don't support them.
1193  *
1194  * Some flags are dependent on the typename, which is also set up here.
1195  * File system types are hardcoded in uts/common/os/vfs_conf.c.
1196  */
1197 static void
1198 smb_tree_get_flags(const smb_kshare_t *si, vfs_t *vfsp, smb_tree_t *tree)
1199 {
1200 	smb_session_t *ssn = tree->t_session;
1201 	struct vfssw	*vswp;
1202 
1203 	typedef struct smb_mtype {
1204 		char		*mt_name;
1205 		size_t		mt_namelen;
1206 		uint32_t	mt_flags;
1207 	} smb_mtype_t;
1208 
1209 	static smb_mtype_t smb_mtype[] = {
1210 #ifdef	_FAKE_KERNEL
1211 		/* See libfksmbsrv:fake_vfs.c */
1212 		{ "fake",    3,	SMB_TREE_SPARSE},
1213 #endif	/* _FAKE_KERNEL */
1214 		{ "zfs",    3,	SMB_TREE_QUOTA | SMB_TREE_SPARSE},
1215 		{ "ufs",    3,	0 },
1216 		{ "nfs",    3,	SMB_TREE_NFS_MOUNTED },
1217 		{ "tmpfs",  5,	SMB_TREE_NO_EXPORT }
1218 	};
1219 	smb_mtype_t	*mtype;
1220 	char		*name;
1221 	uint32_t	flags =
1222 	    SMB_TREE_SUPPORTS_ACLS |
1223 	    SMB_TREE_UNICODE_ON_DISK;
1224 	int		i;
1225 
1226 	if (si->shr_flags & SMB_SHRF_DFSROOT)
1227 		flags |= SMB_TREE_DFSROOT;
1228 
1229 	if (si->shr_flags & SMB_SHRF_CATIA)
1230 		flags |= SMB_TREE_CATIA;
1231 
1232 	if (si->shr_flags & SMB_SHRF_ABE)
1233 		flags |= SMB_TREE_ABE;
1234 
1235 	if (si->shr_flags & SMB_SHRF_CA)
1236 		flags |= SMB_TREE_CA;
1237 
1238 	if (si->shr_flags & SMB_SHRF_FSO)
1239 		flags |= SMB_TREE_FORCE_L2_OPLOCK;
1240 
1241 	if (ssn->s_cfg.skc_oplock_enable) {
1242 		/* if 'smb' zfs property: oplocks=enabled */
1243 		flags |= SMB_TREE_OPLOCKS;
1244 	}
1245 
1246 	/* Global config option for now.  Later make per-share. */
1247 	if (ssn->s_cfg.skc_traverse_mounts)
1248 		flags |= SMB_TREE_TRAVERSE_MOUNTS;
1249 
1250 	/* if 'smb' zfs property: shortnames=enabled */
1251 	if (smb_shortnames)
1252 		flags |= SMB_TREE_SHORTNAMES;
1253 
1254 	if (vfsp->vfs_flag & VFS_RDONLY)
1255 		flags |= SMB_TREE_READONLY;
1256 
1257 	if (vfsp->vfs_flag & VFS_XATTR)
1258 		flags |= SMB_TREE_STREAMS;
1259 
1260 	vswp = vfs_getvfsswbyvfsops(vfs_getops(vfsp));
1261 	if (vswp != NULL) {
1262 		name = vswp->vsw_name;
1263 		vfs_unrefvfssw(vswp);
1264 	} else {
1265 		name = "?";
1266 	}
1267 
1268 	for (i = 0; i < sizeof (smb_mtype) / sizeof (smb_mtype[0]); ++i) {
1269 		mtype = &smb_mtype[i];
1270 		if (strncasecmp(name, mtype->mt_name, mtype->mt_namelen) == 0)
1271 			flags |= mtype->mt_flags;
1272 	}
1273 
1274 	/*
1275 	 * SMB_TREE_QUOTA will be on here if the FS is ZFS.  We want to
1276 	 * turn it OFF when the share property says false.
1277 	 */
1278 	if ((si->shr_flags & SMB_SHRF_QUOTAS) == 0)
1279 		flags &= ~SMB_TREE_QUOTA;
1280 
1281 	(void) strlcpy(tree->t_typename, name, SMB_TYPENAMELEN);
1282 	(void) smb_strupr((char *)tree->t_typename);
1283 
1284 	if (vfs_has_feature(vfsp, VFSFT_XVATTR))
1285 		flags |= SMB_TREE_XVATTR;
1286 
1287 	if (vfs_has_feature(vfsp, VFSFT_CASEINSENSITIVE))
1288 		flags |= SMB_TREE_CASEINSENSITIVE;
1289 
1290 	if (vfs_has_feature(vfsp, VFSFT_NOCASESENSITIVE))
1291 		flags |= SMB_TREE_NO_CASESENSITIVE;
1292 
1293 	if (vfs_has_feature(vfsp, VFSFT_DIRENTFLAGS))
1294 		flags |= SMB_TREE_DIRENTFLAGS;
1295 
1296 	if (vfs_has_feature(vfsp, VFSFT_ACLONCREATE))
1297 		flags |= SMB_TREE_ACLONCREATE;
1298 
1299 	if (vfs_has_feature(vfsp, VFSFT_ACEMASKONACCESS))
1300 		flags |= SMB_TREE_ACEMASKONACCESS;
1301 
1302 	DTRACE_PROBE2(smb__tree__flags, uint32_t, flags, char *, name);
1303 
1304 
1305 	tree->t_flags = flags;
1306 }
1307 
1308 /*
1309  * Report share access result to syslog.
1310  */
1311 static void
1312 smb_tree_log(smb_request_t *sr, const char *sharename, const char *fmt, ...)
1313 {
1314 	va_list ap;
1315 	char buf[128];
1316 	smb_user_t *user = sr->uid_user;
1317 
1318 	ASSERT(user);
1319 
1320 	if (smb_tcon_mute)
1321 		return;
1322 
1323 	if ((user->u_name) && (strcasecmp(sharename, "IPC$") == 0)) {
1324 		/*
1325 		 * Only report normal users, i.e. ignore W2K misuse
1326 		 * of the IPC connection by filtering out internal
1327 		 * names such as nobody and root.
1328 		 */
1329 		if ((strcmp(user->u_name, "root") == 0) ||
1330 		    (strcmp(user->u_name, "nobody") == 0)) {
1331 			return;
1332 		}
1333 	}
1334 
1335 	va_start(ap, fmt);
1336 	(void) vsnprintf(buf, 128, fmt, ap);
1337 	va_end(ap);
1338 
1339 	cmn_err(CE_NOTE, "smbd[%s\\%s]: %s %s",
1340 	    user->u_domain, user->u_name, sharename, buf);
1341 }
1342 
1343 /*
1344  * smb_tree_lookup_odir
1345  *
1346  * Find the specified odir in the tree's list of odirs, and
1347  * attempt to obtain a hold on the odir.
1348  *
1349  * Returns NULL if odir not found or a hold cannot be obtained.
1350  */
1351 smb_odir_t *
1352 smb_tree_lookup_odir(smb_request_t *sr, uint16_t odid)
1353 {
1354 	smb_odir_t	*od;
1355 	smb_llist_t	*od_list;
1356 	smb_tree_t	*tree = sr->tid_tree;
1357 
1358 	ASSERT(tree->t_magic == SMB_TREE_MAGIC);
1359 
1360 	od_list = &tree->t_odir_list;
1361 
1362 	smb_llist_enter(od_list, RW_READER);
1363 	od = smb_llist_head(od_list);
1364 	while (od) {
1365 		if (od->d_odid == odid)
1366 			break;
1367 		od = smb_llist_next(od_list, od);
1368 	}
1369 	if (od == NULL)
1370 		goto out;
1371 
1372 	/*
1373 	 * Only allow use of a given Search ID with the same UID that
1374 	 * was used to create it.  MS-CIFS 3.3.5.14
1375 	 */
1376 	if (od->d_user != sr->uid_user) {
1377 		od = NULL;
1378 		goto out;
1379 	}
1380 	if (!smb_odir_hold(od))
1381 		od = NULL;
1382 
1383 out:
1384 	smb_llist_exit(od_list);
1385 	return (od);
1386 }
1387 
1388 boolean_t
1389 smb_tree_is_connected(smb_tree_t *tree)
1390 {
1391 	boolean_t	rb;
1392 
1393 	mutex_enter(&tree->t_mutex);
1394 	rb = smb_tree_is_connected_locked(tree);
1395 	mutex_exit(&tree->t_mutex);
1396 	return (rb);
1397 }
1398 
1399 /*
1400  * smb_tree_close_odirs
1401  *
1402  * Close all open odirs in the tree's list which were opened by
1403  * the process identified by pid.
1404  * If pid is zero, close all open odirs in the tree's list.
1405  */
1406 static void
1407 smb_tree_close_odirs(smb_tree_t *tree, uint32_t pid)
1408 {
1409 	smb_llist_t	*od_list;
1410 	smb_odir_t	*od;
1411 
1412 	ASSERT(tree);
1413 	ASSERT(tree->t_magic == SMB_TREE_MAGIC);
1414 
1415 	od_list = &tree->t_odir_list;
1416 	smb_llist_enter(od_list, RW_READER);
1417 
1418 	for (od = smb_llist_head(od_list);
1419 	    od != NULL;
1420 	    od = smb_llist_next(od_list, od)) {
1421 
1422 		ASSERT(od->d_magic == SMB_ODIR_MAGIC);
1423 		ASSERT(od->d_tree == tree);
1424 
1425 		if (pid != 0 && od->d_opened_by_pid != pid)
1426 			continue;
1427 
1428 		if (smb_odir_hold(od)) {
1429 			smb_odir_close(od);
1430 			smb_odir_release(od);
1431 		}
1432 	}
1433 
1434 	smb_llist_exit(od_list);
1435 }
1436 
1437 static void
1438 smb_tree_set_execinfo(smb_tree_t *tree, smb_shr_execinfo_t *exec,
1439     int exec_type)
1440 {
1441 	exec->e_sharename = tree->t_sharename;
1442 	exec->e_winname = tree->t_owner->u_name;
1443 	exec->e_userdom = tree->t_owner->u_domain;
1444 	exec->e_srv_ipaddr = tree->t_session->local_ipaddr;
1445 	exec->e_cli_ipaddr = tree->t_session->ipaddr;
1446 	exec->e_cli_netbiosname = tree->t_session->workstation;
1447 	exec->e_uid = crgetuid(tree->t_owner->u_cred);
1448 	exec->e_type = exec_type;
1449 }
1450 
1451 /*
1452  * Private function to support smb_tree_enum.
1453  */
1454 static int
1455 smb_tree_enum_private(smb_tree_t *tree, smb_svcenum_t *svcenum)
1456 {
1457 	uint8_t *pb;
1458 	uint_t nbytes;
1459 	int rc;
1460 
1461 	if (svcenum->se_nskip > 0) {
1462 		svcenum->se_nskip--;
1463 		return (0);
1464 	}
1465 
1466 	if (svcenum->se_nitems >= svcenum->se_nlimit) {
1467 		svcenum->se_nitems = svcenum->se_nlimit;
1468 		return (0);
1469 	}
1470 
1471 	pb = &svcenum->se_buf[svcenum->se_bused];
1472 	rc = smb_tree_netinfo_encode(tree, pb, svcenum->se_bavail, &nbytes);
1473 	if (rc == 0) {
1474 		svcenum->se_bavail -= nbytes;
1475 		svcenum->se_bused += nbytes;
1476 		svcenum->se_nitems++;
1477 	}
1478 
1479 	return (rc);
1480 }
1481 
1482 /*
1483  * Encode connection information into a buffer: connection information
1484  * needed in user space to support RPC requests.
1485  */
1486 static int
1487 smb_tree_netinfo_encode(smb_tree_t *tree, uint8_t *buf, size_t buflen,
1488     uint32_t *nbytes)
1489 {
1490 	smb_netconnectinfo_t	info;
1491 	int			rc;
1492 
1493 	smb_tree_netinfo_init(tree, &info);
1494 	rc = smb_netconnectinfo_encode(&info, buf, buflen, nbytes);
1495 	smb_tree_netinfo_fini(&info);
1496 
1497 	return (rc);
1498 }
1499 
1500 static void
1501 smb_tree_netinfo_username(smb_tree_t *tree, char **namestr, uint32_t *namelen)
1502 {
1503 	smb_user_t		*user = tree->t_owner;
1504 
1505 	/*
1506 	 * u_domain_len and u_name_len include the '\0' in their
1507 	 * lengths, hence the sum of the two lengths gives us room
1508 	 * for both the '\\' and '\0' chars.
1509 	 */
1510 	ASSERT(namestr);
1511 	ASSERT(namelen);
1512 	ASSERT(user->u_domain_len > 0);
1513 	ASSERT(user->u_name_len > 0);
1514 	*namelen = user->u_domain_len + user->u_name_len;
1515 	*namestr = kmem_alloc(*namelen, KM_SLEEP);
1516 	(void) snprintf(*namestr, *namelen, "%s\\%s", user->u_domain,
1517 	    user->u_name);
1518 }
1519 
1520 /*
1521  * Note: ci_numusers should be the number of users connected to
1522  * the share rather than the number of references on the tree but
1523  * we don't have a mechanism to track users/share in smbsrv yet.
1524  */
1525 static void
1526 smb_tree_netinfo_init(smb_tree_t *tree, smb_netconnectinfo_t *info)
1527 {
1528 	ASSERT(tree);
1529 
1530 	info->ci_id = tree->t_tid;
1531 	info->ci_type = tree->t_res_type;
1532 	info->ci_numopens = tree->t_open_files;
1533 	info->ci_numusers = tree->t_refcnt;
1534 	info->ci_time = gethrestime_sec() - tree->t_connect_time;
1535 
1536 	info->ci_sharelen = strlen(tree->t_sharename) + 1;
1537 	info->ci_share = smb_mem_strdup(tree->t_sharename);
1538 
1539 	smb_tree_netinfo_username(tree, &info->ci_username, &info->ci_namelen);
1540 }
1541 
1542 static void
1543 smb_tree_netinfo_fini(smb_netconnectinfo_t *info)
1544 {
1545 	if (info == NULL)
1546 		return;
1547 
1548 	if (info->ci_username)
1549 		kmem_free(info->ci_username, info->ci_namelen);
1550 	if (info->ci_share)
1551 		smb_mem_free(info->ci_share);
1552 
1553 	bzero(info, sizeof (smb_netconnectinfo_t));
1554 }
1555