1da6c28aaSamw /*
2da6c28aaSamw * CDDL HEADER START
3da6c28aaSamw *
4da6c28aaSamw * The contents of this file are subject to the terms of the
5da6c28aaSamw * Common Development and Distribution License (the "License").
6da6c28aaSamw * You may not use this file except in compliance with the License.
7da6c28aaSamw *
8da6c28aaSamw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9da6c28aaSamw * or http://www.opensolaris.org/os/licensing.
10da6c28aaSamw * See the License for the specific language governing permissions
11da6c28aaSamw * and limitations under the License.
12da6c28aaSamw *
13da6c28aaSamw * When distributing Covered Code, include this CDDL HEADER in each
14da6c28aaSamw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15da6c28aaSamw * If applicable, add the following below this CDDL HEADER, with the
16da6c28aaSamw * fields enclosed by brackets "[]" replaced with your own identifying
17da6c28aaSamw * information: Portions Copyright [yyyy] [name of copyright owner]
18da6c28aaSamw *
19da6c28aaSamw * CDDL HEADER END
20da6c28aaSamw */
21148c5f43SAlan Wright
22da6c28aaSamw /*
23c5866007SKeyur Desai * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
2448bbca81SDaniel Hoffman * Copyright (c) 2016 by Delphix. All rights reserved.
25814e0daaSGordon Ross * Copyright 2022 Tintri by DDN, Inc. All rights reserved.
262cf6b79fSGordon Ross * Copyright 2022 RackTop Systems, Inc.
27da6c28aaSamw */
28da6c28aaSamw
29da6c28aaSamw /*
30da6c28aaSamw * General Structures Layout
31da6c28aaSamw * -------------------------
32da6c28aaSamw *
33da6c28aaSamw * This is a simplified diagram showing the relationship between most of the
34da6c28aaSamw * main structures.
35da6c28aaSamw *
36da6c28aaSamw * +-------------------+
37da6c28aaSamw * | SMB_INFO |
38da6c28aaSamw * +-------------------+
39da6c28aaSamw * |
40da6c28aaSamw * |
41da6c28aaSamw * v
42da6c28aaSamw * +-------------------+ +-------------------+ +-------------------+
43da6c28aaSamw * | SESSION |<----->| SESSION |......| SESSION |
44da6c28aaSamw * +-------------------+ +-------------------+ +-------------------+
453b13a1efSThomas Keiser * | |
463b13a1efSThomas Keiser * | |
473b13a1efSThomas Keiser * | v
483b13a1efSThomas Keiser * | +-------------------+ +-------------------+ +-------------------+
493b13a1efSThomas Keiser * | | USER |<--->| USER |...| USER |
503b13a1efSThomas Keiser * | +-------------------+ +-------------------+ +-------------------+
513b13a1efSThomas Keiser * |
523b13a1efSThomas Keiser * |
533b13a1efSThomas Keiser * v
54da6c28aaSamw * +-------------------+ +-------------------+ +-------------------+
55da6c28aaSamw * | TREE |<----->| TREE |......| TREE |
56da6c28aaSamw * +-------------------+ +-------------------+ +-------------------+
57da6c28aaSamw * | |
58da6c28aaSamw * | |
59da6c28aaSamw * | v
60da6c28aaSamw * | +-------+ +-------+ +-------+
61da6c28aaSamw * | | OFILE |<----->| OFILE |......| OFILE |
62da6c28aaSamw * | +-------+ +-------+ +-------+
63da6c28aaSamw * |
64da6c28aaSamw * |
65da6c28aaSamw * v
66da6c28aaSamw * +-------+ +------+ +------+
67da6c28aaSamw * | ODIR |<----->| ODIR |......| ODIR |
68da6c28aaSamw * +-------+ +------+ +------+
69da6c28aaSamw *
70da6c28aaSamw *
71da6c28aaSamw * Tree State Machine
72da6c28aaSamw * ------------------
73da6c28aaSamw *
74da6c28aaSamw * +-----------------------------+ T0
75da6c28aaSamw * | SMB_TREE_STATE_CONNECTED |<----------- Creation/Allocation
76da6c28aaSamw * +-----------------------------+
77da6c28aaSamw * |
78da6c28aaSamw * | T1
79da6c28aaSamw * |
80da6c28aaSamw * v
81da6c28aaSamw * +------------------------------+
82da6c28aaSamw * | SMB_TREE_STATE_DISCONNECTING |
83da6c28aaSamw * +------------------------------+
84da6c28aaSamw * |
85da6c28aaSamw * | T2
86da6c28aaSamw * |
87da6c28aaSamw * v
88da6c28aaSamw * +-----------------------------+ T3
89da6c28aaSamw * | SMB_TREE_STATE_DISCONNECTED |----------> Deletion/Free
90da6c28aaSamw * +-----------------------------+
91da6c28aaSamw *
92da6c28aaSamw * SMB_TREE_STATE_CONNECTED
93da6c28aaSamw *
94da6c28aaSamw * While in this state:
95da6c28aaSamw * - The tree is queued in the list of trees of its user.
96da6c28aaSamw * - References will be given out if the tree is looked up.
97da6c28aaSamw * - Files under that tree can be accessed.
98da6c28aaSamw *
99da6c28aaSamw * SMB_TREE_STATE_DISCONNECTING
100da6c28aaSamw *
101da6c28aaSamw * While in this state:
102da6c28aaSamw * - The tree is queued in the list of trees of its user.
103da6c28aaSamw * - References will not be given out if the tree is looked up.
104da6c28aaSamw * - The files and directories open under the tree are being closed.
105da6c28aaSamw * - The resources associated with the tree remain.
106da6c28aaSamw *
107da6c28aaSamw * SMB_TREE_STATE_DISCONNECTED
108da6c28aaSamw *
109da6c28aaSamw * While in this state:
110da6c28aaSamw * - The tree is queued in the list of trees of its user.
111da6c28aaSamw * - References will not be given out if the tree is looked up.
112da6c28aaSamw * - The tree has no more files and directories opened.
113da6c28aaSamw * - The resources associated with the tree remain.
114da6c28aaSamw *
115da6c28aaSamw * Transition T0
116da6c28aaSamw *
117da6c28aaSamw * This transition occurs in smb_tree_connect(). A new tree is created and
118da6c28aaSamw * added to the list of trees of a user.
119da6c28aaSamw *
120da6c28aaSamw * Transition T1
121da6c28aaSamw *
122da6c28aaSamw * This transition occurs in smb_tree_disconnect().
123da6c28aaSamw *
124da6c28aaSamw * Transition T2
125da6c28aaSamw *
126811599a4SMatt Barden * This transition occurs in smb_tree_disconnect()
127811599a4SMatt Barden *
128811599a4SMatt Barden * Transition T3
129811599a4SMatt Barden *
130da6c28aaSamw * This transition occurs in smb_tree_release(). The resources associated
131da6c28aaSamw * with the tree are freed as well as the tree structure. For the transition
132811599a4SMatt Barden * to occur, the tree must be in the SMB_TREE_STATE_DISCONNECTED and the
133811599a4SMatt Barden * reference count must be zero.
134da6c28aaSamw *
135da6c28aaSamw * Comments
136da6c28aaSamw * --------
137da6c28aaSamw *
138da6c28aaSamw * The state machine of the tree structures is controlled by 3 elements:
139da6c28aaSamw * - The list of trees of the user it belongs to.
140da6c28aaSamw * - The mutex embedded in the structure itself.
141da6c28aaSamw * - The reference count.
142da6c28aaSamw *
143da6c28aaSamw * There's a mutex embedded in the tree structure used to protect its fields
144da6c28aaSamw * and there's a lock embedded in the list of trees of a user. To
145da6c28aaSamw * increment or to decrement the reference count the mutex must be entered.
146da6c28aaSamw * To insert the tree into the list of trees of the user and to remove
147da6c28aaSamw * the tree from it, the lock must be entered in RW_WRITER mode.
148da6c28aaSamw *
149da6c28aaSamw * Rules of access to a tree structure:
150da6c28aaSamw *
151da6c28aaSamw * 1) In order to avoid deadlocks, when both (mutex and lock of the user
152811599a4SMatt Barden * list) have to be entered, the lock must be entered first. Additionally,
153811599a4SMatt Barden * when both the (mutex and lock of the ofile list) have to be entered,
154811599a4SMatt Barden * the mutex must be entered first. However, the ofile list lock must NOT
155811599a4SMatt Barden * be dropped while the mutex is held in such a way that the ofile deleteq
156811599a4SMatt Barden * is flushed.
157da6c28aaSamw *
158da6c28aaSamw * 2) All actions applied to a tree require a reference count.
159da6c28aaSamw *
160c8ec8eeaSjose borrego * 3) There are 2 ways of getting a reference count: when a tree is
161c8ec8eeaSjose borrego * connected and when a tree is looked up.
162da6c28aaSamw *
163da6c28aaSamw * It should be noted that the reference count of a tree registers the
164da6c28aaSamw * number of references to the tree in other structures (such as an smb
165da6c28aaSamw * request). The reference count is not incremented in these 2 instances:
166da6c28aaSamw *
16748bbca81SDaniel Hoffman * 1) The tree is connected. An tree is anchored by its state. If there's
168da6c28aaSamw * no activity involving a tree currently connected, the reference
169da6c28aaSamw * count of that tree is zero.
170da6c28aaSamw *
171da6c28aaSamw * 2) The tree is queued in the list of trees of the user. The fact of
172da6c28aaSamw * being queued in that list is NOT registered by incrementing the
173da6c28aaSamw * reference count.
174da6c28aaSamw */
175148c5f43SAlan Wright
176c8ec8eeaSjose borrego #include <sys/refstr_impl.h>
177bbf6f00cSJordan Brown #include <smbsrv/smb_kproto.h>
178148c5f43SAlan Wright #include <smbsrv/smb_ktypes.h>
179da6c28aaSamw #include <smbsrv/smb_fsops.h>
180cb174861Sjoyce mcintosh #include <smbsrv/smb_share.h>
181c8ec8eeaSjose borrego
18245f8fdd1SGordon Ross int smb_tcon_mute = 1;
183c8ec8eeaSjose borrego
184a90cf9f2SGordon Ross uint32_t smb_tree_connect_core(smb_request_t *);
185a90cf9f2SGordon Ross uint32_t smb_tree_connect_disk(smb_request_t *, smb_arg_tcon_t *);
186a90cf9f2SGordon Ross uint32_t smb_tree_connect_printq(smb_request_t *, smb_arg_tcon_t *);
187a90cf9f2SGordon Ross uint32_t smb_tree_connect_ipc(smb_request_t *, smb_arg_tcon_t *);
188811599a4SMatt Barden static void smb_tree_dealloc(void *);
1898b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States static boolean_t smb_tree_is_connected_locked(smb_tree_t *);
190a90cf9f2SGordon Ross static char *smb_tree_get_sharename(char *);
191148c5f43SAlan Wright static int smb_tree_getattr(const smb_kshare_t *, smb_node_t *, smb_tree_t *);
19225a9a7aaSGordon Ross static void smb_tree_get_creation(smb_node_t *, smb_tree_t *);
193c8ec8eeaSjose borrego static void smb_tree_get_volname(vfs_t *, smb_tree_t *);
194148c5f43SAlan Wright static void smb_tree_get_flags(const smb_kshare_t *, vfs_t *, smb_tree_t *);
195c8ec8eeaSjose borrego static void smb_tree_log(smb_request_t *, const char *, const char *, ...);
1968d94f651SGordon Ross static void smb_tree_close_odirs(smb_tree_t *, uint32_t);
197148c5f43SAlan Wright static void smb_tree_set_execinfo(smb_tree_t *, smb_shr_execinfo_t *, int);
1981fcced4cSJordan Brown static int smb_tree_enum_private(smb_tree_t *, smb_svcenum_t *);
1991fcced4cSJordan Brown static int smb_tree_netinfo_encode(smb_tree_t *, uint8_t *, size_t, uint32_t *);
2001fcced4cSJordan Brown static void smb_tree_netinfo_init(smb_tree_t *tree, smb_netconnectinfo_t *);
2011fcced4cSJordan Brown static void smb_tree_netinfo_fini(smb_netconnectinfo_t *);
202da6c28aaSamw
203a90cf9f2SGordon Ross uint32_t
smb_tree_connect(smb_request_t * sr)204cb174861Sjoyce mcintosh smb_tree_connect(smb_request_t *sr)
205cb174861Sjoyce mcintosh {
206cb174861Sjoyce mcintosh smb_server_t *sv = sr->sr_server;
207a90cf9f2SGordon Ross uint32_t status;
208cb174861Sjoyce mcintosh
209cb174861Sjoyce mcintosh if (smb_threshold_enter(&sv->sv_tcon_ct) != 0) {
210a90cf9f2SGordon Ross return (NT_STATUS_INSUFF_SERVER_RESOURCES);
211cb174861Sjoyce mcintosh }
212cb174861Sjoyce mcintosh
213a90cf9f2SGordon Ross status = smb_tree_connect_core(sr);
214856399cfSGordon Ross smb_threshold_exit(&sv->sv_tcon_ct);
215a90cf9f2SGordon Ross return (status);
216cb174861Sjoyce mcintosh }
217cb174861Sjoyce mcintosh
218da6c28aaSamw /*
219148c5f43SAlan Wright * Lookup the share name dispatch the appropriate stype handler.
220c8ec8eeaSjose borrego * Share names are case insensitive so we map the share name to
221c8ec8eeaSjose borrego * lower-case as a convenience for internal processing.
222148c5f43SAlan Wright *
223148c5f43SAlan Wright * Valid service values are:
224148c5f43SAlan Wright * A: Disk share
225148c5f43SAlan Wright * LPT1: Printer
226148c5f43SAlan Wright * IPC Named pipe (IPC$ is reserved as the named pipe share).
227148c5f43SAlan Wright * COMM Communications device
228148c5f43SAlan Wright * ????? Any type of device (wildcard)
229da6c28aaSamw */
230a90cf9f2SGordon Ross uint32_t
smb_tree_connect_core(smb_request_t * sr)231cb174861Sjoyce mcintosh smb_tree_connect_core(smb_request_t *sr)
232da6c28aaSamw {
233a90cf9f2SGordon Ross smb_arg_tcon_t *tcon = &sr->sr_tcon;
234148c5f43SAlan Wright smb_kshare_t *si;
235a90cf9f2SGordon Ross char *name;
236a90cf9f2SGordon Ross uint32_t status;
237da6c28aaSamw
238a90cf9f2SGordon Ross (void) smb_strlwr(tcon->path);
239da6c28aaSamw
240a90cf9f2SGordon Ross if ((name = smb_tree_get_sharename(tcon->path)) == NULL) {
241a90cf9f2SGordon Ross smb_tree_log(sr, tcon->path, "invalid UNC path");
242a90cf9f2SGordon Ross return (NT_STATUS_BAD_NETWORK_NAME);
243da6c28aaSamw }
244da6c28aaSamw
2458622ec45SGordon Ross si = smb_kshare_lookup(sr->sr_server, name);
2468622ec45SGordon Ross if (si == NULL) {
247148c5f43SAlan Wright smb_tree_log(sr, name, "share not found");
248a90cf9f2SGordon Ross return (NT_STATUS_BAD_NETWORK_NAME);
249da6c28aaSamw }
250cb174861Sjoyce mcintosh
251cb174861Sjoyce mcintosh if (!strcasecmp(SMB_SHARE_PRINT, name)) {
2528622ec45SGordon Ross smb_kshare_release(sr->sr_server, si);
253cb174861Sjoyce mcintosh smb_tree_log(sr, name, "access not permitted");
254a90cf9f2SGordon Ross return (NT_STATUS_ACCESS_DENIED);
255cb174861Sjoyce mcintosh }
256cb174861Sjoyce mcintosh
257a90cf9f2SGordon Ross /* NB: name points into tcon->path - don't free it. */
258a90cf9f2SGordon Ross tcon->name = name;
259148c5f43SAlan Wright sr->sr_tcon.si = si;
260da6c28aaSamw
2611160dcf7SMatt Barden /*
2621160dcf7SMatt Barden * [MS-SMB2] 3.3.5.7 Receiving an SMB2 TREE_CONNECT Request
2631160dcf7SMatt Barden *
2641160dcf7SMatt Barden * If we support 3.x, RejectUnencryptedAccess is TRUE,
2651160dcf7SMatt Barden * if Tcon.EncryptData is TRUE or global EncryptData is TRUE,
2661160dcf7SMatt Barden * and the connection doesn't support encryption,
2671160dcf7SMatt Barden * return ACCESS_DENIED.
2681160dcf7SMatt Barden *
2691160dcf7SMatt Barden * If RejectUnencryptedAccess is TRUE, we force max_protocol
2701160dcf7SMatt Barden * to at least 3.0. Additionally, if the tree requires encryption,
2711160dcf7SMatt Barden * we don't care what we support, we still enforce encryption.
2721160dcf7SMatt Barden */
2731160dcf7SMatt Barden if ((sr->sr_server->sv_cfg.skc_encrypt == SMB_CONFIG_REQUIRED ||
2741160dcf7SMatt Barden si->shr_encrypt == SMB_CONFIG_REQUIRED) &&
2751160dcf7SMatt Barden (sr->session->srv_cap & SMB2_CAP_ENCRYPTION) == 0) {
2761160dcf7SMatt Barden status = NT_STATUS_ACCESS_DENIED;
2771160dcf7SMatt Barden goto out;
2781160dcf7SMatt Barden }
2791160dcf7SMatt Barden
280148c5f43SAlan Wright switch (si->shr_type & STYPE_MASK) {
281da6c28aaSamw case STYPE_DISKTREE:
282a90cf9f2SGordon Ross status = smb_tree_connect_disk(sr, &sr->sr_tcon);
283da6c28aaSamw break;
284da6c28aaSamw case STYPE_IPC:
285a90cf9f2SGordon Ross status = smb_tree_connect_ipc(sr, &sr->sr_tcon);
286c8ec8eeaSjose borrego break;
287148c5f43SAlan Wright case STYPE_PRINTQ:
288a90cf9f2SGordon Ross status = smb_tree_connect_printq(sr, &sr->sr_tcon);
289148c5f43SAlan Wright break;
290da6c28aaSamw default:
291a90cf9f2SGordon Ross status = NT_STATUS_BAD_DEVICE_TYPE;
292da6c28aaSamw break;
293da6c28aaSamw }
294da6c28aaSamw
2951160dcf7SMatt Barden out:
2968622ec45SGordon Ross smb_kshare_release(sr->sr_server, si);
297a90cf9f2SGordon Ross sr->sr_tcon.si = NULL;
298a90cf9f2SGordon Ross
299a90cf9f2SGordon Ross return (status);
300da6c28aaSamw }
301da6c28aaSamw
302da6c28aaSamw /*
303c8ec8eeaSjose borrego * Disconnect a tree.
3048d94f651SGordon Ross *
3058d94f651SGordon Ross * The "do_exec" arg is obsolete and ignored.
306da6c28aaSamw */
307da6c28aaSamw void
smb_tree_disconnect(smb_tree_t * tree,boolean_t do_exec)30829bd2886SAlan Wright smb_tree_disconnect(smb_tree_t *tree, boolean_t do_exec)
309da6c28aaSamw {
3108d94f651SGordon Ross _NOTE(ARGUNUSED(do_exec))
311148c5f43SAlan Wright smb_shr_execinfo_t execinfo;
31229bd2886SAlan Wright
313da6c28aaSamw ASSERT(tree->t_magic == SMB_TREE_MAGIC);
314da6c28aaSamw
315da6c28aaSamw mutex_enter(&tree->t_mutex);
316da6c28aaSamw ASSERT(tree->t_refcnt);
317c8ec8eeaSjose borrego
3188d94f651SGordon Ross if (!smb_tree_is_connected_locked(tree)) {
319da6c28aaSamw mutex_exit(&tree->t_mutex);
3208d94f651SGordon Ross return;
321da6c28aaSamw }
322da6c28aaSamw
3238d94f651SGordon Ross /*
3248d94f651SGordon Ross * Indicate that the disconnect process has started.
3258d94f651SGordon Ross */
3268d94f651SGordon Ross tree->t_state = SMB_TREE_STATE_DISCONNECTING;
327da6c28aaSamw mutex_exit(&tree->t_mutex);
32829bd2886SAlan Wright
3298d94f651SGordon Ross /*
3308d94f651SGordon Ross * The files opened under this tree are closed.
3318d94f651SGordon Ross */
3328d94f651SGordon Ross smb_ofile_close_all(tree, 0);
3338d94f651SGordon Ross /*
3348d94f651SGordon Ross * The directories opened under this tree are closed.
3358d94f651SGordon Ross */
3368d94f651SGordon Ross smb_tree_close_odirs(tree, 0);
33729bd2886SAlan Wright
3388d94f651SGordon Ross if ((tree->t_execflags & SMB_EXEC_UNMAP) != 0) {
339148c5f43SAlan Wright smb_tree_set_execinfo(tree, &execinfo, SMB_EXEC_UNMAP);
3408622ec45SGordon Ross (void) smb_kshare_exec(tree->t_server, &execinfo);
34129bd2886SAlan Wright }
342da6c28aaSamw }
343da6c28aaSamw
344da6c28aaSamw /*
345c8ec8eeaSjose borrego * Take a reference on a tree.
346da6c28aaSamw */
347c8ec8eeaSjose borrego boolean_t
smb_tree_hold(smb_tree_t * tree)348c8ec8eeaSjose borrego smb_tree_hold(
349c8ec8eeaSjose borrego smb_tree_t *tree)
350da6c28aaSamw {
351a90cf9f2SGordon Ross SMB_TREE_VALID(tree);
352da6c28aaSamw
353c8ec8eeaSjose borrego mutex_enter(&tree->t_mutex);
354c8ec8eeaSjose borrego
3558b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (smb_tree_is_connected_locked(tree)) {
356c8ec8eeaSjose borrego tree->t_refcnt++;
357c8ec8eeaSjose borrego mutex_exit(&tree->t_mutex);
358c8ec8eeaSjose borrego return (B_TRUE);
359da6c28aaSamw }
360c8ec8eeaSjose borrego
361c8ec8eeaSjose borrego mutex_exit(&tree->t_mutex);
362c8ec8eeaSjose borrego return (B_FALSE);
363da6c28aaSamw }
364da6c28aaSamw
365a90cf9f2SGordon Ross /*
366a90cf9f2SGordon Ross * Bump the hold count regardless of the tree state. This is used in
367a90cf9f2SGordon Ross * some internal code paths where we've already checked that we had a
368a90cf9f2SGordon Ross * valid tree connection, and don't want to deal with the possiblity
369a90cf9f2SGordon Ross * that the tree state might have changed to disconnecting after our
370a90cf9f2SGordon Ross * original hold was taken. It's correct to continue processing a
371a90cf9f2SGordon Ross * request even when new requests cannot lookup that tree anymore.
372a90cf9f2SGordon Ross */
373a90cf9f2SGordon Ross void
smb_tree_hold_internal(smb_tree_t * tree)374a90cf9f2SGordon Ross smb_tree_hold_internal(
375a90cf9f2SGordon Ross smb_tree_t *tree)
376a90cf9f2SGordon Ross {
377a90cf9f2SGordon Ross SMB_TREE_VALID(tree);
378a90cf9f2SGordon Ross
379a90cf9f2SGordon Ross mutex_enter(&tree->t_mutex);
380a90cf9f2SGordon Ross tree->t_refcnt++;
381a90cf9f2SGordon Ross mutex_exit(&tree->t_mutex);
382a90cf9f2SGordon Ross }
383a90cf9f2SGordon Ross
384da6c28aaSamw /*
385c8ec8eeaSjose borrego * Release a reference on a tree. If the tree is disconnected and the
3869fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * reference count falls to zero, post the object for deletion.
3879fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Object deletion is deferred to avoid modifying a list while an
3889fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * iteration may be in progress.
389da6c28aaSamw */
390da6c28aaSamw void
smb_tree_release(smb_tree_t * tree)391c8ec8eeaSjose borrego smb_tree_release(
392c8ec8eeaSjose borrego smb_tree_t *tree)
393da6c28aaSamw {
3949fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_TREE_VALID(tree);
395da6c28aaSamw
396c5866007SKeyur Desai /* flush the ofile and odir lists' delete queues */
3972cf6b79fSGordon Ross smb_lavl_flush(&tree->t_ofile_list);
398c5866007SKeyur Desai smb_llist_flush(&tree->t_odir_list);
399c5866007SKeyur Desai
400811599a4SMatt Barden mutex_enter(&tree->t_mutex);
401811599a4SMatt Barden ASSERT(tree->t_refcnt);
402811599a4SMatt Barden tree->t_refcnt--;
4039fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
404811599a4SMatt Barden switch (tree->t_state) {
4058d94f651SGordon Ross case SMB_TREE_STATE_DISCONNECTING:
406811599a4SMatt Barden if (tree->t_refcnt == 0) {
407811599a4SMatt Barden smb_session_t *ssn = tree->t_session;
408811599a4SMatt Barden tree->t_state = SMB_TREE_STATE_DISCONNECTED;
409811599a4SMatt Barden smb_llist_post(&ssn->s_tree_list, tree,
410811599a4SMatt Barden smb_tree_dealloc);
411811599a4SMatt Barden }
412811599a4SMatt Barden break;
413811599a4SMatt Barden case SMB_TREE_STATE_CONNECTED:
414811599a4SMatt Barden break;
415811599a4SMatt Barden default:
416811599a4SMatt Barden ASSERT(0);
417811599a4SMatt Barden break;
418811599a4SMatt Barden }
4199fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
420811599a4SMatt Barden mutex_exit(&tree->t_mutex);
4219fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
4229fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
423da6c28aaSamw /*
424c8ec8eeaSjose borrego * Close ofiles and odirs that match pid.
425da6c28aaSamw */
426da6c28aaSamw void
smb_tree_close_pid(smb_tree_t * tree,uint32_t pid)427c8ec8eeaSjose borrego smb_tree_close_pid(
428c8ec8eeaSjose borrego smb_tree_t *tree,
429a90cf9f2SGordon Ross uint32_t pid)
430da6c28aaSamw {
431da6c28aaSamw ASSERT(tree);
432da6c28aaSamw ASSERT(tree->t_magic == SMB_TREE_MAGIC);
433da6c28aaSamw
434811599a4SMatt Barden smb_ofile_close_all(tree, pid);
4357f667e74Sjose borrego smb_tree_close_odirs(tree, pid);
436c8ec8eeaSjose borrego }
437da6c28aaSamw
438c8ec8eeaSjose borrego /*
439c8ec8eeaSjose borrego * Check whether or not a tree supports the features identified by flags.
440c8ec8eeaSjose borrego */
441c8ec8eeaSjose borrego boolean_t
smb_tree_has_feature(smb_tree_t * tree,uint32_t flags)442c8ec8eeaSjose borrego smb_tree_has_feature(smb_tree_t *tree, uint32_t flags)
443c8ec8eeaSjose borrego {
444c8ec8eeaSjose borrego ASSERT(tree);
445c8ec8eeaSjose borrego ASSERT(tree->t_magic == SMB_TREE_MAGIC);
446da6c28aaSamw
447c8ec8eeaSjose borrego return ((tree->t_flags & flags) == flags);
448da6c28aaSamw }
449da6c28aaSamw
4501fcced4cSJordan Brown /*
4511fcced4cSJordan Brown * If the enumeration request is for tree data, handle the request
4521fcced4cSJordan Brown * here. Otherwise, pass it on to the ofiles.
4531fcced4cSJordan Brown *
4541fcced4cSJordan Brown * This function should be called with a hold on the tree.
4551fcced4cSJordan Brown */
4561fcced4cSJordan Brown int
smb_tree_enum(smb_tree_t * tree,smb_svcenum_t * svcenum)4571fcced4cSJordan Brown smb_tree_enum(smb_tree_t *tree, smb_svcenum_t *svcenum)
4581fcced4cSJordan Brown {
4592cf6b79fSGordon Ross smb_lavl_t *lavl;
4601fcced4cSJordan Brown smb_ofile_t *of;
4613b13a1efSThomas Keiser int rc = 0;
4621fcced4cSJordan Brown
4631fcced4cSJordan Brown if (svcenum->se_type == SMB_SVCENUM_TYPE_TREE)
4641fcced4cSJordan Brown return (smb_tree_enum_private(tree, svcenum));
4651fcced4cSJordan Brown
4662cf6b79fSGordon Ross lavl = &tree->t_ofile_list;
4672cf6b79fSGordon Ross smb_lavl_enter(lavl, RW_READER);
4681fcced4cSJordan Brown
4692cf6b79fSGordon Ross of = smb_lavl_first(lavl);
4708d94f651SGordon Ross while (of) {
4718d94f651SGordon Ross if (smb_ofile_hold(of)) {
4728d94f651SGordon Ross rc = smb_ofile_enum(of, svcenum);
4731fcced4cSJordan Brown smb_ofile_release(of);
4741fcced4cSJordan Brown }
4758d94f651SGordon Ross if (rc != 0)
4768d94f651SGordon Ross break;
4772cf6b79fSGordon Ross of = smb_lavl_next(lavl, of);
4781fcced4cSJordan Brown }
4791fcced4cSJordan Brown
4802cf6b79fSGordon Ross smb_lavl_exit(lavl);
4818d94f651SGordon Ross
4821fcced4cSJordan Brown return (rc);
4831fcced4cSJordan Brown }
4841fcced4cSJordan Brown
4851fcced4cSJordan Brown /*
4861fcced4cSJordan Brown * Close a file by its unique id.
4871fcced4cSJordan Brown */
4881fcced4cSJordan Brown int
smb_tree_fclose(smb_tree_t * tree,uint32_t uniqid)4891fcced4cSJordan Brown smb_tree_fclose(smb_tree_t *tree, uint32_t uniqid)
4901fcced4cSJordan Brown {
4911fcced4cSJordan Brown smb_ofile_t *of;
4921fcced4cSJordan Brown
4931fcced4cSJordan Brown ASSERT(tree);
4941fcced4cSJordan Brown ASSERT(tree->t_magic == SMB_TREE_MAGIC);
4951fcced4cSJordan Brown
496811599a4SMatt Barden /*
497811599a4SMatt Barden * Note that ORPHANED ofiles aren't fclosable, as they have
498811599a4SMatt Barden * no session, user, or tree by which they might be found.
499811599a4SMatt Barden * They will eventually expire.
500811599a4SMatt Barden */
5011fcced4cSJordan Brown if ((of = smb_ofile_lookup_by_uniqid(tree, uniqid)) == NULL)
5021fcced4cSJordan Brown return (ENOENT);
5031fcced4cSJordan Brown
5041fcced4cSJordan Brown if (smb_ofile_disallow_fclose(of)) {
5051fcced4cSJordan Brown smb_ofile_release(of);
5061fcced4cSJordan Brown return (EACCES);
5071fcced4cSJordan Brown }
5081fcced4cSJordan Brown
5091fcced4cSJordan Brown smb_ofile_close(of, 0);
5101fcced4cSJordan Brown smb_ofile_release(of);
5111fcced4cSJordan Brown return (0);
5121fcced4cSJordan Brown }
513743a77edSAlan Wright
514c8ec8eeaSjose borrego /* *************************** Static Functions ***************************** */
5151fcced4cSJordan Brown
516743a77edSAlan Wright #define SHARES_DIR ".zfs/shares/"
517148c5f43SAlan Wright
518148c5f43SAlan Wright /*
519148c5f43SAlan Wright * Calculates permissions given by the share's ACL to the
520148c5f43SAlan Wright * user in the passed request. The default is full access.
521148c5f43SAlan Wright * If any error occurs, full access is granted.
522148c5f43SAlan Wright *
523148c5f43SAlan Wright * Using the vnode of the share path find the root directory
524148c5f43SAlan Wright * of the mounted file system. Then look to see if there is a
525148c5f43SAlan Wright * .zfs/shares directory and if there is, lookup the file with
526148c5f43SAlan Wright * the same name as the share name in it. The ACL set for this
527148c5f43SAlan Wright * file is the share's ACL which is used for access check here.
528148c5f43SAlan Wright */
529148c5f43SAlan Wright static uint32_t
smb_tree_acl_access(smb_request_t * sr,const smb_kshare_t * si,vnode_t * pathvp)530148c5f43SAlan Wright smb_tree_acl_access(smb_request_t *sr, const smb_kshare_t *si, vnode_t *pathvp)
531743a77edSAlan Wright {
532fe1c642dSBill Krier smb_user_t *user;
533fe1c642dSBill Krier cred_t *cred;
534fe1c642dSBill Krier int rc;
535fe1c642dSBill Krier vfs_t *vfsp;
536fe1c642dSBill Krier vnode_t *root = NULL;
537fe1c642dSBill Krier vnode_t *sharevp = NULL;
538fe1c642dSBill Krier char *sharepath;
539fe1c642dSBill Krier struct pathname pnp;
540fe1c642dSBill Krier size_t size;
541148c5f43SAlan Wright uint32_t access;
542fe1c642dSBill Krier
543fe1c642dSBill Krier user = sr->uid_user;
544fe1c642dSBill Krier cred = user->u_cred;
545148c5f43SAlan Wright access = ACE_ALL_PERMS;
546743a77edSAlan Wright
547fe1c642dSBill Krier if (si->shr_flags & SMB_SHRF_AUTOHOME) {
548fe1c642dSBill Krier /*
549fe1c642dSBill Krier * An autohome share owner gets full access to the share.
550fe1c642dSBill Krier * Everyone else is denied access.
551fe1c642dSBill Krier */
552c5866007SKeyur Desai if (si->shr_uid != crgetuid(cred))
553148c5f43SAlan Wright access = 0;
554148c5f43SAlan Wright
555148c5f43SAlan Wright return (access);
556fe1c642dSBill Krier }
557fe1c642dSBill Krier
558743a77edSAlan Wright /*
559148c5f43SAlan Wright * The hold on 'root' is released by the lookuppnvp() that follows
560743a77edSAlan Wright */
561743a77edSAlan Wright vfsp = pathvp->v_vfsp;
562743a77edSAlan Wright if (vfsp != NULL)
563743a77edSAlan Wright rc = VFS_ROOT(vfsp, &root);
564743a77edSAlan Wright else
565743a77edSAlan Wright rc = ENOENT;
566743a77edSAlan Wright
567743a77edSAlan Wright if (rc != 0)
568148c5f43SAlan Wright return (access);
569743a77edSAlan Wright
570743a77edSAlan Wright
571fe1c642dSBill Krier size = sizeof (SHARES_DIR) + strlen(si->shr_name) + 1;
572148c5f43SAlan Wright sharepath = smb_srm_alloc(sr, size);
573b819cea2SGordon Ross (void) snprintf(sharepath, size, "%s%s", SHARES_DIR, si->shr_name);
574743a77edSAlan Wright
575743a77edSAlan Wright pn_alloc(&pnp);
576743a77edSAlan Wright (void) pn_set(&pnp, sharepath);
577148c5f43SAlan Wright rc = lookuppnvp(&pnp, NULL, NO_FOLLOW, NULL, &sharevp, rootdir, root,
5788622ec45SGordon Ross zone_kcred());
579743a77edSAlan Wright pn_free(&pnp);
580743a77edSAlan Wright
581743a77edSAlan Wright /*
582148c5f43SAlan Wright * Now get the effective access value based on cred and ACL values.
583743a77edSAlan Wright */
584037cac00Sjoyce mcintosh if (rc == 0) {
585148c5f43SAlan Wright smb_vop_eaccess(sharevp, (int *)&access, V_ACE_MASK, NULL,
586148c5f43SAlan Wright cred);
587037cac00Sjoyce mcintosh VN_RELE(sharevp);
588037cac00Sjoyce mcintosh }
589148c5f43SAlan Wright
590148c5f43SAlan Wright return (access);
591743a77edSAlan Wright }
592c8ec8eeaSjose borrego
593da6c28aaSamw /*
594148c5f43SAlan Wright * Performs the following access checks for a disk share:
595148c5f43SAlan Wright *
596148c5f43SAlan Wright * - No IPC/anonymous user is allowed
597148c5f43SAlan Wright *
598148c5f43SAlan Wright * - If user is Guest, guestok property of the share should be
599148c5f43SAlan Wright * enabled
600148c5f43SAlan Wright *
601148c5f43SAlan Wright * - If this is an Admin share, the user should have administrative
602148c5f43SAlan Wright * privileges
603148c5f43SAlan Wright *
604148c5f43SAlan Wright * - Host based access control lists
605148c5f43SAlan Wright *
606148c5f43SAlan Wright * - Share ACL
607148c5f43SAlan Wright *
608148c5f43SAlan Wright * Returns the access allowed or 0 if access is denied.
609da6c28aaSamw */
610148c5f43SAlan Wright static uint32_t
smb_tree_chkaccess(smb_request_t * sr,smb_kshare_t * shr,vnode_t * vp)611148c5f43SAlan Wright smb_tree_chkaccess(smb_request_t *sr, smb_kshare_t *shr, vnode_t *vp)
612148c5f43SAlan Wright {
613148c5f43SAlan Wright smb_user_t *user = sr->uid_user;
614148c5f43SAlan Wright char *sharename = shr->shr_name;
615148c5f43SAlan Wright uint32_t host_access;
616148c5f43SAlan Wright uint32_t acl_access;
617148c5f43SAlan Wright uint32_t access;
618743a77edSAlan Wright
619a90cf9f2SGordon Ross if (user->u_flags & SMB_USER_FLAG_ANON) {
620148c5f43SAlan Wright smb_tree_log(sr, sharename, "access denied: IPC only");
621148c5f43SAlan Wright return (0);
622148c5f43SAlan Wright }
623148c5f43SAlan Wright
624148c5f43SAlan Wright if ((user->u_flags & SMB_USER_FLAG_GUEST) &&
625148c5f43SAlan Wright ((shr->shr_flags & SMB_SHRF_GUEST_OK) == 0)) {
626148c5f43SAlan Wright smb_tree_log(sr, sharename, "access denied: guest disabled");
627148c5f43SAlan Wright return (0);
628148c5f43SAlan Wright }
629148c5f43SAlan Wright
630*97264293SGordon Ross if ((shr->shr_flags & SMB_SHRF_ADMIN) && !SMB_USER_IS_ADMIN(user)) {
631148c5f43SAlan Wright smb_tree_log(sr, sharename, "access denied: not admin");
632148c5f43SAlan Wright return (0);
633148c5f43SAlan Wright }
634148c5f43SAlan Wright
6358622ec45SGordon Ross host_access = smb_kshare_hostaccess(shr, sr->session);
636148c5f43SAlan Wright if ((host_access & ACE_ALL_PERMS) == 0) {
637148c5f43SAlan Wright smb_tree_log(sr, sharename, "access denied: host access");
638148c5f43SAlan Wright return (0);
639148c5f43SAlan Wright }
640148c5f43SAlan Wright
641*97264293SGordon Ross /*
642*97264293SGordon Ross * This checks the "share" ACL, which is normally "open"
643*97264293SGordon Ross */
644148c5f43SAlan Wright acl_access = smb_tree_acl_access(sr, shr, vp);
645148c5f43SAlan Wright if ((acl_access & ACE_ALL_PERMS) == 0) {
646148c5f43SAlan Wright smb_tree_log(sr, sharename, "access denied: share ACL");
647148c5f43SAlan Wright return (0);
648148c5f43SAlan Wright }
649148c5f43SAlan Wright
650148c5f43SAlan Wright access = host_access & acl_access;
651148c5f43SAlan Wright if ((access & ACE_ALL_PERMS) == 0) {
652148c5f43SAlan Wright smb_tree_log(sr, sharename, "access denied");
653148c5f43SAlan Wright return (0);
654148c5f43SAlan Wright }
655148c5f43SAlan Wright
656148c5f43SAlan Wright return (access);
657148c5f43SAlan Wright }
658148c5f43SAlan Wright
6598d94f651SGordon Ross /* How long should tree connect wait for DH import to complete? */
6608d94f651SGordon Ross int smb_tcon_import_wait = 20; /* sec. */
6618d94f651SGordon Ross
662148c5f43SAlan Wright /*
663148c5f43SAlan Wright * Connect a share for use with files and directories.
664148c5f43SAlan Wright */
665a90cf9f2SGordon Ross uint32_t
smb_tree_connect_disk(smb_request_t * sr,smb_arg_tcon_t * tcon)666a90cf9f2SGordon Ross smb_tree_connect_disk(smb_request_t *sr, smb_arg_tcon_t *tcon)
667da6c28aaSamw {
668a90cf9f2SGordon Ross char *sharename = tcon->path;
669148c5f43SAlan Wright const char *any = "?????";
670c8ec8eeaSjose borrego smb_user_t *user = sr->uid_user;
671c8ec8eeaSjose borrego smb_node_t *snode = NULL;
672811599a4SMatt Barden smb_kshare_t *si = tcon->si;
673a90cf9f2SGordon Ross char *service = tcon->service;
674c8ec8eeaSjose borrego smb_tree_t *tree;
675c8ec8eeaSjose borrego int rc;
676148c5f43SAlan Wright uint32_t access;
677148c5f43SAlan Wright smb_shr_execinfo_t execinfo;
6788d94f651SGordon Ross clock_t time;
679da6c28aaSamw
680da6c28aaSamw ASSERT(user);
681148c5f43SAlan Wright ASSERT(user->u_cred);
682c8ec8eeaSjose borrego
683a90cf9f2SGordon Ross if (service != NULL &&
684a90cf9f2SGordon Ross strcmp(service, any) != 0 &&
685a90cf9f2SGordon Ross strcasecmp(service, "A:") != 0) {
686148c5f43SAlan Wright smb_tree_log(sr, sharename, "invalid service (%s)", service);
687a90cf9f2SGordon Ross return (NT_STATUS_BAD_DEVICE_TYPE);
688c8ec8eeaSjose borrego }
689c8ec8eeaSjose borrego
690148c5f43SAlan Wright /*
691148c5f43SAlan Wright * Check that the shared directory exists.
692148c5f43SAlan Wright */
6938d94f651SGordon Ross snode = si->shr_root_node;
6948d94f651SGordon Ross if (snode == NULL) {
695148c5f43SAlan Wright smb_tree_log(sr, sharename, "bad path: %s", si->shr_path);
696a90cf9f2SGordon Ross return (NT_STATUS_BAD_NETWORK_NAME);
69729bd2886SAlan Wright }
69829bd2886SAlan Wright
699148c5f43SAlan Wright if ((access = smb_tree_chkaccess(sr, si, snode->vp)) == 0) {
700a90cf9f2SGordon Ross return (NT_STATUS_ACCESS_DENIED);
701da6c28aaSamw }
702c8ec8eeaSjose borrego
7038d94f651SGordon Ross /*
7048d94f651SGordon Ross * Wait for DH import of persistent handles to finish.
7058d94f651SGordon Ross * If we timeout, it's not clear what status to return,
7068d94f651SGordon Ross * but as the share is not really available yet, let's
7078d94f651SGordon Ross * return the status for "no such share".
7088d94f651SGordon Ross */
7098d94f651SGordon Ross time = SEC_TO_TICK(smb_tcon_import_wait) + ddi_get_lbolt();
7108d94f651SGordon Ross mutex_enter(&si->shr_mutex);
7118d94f651SGordon Ross while (si->shr_import_busy != NULL) {
7128d94f651SGordon Ross if (cv_timedwait(&si->shr_cv, &si->shr_mutex, time) < 0) {
7138d94f651SGordon Ross mutex_exit(&si->shr_mutex);
7148d94f651SGordon Ross return (NT_STATUS_BAD_NETWORK_NAME);
7158d94f651SGordon Ross }
7168d94f651SGordon Ross }
7178d94f651SGordon Ross mutex_exit(&si->shr_mutex);
7188d94f651SGordon Ross
7198d7e4166Sjose borrego /*
7208d7e4166Sjose borrego * Set up the OptionalSupport for this share.
7218d7e4166Sjose borrego */
722a90cf9f2SGordon Ross tcon->optional_support = SMB_SUPPORT_SEARCH_BITS;
7238d7e4166Sjose borrego
7248d7e4166Sjose borrego switch (si->shr_flags & SMB_SHRF_CSC_MASK) {
7258d7e4166Sjose borrego case SMB_SHRF_CSC_DISABLED:
726a90cf9f2SGordon Ross tcon->optional_support |= SMB_CSC_CACHE_NONE;
7278d7e4166Sjose borrego break;
7288d7e4166Sjose borrego case SMB_SHRF_CSC_AUTO:
729a90cf9f2SGordon Ross tcon->optional_support |= SMB_CSC_CACHE_AUTO_REINT;
7308d7e4166Sjose borrego break;
7318d7e4166Sjose borrego case SMB_SHRF_CSC_VDO:
732a90cf9f2SGordon Ross tcon->optional_support |= SMB_CSC_CACHE_VDO;
7338d7e4166Sjose borrego break;
7348d7e4166Sjose borrego case SMB_SHRF_CSC_MANUAL:
7358d7e4166Sjose borrego default:
7368d7e4166Sjose borrego /*
7378d7e4166Sjose borrego * Default to SMB_CSC_CACHE_MANUAL_REINT.
7388d7e4166Sjose borrego */
7398d7e4166Sjose borrego break;
7408d7e4166Sjose borrego }
7418d7e4166Sjose borrego
742e3f2c991SKeyur Desai /* ABE support */
743e3f2c991SKeyur Desai if (si->shr_flags & SMB_SHRF_ABE)
744a90cf9f2SGordon Ross tcon->optional_support |=
745e3f2c991SKeyur Desai SHI1005_FLAGS_ACCESS_BASED_DIRECTORY_ENUM;
746e3f2c991SKeyur Desai
7479fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (si->shr_flags & SMB_SHRF_DFSROOT)
748a90cf9f2SGordon Ross tcon->optional_support |= SMB_SHARE_IS_IN_DFS;
7499fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
7503b13a1efSThomas Keiser tree = smb_tree_alloc(sr, si, snode, access, sr->sr_cfg->skc_execflags);
751b89a8333Snatalie li - Sun Microsystems - Irvine United States
752a90cf9f2SGordon Ross if (tree == NULL)
753a90cf9f2SGordon Ross return (NT_STATUS_INSUFF_SERVER_RESOURCES);
754a90cf9f2SGordon Ross
755814e0daaSGordon Ross if (tree->t_flags & SMB_TREE_SHORTNAMES)
756814e0daaSGordon Ross tcon->optional_support |= SMB_UNIQUE_FILE_NAME;
757814e0daaSGordon Ross
758a90cf9f2SGordon Ross if (tree->t_execflags & SMB_EXEC_MAP) {
759a90cf9f2SGordon Ross smb_tree_set_execinfo(tree, &execinfo, SMB_EXEC_MAP);
760148c5f43SAlan Wright
761a90cf9f2SGordon Ross rc = smb_kshare_exec(tree->t_server, &execinfo);
762148c5f43SAlan Wright
763a90cf9f2SGordon Ross if ((rc != 0) && (tree->t_execflags & SMB_EXEC_TERM)) {
7648d94f651SGordon Ross /*
7658d94f651SGordon Ross * Inline parts of: smb_tree_disconnect()
7668d94f651SGordon Ross * Not using smb_tree_disconnect() for cleanup
7678d94f651SGordon Ross * here because: we don't want an exec up-call,
7688d94f651SGordon Ross * and there can't be any opens as we never
7698d94f651SGordon Ross * returned this TID to the client.
7708d94f651SGordon Ross */
7718d94f651SGordon Ross mutex_enter(&tree->t_mutex);
7728d94f651SGordon Ross tree->t_state = SMB_TREE_STATE_DISCONNECTING;
7738d94f651SGordon Ross mutex_exit(&tree->t_mutex);
7748d94f651SGordon Ross
775a90cf9f2SGordon Ross smb_tree_release(tree);
776a90cf9f2SGordon Ross return (NT_STATUS_ACCESS_DENIED);
777148c5f43SAlan Wright }
778148c5f43SAlan Wright }
779148c5f43SAlan Wright
780a90cf9f2SGordon Ross sr->tid_tree = tree;
781a90cf9f2SGordon Ross sr->smb_tid = tree->t_tid;
782a90cf9f2SGordon Ross
783a90cf9f2SGordon Ross return (0);
784148c5f43SAlan Wright }
785148c5f43SAlan Wright
786148c5f43SAlan Wright /*
787148c5f43SAlan Wright * Shares have both a share and host based access control. The access
788148c5f43SAlan Wright * granted will be minimum permissions based on both hostaccess
789148c5f43SAlan Wright * (permissions allowed by host based access) and aclaccess (from the
790148c5f43SAlan Wright * share ACL).
791148c5f43SAlan Wright */
792a90cf9f2SGordon Ross uint32_t
smb_tree_connect_printq(smb_request_t * sr,smb_arg_tcon_t * tcon)793a90cf9f2SGordon Ross smb_tree_connect_printq(smb_request_t *sr, smb_arg_tcon_t *tcon)
794148c5f43SAlan Wright {
795a90cf9f2SGordon Ross char *sharename = tcon->path;
796148c5f43SAlan Wright const char *any = "?????";
797148c5f43SAlan Wright smb_user_t *user = sr->uid_user;
798148c5f43SAlan Wright smb_node_t *dnode = NULL;
799148c5f43SAlan Wright smb_node_t *snode = NULL;
800811599a4SMatt Barden smb_kshare_t *si = tcon->si;
801a90cf9f2SGordon Ross char *service = tcon->service;
802148c5f43SAlan Wright char last_component[MAXNAMELEN];
803148c5f43SAlan Wright smb_tree_t *tree;
804148c5f43SAlan Wright int rc;
805148c5f43SAlan Wright uint32_t access;
806148c5f43SAlan Wright
807148c5f43SAlan Wright ASSERT(user);
808148c5f43SAlan Wright ASSERT(user->u_cred);
809148c5f43SAlan Wright
810b7301bf5SGordon Ross if (sr->sr_server->sv_cfg.skc_print_enable == 0) {
811b7301bf5SGordon Ross smb_tree_log(sr, sharename, "printing disabled");
812a90cf9f2SGordon Ross return (NT_STATUS_BAD_NETWORK_NAME);
813b7301bf5SGordon Ross }
814b7301bf5SGordon Ross
815a90cf9f2SGordon Ross if (service != NULL &&
816a90cf9f2SGordon Ross strcmp(service, any) != 0 &&
817a90cf9f2SGordon Ross strcasecmp(service, "LPT1:") != 0) {
818148c5f43SAlan Wright smb_tree_log(sr, sharename, "invalid service (%s)", service);
819a90cf9f2SGordon Ross return (NT_STATUS_BAD_DEVICE_TYPE);
820b89a8333Snatalie li - Sun Microsystems - Irvine United States }
821b89a8333Snatalie li - Sun Microsystems - Irvine United States
822c8ec8eeaSjose borrego /*
823c8ec8eeaSjose borrego * Check that the shared directory exists.
824c8ec8eeaSjose borrego */
825148c5f43SAlan Wright rc = smb_pathname_reduce(sr, user->u_cred, si->shr_path, 0, 0, &dnode,
826c8ec8eeaSjose borrego last_component);
827c8ec8eeaSjose borrego if (rc == 0) {
828148c5f43SAlan Wright rc = smb_fsop_lookup(sr, user->u_cred, SMB_FOLLOW_LINKS,
8291fcced4cSJordan Brown sr->sr_server->si_root_smb_node, dnode, last_component,
830037cac00Sjoyce mcintosh &snode);
831c8ec8eeaSjose borrego
8321fcced4cSJordan Brown smb_node_release(dnode);
833c8ec8eeaSjose borrego }
834c8ec8eeaSjose borrego
835c8ec8eeaSjose borrego if (rc) {
836c8ec8eeaSjose borrego if (snode)
837c8ec8eeaSjose borrego smb_node_release(snode);
838c8ec8eeaSjose borrego
839b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_tree_log(sr, sharename, "bad path: %s", si->shr_path);
840a90cf9f2SGordon Ross return (NT_STATUS_BAD_NETWORK_NAME);
841c8ec8eeaSjose borrego }
842c8ec8eeaSjose borrego
843148c5f43SAlan Wright if ((access = smb_tree_chkaccess(sr, si, snode->vp)) == 0) {
844037cac00Sjoyce mcintosh smb_node_release(snode);
845a90cf9f2SGordon Ross return (NT_STATUS_ACCESS_DENIED);
846743a77edSAlan Wright }
847743a77edSAlan Wright
848a90cf9f2SGordon Ross tcon->optional_support = SMB_SUPPORT_SEARCH_BITS;
8492c2961f8Sjose borrego
8503b13a1efSThomas Keiser tree = smb_tree_alloc(sr, si, snode, access, sr->sr_cfg->skc_execflags);
851b89a8333Snatalie li - Sun Microsystems - Irvine United States
85229bd2886SAlan Wright smb_node_release(snode);
85329bd2886SAlan Wright
854c8ec8eeaSjose borrego if (tree == NULL)
855a90cf9f2SGordon Ross return (NT_STATUS_INSUFF_SERVER_RESOURCES);
85629bd2886SAlan Wright
857a90cf9f2SGordon Ross sr->tid_tree = tree;
858a90cf9f2SGordon Ross sr->smb_tid = tree->t_tid;
859a90cf9f2SGordon Ross
860a90cf9f2SGordon Ross return (0);
861da6c28aaSamw }
862da6c28aaSamw
863da6c28aaSamw /*
864c8ec8eeaSjose borrego * Connect an IPC share for use with named pipes.
865da6c28aaSamw */
866a90cf9f2SGordon Ross uint32_t
smb_tree_connect_ipc(smb_request_t * sr,smb_arg_tcon_t * tcon)867a90cf9f2SGordon Ross smb_tree_connect_ipc(smb_request_t *sr, smb_arg_tcon_t *tcon)
868da6c28aaSamw {
869a90cf9f2SGordon Ross char *name = tcon->path;
870148c5f43SAlan Wright const char *any = "?????";
8718b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_user_t *user = sr->uid_user;
8728b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_tree_t *tree;
873a90cf9f2SGordon Ross smb_kshare_t *si = tcon->si;
874a90cf9f2SGordon Ross char *service = tcon->service;
875da6c28aaSamw
876c8ec8eeaSjose borrego ASSERT(user);
877da6c28aaSamw
878a90cf9f2SGordon Ross if (service != NULL &&
879a90cf9f2SGordon Ross strcmp(service, any) != 0 &&
880a90cf9f2SGordon Ross strcasecmp(service, "IPC") != 0) {
881a90cf9f2SGordon Ross smb_tree_log(sr, name, "invalid service (%s)", service);
882a90cf9f2SGordon Ross return (NT_STATUS_BAD_DEVICE_TYPE);
883da6c28aaSamw }
884da6c28aaSamw
885a90cf9f2SGordon Ross if ((user->u_flags & SMB_USER_FLAG_ANON) &&
886a90cf9f2SGordon Ross sr->sr_cfg->skc_restrict_anon) {
887a90cf9f2SGordon Ross smb_tree_log(sr, name, "access denied: restrict anonymous");
888a90cf9f2SGordon Ross return (NT_STATUS_ACCESS_DENIED);
889148c5f43SAlan Wright }
8908d7e4166Sjose borrego
891a90cf9f2SGordon Ross tcon->optional_support = SMB_SUPPORT_SEARCH_BITS;
8928b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States
8933b13a1efSThomas Keiser tree = smb_tree_alloc(sr, si, NULL, ACE_ALL_PERMS, 0);
894a90cf9f2SGordon Ross if (tree == NULL)
895a90cf9f2SGordon Ross return (NT_STATUS_INSUFF_SERVER_RESOURCES);
896c8ec8eeaSjose borrego
897a90cf9f2SGordon Ross sr->tid_tree = tree;
898a90cf9f2SGordon Ross sr->smb_tid = tree->t_tid;
899a90cf9f2SGordon Ross
900a90cf9f2SGordon Ross return (0);
901da6c28aaSamw }
902da6c28aaSamw
903da6c28aaSamw /*
904c8ec8eeaSjose borrego * Allocate a tree.
905da6c28aaSamw */
9068d94f651SGordon Ross smb_tree_t *
smb_tree_alloc(smb_request_t * sr,const smb_kshare_t * si,smb_node_t * snode,uint32_t access,uint32_t execflags)9073b13a1efSThomas Keiser smb_tree_alloc(smb_request_t *sr, const smb_kshare_t *si,
9083b13a1efSThomas Keiser smb_node_t *snode, uint32_t access, uint32_t execflags)
909da6c28aaSamw {
9103b13a1efSThomas Keiser smb_session_t *session = sr->session;
911c8ec8eeaSjose borrego smb_tree_t *tree;
912148c5f43SAlan Wright uint32_t stype = si->shr_type;
913c8ec8eeaSjose borrego uint16_t tid;
914da6c28aaSamw
9153b13a1efSThomas Keiser if (smb_idpool_alloc(&session->s_tid_pool, &tid))
916c8ec8eeaSjose borrego return (NULL);
917da6c28aaSamw
9188622ec45SGordon Ross tree = kmem_cache_alloc(smb_cache_tree, KM_SLEEP);
919c8ec8eeaSjose borrego bzero(tree, sizeof (smb_tree_t));
920da6c28aaSamw
9213b13a1efSThomas Keiser tree->t_session = session;
9223b13a1efSThomas Keiser tree->t_server = session->s_server;
9233b13a1efSThomas Keiser
924148c5f43SAlan Wright if (STYPE_ISDSK(stype) || STYPE_ISPRN(stype)) {
9258b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (smb_tree_getattr(si, snode, tree) != 0) {
9263b13a1efSThomas Keiser smb_idpool_free(&session->s_tid_pool, tid);
9278622ec45SGordon Ross kmem_cache_free(smb_cache_tree, tree);
928c8ec8eeaSjose borrego return (NULL);
929da6c28aaSamw }
930da6c28aaSamw }
931c8ec8eeaSjose borrego
932c8ec8eeaSjose borrego if (smb_idpool_constructor(&tree->t_fid_pool)) {
9333b13a1efSThomas Keiser smb_idpool_free(&session->s_tid_pool, tid);
9348622ec45SGordon Ross kmem_cache_free(smb_cache_tree, tree);
935c8ec8eeaSjose borrego return (NULL);
936c8ec8eeaSjose borrego }
937c8ec8eeaSjose borrego
9387f667e74Sjose borrego if (smb_idpool_constructor(&tree->t_odid_pool)) {
939c8ec8eeaSjose borrego smb_idpool_destructor(&tree->t_fid_pool);
9403b13a1efSThomas Keiser smb_idpool_free(&session->s_tid_pool, tid);
9418622ec45SGordon Ross kmem_cache_free(smb_cache_tree, tree);
942c8ec8eeaSjose borrego return (NULL);
943c8ec8eeaSjose borrego }
944c8ec8eeaSjose borrego
9452cf6b79fSGordon Ross smb_lavl_constructor(&tree->t_ofile_list,
9462cf6b79fSGordon Ross smb_ofile_avl_compare, sizeof (smb_ofile_t),
947811599a4SMatt Barden offsetof(smb_ofile_t, f_tree_lnd));
948c8ec8eeaSjose borrego
949c8ec8eeaSjose borrego smb_llist_constructor(&tree->t_odir_list, sizeof (smb_odir_t),
950c8ec8eeaSjose borrego offsetof(smb_odir_t, d_lnd));
951c8ec8eeaSjose borrego
9528b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States (void) strlcpy(tree->t_sharename, si->shr_name,
953c8ec8eeaSjose borrego sizeof (tree->t_sharename));
9548b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States (void) strlcpy(tree->t_resource, si->shr_path,
9558b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States sizeof (tree->t_resource));
956c8ec8eeaSjose borrego
957c8ec8eeaSjose borrego mutex_init(&tree->t_mutex, NULL, MUTEX_DEFAULT, NULL);
958c8ec8eeaSjose borrego
959c8ec8eeaSjose borrego tree->t_refcnt = 1;
960c8ec8eeaSjose borrego tree->t_tid = tid;
961c8ec8eeaSjose borrego tree->t_res_type = stype;
962c8ec8eeaSjose borrego tree->t_state = SMB_TREE_STATE_CONNECTED;
963c8ec8eeaSjose borrego tree->t_magic = SMB_TREE_MAGIC;
964743a77edSAlan Wright tree->t_access = access;
9651fcced4cSJordan Brown tree->t_connect_time = gethrestime_sec();
966148c5f43SAlan Wright tree->t_execflags = execflags;
967743a77edSAlan Wright
968af536d7dSGordon Ross /* grab a ref for tree->t_owner */
969af536d7dSGordon Ross smb_user_hold_internal(sr->uid_user);
9701baeef30SPrashanth Badari smb_user_inc_trees(sr->uid_user);
971af536d7dSGordon Ross tree->t_owner = sr->uid_user;
972af536d7dSGordon Ross
973743a77edSAlan Wright /* if FS is readonly, enforce that here */
974743a77edSAlan Wright if (tree->t_flags & SMB_TREE_READONLY)
975743a77edSAlan Wright tree->t_access &= ~ACE_ALL_WRITE_PERMS;
976c8ec8eeaSjose borrego
977148c5f43SAlan Wright if (STYPE_ISDSK(stype) || STYPE_ISPRN(stype)) {
978c8ec8eeaSjose borrego smb_node_ref(snode);
979c8ec8eeaSjose borrego tree->t_snode = snode;
980c8ec8eeaSjose borrego tree->t_acltype = smb_fsop_acltype(snode);
981c8ec8eeaSjose borrego }
982c8ec8eeaSjose borrego
9833b13a1efSThomas Keiser smb_llist_enter(&session->s_tree_list, RW_WRITER);
9843b13a1efSThomas Keiser smb_llist_insert_head(&session->s_tree_list, tree);
9853b13a1efSThomas Keiser smb_llist_exit(&session->s_tree_list);
9863b13a1efSThomas Keiser atomic_inc_32(&session->s_tree_cnt);
9873b13a1efSThomas Keiser smb_server_inc_trees(session->s_server);
988c8ec8eeaSjose borrego return (tree);
989c8ec8eeaSjose borrego }
990da6c28aaSamw
991da6c28aaSamw /*
9929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Deallocate a tree. The open file and open directory lists should be
9939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * empty.
994c8ec8eeaSjose borrego *
9959fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Remove the tree from the user's tree list before freeing resources
9969fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * associated with the tree.
997da6c28aaSamw */
998811599a4SMatt Barden static void
smb_tree_dealloc(void * arg)9999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_tree_dealloc(void *arg)
1000da6c28aaSamw {
10013b13a1efSThomas Keiser smb_session_t *session;
10029fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_tree_t *tree = (smb_tree_t *)arg;
10039fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
10049fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_TREE_VALID(tree);
1005da6c28aaSamw ASSERT(tree->t_state == SMB_TREE_STATE_DISCONNECTED);
1006da6c28aaSamw ASSERT(tree->t_refcnt == 0);
1007da6c28aaSamw
10088d94f651SGordon Ross smb_server_dec_trees(tree->t_server);
10098d94f651SGordon Ross
10103b13a1efSThomas Keiser session = tree->t_session;
10113b13a1efSThomas Keiser smb_llist_enter(&session->s_tree_list, RW_WRITER);
10123b13a1efSThomas Keiser smb_llist_remove(&session->s_tree_list, tree);
10133b13a1efSThomas Keiser smb_idpool_free(&session->s_tid_pool, tree->t_tid);
10143b13a1efSThomas Keiser atomic_dec_32(&session->s_tree_cnt);
10153b13a1efSThomas Keiser smb_llist_exit(&session->s_tree_list);
10169fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
1017811599a4SMatt Barden /*
1018811599a4SMatt Barden * This tree is no longer on s_tree_list, however...
1019811599a4SMatt Barden *
1020811599a4SMatt Barden * This is called via smb_llist_post, which means it may run
1021811599a4SMatt Barden * BEFORE smb_tree_release drops t_mutex (if another thread
1022811599a4SMatt Barden * flushes the delete queue before we do). Synchronize.
1023811599a4SMatt Barden */
10249fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States mutex_enter(&tree->t_mutex);
10259fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States mutex_exit(&tree->t_mutex);
1026da6c28aaSamw
1027da6c28aaSamw tree->t_magic = (uint32_t)~SMB_TREE_MAGIC;
1028da6c28aaSamw
1029c8ec8eeaSjose borrego if (tree->t_snode)
1030da6c28aaSamw smb_node_release(tree->t_snode);
1031c8ec8eeaSjose borrego
1032da6c28aaSamw mutex_destroy(&tree->t_mutex);
10332cf6b79fSGordon Ross smb_lavl_destructor(&tree->t_ofile_list);
1034da6c28aaSamw smb_llist_destructor(&tree->t_odir_list);
1035da6c28aaSamw smb_idpool_destructor(&tree->t_fid_pool);
10367f667e74Sjose borrego smb_idpool_destructor(&tree->t_odid_pool);
10373b13a1efSThomas Keiser
10383b13a1efSThomas Keiser SMB_USER_VALID(tree->t_owner);
10391baeef30SPrashanth Badari smb_user_dec_trees(tree->t_owner);
10403b13a1efSThomas Keiser smb_user_release(tree->t_owner);
10413b13a1efSThomas Keiser
10428622ec45SGordon Ross kmem_cache_free(smb_cache_tree, tree);
1043da6c28aaSamw }
1044da6c28aaSamw
1045da6c28aaSamw /*
1046c8ec8eeaSjose borrego * Determine whether or not a tree is connected.
1047c8ec8eeaSjose borrego * This function must be called with the tree mutex held.
1048c8ec8eeaSjose borrego */
1049c8ec8eeaSjose borrego static boolean_t
smb_tree_is_connected_locked(smb_tree_t * tree)10508b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_tree_is_connected_locked(smb_tree_t *tree)
1051c8ec8eeaSjose borrego {
1052c8ec8eeaSjose borrego switch (tree->t_state) {
1053c8ec8eeaSjose borrego case SMB_TREE_STATE_CONNECTED:
1054c8ec8eeaSjose borrego return (B_TRUE);
1055c8ec8eeaSjose borrego
1056c8ec8eeaSjose borrego case SMB_TREE_STATE_DISCONNECTING:
1057c8ec8eeaSjose borrego case SMB_TREE_STATE_DISCONNECTED:
1058c8ec8eeaSjose borrego /*
1059811599a4SMatt Barden * The tree exists but is being disconnected or destroyed.
1060c8ec8eeaSjose borrego */
1061c8ec8eeaSjose borrego return (B_FALSE);
1062c8ec8eeaSjose borrego
1063c8ec8eeaSjose borrego default:
1064c8ec8eeaSjose borrego ASSERT(0);
1065c8ec8eeaSjose borrego return (B_FALSE);
1066c8ec8eeaSjose borrego }
1067c8ec8eeaSjose borrego }
1068c8ec8eeaSjose borrego
1069c8ec8eeaSjose borrego /*
1070c8ec8eeaSjose borrego * Return a pointer to the share name within a share resource path.
1071da6c28aaSamw *
1072c8ec8eeaSjose borrego * The share path may be a Uniform Naming Convention (UNC) string
1073c8ec8eeaSjose borrego * (\\server\share) or simply the share name. We validate the UNC
1074c8ec8eeaSjose borrego * format but we don't look at the server name.
1075c8ec8eeaSjose borrego */
1076a90cf9f2SGordon Ross static char *
smb_tree_get_sharename(char * unc_path)1077a90cf9f2SGordon Ross smb_tree_get_sharename(char *unc_path)
1078c8ec8eeaSjose borrego {
1079a90cf9f2SGordon Ross char *sharename = unc_path;
1080c8ec8eeaSjose borrego
1081c8ec8eeaSjose borrego if (sharename[0] == '\\') {
1082c8ec8eeaSjose borrego /*
1083c8ec8eeaSjose borrego * Looks like a UNC path, validate the format.
1084c8ec8eeaSjose borrego */
1085c8ec8eeaSjose borrego if (sharename[1] != '\\')
1086c8ec8eeaSjose borrego return (NULL);
1087c8ec8eeaSjose borrego
1088c8ec8eeaSjose borrego if ((sharename = strchr(sharename+2, '\\')) == NULL)
1089c8ec8eeaSjose borrego return (NULL);
1090c8ec8eeaSjose borrego
1091c8ec8eeaSjose borrego ++sharename;
1092c8ec8eeaSjose borrego } else if (strchr(sharename, '\\') != NULL) {
1093c8ec8eeaSjose borrego /*
1094c8ec8eeaSjose borrego * This should be a share name (no embedded \'s).
1095c8ec8eeaSjose borrego */
1096c8ec8eeaSjose borrego return (NULL);
1097c8ec8eeaSjose borrego }
1098c8ec8eeaSjose borrego
1099c8ec8eeaSjose borrego return (sharename);
1100c8ec8eeaSjose borrego }
1101c8ec8eeaSjose borrego
1102da6c28aaSamw /*
1103c8ec8eeaSjose borrego * Obtain the tree attributes: volume name, typename and flags.
1104814e0daaSGordon Ross * Called only with DISK and PRINTQ shares.
1105c8ec8eeaSjose borrego */
1106c8ec8eeaSjose borrego static int
smb_tree_getattr(const smb_kshare_t * si,smb_node_t * node,smb_tree_t * tree)1107148c5f43SAlan Wright smb_tree_getattr(const smb_kshare_t *si, smb_node_t *node, smb_tree_t *tree)
1108c8ec8eeaSjose borrego {
1109c8ec8eeaSjose borrego vfs_t *vfsp = SMB_NODE_VFS(node);
1110af536d7dSGordon Ross vfs_t *realvfsp;
1111c8ec8eeaSjose borrego
1112c8ec8eeaSjose borrego ASSERT(vfsp);
1113c8ec8eeaSjose borrego
111425a9a7aaSGordon Ross smb_tree_get_creation(node, tree);
1115c8ec8eeaSjose borrego smb_tree_get_volname(vfsp, tree);
1116af536d7dSGordon Ross
1117af536d7dSGordon Ross /*
1118af536d7dSGordon Ross * In the case of an lofs mount, we need to ask the (real)
1119af536d7dSGordon Ross * underlying filesystem about capabilities, where the
1120af536d7dSGordon Ross * passed in vfs_t will be from lofs.
1121af536d7dSGordon Ross */
1122af536d7dSGordon Ross realvfsp = getvfs(&vfsp->vfs_fsid);
1123af536d7dSGordon Ross if (realvfsp != NULL) {
1124af536d7dSGordon Ross smb_tree_get_flags(si, realvfsp, tree);
1125af536d7dSGordon Ross VFS_RELE(realvfsp);
1126af536d7dSGordon Ross } else {
1127af536d7dSGordon Ross cmn_err(CE_NOTE, "Failed getting info for share: %s",
1128af536d7dSGordon Ross si->shr_name);
1129af536d7dSGordon Ross /* do the best we can without realvfsp */
1130af536d7dSGordon Ross smb_tree_get_flags(si, vfsp, tree);
1131af536d7dSGordon Ross }
1132c8ec8eeaSjose borrego
1133ab017dbaSGordon Ross if (tree->t_session->dialect >= SMB_VERS_3_0)
1134ab017dbaSGordon Ross tree->t_encrypt = si->shr_encrypt;
1135ab017dbaSGordon Ross else
11361160dcf7SMatt Barden tree->t_encrypt = SMB_CONFIG_DISABLED;
11371160dcf7SMatt Barden
1138c8ec8eeaSjose borrego return (0);
1139c8ec8eeaSjose borrego }
1140c8ec8eeaSjose borrego
114125a9a7aaSGordon Ross /*
114225a9a7aaSGordon Ross * File volume creation time
114325a9a7aaSGordon Ross */
114425a9a7aaSGordon Ross static void
smb_tree_get_creation(smb_node_t * node,smb_tree_t * tree)114525a9a7aaSGordon Ross smb_tree_get_creation(smb_node_t *node, smb_tree_t *tree)
114625a9a7aaSGordon Ross {
114725a9a7aaSGordon Ross smb_attr_t attr;
114825a9a7aaSGordon Ross cred_t *kcr = zone_kcred();
114925a9a7aaSGordon Ross
115025a9a7aaSGordon Ross bzero(&attr, sizeof (attr));
115125a9a7aaSGordon Ross attr.sa_mask = SMB_AT_CRTIME;
115225a9a7aaSGordon Ross (void) smb_node_getattr(NULL, node, kcr, NULL, &attr);
115325a9a7aaSGordon Ross /* On failure we'll have time zero, which is OK */
115425a9a7aaSGordon Ross
115525a9a7aaSGordon Ross tree->t_create_time = attr.sa_crtime;
115625a9a7aaSGordon Ross }
115725a9a7aaSGordon Ross
1158c8ec8eeaSjose borrego /*
1159c8ec8eeaSjose borrego * Extract the volume name.
1160c8ec8eeaSjose borrego */
1161c8ec8eeaSjose borrego static void
smb_tree_get_volname(vfs_t * vfsp,smb_tree_t * tree)1162c8ec8eeaSjose borrego smb_tree_get_volname(vfs_t *vfsp, smb_tree_t *tree)
1163c8ec8eeaSjose borrego {
1164a90cf9f2SGordon Ross #ifdef _FAKE_KERNEL
1165a90cf9f2SGordon Ross _NOTE(ARGUNUSED(vfsp))
1166a90cf9f2SGordon Ross (void) strlcpy(tree->t_volume, "fake", SMB_VOLNAMELEN);
1167a90cf9f2SGordon Ross #else /* _FAKE_KERNEL */
1168c8ec8eeaSjose borrego refstr_t *vfs_mntpoint;
1169c8ec8eeaSjose borrego const char *s;
1170c8ec8eeaSjose borrego char *name;
1171c8ec8eeaSjose borrego
1172c8ec8eeaSjose borrego vfs_mntpoint = vfs_getmntpoint(vfsp);
1173c8ec8eeaSjose borrego
1174b819cea2SGordon Ross s = refstr_value(vfs_mntpoint);
1175c8ec8eeaSjose borrego s += strspn(s, "/");
1176c8ec8eeaSjose borrego (void) strlcpy(tree->t_volume, s, SMB_VOLNAMELEN);
1177c8ec8eeaSjose borrego
1178c8ec8eeaSjose borrego refstr_rele(vfs_mntpoint);
1179c8ec8eeaSjose borrego
1180c8ec8eeaSjose borrego name = tree->t_volume;
1181c8ec8eeaSjose borrego (void) strsep((char **)&name, "/");
1182a90cf9f2SGordon Ross #endif /* _FAKE_KERNEL */
1183c8ec8eeaSjose borrego }
1184c8ec8eeaSjose borrego
1185c8ec8eeaSjose borrego /*
1186814e0daaSGordon Ross * Get flags from the VFS (and other places) for a new tree.
1187814e0daaSGordon Ross * Called only with DISK and PRINTQ shares.
1188814e0daaSGordon Ross *
1189a90cf9f2SGordon Ross * Always set "unicode on disk" because we always use utf8 names locally.
1190c8ec8eeaSjose borrego * Always set ACL support because the VFS will fake ACLs for file systems
1191c8ec8eeaSjose borrego * that don't support them.
1192da6c28aaSamw *
1193c8ec8eeaSjose borrego * Some flags are dependent on the typename, which is also set up here.
1194c8ec8eeaSjose borrego * File system types are hardcoded in uts/common/os/vfs_conf.c.
1195da6c28aaSamw */
1196c8ec8eeaSjose borrego static void
smb_tree_get_flags(const smb_kshare_t * si,vfs_t * vfsp,smb_tree_t * tree)1197148c5f43SAlan Wright smb_tree_get_flags(const smb_kshare_t *si, vfs_t *vfsp, smb_tree_t *tree)
1198da6c28aaSamw {
11995f1ef25cSAram Hăvărneanu smb_session_t *ssn = tree->t_session;
1200b819cea2SGordon Ross struct vfssw *vswp;
12015f1ef25cSAram Hăvărneanu
1202fc724630SAlan Wright typedef struct smb_mtype {
1203fc724630SAlan Wright char *mt_name;
1204fc724630SAlan Wright size_t mt_namelen;
1205fc724630SAlan Wright uint32_t mt_flags;
1206fc724630SAlan Wright } smb_mtype_t;
1207fc724630SAlan Wright
1208fc724630SAlan Wright static smb_mtype_t smb_mtype[] = {
120955f0a249SGordon Ross #ifdef _FAKE_KERNEL
121055f0a249SGordon Ross /* See libfksmbsrv:fake_vfs.c */
121155f0a249SGordon Ross { "fake", 3, SMB_TREE_SPARSE},
121255f0a249SGordon Ross #endif /* _FAKE_KERNEL */
1213a90cf9f2SGordon Ross { "zfs", 3, SMB_TREE_QUOTA | SMB_TREE_SPARSE},
1214a90cf9f2SGordon Ross { "ufs", 3, 0 },
12159fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States { "nfs", 3, SMB_TREE_NFS_MOUNTED },
12169fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States { "tmpfs", 5, SMB_TREE_NO_EXPORT }
1217fc724630SAlan Wright };
1218fc724630SAlan Wright smb_mtype_t *mtype;
1219fc724630SAlan Wright char *name;
1220a90cf9f2SGordon Ross uint32_t flags =
1221a90cf9f2SGordon Ross SMB_TREE_SUPPORTS_ACLS |
1222a90cf9f2SGordon Ross SMB_TREE_UNICODE_ON_DISK;
1223fc724630SAlan Wright int i;
1224da6c28aaSamw
12259fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (si->shr_flags & SMB_SHRF_DFSROOT)
12269fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States flags |= SMB_TREE_DFSROOT;
12279fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
12288b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (si->shr_flags & SMB_SHRF_CATIA)
12298b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States flags |= SMB_TREE_CATIA;
12308b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States
1231e3f2c991SKeyur Desai if (si->shr_flags & SMB_SHRF_ABE)
1232e3f2c991SKeyur Desai flags |= SMB_TREE_ABE;
1233e3f2c991SKeyur Desai
12348d94f651SGordon Ross if (si->shr_flags & SMB_SHRF_CA)
12358d94f651SGordon Ross flags |= SMB_TREE_CA;
12368d94f651SGordon Ross
123794047d49SGordon Ross if (si->shr_flags & SMB_SHRF_FSO)
123894047d49SGordon Ross flags |= SMB_TREE_FORCE_L2_OPLOCK;
123994047d49SGordon Ross
1240814e0daaSGordon Ross if (ssn->s_cfg.skc_oplock_enable)
1241cb174861Sjoyce mcintosh flags |= SMB_TREE_OPLOCKS;
1242cb174861Sjoyce mcintosh
12435f1ef25cSAram Hăvărneanu if (ssn->s_cfg.skc_traverse_mounts)
12445f1ef25cSAram Hăvărneanu flags |= SMB_TREE_TRAVERSE_MOUNTS;
12455f1ef25cSAram Hăvărneanu
1246814e0daaSGordon Ross if (ssn->s_cfg.skc_short_names)
1247cb174861Sjoyce mcintosh flags |= SMB_TREE_SHORTNAMES;
1248cb174861Sjoyce mcintosh
1249c8ec8eeaSjose borrego if (vfsp->vfs_flag & VFS_RDONLY)
1250c8ec8eeaSjose borrego flags |= SMB_TREE_READONLY;
1251c8ec8eeaSjose borrego
1252c8ec8eeaSjose borrego if (vfsp->vfs_flag & VFS_XATTR)
1253c8ec8eeaSjose borrego flags |= SMB_TREE_STREAMS;
1254c8ec8eeaSjose borrego
1255b819cea2SGordon Ross vswp = vfs_getvfsswbyvfsops(vfs_getops(vfsp));
1256b819cea2SGordon Ross if (vswp != NULL) {
1257b819cea2SGordon Ross name = vswp->vsw_name;
1258b819cea2SGordon Ross vfs_unrefvfssw(vswp);
1259b819cea2SGordon Ross } else {
1260b819cea2SGordon Ross name = "?";
1261b819cea2SGordon Ross }
1262c8ec8eeaSjose borrego
1263fc724630SAlan Wright for (i = 0; i < sizeof (smb_mtype) / sizeof (smb_mtype[0]); ++i) {
1264fc724630SAlan Wright mtype = &smb_mtype[i];
1265fc724630SAlan Wright if (strncasecmp(name, mtype->mt_name, mtype->mt_namelen) == 0)
1266fc724630SAlan Wright flags |= mtype->mt_flags;
1267fc724630SAlan Wright }
1268c8ec8eeaSjose borrego
1269ca5fb90aSGordon Ross /*
1270ca5fb90aSGordon Ross * SMB_TREE_QUOTA will be on here if the FS is ZFS. We want to
1271ca5fb90aSGordon Ross * turn it OFF when the share property says false.
1272ca5fb90aSGordon Ross */
1273ca5fb90aSGordon Ross if ((si->shr_flags & SMB_SHRF_QUOTAS) == 0)
1274ca5fb90aSGordon Ross flags &= ~SMB_TREE_QUOTA;
1275ca5fb90aSGordon Ross
1276c8ec8eeaSjose borrego (void) strlcpy(tree->t_typename, name, SMB_TYPENAMELEN);
1277bbf6f00cSJordan Brown (void) smb_strupr((char *)tree->t_typename);
1278da6c28aaSamw
1279c8ec8eeaSjose borrego if (vfs_has_feature(vfsp, VFSFT_XVATTR))
1280c8ec8eeaSjose borrego flags |= SMB_TREE_XVATTR;
1281c8ec8eeaSjose borrego
1282c8ec8eeaSjose borrego if (vfs_has_feature(vfsp, VFSFT_CASEINSENSITIVE))
1283c8ec8eeaSjose borrego flags |= SMB_TREE_CASEINSENSITIVE;
1284c8ec8eeaSjose borrego
1285c8ec8eeaSjose borrego if (vfs_has_feature(vfsp, VFSFT_NOCASESENSITIVE))
1286c8ec8eeaSjose borrego flags |= SMB_TREE_NO_CASESENSITIVE;
1287c8ec8eeaSjose borrego
1288c8ec8eeaSjose borrego if (vfs_has_feature(vfsp, VFSFT_DIRENTFLAGS))
1289c8ec8eeaSjose borrego flags |= SMB_TREE_DIRENTFLAGS;
1290c8ec8eeaSjose borrego
1291c8ec8eeaSjose borrego if (vfs_has_feature(vfsp, VFSFT_ACLONCREATE))
1292c8ec8eeaSjose borrego flags |= SMB_TREE_ACLONCREATE;
1293c8ec8eeaSjose borrego
1294c8ec8eeaSjose borrego if (vfs_has_feature(vfsp, VFSFT_ACEMASKONACCESS))
1295c8ec8eeaSjose borrego flags |= SMB_TREE_ACEMASKONACCESS;
1296c8ec8eeaSjose borrego
1297fc724630SAlan Wright DTRACE_PROBE2(smb__tree__flags, uint32_t, flags, char *, name);
1298fc724630SAlan Wright
1299c8ec8eeaSjose borrego
1300c8ec8eeaSjose borrego tree->t_flags = flags;
1301c8ec8eeaSjose borrego }
1302c8ec8eeaSjose borrego
1303c8ec8eeaSjose borrego /*
1304c8ec8eeaSjose borrego * Report share access result to syslog.
1305c8ec8eeaSjose borrego */
1306c8ec8eeaSjose borrego static void
smb_tree_log(smb_request_t * sr,const char * sharename,const char * fmt,...)1307c8ec8eeaSjose borrego smb_tree_log(smb_request_t *sr, const char *sharename, const char *fmt, ...)
1308c8ec8eeaSjose borrego {
1309c8ec8eeaSjose borrego va_list ap;
1310c8ec8eeaSjose borrego char buf[128];
1311c8ec8eeaSjose borrego smb_user_t *user = sr->uid_user;
1312c8ec8eeaSjose borrego
1313c8ec8eeaSjose borrego ASSERT(user);
1314c8ec8eeaSjose borrego
1315c8ec8eeaSjose borrego if (smb_tcon_mute)
1316c8ec8eeaSjose borrego return;
1317c8ec8eeaSjose borrego
1318c8ec8eeaSjose borrego if ((user->u_name) && (strcasecmp(sharename, "IPC$") == 0)) {
1319c8ec8eeaSjose borrego /*
1320c8ec8eeaSjose borrego * Only report normal users, i.e. ignore W2K misuse
1321c8ec8eeaSjose borrego * of the IPC connection by filtering out internal
1322c8ec8eeaSjose borrego * names such as nobody and root.
1323c8ec8eeaSjose borrego */
1324c8ec8eeaSjose borrego if ((strcmp(user->u_name, "root") == 0) ||
1325c8ec8eeaSjose borrego (strcmp(user->u_name, "nobody") == 0)) {
1326c8ec8eeaSjose borrego return;
1327da6c28aaSamw }
1328da6c28aaSamw }
1329da6c28aaSamw
1330c8ec8eeaSjose borrego va_start(ap, fmt);
1331c8ec8eeaSjose borrego (void) vsnprintf(buf, 128, fmt, ap);
1332c8ec8eeaSjose borrego va_end(ap);
1333c8ec8eeaSjose borrego
1334c8ec8eeaSjose borrego cmn_err(CE_NOTE, "smbd[%s\\%s]: %s %s",
1335c8ec8eeaSjose borrego user->u_domain, user->u_name, sharename, buf);
1336da6c28aaSamw }
13377f667e74Sjose borrego
13387f667e74Sjose borrego /*
13397f667e74Sjose borrego * smb_tree_lookup_odir
13407f667e74Sjose borrego *
13417f667e74Sjose borrego * Find the specified odir in the tree's list of odirs, and
13427f667e74Sjose borrego * attempt to obtain a hold on the odir.
13437f667e74Sjose borrego *
13447f667e74Sjose borrego * Returns NULL if odir not found or a hold cannot be obtained.
13457f667e74Sjose borrego */
13467f667e74Sjose borrego smb_odir_t *
smb_tree_lookup_odir(smb_request_t * sr,uint16_t odid)13473b13a1efSThomas Keiser smb_tree_lookup_odir(smb_request_t *sr, uint16_t odid)
13487f667e74Sjose borrego {
13497f667e74Sjose borrego smb_odir_t *od;
13507f667e74Sjose borrego smb_llist_t *od_list;
13513b13a1efSThomas Keiser smb_tree_t *tree = sr->tid_tree;
13527f667e74Sjose borrego
13537f667e74Sjose borrego ASSERT(tree->t_magic == SMB_TREE_MAGIC);
13547f667e74Sjose borrego
13557f667e74Sjose borrego od_list = &tree->t_odir_list;
13567f667e74Sjose borrego
13573b13a1efSThomas Keiser smb_llist_enter(od_list, RW_READER);
13587f667e74Sjose borrego od = smb_llist_head(od_list);
13597f667e74Sjose borrego while (od) {
13603b13a1efSThomas Keiser if (od->d_odid == odid)
13617f667e74Sjose borrego break;
13627f667e74Sjose borrego od = smb_llist_next(od_list, od);
13637f667e74Sjose borrego }
13643b13a1efSThomas Keiser if (od == NULL)
13653b13a1efSThomas Keiser goto out;
13663b13a1efSThomas Keiser
13673b13a1efSThomas Keiser /*
13683b13a1efSThomas Keiser * Only allow use of a given Search ID with the same UID that
13693b13a1efSThomas Keiser * was used to create it. MS-CIFS 3.3.5.14
13703b13a1efSThomas Keiser */
13713b13a1efSThomas Keiser if (od->d_user != sr->uid_user) {
13723b13a1efSThomas Keiser od = NULL;
13733b13a1efSThomas Keiser goto out;
13743b13a1efSThomas Keiser }
13753b13a1efSThomas Keiser if (!smb_odir_hold(od))
13763b13a1efSThomas Keiser od = NULL;
13777f667e74Sjose borrego
13783b13a1efSThomas Keiser out:
13797f667e74Sjose borrego smb_llist_exit(od_list);
13807f667e74Sjose borrego return (od);
13817f667e74Sjose borrego }
13827f667e74Sjose borrego
13838b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States boolean_t
smb_tree_is_connected(smb_tree_t * tree)13848b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_tree_is_connected(smb_tree_t *tree)
13858b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States {
13868b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States boolean_t rb;
13878b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States
13888b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States mutex_enter(&tree->t_mutex);
13898b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States rb = smb_tree_is_connected_locked(tree);
13908b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States mutex_exit(&tree->t_mutex);
13918b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States return (rb);
13928b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States }
13938b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States
13947f667e74Sjose borrego /*
13957f667e74Sjose borrego * smb_tree_close_odirs
13967f667e74Sjose borrego *
13977f667e74Sjose borrego * Close all open odirs in the tree's list which were opened by
13987f667e74Sjose borrego * the process identified by pid.
13997f667e74Sjose borrego * If pid is zero, close all open odirs in the tree's list.
14007f667e74Sjose borrego */
14017f667e74Sjose borrego static void
smb_tree_close_odirs(smb_tree_t * tree,uint32_t pid)14028d94f651SGordon Ross smb_tree_close_odirs(smb_tree_t *tree, uint32_t pid)
14037f667e74Sjose borrego {
14048d94f651SGordon Ross smb_llist_t *od_list;
14058d94f651SGordon Ross smb_odir_t *od;
14067f667e74Sjose borrego
14077f667e74Sjose borrego ASSERT(tree);
14087f667e74Sjose borrego ASSERT(tree->t_magic == SMB_TREE_MAGIC);
14097f667e74Sjose borrego
14108d94f651SGordon Ross od_list = &tree->t_odir_list;
14118d94f651SGordon Ross smb_llist_enter(od_list, RW_READER);
14128d94f651SGordon Ross
14138d94f651SGordon Ross for (od = smb_llist_head(od_list);
14148d94f651SGordon Ross od != NULL;
14158d94f651SGordon Ross od = smb_llist_next(od_list, od)) {
14168d94f651SGordon Ross
14177f667e74Sjose borrego ASSERT(od->d_magic == SMB_ODIR_MAGIC);
14187f667e74Sjose borrego ASSERT(od->d_tree == tree);
14197f667e74Sjose borrego
14208d94f651SGordon Ross if (pid != 0 && od->d_opened_by_pid != pid)
14218d94f651SGordon Ross continue;
14227f667e74Sjose borrego
14238d94f651SGordon Ross if (smb_odir_hold(od)) {
14248d94f651SGordon Ross smb_odir_close(od);
14258d94f651SGordon Ross smb_odir_release(od);
14268d94f651SGordon Ross }
14277f667e74Sjose borrego }
14288d94f651SGordon Ross
14298d94f651SGordon Ross smb_llist_exit(od_list);
14307f667e74Sjose borrego }
143129bd2886SAlan Wright
143229bd2886SAlan Wright static void
smb_tree_set_execinfo(smb_tree_t * tree,smb_shr_execinfo_t * exec,int exec_type)14333b13a1efSThomas Keiser smb_tree_set_execinfo(smb_tree_t *tree, smb_shr_execinfo_t *exec,
14343b13a1efSThomas Keiser int exec_type)
143529bd2886SAlan Wright {
1436148c5f43SAlan Wright exec->e_sharename = tree->t_sharename;
14373b13a1efSThomas Keiser exec->e_winname = tree->t_owner->u_name;
14383b13a1efSThomas Keiser exec->e_userdom = tree->t_owner->u_domain;
1439148c5f43SAlan Wright exec->e_srv_ipaddr = tree->t_session->local_ipaddr;
1440148c5f43SAlan Wright exec->e_cli_ipaddr = tree->t_session->ipaddr;
1441148c5f43SAlan Wright exec->e_cli_netbiosname = tree->t_session->workstation;
14423b13a1efSThomas Keiser exec->e_uid = crgetuid(tree->t_owner->u_cred);
1443148c5f43SAlan Wright exec->e_type = exec_type;
144429bd2886SAlan Wright }
14451fcced4cSJordan Brown
14461fcced4cSJordan Brown /*
14471fcced4cSJordan Brown * Private function to support smb_tree_enum.
14481fcced4cSJordan Brown */
14491fcced4cSJordan Brown static int
smb_tree_enum_private(smb_tree_t * tree,smb_svcenum_t * svcenum)14501fcced4cSJordan Brown smb_tree_enum_private(smb_tree_t *tree, smb_svcenum_t *svcenum)
14511fcced4cSJordan Brown {
14521fcced4cSJordan Brown uint8_t *pb;
14531fcced4cSJordan Brown uint_t nbytes;
14541fcced4cSJordan Brown int rc;
14551fcced4cSJordan Brown
14561fcced4cSJordan Brown if (svcenum->se_nskip > 0) {
14571fcced4cSJordan Brown svcenum->se_nskip--;
14581fcced4cSJordan Brown return (0);
14591fcced4cSJordan Brown }
14601fcced4cSJordan Brown
14611fcced4cSJordan Brown if (svcenum->se_nitems >= svcenum->se_nlimit) {
14621fcced4cSJordan Brown svcenum->se_nitems = svcenum->se_nlimit;
14631fcced4cSJordan Brown return (0);
14641fcced4cSJordan Brown }
14651fcced4cSJordan Brown
14661fcced4cSJordan Brown pb = &svcenum->se_buf[svcenum->se_bused];
14671fcced4cSJordan Brown rc = smb_tree_netinfo_encode(tree, pb, svcenum->se_bavail, &nbytes);
14681fcced4cSJordan Brown if (rc == 0) {
14691fcced4cSJordan Brown svcenum->se_bavail -= nbytes;
14701fcced4cSJordan Brown svcenum->se_bused += nbytes;
14711fcced4cSJordan Brown svcenum->se_nitems++;
14721fcced4cSJordan Brown }
14731fcced4cSJordan Brown
14741fcced4cSJordan Brown return (rc);
14751fcced4cSJordan Brown }
14761fcced4cSJordan Brown
14771fcced4cSJordan Brown /*
14781fcced4cSJordan Brown * Encode connection information into a buffer: connection information
14791fcced4cSJordan Brown * needed in user space to support RPC requests.
14801fcced4cSJordan Brown */
14811fcced4cSJordan Brown static int
smb_tree_netinfo_encode(smb_tree_t * tree,uint8_t * buf,size_t buflen,uint32_t * nbytes)14821fcced4cSJordan Brown smb_tree_netinfo_encode(smb_tree_t *tree, uint8_t *buf, size_t buflen,
14831fcced4cSJordan Brown uint32_t *nbytes)
14841fcced4cSJordan Brown {
14851fcced4cSJordan Brown smb_netconnectinfo_t info;
14861fcced4cSJordan Brown int rc;
14871fcced4cSJordan Brown
14881fcced4cSJordan Brown smb_tree_netinfo_init(tree, &info);
14891fcced4cSJordan Brown rc = smb_netconnectinfo_encode(&info, buf, buflen, nbytes);
14901fcced4cSJordan Brown smb_tree_netinfo_fini(&info);
14911fcced4cSJordan Brown
14921fcced4cSJordan Brown return (rc);
14931fcced4cSJordan Brown }
14941fcced4cSJordan Brown
14953b13a1efSThomas Keiser static void
smb_tree_netinfo_username(smb_tree_t * tree,char ** namestr,uint32_t * namelen)14963b13a1efSThomas Keiser smb_tree_netinfo_username(smb_tree_t *tree, char **namestr, uint32_t *namelen)
14973b13a1efSThomas Keiser {
14983b13a1efSThomas Keiser smb_user_t *user = tree->t_owner;
14993b13a1efSThomas Keiser
15003b13a1efSThomas Keiser /*
15013b13a1efSThomas Keiser * u_domain_len and u_name_len include the '\0' in their
15023b13a1efSThomas Keiser * lengths, hence the sum of the two lengths gives us room
15033b13a1efSThomas Keiser * for both the '\\' and '\0' chars.
15043b13a1efSThomas Keiser */
15053b13a1efSThomas Keiser ASSERT(namestr);
15063b13a1efSThomas Keiser ASSERT(namelen);
15073b13a1efSThomas Keiser ASSERT(user->u_domain_len > 0);
15083b13a1efSThomas Keiser ASSERT(user->u_name_len > 0);
15093b13a1efSThomas Keiser *namelen = user->u_domain_len + user->u_name_len;
15103b13a1efSThomas Keiser *namestr = kmem_alloc(*namelen, KM_SLEEP);
15113b13a1efSThomas Keiser (void) snprintf(*namestr, *namelen, "%s\\%s", user->u_domain,
15123b13a1efSThomas Keiser user->u_name);
15133b13a1efSThomas Keiser }
15143b13a1efSThomas Keiser
15151fcced4cSJordan Brown /*
15161fcced4cSJordan Brown * Note: ci_numusers should be the number of users connected to
15171fcced4cSJordan Brown * the share rather than the number of references on the tree but
15181fcced4cSJordan Brown * we don't have a mechanism to track users/share in smbsrv yet.
15191fcced4cSJordan Brown */
15201fcced4cSJordan Brown static void
smb_tree_netinfo_init(smb_tree_t * tree,smb_netconnectinfo_t * info)15211fcced4cSJordan Brown smb_tree_netinfo_init(smb_tree_t *tree, smb_netconnectinfo_t *info)
15221fcced4cSJordan Brown {
15231fcced4cSJordan Brown ASSERT(tree);
15241fcced4cSJordan Brown
15251fcced4cSJordan Brown info->ci_id = tree->t_tid;
15261fcced4cSJordan Brown info->ci_type = tree->t_res_type;
15271fcced4cSJordan Brown info->ci_numopens = tree->t_open_files;
15281fcced4cSJordan Brown info->ci_numusers = tree->t_refcnt;
15291fcced4cSJordan Brown info->ci_time = gethrestime_sec() - tree->t_connect_time;
15301fcced4cSJordan Brown
15311fcced4cSJordan Brown info->ci_sharelen = strlen(tree->t_sharename) + 1;
15329fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States info->ci_share = smb_mem_strdup(tree->t_sharename);
15331fcced4cSJordan Brown
15343b13a1efSThomas Keiser smb_tree_netinfo_username(tree, &info->ci_username, &info->ci_namelen);
15351fcced4cSJordan Brown }
15361fcced4cSJordan Brown
15371fcced4cSJordan Brown static void
smb_tree_netinfo_fini(smb_netconnectinfo_t * info)15381fcced4cSJordan Brown smb_tree_netinfo_fini(smb_netconnectinfo_t *info)
15391fcced4cSJordan Brown {
15401fcced4cSJordan Brown if (info == NULL)
15411fcced4cSJordan Brown return;
15421fcced4cSJordan Brown
15431fcced4cSJordan Brown if (info->ci_username)
15441fcced4cSJordan Brown kmem_free(info->ci_username, info->ci_namelen);
15451fcced4cSJordan Brown if (info->ci_share)
15469fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_mem_free(info->ci_share);
15471fcced4cSJordan Brown
15481fcced4cSJordan Brown bzero(info, sizeof (smb_netconnectinfo_t));
15491fcced4cSJordan Brown }
1550