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.
24b819cea2SGordon Ross * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
25da6c28aaSamw */
26da6c28aaSamw
27da6c28aaSamw /*
28da6c28aaSamw * General Structures Layout
29da6c28aaSamw * -------------------------
30da6c28aaSamw *
31da6c28aaSamw * This is a simplified diagram showing the relationship between most of the
32da6c28aaSamw * main structures.
33da6c28aaSamw *
34da6c28aaSamw * +-------------------+
35da6c28aaSamw * | SMB_INFO |
36da6c28aaSamw * +-------------------+
37da6c28aaSamw * |
38da6c28aaSamw * |
39da6c28aaSamw * v
40da6c28aaSamw * +-------------------+ +-------------------+ +-------------------+
41da6c28aaSamw * | SESSION |<----->| SESSION |......| SESSION |
42da6c28aaSamw * +-------------------+ +-------------------+ +-------------------+
433b13a1efSThomas Keiser * | |
443b13a1efSThomas Keiser * | |
453b13a1efSThomas Keiser * | v
463b13a1efSThomas Keiser * | +-------------------+ +-------------------+ +-------------------+
473b13a1efSThomas Keiser * | | USER |<--->| USER |...| USER |
483b13a1efSThomas Keiser * | +-------------------+ +-------------------+ +-------------------+
49da6c28aaSamw * |
50da6c28aaSamw * |
51da6c28aaSamw * v
52da6c28aaSamw * +-------------------+ +-------------------+ +-------------------+
53da6c28aaSamw * | TREE |<----->| TREE |......| TREE |
54da6c28aaSamw * +-------------------+ +-------------------+ +-------------------+
55da6c28aaSamw * | |
56da6c28aaSamw * | |
57da6c28aaSamw * | v
58da6c28aaSamw * | +-------+ +-------+ +-------+
59da6c28aaSamw * | | OFILE |<----->| OFILE |......| OFILE |
60da6c28aaSamw * | +-------+ +-------+ +-------+
61da6c28aaSamw * |
62da6c28aaSamw * |
63da6c28aaSamw * v
64da6c28aaSamw * +-------+ +------+ +------+
65da6c28aaSamw * | ODIR |<----->| ODIR |......| ODIR |
66da6c28aaSamw * +-------+ +------+ +------+
67da6c28aaSamw *
68da6c28aaSamw *
69da6c28aaSamw * Tree State Machine
70da6c28aaSamw * ------------------
71da6c28aaSamw *
72da6c28aaSamw * +-----------------------------+ T0
73da6c28aaSamw * | SMB_TREE_STATE_CONNECTED |<----------- Creation/Allocation
74da6c28aaSamw * +-----------------------------+
75da6c28aaSamw * |
76da6c28aaSamw * | T1
77da6c28aaSamw * |
78da6c28aaSamw * v
79da6c28aaSamw * +------------------------------+
80da6c28aaSamw * | SMB_TREE_STATE_DISCONNECTING |
81da6c28aaSamw * +------------------------------+
82da6c28aaSamw * |
83da6c28aaSamw * | T2
84da6c28aaSamw * |
85da6c28aaSamw * v
86da6c28aaSamw * +-----------------------------+ T3
87da6c28aaSamw * | SMB_TREE_STATE_DISCONNECTED |----------> Deletion/Free
88da6c28aaSamw * +-----------------------------+
89da6c28aaSamw *
90da6c28aaSamw * SMB_TREE_STATE_CONNECTED
91da6c28aaSamw *
92da6c28aaSamw * While in this state:
93da6c28aaSamw * - The tree is queued in the list of trees of its user.
94da6c28aaSamw * - References will be given out if the tree is looked up.
95da6c28aaSamw * - Files under that tree can be accessed.
96da6c28aaSamw *
97da6c28aaSamw * SMB_TREE_STATE_DISCONNECTING
98da6c28aaSamw *
99da6c28aaSamw * While in this state:
100da6c28aaSamw * - The tree is queued in the list of trees of its user.
101da6c28aaSamw * - References will not be given out if the tree is looked up.
102da6c28aaSamw * - The files and directories open under the tree are being closed.
103da6c28aaSamw * - The resources associated with the tree remain.
104da6c28aaSamw *
105da6c28aaSamw * SMB_TREE_STATE_DISCONNECTED
106da6c28aaSamw *
107da6c28aaSamw * While in this state:
108da6c28aaSamw * - The tree is queued in the list of trees of its user.
109da6c28aaSamw * - References will not be given out if the tree is looked up.
110da6c28aaSamw * - The tree has no more files and directories opened.
111da6c28aaSamw * - The resources associated with the tree remain.
112da6c28aaSamw *
113da6c28aaSamw * Transition T0
114da6c28aaSamw *
115da6c28aaSamw * This transition occurs in smb_tree_connect(). A new tree is created and
116da6c28aaSamw * added to the list of trees of a user.
117da6c28aaSamw *
118da6c28aaSamw * Transition T1
119da6c28aaSamw *
120da6c28aaSamw * This transition occurs in smb_tree_disconnect().
121da6c28aaSamw *
122da6c28aaSamw * Transition T2
123da6c28aaSamw *
124da6c28aaSamw * This transition occurs in smb_tree_release(). The resources associated
125da6c28aaSamw * with the tree are freed as well as the tree structure. For the transition
126da6c28aaSamw * to occur, the tree must be in the SMB_TREE_STATE_DISCONNECTED state and
127da6c28aaSamw * the reference count be zero.
128da6c28aaSamw *
129da6c28aaSamw * Comments
130da6c28aaSamw * --------
131da6c28aaSamw *
132da6c28aaSamw * The state machine of the tree structures is controlled by 3 elements:
133da6c28aaSamw * - The list of trees of the user it belongs to.
134da6c28aaSamw * - The mutex embedded in the structure itself.
135da6c28aaSamw * - The reference count.
136da6c28aaSamw *
137da6c28aaSamw * There's a mutex embedded in the tree structure used to protect its fields
138da6c28aaSamw * and there's a lock embedded in the list of trees of a user. To
139da6c28aaSamw * increment or to decrement the reference count the mutex must be entered.
140da6c28aaSamw * To insert the tree into the list of trees of the user and to remove
141da6c28aaSamw * the tree from it, the lock must be entered in RW_WRITER mode.
142da6c28aaSamw *
143da6c28aaSamw * Rules of access to a tree structure:
144da6c28aaSamw *
145da6c28aaSamw * 1) In order to avoid deadlocks, when both (mutex and lock of the user
146da6c28aaSamw * list) have to be entered, the lock must be entered first.
147da6c28aaSamw *
148da6c28aaSamw * 2) All actions applied to a tree require a reference count.
149da6c28aaSamw *
150c8ec8eeaSjose borrego * 3) There are 2 ways of getting a reference count: when a tree is
151c8ec8eeaSjose borrego * connected and when a tree is looked up.
152da6c28aaSamw *
153da6c28aaSamw * It should be noted that the reference count of a tree registers the
154da6c28aaSamw * number of references to the tree in other structures (such as an smb
155da6c28aaSamw * request). The reference count is not incremented in these 2 instances:
156da6c28aaSamw *
157da6c28aaSamw * 1) The tree is connected. An tree is anchored by his state. If there's
158da6c28aaSamw * no activity involving a tree currently connected, the reference
159da6c28aaSamw * count of that tree is zero.
160da6c28aaSamw *
161da6c28aaSamw * 2) The tree is queued in the list of trees of the user. The fact of
162da6c28aaSamw * being queued in that list is NOT registered by incrementing the
163da6c28aaSamw * reference count.
164da6c28aaSamw */
165148c5f43SAlan Wright
166c8ec8eeaSjose borrego #include <sys/refstr_impl.h>
167bbf6f00cSJordan Brown #include <smbsrv/smb_kproto.h>
168148c5f43SAlan Wright #include <smbsrv/smb_ktypes.h>
169da6c28aaSamw #include <smbsrv/smb_fsops.h>
170cb174861Sjoyce mcintosh #include <smbsrv/smb_share.h>
171da6c28aaSamw
172c8ec8eeaSjose borrego int smb_tcon_mute = 0;
173c8ec8eeaSjose borrego
174*a90cf9f2SGordon Ross uint32_t smb_tree_connect_core(smb_request_t *);
175*a90cf9f2SGordon Ross uint32_t smb_tree_connect_disk(smb_request_t *, smb_arg_tcon_t *);
176*a90cf9f2SGordon Ross uint32_t smb_tree_connect_printq(smb_request_t *, smb_arg_tcon_t *);
177*a90cf9f2SGordon Ross uint32_t smb_tree_connect_ipc(smb_request_t *, smb_arg_tcon_t *);
1783b13a1efSThomas Keiser static smb_tree_t *smb_tree_alloc(smb_request_t *, const smb_kshare_t *,
179148c5f43SAlan Wright smb_node_t *, uint32_t, uint32_t);
1808b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States static boolean_t smb_tree_is_connected_locked(smb_tree_t *);
181c8ec8eeaSjose borrego static boolean_t smb_tree_is_disconnected(smb_tree_t *);
182*a90cf9f2SGordon Ross static char *smb_tree_get_sharename(char *);
183148c5f43SAlan Wright static int smb_tree_getattr(const smb_kshare_t *, smb_node_t *, smb_tree_t *);
184c8ec8eeaSjose borrego static void smb_tree_get_volname(vfs_t *, smb_tree_t *);
185148c5f43SAlan Wright static void smb_tree_get_flags(const smb_kshare_t *, vfs_t *, smb_tree_t *);
186c8ec8eeaSjose borrego static void smb_tree_log(smb_request_t *, const char *, const char *, ...);
1877f667e74Sjose borrego static void smb_tree_close_odirs(smb_tree_t *, uint16_t);
1881fcced4cSJordan Brown static smb_ofile_t *smb_tree_get_ofile(smb_tree_t *, smb_ofile_t *);
1897f667e74Sjose borrego static smb_odir_t *smb_tree_get_odir(smb_tree_t *, smb_odir_t *);
190148c5f43SAlan Wright static void smb_tree_set_execinfo(smb_tree_t *, smb_shr_execinfo_t *, int);
1911fcced4cSJordan Brown static int smb_tree_enum_private(smb_tree_t *, smb_svcenum_t *);
1921fcced4cSJordan Brown static int smb_tree_netinfo_encode(smb_tree_t *, uint8_t *, size_t, uint32_t *);
1931fcced4cSJordan Brown static void smb_tree_netinfo_init(smb_tree_t *tree, smb_netconnectinfo_t *);
1941fcced4cSJordan Brown static void smb_tree_netinfo_fini(smb_netconnectinfo_t *);
195da6c28aaSamw
196*a90cf9f2SGordon Ross uint32_t
smb_tree_connect(smb_request_t * sr)197cb174861Sjoyce mcintosh smb_tree_connect(smb_request_t *sr)
198cb174861Sjoyce mcintosh {
199cb174861Sjoyce mcintosh smb_server_t *sv = sr->sr_server;
200*a90cf9f2SGordon Ross uint32_t status;
201cb174861Sjoyce mcintosh
202cb174861Sjoyce mcintosh if (smb_threshold_enter(&sv->sv_tcon_ct) != 0) {
203*a90cf9f2SGordon Ross return (NT_STATUS_INSUFF_SERVER_RESOURCES);
204cb174861Sjoyce mcintosh }
205cb174861Sjoyce mcintosh
206*a90cf9f2SGordon Ross status = smb_tree_connect_core(sr);
207856399cfSGordon Ross smb_threshold_exit(&sv->sv_tcon_ct);
208*a90cf9f2SGordon Ross return (status);
209cb174861Sjoyce mcintosh }
210cb174861Sjoyce mcintosh
211da6c28aaSamw /*
212148c5f43SAlan Wright * Lookup the share name dispatch the appropriate stype handler.
213c8ec8eeaSjose borrego * Share names are case insensitive so we map the share name to
214c8ec8eeaSjose borrego * lower-case as a convenience for internal processing.
215148c5f43SAlan Wright *
216148c5f43SAlan Wright * Valid service values are:
217148c5f43SAlan Wright * A: Disk share
218148c5f43SAlan Wright * LPT1: Printer
219148c5f43SAlan Wright * IPC Named pipe (IPC$ is reserved as the named pipe share).
220148c5f43SAlan Wright * COMM Communications device
221148c5f43SAlan Wright * ????? Any type of device (wildcard)
222da6c28aaSamw */
223*a90cf9f2SGordon Ross uint32_t
smb_tree_connect_core(smb_request_t * sr)224cb174861Sjoyce mcintosh smb_tree_connect_core(smb_request_t *sr)
225c8ec8eeaSjose borrego {
226*a90cf9f2SGordon Ross smb_arg_tcon_t *tcon = &sr->sr_tcon;
227148c5f43SAlan Wright smb_kshare_t *si;
228*a90cf9f2SGordon Ross char *name;
229*a90cf9f2SGordon Ross uint32_t status;
230c8ec8eeaSjose borrego
231*a90cf9f2SGordon Ross (void) smb_strlwr(tcon->path);
232c8ec8eeaSjose borrego
233*a90cf9f2SGordon Ross if ((name = smb_tree_get_sharename(tcon->path)) == NULL) {
234*a90cf9f2SGordon Ross smb_tree_log(sr, tcon->path, "invalid UNC path");
235*a90cf9f2SGordon Ross return (NT_STATUS_BAD_NETWORK_NAME);
236c8ec8eeaSjose borrego }
237c8ec8eeaSjose borrego
2388622ec45SGordon Ross si = smb_kshare_lookup(sr->sr_server, name);
2398622ec45SGordon Ross if (si == NULL) {
240148c5f43SAlan Wright smb_tree_log(sr, name, "share not found");
241*a90cf9f2SGordon Ross return (NT_STATUS_BAD_NETWORK_NAME);
242c8ec8eeaSjose borrego }
243cb174861Sjoyce mcintosh
244cb174861Sjoyce mcintosh if (!strcasecmp(SMB_SHARE_PRINT, name)) {
2458622ec45SGordon Ross smb_kshare_release(sr->sr_server, si);
246cb174861Sjoyce mcintosh smb_tree_log(sr, name, "access not permitted");
247*a90cf9f2SGordon Ross return (NT_STATUS_ACCESS_DENIED);
248cb174861Sjoyce mcintosh }
249cb174861Sjoyce mcintosh
250*a90cf9f2SGordon Ross /* NB: name points into tcon->path - don't free it. */
251*a90cf9f2SGordon Ross tcon->name = name;
252148c5f43SAlan Wright sr->sr_tcon.si = si;
253c8ec8eeaSjose borrego
254148c5f43SAlan Wright switch (si->shr_type & STYPE_MASK) {
255c8ec8eeaSjose borrego case STYPE_DISKTREE:
256*a90cf9f2SGordon Ross status = smb_tree_connect_disk(sr, &sr->sr_tcon);
257c8ec8eeaSjose borrego break;
258c8ec8eeaSjose borrego case STYPE_IPC:
259*a90cf9f2SGordon Ross status = smb_tree_connect_ipc(sr, &sr->sr_tcon);
260c8ec8eeaSjose borrego break;
261148c5f43SAlan Wright case STYPE_PRINTQ:
262*a90cf9f2SGordon Ross status = smb_tree_connect_printq(sr, &sr->sr_tcon);
263148c5f43SAlan Wright break;
264c8ec8eeaSjose borrego default:
265*a90cf9f2SGordon Ross status = NT_STATUS_BAD_DEVICE_TYPE;
266c8ec8eeaSjose borrego break;
267c8ec8eeaSjose borrego }
268c8ec8eeaSjose borrego
2698622ec45SGordon Ross smb_kshare_release(sr->sr_server, si);
270*a90cf9f2SGordon Ross sr->sr_tcon.si = NULL;
271*a90cf9f2SGordon Ross
272*a90cf9f2SGordon Ross return (status);
273c8ec8eeaSjose borrego }
274c8ec8eeaSjose borrego
275c8ec8eeaSjose borrego /*
276c8ec8eeaSjose borrego * Disconnect a tree.
277c8ec8eeaSjose borrego */
278c8ec8eeaSjose borrego void
smb_tree_disconnect(smb_tree_t * tree,boolean_t do_exec)27929bd2886SAlan Wright smb_tree_disconnect(smb_tree_t *tree, boolean_t do_exec)
280c8ec8eeaSjose borrego {
281148c5f43SAlan Wright smb_shr_execinfo_t execinfo;
28229bd2886SAlan Wright
283c8ec8eeaSjose borrego ASSERT(tree->t_magic == SMB_TREE_MAGIC);
284c8ec8eeaSjose borrego
285c8ec8eeaSjose borrego mutex_enter(&tree->t_mutex);
286c8ec8eeaSjose borrego ASSERT(tree->t_refcnt);
287c8ec8eeaSjose borrego
2888b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (smb_tree_is_connected_locked(tree)) {
289c8ec8eeaSjose borrego /*
290c8ec8eeaSjose borrego * Indicate that the disconnect process has started.
291c8ec8eeaSjose borrego */
292c8ec8eeaSjose borrego tree->t_state = SMB_TREE_STATE_DISCONNECTING;
293c8ec8eeaSjose borrego mutex_exit(&tree->t_mutex);
294c8ec8eeaSjose borrego
29529bd2886SAlan Wright if (do_exec) {
296c8ec8eeaSjose borrego /*
297c8ec8eeaSjose borrego * The files opened under this tree are closed.
298c8ec8eeaSjose borrego */
299c8ec8eeaSjose borrego smb_ofile_close_all(tree);
300c8ec8eeaSjose borrego /*
301c8ec8eeaSjose borrego * The directories opened under this tree are closed.
302c8ec8eeaSjose borrego */
3037f667e74Sjose borrego smb_tree_close_odirs(tree, 0);
30429bd2886SAlan Wright }
30529bd2886SAlan Wright
306c8ec8eeaSjose borrego mutex_enter(&tree->t_mutex);
307c8ec8eeaSjose borrego tree->t_state = SMB_TREE_STATE_DISCONNECTED;
308148c5f43SAlan Wright smb_server_dec_trees(tree->t_server);
309c8ec8eeaSjose borrego }
310c8ec8eeaSjose borrego
311c8ec8eeaSjose borrego mutex_exit(&tree->t_mutex);
31229bd2886SAlan Wright
313148c5f43SAlan Wright if (do_exec && (tree->t_state == SMB_TREE_STATE_DISCONNECTED) &&
314148c5f43SAlan Wright (tree->t_execflags & SMB_EXEC_UNMAP)) {
31529bd2886SAlan Wright
316148c5f43SAlan Wright smb_tree_set_execinfo(tree, &execinfo, SMB_EXEC_UNMAP);
3178622ec45SGordon Ross (void) smb_kshare_exec(tree->t_server, &execinfo);
31829bd2886SAlan Wright }
319c8ec8eeaSjose borrego }
320c8ec8eeaSjose borrego
321c8ec8eeaSjose borrego /*
322c8ec8eeaSjose borrego * Take a reference on a tree.
323c8ec8eeaSjose borrego */
324c8ec8eeaSjose borrego boolean_t
smb_tree_hold(smb_tree_t * tree)325c8ec8eeaSjose borrego smb_tree_hold(
326c8ec8eeaSjose borrego smb_tree_t *tree)
327c8ec8eeaSjose borrego {
328*a90cf9f2SGordon Ross SMB_TREE_VALID(tree);
329c8ec8eeaSjose borrego
330c8ec8eeaSjose borrego mutex_enter(&tree->t_mutex);
331c8ec8eeaSjose borrego
3328b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (smb_tree_is_connected_locked(tree)) {
333c8ec8eeaSjose borrego tree->t_refcnt++;
334c8ec8eeaSjose borrego mutex_exit(&tree->t_mutex);
335c8ec8eeaSjose borrego return (B_TRUE);
336c8ec8eeaSjose borrego }
337c8ec8eeaSjose borrego
338c8ec8eeaSjose borrego mutex_exit(&tree->t_mutex);
339c8ec8eeaSjose borrego return (B_FALSE);
340c8ec8eeaSjose borrego }
341c8ec8eeaSjose borrego
342c8ec8eeaSjose borrego /*
343*a90cf9f2SGordon Ross * Bump the hold count regardless of the tree state. This is used in
344*a90cf9f2SGordon Ross * some internal code paths where we've already checked that we had a
345*a90cf9f2SGordon Ross * valid tree connection, and don't want to deal with the possiblity
346*a90cf9f2SGordon Ross * that the tree state might have changed to disconnecting after our
347*a90cf9f2SGordon Ross * original hold was taken. It's correct to continue processing a
348*a90cf9f2SGordon Ross * request even when new requests cannot lookup that tree anymore.
349*a90cf9f2SGordon Ross */
350*a90cf9f2SGordon Ross void
smb_tree_hold_internal(smb_tree_t * tree)351*a90cf9f2SGordon Ross smb_tree_hold_internal(
352*a90cf9f2SGordon Ross smb_tree_t *tree)
353*a90cf9f2SGordon Ross {
354*a90cf9f2SGordon Ross SMB_TREE_VALID(tree);
355*a90cf9f2SGordon Ross
356*a90cf9f2SGordon Ross mutex_enter(&tree->t_mutex);
357*a90cf9f2SGordon Ross tree->t_refcnt++;
358*a90cf9f2SGordon Ross mutex_exit(&tree->t_mutex);
359*a90cf9f2SGordon Ross }
360*a90cf9f2SGordon Ross
361*a90cf9f2SGordon Ross /*
362c8ec8eeaSjose borrego * Release a reference on a tree. If the tree is disconnected and the
3639fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * reference count falls to zero, post the object for deletion.
3649fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Object deletion is deferred to avoid modifying a list while an
3659fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * iteration may be in progress.
366c8ec8eeaSjose borrego */
367c8ec8eeaSjose borrego void
smb_tree_release(smb_tree_t * tree)368c8ec8eeaSjose borrego smb_tree_release(
369c8ec8eeaSjose borrego smb_tree_t *tree)
370c8ec8eeaSjose borrego {
3719fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_TREE_VALID(tree);
372c8ec8eeaSjose borrego
373c8ec8eeaSjose borrego mutex_enter(&tree->t_mutex);
374c8ec8eeaSjose borrego ASSERT(tree->t_refcnt);
375c8ec8eeaSjose borrego tree->t_refcnt--;
376c8ec8eeaSjose borrego
377c5866007SKeyur Desai /* flush the ofile and odir lists' delete queues */
378c5866007SKeyur Desai smb_llist_flush(&tree->t_ofile_list);
379c5866007SKeyur Desai smb_llist_flush(&tree->t_odir_list);
380c5866007SKeyur Desai
3819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (smb_tree_is_disconnected(tree) && (tree->t_refcnt == 0))
3823b13a1efSThomas Keiser smb_session_post_tree(tree->t_session, tree);
383c8ec8eeaSjose borrego
384c8ec8eeaSjose borrego mutex_exit(&tree->t_mutex);
385c8ec8eeaSjose borrego }
386c8ec8eeaSjose borrego
3879fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States void
smb_tree_post_ofile(smb_tree_t * tree,smb_ofile_t * of)3889fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_tree_post_ofile(smb_tree_t *tree, smb_ofile_t *of)
3899fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
3909fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_TREE_VALID(tree);
3919fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_OFILE_VALID(of);
3929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ASSERT(of->f_refcnt == 0);
3939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ASSERT(of->f_state == SMB_OFILE_STATE_CLOSED);
3949fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ASSERT(of->f_tree == tree);
3959fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
3969fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_llist_post(&tree->t_ofile_list, of, smb_ofile_delete);
3979fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
3989fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
3999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States void
smb_tree_post_odir(smb_tree_t * tree,smb_odir_t * od)4009fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_tree_post_odir(smb_tree_t *tree, smb_odir_t *od)
4019fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
4029fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_TREE_VALID(tree);
4039fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_ODIR_VALID(od);
4049fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ASSERT(od->d_refcnt == 0);
4059fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ASSERT(od->d_state == SMB_ODIR_STATE_CLOSED);
4069fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ASSERT(od->d_tree == tree);
4079fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
4089fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_llist_post(&tree->t_odir_list, od, smb_odir_delete);
4099fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
4109fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
411c8ec8eeaSjose borrego /*
412c8ec8eeaSjose borrego * Close ofiles and odirs that match pid.
413c8ec8eeaSjose borrego */
414c8ec8eeaSjose borrego void
smb_tree_close_pid(smb_tree_t * tree,uint32_t pid)415c8ec8eeaSjose borrego smb_tree_close_pid(
416c8ec8eeaSjose borrego smb_tree_t *tree,
417*a90cf9f2SGordon Ross uint32_t pid)
418c8ec8eeaSjose borrego {
419c8ec8eeaSjose borrego ASSERT(tree);
420c8ec8eeaSjose borrego ASSERT(tree->t_magic == SMB_TREE_MAGIC);
421c8ec8eeaSjose borrego
422c8ec8eeaSjose borrego smb_ofile_close_all_by_pid(tree, pid);
4237f667e74Sjose borrego smb_tree_close_odirs(tree, pid);
424c8ec8eeaSjose borrego }
425c8ec8eeaSjose borrego
426c8ec8eeaSjose borrego /*
427c8ec8eeaSjose borrego * Check whether or not a tree supports the features identified by flags.
428c8ec8eeaSjose borrego */
429c8ec8eeaSjose borrego boolean_t
smb_tree_has_feature(smb_tree_t * tree,uint32_t flags)430c8ec8eeaSjose borrego smb_tree_has_feature(smb_tree_t *tree, uint32_t flags)
431c8ec8eeaSjose borrego {
432c8ec8eeaSjose borrego ASSERT(tree);
433c8ec8eeaSjose borrego ASSERT(tree->t_magic == SMB_TREE_MAGIC);
434c8ec8eeaSjose borrego
435c8ec8eeaSjose borrego return ((tree->t_flags & flags) == flags);
436c8ec8eeaSjose borrego }
437c8ec8eeaSjose borrego
4381fcced4cSJordan Brown /*
4391fcced4cSJordan Brown * If the enumeration request is for tree data, handle the request
4401fcced4cSJordan Brown * here. Otherwise, pass it on to the ofiles.
4411fcced4cSJordan Brown *
4421fcced4cSJordan Brown * This function should be called with a hold on the tree.
4431fcced4cSJordan Brown */
4441fcced4cSJordan Brown int
smb_tree_enum(smb_tree_t * tree,smb_svcenum_t * svcenum)4451fcced4cSJordan Brown smb_tree_enum(smb_tree_t *tree, smb_svcenum_t *svcenum)
4461fcced4cSJordan Brown {
4471fcced4cSJordan Brown smb_ofile_t *of;
4481fcced4cSJordan Brown smb_ofile_t *next;
4493b13a1efSThomas Keiser int rc = 0;
4501fcced4cSJordan Brown
4511fcced4cSJordan Brown ASSERT(tree);
4521fcced4cSJordan Brown ASSERT(tree->t_magic == SMB_TREE_MAGIC);
4531fcced4cSJordan Brown
4541fcced4cSJordan Brown if (svcenum->se_type == SMB_SVCENUM_TYPE_TREE)
4551fcced4cSJordan Brown return (smb_tree_enum_private(tree, svcenum));
4561fcced4cSJordan Brown
4571fcced4cSJordan Brown of = smb_tree_get_ofile(tree, NULL);
4581fcced4cSJordan Brown while (of) {
4591fcced4cSJordan Brown ASSERT(of->f_tree == tree);
4601fcced4cSJordan Brown
4611fcced4cSJordan Brown rc = smb_ofile_enum(of, svcenum);
4621fcced4cSJordan Brown if (rc != 0) {
4631fcced4cSJordan Brown smb_ofile_release(of);
4641fcced4cSJordan Brown break;
4651fcced4cSJordan Brown }
4661fcced4cSJordan Brown
4671fcced4cSJordan Brown next = smb_tree_get_ofile(tree, of);
4681fcced4cSJordan Brown smb_ofile_release(of);
4691fcced4cSJordan Brown of = next;
4701fcced4cSJordan Brown }
4711fcced4cSJordan Brown
4721fcced4cSJordan Brown return (rc);
4731fcced4cSJordan Brown }
4741fcced4cSJordan Brown
4751fcced4cSJordan Brown /*
4761fcced4cSJordan Brown * Close a file by its unique id.
4771fcced4cSJordan Brown */
4781fcced4cSJordan Brown int
smb_tree_fclose(smb_tree_t * tree,uint32_t uniqid)4791fcced4cSJordan Brown smb_tree_fclose(smb_tree_t *tree, uint32_t uniqid)
4801fcced4cSJordan Brown {
4811fcced4cSJordan Brown smb_ofile_t *of;
4821fcced4cSJordan Brown
4831fcced4cSJordan Brown ASSERT(tree);
4841fcced4cSJordan Brown ASSERT(tree->t_magic == SMB_TREE_MAGIC);
4851fcced4cSJordan Brown
4861fcced4cSJordan Brown if ((of = smb_ofile_lookup_by_uniqid(tree, uniqid)) == NULL)
4871fcced4cSJordan Brown return (ENOENT);
4881fcced4cSJordan Brown
4891fcced4cSJordan Brown if (smb_ofile_disallow_fclose(of)) {
4901fcced4cSJordan Brown smb_ofile_release(of);
4911fcced4cSJordan Brown return (EACCES);
4921fcced4cSJordan Brown }
4931fcced4cSJordan Brown
4941fcced4cSJordan Brown smb_ofile_close(of, 0);
4951fcced4cSJordan Brown smb_ofile_release(of);
4961fcced4cSJordan Brown return (0);
4971fcced4cSJordan Brown }
498743a77edSAlan Wright
499c8ec8eeaSjose borrego /* *************************** Static Functions ***************************** */
5001fcced4cSJordan Brown
501743a77edSAlan Wright #define SHARES_DIR ".zfs/shares/"
502148c5f43SAlan Wright
503148c5f43SAlan Wright /*
504148c5f43SAlan Wright * Calculates permissions given by the share's ACL to the
505148c5f43SAlan Wright * user in the passed request. The default is full access.
506148c5f43SAlan Wright * If any error occurs, full access is granted.
507148c5f43SAlan Wright *
508148c5f43SAlan Wright * Using the vnode of the share path find the root directory
509148c5f43SAlan Wright * of the mounted file system. Then look to see if there is a
510148c5f43SAlan Wright * .zfs/shares directory and if there is, lookup the file with
511148c5f43SAlan Wright * the same name as the share name in it. The ACL set for this
512148c5f43SAlan Wright * file is the share's ACL which is used for access check here.
513148c5f43SAlan Wright */
514148c5f43SAlan Wright static uint32_t
smb_tree_acl_access(smb_request_t * sr,const smb_kshare_t * si,vnode_t * pathvp)515148c5f43SAlan Wright smb_tree_acl_access(smb_request_t *sr, const smb_kshare_t *si, vnode_t *pathvp)
516743a77edSAlan Wright {
517fe1c642dSBill Krier smb_user_t *user;
518fe1c642dSBill Krier cred_t *cred;
519743a77edSAlan Wright int rc;
520743a77edSAlan Wright vfs_t *vfsp;
521743a77edSAlan Wright vnode_t *root = NULL;
522743a77edSAlan Wright vnode_t *sharevp = NULL;
523743a77edSAlan Wright char *sharepath;
524743a77edSAlan Wright struct pathname pnp;
525743a77edSAlan Wright size_t size;
526148c5f43SAlan Wright uint32_t access;
527743a77edSAlan Wright
528fe1c642dSBill Krier user = sr->uid_user;
529fe1c642dSBill Krier cred = user->u_cred;
530148c5f43SAlan Wright access = ACE_ALL_PERMS;
531743a77edSAlan Wright
532fe1c642dSBill Krier if (si->shr_flags & SMB_SHRF_AUTOHOME) {
533fe1c642dSBill Krier /*
534fe1c642dSBill Krier * An autohome share owner gets full access to the share.
535fe1c642dSBill Krier * Everyone else is denied access.
536fe1c642dSBill Krier */
537c5866007SKeyur Desai if (si->shr_uid != crgetuid(cred))
538148c5f43SAlan Wright access = 0;
539148c5f43SAlan Wright
540148c5f43SAlan Wright return (access);
541fe1c642dSBill Krier }
542fe1c642dSBill Krier
543743a77edSAlan Wright /*
544148c5f43SAlan Wright * The hold on 'root' is released by the lookuppnvp() that follows
545743a77edSAlan Wright */
546743a77edSAlan Wright vfsp = pathvp->v_vfsp;
547743a77edSAlan Wright if (vfsp != NULL)
548743a77edSAlan Wright rc = VFS_ROOT(vfsp, &root);
549743a77edSAlan Wright else
550743a77edSAlan Wright rc = ENOENT;
551743a77edSAlan Wright
552743a77edSAlan Wright if (rc != 0)
553148c5f43SAlan Wright return (access);
554743a77edSAlan Wright
555743a77edSAlan Wright
556fe1c642dSBill Krier size = sizeof (SHARES_DIR) + strlen(si->shr_name) + 1;
557148c5f43SAlan Wright sharepath = smb_srm_alloc(sr, size);
558b819cea2SGordon Ross (void) snprintf(sharepath, size, "%s%s", SHARES_DIR, si->shr_name);
559743a77edSAlan Wright
560743a77edSAlan Wright pn_alloc(&pnp);
561743a77edSAlan Wright (void) pn_set(&pnp, sharepath);
562148c5f43SAlan Wright rc = lookuppnvp(&pnp, NULL, NO_FOLLOW, NULL, &sharevp, rootdir, root,
5638622ec45SGordon Ross zone_kcred());
564743a77edSAlan Wright pn_free(&pnp);
565743a77edSAlan Wright
566743a77edSAlan Wright /*
567148c5f43SAlan Wright * Now get the effective access value based on cred and ACL values.
568743a77edSAlan Wright */
569037cac00Sjoyce mcintosh if (rc == 0) {
570148c5f43SAlan Wright smb_vop_eaccess(sharevp, (int *)&access, V_ACE_MASK, NULL,
571148c5f43SAlan Wright cred);
572037cac00Sjoyce mcintosh VN_RELE(sharevp);
573037cac00Sjoyce mcintosh }
574148c5f43SAlan Wright
575148c5f43SAlan Wright return (access);
576148c5f43SAlan Wright }
577148c5f43SAlan Wright
578148c5f43SAlan Wright /*
579148c5f43SAlan Wright * Performs the following access checks for a disk share:
580148c5f43SAlan Wright *
581148c5f43SAlan Wright * - No IPC/anonymous user is allowed
582148c5f43SAlan Wright *
583148c5f43SAlan Wright * - If user is Guest, guestok property of the share should be
584148c5f43SAlan Wright * enabled
585148c5f43SAlan Wright *
586148c5f43SAlan Wright * - If this is an Admin share, the user should have administrative
587148c5f43SAlan Wright * privileges
588148c5f43SAlan Wright *
589148c5f43SAlan Wright * - Host based access control lists
590148c5f43SAlan Wright *
591148c5f43SAlan Wright * - Share ACL
592148c5f43SAlan Wright *
593148c5f43SAlan Wright * Returns the access allowed or 0 if access is denied.
594148c5f43SAlan Wright */
595148c5f43SAlan Wright static uint32_t
smb_tree_chkaccess(smb_request_t * sr,smb_kshare_t * shr,vnode_t * vp)596148c5f43SAlan Wright smb_tree_chkaccess(smb_request_t *sr, smb_kshare_t *shr, vnode_t *vp)
597148c5f43SAlan Wright {
598148c5f43SAlan Wright smb_user_t *user = sr->uid_user;
599148c5f43SAlan Wright char *sharename = shr->shr_name;
600148c5f43SAlan Wright uint32_t host_access;
601148c5f43SAlan Wright uint32_t acl_access;
602148c5f43SAlan Wright uint32_t access;
603148c5f43SAlan Wright
604*a90cf9f2SGordon Ross if (user->u_flags & SMB_USER_FLAG_ANON) {
605148c5f43SAlan Wright smb_tree_log(sr, sharename, "access denied: IPC only");
606148c5f43SAlan Wright return (0);
607148c5f43SAlan Wright }
608148c5f43SAlan Wright
609148c5f43SAlan Wright if ((user->u_flags & SMB_USER_FLAG_GUEST) &&
610148c5f43SAlan Wright ((shr->shr_flags & SMB_SHRF_GUEST_OK) == 0)) {
611148c5f43SAlan Wright smb_tree_log(sr, sharename, "access denied: guest disabled");
612148c5f43SAlan Wright return (0);
613148c5f43SAlan Wright }
614148c5f43SAlan Wright
615148c5f43SAlan Wright if ((shr->shr_flags & SMB_SHRF_ADMIN) && !smb_user_is_admin(user)) {
616148c5f43SAlan Wright smb_tree_log(sr, sharename, "access denied: not admin");
617148c5f43SAlan Wright return (0);
618148c5f43SAlan Wright }
619148c5f43SAlan Wright
6208622ec45SGordon Ross host_access = smb_kshare_hostaccess(shr, sr->session);
621148c5f43SAlan Wright if ((host_access & ACE_ALL_PERMS) == 0) {
622148c5f43SAlan Wright smb_tree_log(sr, sharename, "access denied: host access");
623148c5f43SAlan Wright return (0);
624148c5f43SAlan Wright }
625148c5f43SAlan Wright
626148c5f43SAlan Wright acl_access = smb_tree_acl_access(sr, shr, vp);
627148c5f43SAlan Wright if ((acl_access & ACE_ALL_PERMS) == 0) {
628148c5f43SAlan Wright smb_tree_log(sr, sharename, "access denied: share ACL");
629148c5f43SAlan Wright return (0);
630148c5f43SAlan Wright }
631148c5f43SAlan Wright
632148c5f43SAlan Wright access = host_access & acl_access;
633148c5f43SAlan Wright if ((access & ACE_ALL_PERMS) == 0) {
634148c5f43SAlan Wright smb_tree_log(sr, sharename, "access denied");
635148c5f43SAlan Wright return (0);
636148c5f43SAlan Wright }
637148c5f43SAlan Wright
638148c5f43SAlan Wright return (access);
639743a77edSAlan Wright }
640c8ec8eeaSjose borrego
641c8ec8eeaSjose borrego /*
642c8ec8eeaSjose borrego * Connect a share for use with files and directories.
643c8ec8eeaSjose borrego */
644*a90cf9f2SGordon Ross uint32_t
smb_tree_connect_disk(smb_request_t * sr,smb_arg_tcon_t * tcon)645*a90cf9f2SGordon Ross smb_tree_connect_disk(smb_request_t *sr, smb_arg_tcon_t *tcon)
646c8ec8eeaSjose borrego {
647*a90cf9f2SGordon Ross char *sharename = tcon->path;
648148c5f43SAlan Wright const char *any = "?????";
649c8ec8eeaSjose borrego smb_user_t *user = sr->uid_user;
6501fcced4cSJordan Brown smb_node_t *dnode = NULL;
651c8ec8eeaSjose borrego smb_node_t *snode = NULL;
652*a90cf9f2SGordon Ross smb_kshare_t *si = tcon->si;
653*a90cf9f2SGordon Ross char *service = tcon->service;
654c8ec8eeaSjose borrego char last_component[MAXNAMELEN];
655c8ec8eeaSjose borrego smb_tree_t *tree;
656c8ec8eeaSjose borrego int rc;
657148c5f43SAlan Wright uint32_t access;
658148c5f43SAlan Wright smb_shr_execinfo_t execinfo;
659c8ec8eeaSjose borrego
660c8ec8eeaSjose borrego ASSERT(user);
661148c5f43SAlan Wright ASSERT(user->u_cred);
662c8ec8eeaSjose borrego
663*a90cf9f2SGordon Ross if (service != NULL &&
664*a90cf9f2SGordon Ross strcmp(service, any) != 0 &&
665*a90cf9f2SGordon Ross strcasecmp(service, "A:") != 0) {
666148c5f43SAlan Wright smb_tree_log(sr, sharename, "invalid service (%s)", service);
667*a90cf9f2SGordon Ross return (NT_STATUS_BAD_DEVICE_TYPE);
668b89a8333Snatalie li - Sun Microsystems - Irvine United States }
669b89a8333Snatalie li - Sun Microsystems - Irvine United States
670c8ec8eeaSjose borrego /*
671c8ec8eeaSjose borrego * Check that the shared directory exists.
672c8ec8eeaSjose borrego */
673148c5f43SAlan Wright rc = smb_pathname_reduce(sr, user->u_cred, si->shr_path, 0, 0, &dnode,
674c8ec8eeaSjose borrego last_component);
675c8ec8eeaSjose borrego if (rc == 0) {
676148c5f43SAlan Wright rc = smb_fsop_lookup(sr, user->u_cred, SMB_FOLLOW_LINKS,
6771fcced4cSJordan Brown sr->sr_server->si_root_smb_node, dnode, last_component,
678037cac00Sjoyce mcintosh &snode);
679c8ec8eeaSjose borrego
6801fcced4cSJordan Brown smb_node_release(dnode);
681c8ec8eeaSjose borrego }
682c8ec8eeaSjose borrego
683c8ec8eeaSjose borrego if (rc) {
684c8ec8eeaSjose borrego if (snode)
685c8ec8eeaSjose borrego smb_node_release(snode);
686c8ec8eeaSjose borrego
687b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_tree_log(sr, sharename, "bad path: %s", si->shr_path);
688*a90cf9f2SGordon Ross return (NT_STATUS_BAD_NETWORK_NAME);
689c8ec8eeaSjose borrego }
690c8ec8eeaSjose borrego
691148c5f43SAlan Wright if ((access = smb_tree_chkaccess(sr, si, snode->vp)) == 0) {
692743a77edSAlan Wright smb_node_release(snode);
693*a90cf9f2SGordon Ross return (NT_STATUS_ACCESS_DENIED);
694743a77edSAlan Wright }
695743a77edSAlan Wright
696743a77edSAlan Wright /*
697148c5f43SAlan Wright * Set up the OptionalSupport for this share.
698743a77edSAlan Wright */
699*a90cf9f2SGordon Ross tcon->optional_support = SMB_SUPPORT_SEARCH_BITS;
7002c2961f8Sjose borrego
701148c5f43SAlan Wright switch (si->shr_flags & SMB_SHRF_CSC_MASK) {
702148c5f43SAlan Wright case SMB_SHRF_CSC_DISABLED:
703*a90cf9f2SGordon Ross tcon->optional_support |= SMB_CSC_CACHE_NONE;
704148c5f43SAlan Wright break;
705148c5f43SAlan Wright case SMB_SHRF_CSC_AUTO:
706*a90cf9f2SGordon Ross tcon->optional_support |= SMB_CSC_CACHE_AUTO_REINT;
707148c5f43SAlan Wright break;
708148c5f43SAlan Wright case SMB_SHRF_CSC_VDO:
709*a90cf9f2SGordon Ross tcon->optional_support |= SMB_CSC_CACHE_VDO;
710148c5f43SAlan Wright break;
711148c5f43SAlan Wright case SMB_SHRF_CSC_MANUAL:
712148c5f43SAlan Wright default:
713148c5f43SAlan Wright /*
714148c5f43SAlan Wright * Default to SMB_CSC_CACHE_MANUAL_REINT.
715148c5f43SAlan Wright */
716148c5f43SAlan Wright break;
717148c5f43SAlan Wright }
718148c5f43SAlan Wright
719148c5f43SAlan Wright /* ABE support */
720148c5f43SAlan Wright if (si->shr_flags & SMB_SHRF_ABE)
721*a90cf9f2SGordon Ross tcon->optional_support |=
722148c5f43SAlan Wright SHI1005_FLAGS_ACCESS_BASED_DIRECTORY_ENUM;
723148c5f43SAlan Wright
724148c5f43SAlan Wright if (si->shr_flags & SMB_SHRF_DFSROOT)
725*a90cf9f2SGordon Ross tcon->optional_support |= SMB_SHARE_IS_IN_DFS;
726148c5f43SAlan Wright
727cb174861Sjoyce mcintosh /* if 'smb' zfs property: shortnames=disabled */
728cb174861Sjoyce mcintosh if (!smb_shortnames)
729cb174861Sjoyce mcintosh sr->arg.tcon.optional_support |= SMB_UNIQUE_FILE_NAME;
730cb174861Sjoyce mcintosh
7313b13a1efSThomas Keiser tree = smb_tree_alloc(sr, si, snode, access, sr->sr_cfg->skc_execflags);
732148c5f43SAlan Wright
733148c5f43SAlan Wright smb_node_release(snode);
734148c5f43SAlan Wright
735*a90cf9f2SGordon Ross if (tree == NULL)
736*a90cf9f2SGordon Ross return (NT_STATUS_INSUFF_SERVER_RESOURCES);
737*a90cf9f2SGordon Ross
738148c5f43SAlan Wright if (tree->t_execflags & SMB_EXEC_MAP) {
739148c5f43SAlan Wright smb_tree_set_execinfo(tree, &execinfo, SMB_EXEC_MAP);
740148c5f43SAlan Wright
7418622ec45SGordon Ross rc = smb_kshare_exec(tree->t_server, &execinfo);
742148c5f43SAlan Wright
743148c5f43SAlan Wright if ((rc != 0) && (tree->t_execflags & SMB_EXEC_TERM)) {
744148c5f43SAlan Wright smb_tree_disconnect(tree, B_FALSE);
745148c5f43SAlan Wright smb_tree_release(tree);
746*a90cf9f2SGordon Ross return (NT_STATUS_ACCESS_DENIED);
747148c5f43SAlan Wright }
748148c5f43SAlan Wright }
749148c5f43SAlan Wright
750*a90cf9f2SGordon Ross sr->tid_tree = tree;
751*a90cf9f2SGordon Ross sr->smb_tid = tree->t_tid;
752*a90cf9f2SGordon Ross
753*a90cf9f2SGordon Ross return (0);
754148c5f43SAlan Wright }
755148c5f43SAlan Wright
756148c5f43SAlan Wright /*
757148c5f43SAlan Wright * Shares have both a share and host based access control. The access
758148c5f43SAlan Wright * granted will be minimum permissions based on both hostaccess
759148c5f43SAlan Wright * (permissions allowed by host based access) and aclaccess (from the
760148c5f43SAlan Wright * share ACL).
761148c5f43SAlan Wright */
762*a90cf9f2SGordon Ross uint32_t
smb_tree_connect_printq(smb_request_t * sr,smb_arg_tcon_t * tcon)763*a90cf9f2SGordon Ross smb_tree_connect_printq(smb_request_t *sr, smb_arg_tcon_t *tcon)
764148c5f43SAlan Wright {
765*a90cf9f2SGordon Ross char *sharename = tcon->path;
766148c5f43SAlan Wright const char *any = "?????";
767148c5f43SAlan Wright smb_user_t *user = sr->uid_user;
768148c5f43SAlan Wright smb_node_t *dnode = NULL;
769148c5f43SAlan Wright smb_node_t *snode = NULL;
770*a90cf9f2SGordon Ross smb_kshare_t *si = tcon->si;
771*a90cf9f2SGordon Ross char *service = tcon->service;
772148c5f43SAlan Wright char last_component[MAXNAMELEN];
773148c5f43SAlan Wright smb_tree_t *tree;
774148c5f43SAlan Wright int rc;
775148c5f43SAlan Wright uint32_t access;
776148c5f43SAlan Wright
777148c5f43SAlan Wright ASSERT(user);
778148c5f43SAlan Wright ASSERT(user->u_cred);
779148c5f43SAlan Wright
780b7301bf5SGordon Ross if (sr->sr_server->sv_cfg.skc_print_enable == 0) {
781b7301bf5SGordon Ross smb_tree_log(sr, sharename, "printing disabled");
782*a90cf9f2SGordon Ross return (NT_STATUS_BAD_NETWORK_NAME);
783b7301bf5SGordon Ross }
784b7301bf5SGordon Ross
785*a90cf9f2SGordon Ross if (service != NULL &&
786*a90cf9f2SGordon Ross strcmp(service, any) != 0 &&
787*a90cf9f2SGordon Ross strcasecmp(service, "LPT1:") != 0) {
788148c5f43SAlan Wright smb_tree_log(sr, sharename, "invalid service (%s)", service);
789*a90cf9f2SGordon Ross return (NT_STATUS_BAD_DEVICE_TYPE);
790148c5f43SAlan Wright }
791148c5f43SAlan Wright
792148c5f43SAlan Wright /*
793148c5f43SAlan Wright * Check that the shared directory exists.
794148c5f43SAlan Wright */
795148c5f43SAlan Wright rc = smb_pathname_reduce(sr, user->u_cred, si->shr_path, 0, 0, &dnode,
796148c5f43SAlan Wright last_component);
797148c5f43SAlan Wright if (rc == 0) {
798148c5f43SAlan Wright rc = smb_fsop_lookup(sr, user->u_cred, SMB_FOLLOW_LINKS,
799148c5f43SAlan Wright sr->sr_server->si_root_smb_node, dnode, last_component,
800148c5f43SAlan Wright &snode);
801148c5f43SAlan Wright
802148c5f43SAlan Wright smb_node_release(dnode);
803148c5f43SAlan Wright }
804148c5f43SAlan Wright
805148c5f43SAlan Wright if (rc) {
806148c5f43SAlan Wright if (snode)
807148c5f43SAlan Wright smb_node_release(snode);
808148c5f43SAlan Wright
809148c5f43SAlan Wright smb_tree_log(sr, sharename, "bad path: %s", si->shr_path);
810*a90cf9f2SGordon Ross return (NT_STATUS_BAD_NETWORK_NAME);
811148c5f43SAlan Wright }
812148c5f43SAlan Wright
813148c5f43SAlan Wright if ((access = smb_tree_chkaccess(sr, si, snode->vp)) == 0) {
814148c5f43SAlan Wright smb_node_release(snode);
815*a90cf9f2SGordon Ross return (NT_STATUS_ACCESS_DENIED);
816148c5f43SAlan Wright }
817148c5f43SAlan Wright
818*a90cf9f2SGordon Ross tcon->optional_support = SMB_SUPPORT_SEARCH_BITS;
819148c5f43SAlan Wright
8203b13a1efSThomas Keiser tree = smb_tree_alloc(sr, si, snode, access, sr->sr_cfg->skc_execflags);
821b89a8333Snatalie li - Sun Microsystems - Irvine United States
82229bd2886SAlan Wright smb_node_release(snode);
82329bd2886SAlan Wright
824c8ec8eeaSjose borrego if (tree == NULL)
825*a90cf9f2SGordon Ross return (NT_STATUS_INSUFF_SERVER_RESOURCES);
82629bd2886SAlan Wright
827*a90cf9f2SGordon Ross sr->tid_tree = tree;
828*a90cf9f2SGordon Ross sr->smb_tid = tree->t_tid;
829*a90cf9f2SGordon Ross
830*a90cf9f2SGordon Ross return (0);
831c8ec8eeaSjose borrego }
832c8ec8eeaSjose borrego
833c8ec8eeaSjose borrego /*
834c8ec8eeaSjose borrego * Connect an IPC share for use with named pipes.
835c8ec8eeaSjose borrego */
836*a90cf9f2SGordon Ross uint32_t
smb_tree_connect_ipc(smb_request_t * sr,smb_arg_tcon_t * tcon)837*a90cf9f2SGordon Ross smb_tree_connect_ipc(smb_request_t *sr, smb_arg_tcon_t *tcon)
838c8ec8eeaSjose borrego {
839*a90cf9f2SGordon Ross char *name = tcon->path;
840148c5f43SAlan Wright const char *any = "?????";
841c8ec8eeaSjose borrego smb_user_t *user = sr->uid_user;
842c8ec8eeaSjose borrego smb_tree_t *tree;
843*a90cf9f2SGordon Ross smb_kshare_t *si = tcon->si;
844*a90cf9f2SGordon Ross char *service = tcon->service;
845c8ec8eeaSjose borrego
846c8ec8eeaSjose borrego ASSERT(user);
847c8ec8eeaSjose borrego
848*a90cf9f2SGordon Ross if (service != NULL &&
849*a90cf9f2SGordon Ross strcmp(service, any) != 0 &&
850*a90cf9f2SGordon Ross strcasecmp(service, "IPC") != 0) {
851*a90cf9f2SGordon Ross smb_tree_log(sr, name, "invalid service (%s)", service);
852*a90cf9f2SGordon Ross return (NT_STATUS_BAD_DEVICE_TYPE);
853*a90cf9f2SGordon Ross }
854*a90cf9f2SGordon Ross
855*a90cf9f2SGordon Ross if ((user->u_flags & SMB_USER_FLAG_ANON) &&
856c8ec8eeaSjose borrego sr->sr_cfg->skc_restrict_anon) {
857c8ec8eeaSjose borrego smb_tree_log(sr, name, "access denied: restrict anonymous");
858*a90cf9f2SGordon Ross return (NT_STATUS_ACCESS_DENIED);
859c8ec8eeaSjose borrego }
860c8ec8eeaSjose borrego
861*a90cf9f2SGordon Ross tcon->optional_support = SMB_SUPPORT_SEARCH_BITS;
8628b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States
8633b13a1efSThomas Keiser tree = smb_tree_alloc(sr, si, NULL, ACE_ALL_PERMS, 0);
864*a90cf9f2SGordon Ross if (tree == NULL)
865*a90cf9f2SGordon Ross return (NT_STATUS_INSUFF_SERVER_RESOURCES);
866c8ec8eeaSjose borrego
867*a90cf9f2SGordon Ross sr->tid_tree = tree;
868*a90cf9f2SGordon Ross sr->smb_tid = tree->t_tid;
869*a90cf9f2SGordon Ross
870*a90cf9f2SGordon Ross return (0);
871c8ec8eeaSjose borrego }
872c8ec8eeaSjose borrego
873c8ec8eeaSjose borrego /*
874c8ec8eeaSjose borrego * Allocate a tree.
875c8ec8eeaSjose borrego */
876c8ec8eeaSjose borrego static 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)8773b13a1efSThomas Keiser smb_tree_alloc(smb_request_t *sr, const smb_kshare_t *si,
8783b13a1efSThomas Keiser smb_node_t *snode, uint32_t access, uint32_t execflags)
879da6c28aaSamw {
8803b13a1efSThomas Keiser smb_session_t *session = sr->session;
881da6c28aaSamw smb_tree_t *tree;
882148c5f43SAlan Wright uint32_t stype = si->shr_type;
883da6c28aaSamw uint16_t tid;
884da6c28aaSamw
8853b13a1efSThomas Keiser if (smb_idpool_alloc(&session->s_tid_pool, &tid))
886da6c28aaSamw return (NULL);
887da6c28aaSamw
8888622ec45SGordon Ross tree = kmem_cache_alloc(smb_cache_tree, KM_SLEEP);
889da6c28aaSamw bzero(tree, sizeof (smb_tree_t));
890da6c28aaSamw
8913b13a1efSThomas Keiser tree->t_session = session;
8923b13a1efSThomas Keiser tree->t_server = session->s_server;
8933b13a1efSThomas Keiser
8943b13a1efSThomas Keiser /* grab a ref for tree->t_owner */
8953b13a1efSThomas Keiser smb_user_hold_internal(sr->uid_user);
8963b13a1efSThomas Keiser tree->t_owner = sr->uid_user;
897cb174861Sjoyce mcintosh
898148c5f43SAlan Wright if (STYPE_ISDSK(stype) || STYPE_ISPRN(stype)) {
8998b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (smb_tree_getattr(si, snode, tree) != 0) {
9003b13a1efSThomas Keiser smb_idpool_free(&session->s_tid_pool, tid);
9018622ec45SGordon Ross kmem_cache_free(smb_cache_tree, tree);
902c8ec8eeaSjose borrego return (NULL);
903c8ec8eeaSjose borrego }
904c8ec8eeaSjose borrego }
905c8ec8eeaSjose borrego
906da6c28aaSamw if (smb_idpool_constructor(&tree->t_fid_pool)) {
9073b13a1efSThomas Keiser smb_idpool_free(&session->s_tid_pool, tid);
9088622ec45SGordon Ross kmem_cache_free(smb_cache_tree, tree);
909da6c28aaSamw return (NULL);
910da6c28aaSamw }
911da6c28aaSamw
9127f667e74Sjose borrego if (smb_idpool_constructor(&tree->t_odid_pool)) {
913da6c28aaSamw smb_idpool_destructor(&tree->t_fid_pool);
9143b13a1efSThomas Keiser smb_idpool_free(&session->s_tid_pool, tid);
9158622ec45SGordon Ross kmem_cache_free(smb_cache_tree, tree);
916da6c28aaSamw return (NULL);
917da6c28aaSamw }
918da6c28aaSamw
919da6c28aaSamw smb_llist_constructor(&tree->t_ofile_list, sizeof (smb_ofile_t),
920da6c28aaSamw offsetof(smb_ofile_t, f_lnd));
921da6c28aaSamw
922da6c28aaSamw smb_llist_constructor(&tree->t_odir_list, sizeof (smb_odir_t),
923da6c28aaSamw offsetof(smb_odir_t, d_lnd));
924da6c28aaSamw
9258b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States (void) strlcpy(tree->t_sharename, si->shr_name,
926da6c28aaSamw sizeof (tree->t_sharename));
9278b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States (void) strlcpy(tree->t_resource, si->shr_path,
9288b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States sizeof (tree->t_resource));
929da6c28aaSamw
930da6c28aaSamw mutex_init(&tree->t_mutex, NULL, MUTEX_DEFAULT, NULL);
931da6c28aaSamw
932da6c28aaSamw tree->t_refcnt = 1;
933da6c28aaSamw tree->t_tid = tid;
934da6c28aaSamw tree->t_res_type = stype;
935da6c28aaSamw tree->t_state = SMB_TREE_STATE_CONNECTED;
936da6c28aaSamw tree->t_magic = SMB_TREE_MAGIC;
937743a77edSAlan Wright tree->t_access = access;
9381fcced4cSJordan Brown tree->t_connect_time = gethrestime_sec();
939148c5f43SAlan Wright tree->t_execflags = execflags;
940743a77edSAlan Wright
941743a77edSAlan Wright /* if FS is readonly, enforce that here */
942743a77edSAlan Wright if (tree->t_flags & SMB_TREE_READONLY)
943743a77edSAlan Wright tree->t_access &= ~ACE_ALL_WRITE_PERMS;
944da6c28aaSamw
945148c5f43SAlan Wright if (STYPE_ISDSK(stype) || STYPE_ISPRN(stype)) {
946c8ec8eeaSjose borrego smb_node_ref(snode);
947c8ec8eeaSjose borrego tree->t_snode = snode;
948da6c28aaSamw tree->t_acltype = smb_fsop_acltype(snode);
949da6c28aaSamw }
950da6c28aaSamw
9513b13a1efSThomas Keiser smb_llist_enter(&session->s_tree_list, RW_WRITER);
9523b13a1efSThomas Keiser smb_llist_insert_head(&session->s_tree_list, tree);
9533b13a1efSThomas Keiser smb_llist_exit(&session->s_tree_list);
9543b13a1efSThomas Keiser atomic_inc_32(&session->s_tree_cnt);
9553b13a1efSThomas Keiser smb_server_inc_trees(session->s_server);
956da6c28aaSamw return (tree);
957da6c28aaSamw }
958da6c28aaSamw
959da6c28aaSamw /*
9609fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Deallocate a tree. The open file and open directory lists should be
9619fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * empty.
962da6c28aaSamw *
9639fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Remove the tree from the user's tree list before freeing resources
9649fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * associated with the tree.
965da6c28aaSamw */
9669fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States void
smb_tree_dealloc(void * arg)9679fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_tree_dealloc(void *arg)
968da6c28aaSamw {
9693b13a1efSThomas Keiser smb_session_t *session;
9709fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_tree_t *tree = (smb_tree_t *)arg;
9719fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
9729fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_TREE_VALID(tree);
973da6c28aaSamw ASSERT(tree->t_state == SMB_TREE_STATE_DISCONNECTED);
974da6c28aaSamw ASSERT(tree->t_refcnt == 0);
975da6c28aaSamw
9763b13a1efSThomas Keiser session = tree->t_session;
9773b13a1efSThomas Keiser smb_llist_enter(&session->s_tree_list, RW_WRITER);
9783b13a1efSThomas Keiser smb_llist_remove(&session->s_tree_list, tree);
9793b13a1efSThomas Keiser smb_idpool_free(&session->s_tid_pool, tree->t_tid);
9803b13a1efSThomas Keiser atomic_dec_32(&session->s_tree_cnt);
9813b13a1efSThomas Keiser smb_llist_exit(&session->s_tree_list);
9829fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
9839fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States mutex_enter(&tree->t_mutex);
9849fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States mutex_exit(&tree->t_mutex);
985da6c28aaSamw
986da6c28aaSamw tree->t_magic = (uint32_t)~SMB_TREE_MAGIC;
987da6c28aaSamw
988c8ec8eeaSjose borrego if (tree->t_snode)
989da6c28aaSamw smb_node_release(tree->t_snode);
990c8ec8eeaSjose borrego
991da6c28aaSamw mutex_destroy(&tree->t_mutex);
992da6c28aaSamw smb_llist_destructor(&tree->t_ofile_list);
993da6c28aaSamw smb_llist_destructor(&tree->t_odir_list);
994da6c28aaSamw smb_idpool_destructor(&tree->t_fid_pool);
9957f667e74Sjose borrego smb_idpool_destructor(&tree->t_odid_pool);
9963b13a1efSThomas Keiser
9973b13a1efSThomas Keiser SMB_USER_VALID(tree->t_owner);
9983b13a1efSThomas Keiser smb_user_release(tree->t_owner);
9993b13a1efSThomas Keiser
10008622ec45SGordon Ross kmem_cache_free(smb_cache_tree, tree);
1001da6c28aaSamw }
1002da6c28aaSamw
1003da6c28aaSamw /*
1004c8ec8eeaSjose borrego * Determine whether or not a tree is connected.
1005c8ec8eeaSjose borrego * This function must be called with the tree mutex held.
1006da6c28aaSamw */
1007c8ec8eeaSjose borrego static boolean_t
smb_tree_is_connected_locked(smb_tree_t * tree)10088b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_tree_is_connected_locked(smb_tree_t *tree)
1009da6c28aaSamw {
1010c8ec8eeaSjose borrego switch (tree->t_state) {
1011c8ec8eeaSjose borrego case SMB_TREE_STATE_CONNECTED:
1012c8ec8eeaSjose borrego return (B_TRUE);
1013da6c28aaSamw
1014c8ec8eeaSjose borrego case SMB_TREE_STATE_DISCONNECTING:
1015c8ec8eeaSjose borrego case SMB_TREE_STATE_DISCONNECTED:
1016c8ec8eeaSjose borrego /*
1017c8ec8eeaSjose borrego * The tree exists but being diconnected or destroyed.
1018c8ec8eeaSjose borrego */
1019c8ec8eeaSjose borrego return (B_FALSE);
1020c8ec8eeaSjose borrego
1021c8ec8eeaSjose borrego default:
1022da6c28aaSamw ASSERT(0);
1023c8ec8eeaSjose borrego return (B_FALSE);
1024da6c28aaSamw }
1025da6c28aaSamw }
1026da6c28aaSamw
1027da6c28aaSamw /*
1028c8ec8eeaSjose borrego * Determine whether or not a tree is disconnected.
1029c8ec8eeaSjose borrego * This function must be called with the tree mutex held.
1030da6c28aaSamw */
1031c8ec8eeaSjose borrego static boolean_t
smb_tree_is_disconnected(smb_tree_t * tree)1032c8ec8eeaSjose borrego smb_tree_is_disconnected(smb_tree_t *tree)
1033da6c28aaSamw {
1034c8ec8eeaSjose borrego switch (tree->t_state) {
1035c8ec8eeaSjose borrego case SMB_TREE_STATE_DISCONNECTED:
1036c8ec8eeaSjose borrego return (B_TRUE);
1037da6c28aaSamw
1038c8ec8eeaSjose borrego case SMB_TREE_STATE_CONNECTED:
1039c8ec8eeaSjose borrego case SMB_TREE_STATE_DISCONNECTING:
1040c8ec8eeaSjose borrego return (B_FALSE);
1041da6c28aaSamw
1042c8ec8eeaSjose borrego default:
1043da6c28aaSamw ASSERT(0);
1044c8ec8eeaSjose borrego return (B_FALSE);
1045da6c28aaSamw }
1046da6c28aaSamw }
1047da6c28aaSamw
1048c8ec8eeaSjose borrego /*
1049c8ec8eeaSjose borrego * Return a pointer to the share name within a share resource path.
1050c8ec8eeaSjose borrego *
1051c8ec8eeaSjose borrego * The share path may be a Uniform Naming Convention (UNC) string
1052c8ec8eeaSjose borrego * (\\server\share) or simply the share name. We validate the UNC
1053c8ec8eeaSjose borrego * format but we don't look at the server name.
1054c8ec8eeaSjose borrego */
1055*a90cf9f2SGordon Ross static char *
smb_tree_get_sharename(char * unc_path)1056*a90cf9f2SGordon Ross smb_tree_get_sharename(char *unc_path)
1057c8ec8eeaSjose borrego {
1058*a90cf9f2SGordon Ross char *sharename = unc_path;
1059c8ec8eeaSjose borrego
1060c8ec8eeaSjose borrego if (sharename[0] == '\\') {
1061c8ec8eeaSjose borrego /*
1062c8ec8eeaSjose borrego * Looks like a UNC path, validate the format.
1063c8ec8eeaSjose borrego */
1064c8ec8eeaSjose borrego if (sharename[1] != '\\')
1065c8ec8eeaSjose borrego return (NULL);
1066c8ec8eeaSjose borrego
1067c8ec8eeaSjose borrego if ((sharename = strchr(sharename+2, '\\')) == NULL)
1068c8ec8eeaSjose borrego return (NULL);
1069c8ec8eeaSjose borrego
1070c8ec8eeaSjose borrego ++sharename;
1071c8ec8eeaSjose borrego } else if (strchr(sharename, '\\') != NULL) {
1072c8ec8eeaSjose borrego /*
1073c8ec8eeaSjose borrego * This should be a share name (no embedded \'s).
1074c8ec8eeaSjose borrego */
1075c8ec8eeaSjose borrego return (NULL);
1076c8ec8eeaSjose borrego }
1077c8ec8eeaSjose borrego
1078c8ec8eeaSjose borrego return (sharename);
1079c8ec8eeaSjose borrego }
1080c8ec8eeaSjose borrego
1081c8ec8eeaSjose borrego /*
1082c8ec8eeaSjose borrego * Obtain the tree attributes: volume name, typename and flags.
1083c8ec8eeaSjose borrego */
1084c8ec8eeaSjose borrego static int
smb_tree_getattr(const smb_kshare_t * si,smb_node_t * node,smb_tree_t * tree)1085148c5f43SAlan Wright smb_tree_getattr(const smb_kshare_t *si, smb_node_t *node, smb_tree_t *tree)
1086c8ec8eeaSjose borrego {
1087c8ec8eeaSjose borrego vfs_t *vfsp = SMB_NODE_VFS(node);
1088c8ec8eeaSjose borrego
1089c8ec8eeaSjose borrego ASSERT(vfsp);
1090c8ec8eeaSjose borrego
1091c8ec8eeaSjose borrego if (getvfs(&vfsp->vfs_fsid) != vfsp)
1092c8ec8eeaSjose borrego return (ESTALE);
1093c8ec8eeaSjose borrego
1094c8ec8eeaSjose borrego smb_tree_get_volname(vfsp, tree);
10958b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_tree_get_flags(si, vfsp, tree);
1096c8ec8eeaSjose borrego
1097c8ec8eeaSjose borrego VFS_RELE(vfsp);
1098c8ec8eeaSjose borrego return (0);
1099c8ec8eeaSjose borrego }
1100c8ec8eeaSjose borrego
1101c8ec8eeaSjose borrego /*
1102c8ec8eeaSjose borrego * Extract the volume name.
1103c8ec8eeaSjose borrego */
1104c8ec8eeaSjose borrego static void
smb_tree_get_volname(vfs_t * vfsp,smb_tree_t * tree)1105c8ec8eeaSjose borrego smb_tree_get_volname(vfs_t *vfsp, smb_tree_t *tree)
1106c8ec8eeaSjose borrego {
1107*a90cf9f2SGordon Ross #ifdef _FAKE_KERNEL
1108*a90cf9f2SGordon Ross _NOTE(ARGUNUSED(vfsp))
1109*a90cf9f2SGordon Ross (void) strlcpy(tree->t_volume, "fake", SMB_VOLNAMELEN);
1110*a90cf9f2SGordon Ross #else /* _FAKE_KERNEL */
1111c8ec8eeaSjose borrego refstr_t *vfs_mntpoint;
1112c8ec8eeaSjose borrego const char *s;
1113c8ec8eeaSjose borrego char *name;
1114c8ec8eeaSjose borrego
1115c8ec8eeaSjose borrego vfs_mntpoint = vfs_getmntpoint(vfsp);
1116c8ec8eeaSjose borrego
1117b819cea2SGordon Ross s = refstr_value(vfs_mntpoint);
1118c8ec8eeaSjose borrego s += strspn(s, "/");
1119c8ec8eeaSjose borrego (void) strlcpy(tree->t_volume, s, SMB_VOLNAMELEN);
1120c8ec8eeaSjose borrego
1121c8ec8eeaSjose borrego refstr_rele(vfs_mntpoint);
1122c8ec8eeaSjose borrego
1123c8ec8eeaSjose borrego name = tree->t_volume;
1124c8ec8eeaSjose borrego (void) strsep((char **)&name, "/");
1125*a90cf9f2SGordon Ross #endif /* _FAKE_KERNEL */
1126c8ec8eeaSjose borrego }
1127c8ec8eeaSjose borrego
1128c8ec8eeaSjose borrego /*
1129*a90cf9f2SGordon Ross * Always set "unicode on disk" because we always use utf8 names locally.
1130c8ec8eeaSjose borrego * Always set ACL support because the VFS will fake ACLs for file systems
1131c8ec8eeaSjose borrego * that don't support them.
1132c8ec8eeaSjose borrego *
1133c8ec8eeaSjose borrego * Some flags are dependent on the typename, which is also set up here.
1134c8ec8eeaSjose borrego * File system types are hardcoded in uts/common/os/vfs_conf.c.
1135c8ec8eeaSjose borrego */
1136c8ec8eeaSjose borrego static void
smb_tree_get_flags(const smb_kshare_t * si,vfs_t * vfsp,smb_tree_t * tree)1137148c5f43SAlan Wright smb_tree_get_flags(const smb_kshare_t *si, vfs_t *vfsp, smb_tree_t *tree)
1138c8ec8eeaSjose borrego {
11395f1ef25cSAram Hăvărneanu smb_session_t *ssn = tree->t_session;
1140b819cea2SGordon Ross struct vfssw *vswp;
11415f1ef25cSAram Hăvărneanu
1142fc724630SAlan Wright typedef struct smb_mtype {
1143fc724630SAlan Wright char *mt_name;
1144fc724630SAlan Wright size_t mt_namelen;
1145fc724630SAlan Wright uint32_t mt_flags;
1146fc724630SAlan Wright } smb_mtype_t;
1147fc724630SAlan Wright
1148fc724630SAlan Wright static smb_mtype_t smb_mtype[] = {
1149*a90cf9f2SGordon Ross { "zfs", 3, SMB_TREE_QUOTA | SMB_TREE_SPARSE},
1150*a90cf9f2SGordon Ross { "ufs", 3, 0 },
1151fc724630SAlan Wright { "nfs", 3, SMB_TREE_NFS_MOUNTED },
1152fc724630SAlan Wright { "tmpfs", 5, SMB_TREE_NO_EXPORT }
1153fc724630SAlan Wright };
1154fc724630SAlan Wright smb_mtype_t *mtype;
1155c8ec8eeaSjose borrego char *name;
1156*a90cf9f2SGordon Ross uint32_t flags =
1157*a90cf9f2SGordon Ross SMB_TREE_SUPPORTS_ACLS |
1158*a90cf9f2SGordon Ross SMB_TREE_UNICODE_ON_DISK;
1159fc724630SAlan Wright int i;
1160c8ec8eeaSjose borrego
11619fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (si->shr_flags & SMB_SHRF_DFSROOT)
11629fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States flags |= SMB_TREE_DFSROOT;
11639fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
11648b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (si->shr_flags & SMB_SHRF_CATIA)
11658b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States flags |= SMB_TREE_CATIA;
11668b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States
1167e3f2c991SKeyur Desai if (si->shr_flags & SMB_SHRF_ABE)
1168e3f2c991SKeyur Desai flags |= SMB_TREE_ABE;
1169e3f2c991SKeyur Desai
11705f1ef25cSAram Hăvărneanu if (ssn->s_cfg.skc_oplock_enable) {
1171cb174861Sjoyce mcintosh /* if 'smb' zfs property: oplocks=enabled */
1172cb174861Sjoyce mcintosh flags |= SMB_TREE_OPLOCKS;
1173cb174861Sjoyce mcintosh }
1174cb174861Sjoyce mcintosh
11755f1ef25cSAram Hăvărneanu /* Global config option for now. Later make per-share. */
11765f1ef25cSAram Hăvărneanu if (ssn->s_cfg.skc_traverse_mounts)
11775f1ef25cSAram Hăvărneanu flags |= SMB_TREE_TRAVERSE_MOUNTS;
11785f1ef25cSAram Hăvărneanu
1179cb174861Sjoyce mcintosh /* if 'smb' zfs property: shortnames=enabled */
1180cb174861Sjoyce mcintosh if (smb_shortnames)
1181cb174861Sjoyce mcintosh flags |= SMB_TREE_SHORTNAMES;
1182cb174861Sjoyce mcintosh
1183c8ec8eeaSjose borrego if (vfsp->vfs_flag & VFS_RDONLY)
1184c8ec8eeaSjose borrego flags |= SMB_TREE_READONLY;
1185c8ec8eeaSjose borrego
1186c8ec8eeaSjose borrego if (vfsp->vfs_flag & VFS_XATTR)
1187c8ec8eeaSjose borrego flags |= SMB_TREE_STREAMS;
1188c8ec8eeaSjose borrego
1189b819cea2SGordon Ross vswp = vfs_getvfsswbyvfsops(vfs_getops(vfsp));
1190b819cea2SGordon Ross if (vswp != NULL) {
1191b819cea2SGordon Ross name = vswp->vsw_name;
1192b819cea2SGordon Ross vfs_unrefvfssw(vswp);
1193b819cea2SGordon Ross } else {
1194b819cea2SGordon Ross name = "?";
1195b819cea2SGordon Ross }
1196c8ec8eeaSjose borrego
1197fc724630SAlan Wright for (i = 0; i < sizeof (smb_mtype) / sizeof (smb_mtype[0]); ++i) {
1198fc724630SAlan Wright mtype = &smb_mtype[i];
1199fc724630SAlan Wright if (strncasecmp(name, mtype->mt_name, mtype->mt_namelen) == 0)
1200fc724630SAlan Wright flags |= mtype->mt_flags;
1201fc724630SAlan Wright }
1202c8ec8eeaSjose borrego
1203c8ec8eeaSjose borrego (void) strlcpy(tree->t_typename, name, SMB_TYPENAMELEN);
1204bbf6f00cSJordan Brown (void) smb_strupr((char *)tree->t_typename);
1205c8ec8eeaSjose borrego
1206c8ec8eeaSjose borrego if (vfs_has_feature(vfsp, VFSFT_XVATTR))
1207c8ec8eeaSjose borrego flags |= SMB_TREE_XVATTR;
1208c8ec8eeaSjose borrego
1209c8ec8eeaSjose borrego if (vfs_has_feature(vfsp, VFSFT_CASEINSENSITIVE))
1210c8ec8eeaSjose borrego flags |= SMB_TREE_CASEINSENSITIVE;
1211c8ec8eeaSjose borrego
1212c8ec8eeaSjose borrego if (vfs_has_feature(vfsp, VFSFT_NOCASESENSITIVE))
1213c8ec8eeaSjose borrego flags |= SMB_TREE_NO_CASESENSITIVE;
1214c8ec8eeaSjose borrego
1215c8ec8eeaSjose borrego if (vfs_has_feature(vfsp, VFSFT_DIRENTFLAGS))
1216c8ec8eeaSjose borrego flags |= SMB_TREE_DIRENTFLAGS;
1217c8ec8eeaSjose borrego
1218c8ec8eeaSjose borrego if (vfs_has_feature(vfsp, VFSFT_ACLONCREATE))
1219c8ec8eeaSjose borrego flags |= SMB_TREE_ACLONCREATE;
1220c8ec8eeaSjose borrego
1221c8ec8eeaSjose borrego if (vfs_has_feature(vfsp, VFSFT_ACEMASKONACCESS))
1222c8ec8eeaSjose borrego flags |= SMB_TREE_ACEMASKONACCESS;
1223c8ec8eeaSjose borrego
1224fc724630SAlan Wright DTRACE_PROBE2(smb__tree__flags, uint32_t, flags, char *, name);
1225fc724630SAlan Wright
1226c8ec8eeaSjose borrego
1227c8ec8eeaSjose borrego tree->t_flags = flags;
1228c8ec8eeaSjose borrego }
1229c8ec8eeaSjose borrego
1230c8ec8eeaSjose borrego /*
1231c8ec8eeaSjose borrego * Report share access result to syslog.
1232c8ec8eeaSjose borrego */
1233c8ec8eeaSjose borrego static void
smb_tree_log(smb_request_t * sr,const char * sharename,const char * fmt,...)1234c8ec8eeaSjose borrego smb_tree_log(smb_request_t *sr, const char *sharename, const char *fmt, ...)
1235c8ec8eeaSjose borrego {
1236c8ec8eeaSjose borrego va_list ap;
1237c8ec8eeaSjose borrego char buf[128];
1238c8ec8eeaSjose borrego smb_user_t *user = sr->uid_user;
1239c8ec8eeaSjose borrego
1240c8ec8eeaSjose borrego ASSERT(user);
1241c8ec8eeaSjose borrego
1242c8ec8eeaSjose borrego if (smb_tcon_mute)
1243c8ec8eeaSjose borrego return;
1244c8ec8eeaSjose borrego
1245c8ec8eeaSjose borrego if ((user->u_name) && (strcasecmp(sharename, "IPC$") == 0)) {
1246c8ec8eeaSjose borrego /*
1247c8ec8eeaSjose borrego * Only report normal users, i.e. ignore W2K misuse
1248c8ec8eeaSjose borrego * of the IPC connection by filtering out internal
1249c8ec8eeaSjose borrego * names such as nobody and root.
1250c8ec8eeaSjose borrego */
1251c8ec8eeaSjose borrego if ((strcmp(user->u_name, "root") == 0) ||
1252c8ec8eeaSjose borrego (strcmp(user->u_name, "nobody") == 0)) {
1253c8ec8eeaSjose borrego return;
1254c8ec8eeaSjose borrego }
1255c8ec8eeaSjose borrego }
1256c8ec8eeaSjose borrego
1257c8ec8eeaSjose borrego va_start(ap, fmt);
1258c8ec8eeaSjose borrego (void) vsnprintf(buf, 128, fmt, ap);
1259c8ec8eeaSjose borrego va_end(ap);
1260c8ec8eeaSjose borrego
1261c8ec8eeaSjose borrego cmn_err(CE_NOTE, "smbd[%s\\%s]: %s %s",
1262c8ec8eeaSjose borrego user->u_domain, user->u_name, sharename, buf);
1263da6c28aaSamw }
12647f667e74Sjose borrego
12657f667e74Sjose borrego /*
12667f667e74Sjose borrego * smb_tree_lookup_odir
12677f667e74Sjose borrego *
12687f667e74Sjose borrego * Find the specified odir in the tree's list of odirs, and
12697f667e74Sjose borrego * attempt to obtain a hold on the odir.
12707f667e74Sjose borrego *
12717f667e74Sjose borrego * Returns NULL if odir not found or a hold cannot be obtained.
12727f667e74Sjose borrego */
12737f667e74Sjose borrego smb_odir_t *
smb_tree_lookup_odir(smb_request_t * sr,uint16_t odid)12743b13a1efSThomas Keiser smb_tree_lookup_odir(smb_request_t *sr, uint16_t odid)
12757f667e74Sjose borrego {
12767f667e74Sjose borrego smb_odir_t *od;
12777f667e74Sjose borrego smb_llist_t *od_list;
12783b13a1efSThomas Keiser smb_tree_t *tree = sr->tid_tree;
12797f667e74Sjose borrego
12807f667e74Sjose borrego ASSERT(tree->t_magic == SMB_TREE_MAGIC);
12817f667e74Sjose borrego
12827f667e74Sjose borrego od_list = &tree->t_odir_list;
12837f667e74Sjose borrego
12843b13a1efSThomas Keiser smb_llist_enter(od_list, RW_READER);
12857f667e74Sjose borrego od = smb_llist_head(od_list);
12867f667e74Sjose borrego while (od) {
12873b13a1efSThomas Keiser if (od->d_odid == odid)
12887f667e74Sjose borrego break;
12897f667e74Sjose borrego od = smb_llist_next(od_list, od);
12907f667e74Sjose borrego }
12913b13a1efSThomas Keiser if (od == NULL)
12923b13a1efSThomas Keiser goto out;
12937f667e74Sjose borrego
12943b13a1efSThomas Keiser /*
12953b13a1efSThomas Keiser * Only allow use of a given Search ID with the same UID that
12963b13a1efSThomas Keiser * was used to create it. MS-CIFS 3.3.5.14
12973b13a1efSThomas Keiser */
12983b13a1efSThomas Keiser if (od->d_user != sr->uid_user) {
12993b13a1efSThomas Keiser od = NULL;
13003b13a1efSThomas Keiser goto out;
13013b13a1efSThomas Keiser }
13023b13a1efSThomas Keiser if (!smb_odir_hold(od))
13033b13a1efSThomas Keiser od = NULL;
13043b13a1efSThomas Keiser
13053b13a1efSThomas Keiser out:
13067f667e74Sjose borrego smb_llist_exit(od_list);
13077f667e74Sjose borrego return (od);
13087f667e74Sjose borrego }
13097f667e74Sjose borrego
13108b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States boolean_t
smb_tree_is_connected(smb_tree_t * tree)13118b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_tree_is_connected(smb_tree_t *tree)
13128b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States {
13138b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States boolean_t rb;
13148b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States
13158b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States mutex_enter(&tree->t_mutex);
13168b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States rb = smb_tree_is_connected_locked(tree);
13178b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States mutex_exit(&tree->t_mutex);
13188b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States return (rb);
13198b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States }
13208b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States
13217f667e74Sjose borrego /*
13221fcced4cSJordan Brown * Get the next open ofile in the list. A reference is taken on
13231fcced4cSJordan Brown * the ofile, which can be released later with smb_ofile_release().
13241fcced4cSJordan Brown *
13251fcced4cSJordan Brown * If the specified ofile is NULL, search from the beginning of the
13261fcced4cSJordan Brown * list. Otherwise, the search starts just after that ofile.
13271fcced4cSJordan Brown *
13281fcced4cSJordan Brown * Returns NULL if there are no open files in the list.
13291fcced4cSJordan Brown */
13301fcced4cSJordan Brown static smb_ofile_t *
smb_tree_get_ofile(smb_tree_t * tree,smb_ofile_t * of)13311fcced4cSJordan Brown smb_tree_get_ofile(smb_tree_t *tree, smb_ofile_t *of)
13321fcced4cSJordan Brown {
13331fcced4cSJordan Brown smb_llist_t *ofile_list;
13341fcced4cSJordan Brown
13351fcced4cSJordan Brown ASSERT(tree);
13361fcced4cSJordan Brown ASSERT(tree->t_magic == SMB_TREE_MAGIC);
13371fcced4cSJordan Brown
13381fcced4cSJordan Brown ofile_list = &tree->t_ofile_list;
13391fcced4cSJordan Brown smb_llist_enter(ofile_list, RW_READER);
13401fcced4cSJordan Brown
13411fcced4cSJordan Brown if (of) {
13421fcced4cSJordan Brown ASSERT(of->f_magic == SMB_OFILE_MAGIC);
13431fcced4cSJordan Brown of = smb_llist_next(ofile_list, of);
13441fcced4cSJordan Brown } else {
13451fcced4cSJordan Brown of = smb_llist_head(ofile_list);
13461fcced4cSJordan Brown }
13471fcced4cSJordan Brown
13481fcced4cSJordan Brown while (of) {
13491fcced4cSJordan Brown if (smb_ofile_hold(of))
13501fcced4cSJordan Brown break;
13511fcced4cSJordan Brown
13521fcced4cSJordan Brown of = smb_llist_next(ofile_list, of);
13531fcced4cSJordan Brown }
13541fcced4cSJordan Brown
13551fcced4cSJordan Brown smb_llist_exit(ofile_list);
13561fcced4cSJordan Brown return (of);
13571fcced4cSJordan Brown }
13581fcced4cSJordan Brown
13591fcced4cSJordan Brown /*
13607f667e74Sjose borrego * smb_tree_get_odir
13617f667e74Sjose borrego *
1362a1511e6bSjoyce mcintosh * Find the next odir in the tree's list of odirs, and obtain a
1363a1511e6bSjoyce mcintosh * hold on it.
13647f667e74Sjose borrego * If the specified odir is NULL the search starts at the beginning
13657f667e74Sjose borrego * of the tree's odir list, otherwise the search starts after the
13667f667e74Sjose borrego * specified odir.
13677f667e74Sjose borrego */
13687f667e74Sjose borrego static smb_odir_t *
smb_tree_get_odir(smb_tree_t * tree,smb_odir_t * od)13697f667e74Sjose borrego smb_tree_get_odir(smb_tree_t *tree, smb_odir_t *od)
13707f667e74Sjose borrego {
13717f667e74Sjose borrego smb_llist_t *od_list;
13727f667e74Sjose borrego
13737f667e74Sjose borrego ASSERT(tree);
13747f667e74Sjose borrego ASSERT(tree->t_magic == SMB_TREE_MAGIC);
13757f667e74Sjose borrego
13767f667e74Sjose borrego od_list = &tree->t_odir_list;
13777f667e74Sjose borrego smb_llist_enter(od_list, RW_READER);
13787f667e74Sjose borrego
13797f667e74Sjose borrego if (od) {
13807f667e74Sjose borrego ASSERT(od->d_magic == SMB_ODIR_MAGIC);
13817f667e74Sjose borrego od = smb_llist_next(od_list, od);
13827f667e74Sjose borrego } else {
13837f667e74Sjose borrego od = smb_llist_head(od_list);
13847f667e74Sjose borrego }
13857f667e74Sjose borrego
13867f667e74Sjose borrego while (od) {
13877f667e74Sjose borrego ASSERT(od->d_magic == SMB_ODIR_MAGIC);
13887f667e74Sjose borrego
13897f667e74Sjose borrego if (smb_odir_hold(od))
13907f667e74Sjose borrego break;
13917f667e74Sjose borrego od = smb_llist_next(od_list, od);
13927f667e74Sjose borrego }
13937f667e74Sjose borrego
13947f667e74Sjose borrego smb_llist_exit(od_list);
13957f667e74Sjose borrego return (od);
13967f667e74Sjose borrego }
13977f667e74Sjose borrego
13987f667e74Sjose borrego /*
13997f667e74Sjose borrego * smb_tree_close_odirs
14007f667e74Sjose borrego *
14017f667e74Sjose borrego * Close all open odirs in the tree's list which were opened by
14027f667e74Sjose borrego * the process identified by pid.
14037f667e74Sjose borrego * If pid is zero, close all open odirs in the tree's list.
14047f667e74Sjose borrego */
14057f667e74Sjose borrego static void
smb_tree_close_odirs(smb_tree_t * tree,uint16_t pid)14067f667e74Sjose borrego smb_tree_close_odirs(smb_tree_t *tree, uint16_t pid)
14077f667e74Sjose borrego {
14087f667e74Sjose borrego smb_odir_t *od, *next_od;
14097f667e74Sjose borrego
14107f667e74Sjose borrego ASSERT(tree);
14117f667e74Sjose borrego ASSERT(tree->t_magic == SMB_TREE_MAGIC);
14127f667e74Sjose borrego
14137f667e74Sjose borrego od = smb_tree_get_odir(tree, NULL);
14147f667e74Sjose borrego while (od) {
14157f667e74Sjose borrego ASSERT(od->d_magic == SMB_ODIR_MAGIC);
14167f667e74Sjose borrego ASSERT(od->d_tree == tree);
14177f667e74Sjose borrego
14187f667e74Sjose borrego next_od = smb_tree_get_odir(tree, od);
14197f667e74Sjose borrego if ((pid == 0) || (od->d_opened_by_pid == pid))
14207f667e74Sjose borrego smb_odir_close(od);
14217f667e74Sjose borrego smb_odir_release(od);
14227f667e74Sjose borrego
14237f667e74Sjose borrego od = next_od;
14247f667e74Sjose borrego }
14257f667e74Sjose borrego }
142629bd2886SAlan Wright
142729bd2886SAlan Wright static void
smb_tree_set_execinfo(smb_tree_t * tree,smb_shr_execinfo_t * exec,int exec_type)14283b13a1efSThomas Keiser smb_tree_set_execinfo(smb_tree_t *tree, smb_shr_execinfo_t *exec,
14293b13a1efSThomas Keiser int exec_type)
143029bd2886SAlan Wright {
1431148c5f43SAlan Wright exec->e_sharename = tree->t_sharename;
14323b13a1efSThomas Keiser exec->e_winname = tree->t_owner->u_name;
14333b13a1efSThomas Keiser exec->e_userdom = tree->t_owner->u_domain;
1434148c5f43SAlan Wright exec->e_srv_ipaddr = tree->t_session->local_ipaddr;
1435148c5f43SAlan Wright exec->e_cli_ipaddr = tree->t_session->ipaddr;
1436148c5f43SAlan Wright exec->e_cli_netbiosname = tree->t_session->workstation;
14373b13a1efSThomas Keiser exec->e_uid = crgetuid(tree->t_owner->u_cred);
1438148c5f43SAlan Wright exec->e_type = exec_type;
143929bd2886SAlan Wright }
14401fcced4cSJordan Brown
14411fcced4cSJordan Brown /*
14421fcced4cSJordan Brown * Private function to support smb_tree_enum.
14431fcced4cSJordan Brown */
14441fcced4cSJordan Brown static int
smb_tree_enum_private(smb_tree_t * tree,smb_svcenum_t * svcenum)14451fcced4cSJordan Brown smb_tree_enum_private(smb_tree_t *tree, smb_svcenum_t *svcenum)
14461fcced4cSJordan Brown {
14471fcced4cSJordan Brown uint8_t *pb;
14481fcced4cSJordan Brown uint_t nbytes;
14491fcced4cSJordan Brown int rc;
14501fcced4cSJordan Brown
14511fcced4cSJordan Brown if (svcenum->se_nskip > 0) {
14521fcced4cSJordan Brown svcenum->se_nskip--;
14531fcced4cSJordan Brown return (0);
14541fcced4cSJordan Brown }
14551fcced4cSJordan Brown
14561fcced4cSJordan Brown if (svcenum->se_nitems >= svcenum->se_nlimit) {
14571fcced4cSJordan Brown svcenum->se_nitems = svcenum->se_nlimit;
14581fcced4cSJordan Brown return (0);
14591fcced4cSJordan Brown }
14601fcced4cSJordan Brown
14611fcced4cSJordan Brown pb = &svcenum->se_buf[svcenum->se_bused];
14621fcced4cSJordan Brown rc = smb_tree_netinfo_encode(tree, pb, svcenum->se_bavail, &nbytes);
14631fcced4cSJordan Brown if (rc == 0) {
14641fcced4cSJordan Brown svcenum->se_bavail -= nbytes;
14651fcced4cSJordan Brown svcenum->se_bused += nbytes;
14661fcced4cSJordan Brown svcenum->se_nitems++;
14671fcced4cSJordan Brown }
14681fcced4cSJordan Brown
14691fcced4cSJordan Brown return (rc);
14701fcced4cSJordan Brown }
14711fcced4cSJordan Brown
14721fcced4cSJordan Brown /*
14731fcced4cSJordan Brown * Encode connection information into a buffer: connection information
14741fcced4cSJordan Brown * needed in user space to support RPC requests.
14751fcced4cSJordan Brown */
14761fcced4cSJordan Brown static int
smb_tree_netinfo_encode(smb_tree_t * tree,uint8_t * buf,size_t buflen,uint32_t * nbytes)14771fcced4cSJordan Brown smb_tree_netinfo_encode(smb_tree_t *tree, uint8_t *buf, size_t buflen,
14781fcced4cSJordan Brown uint32_t *nbytes)
14791fcced4cSJordan Brown {
14801fcced4cSJordan Brown smb_netconnectinfo_t info;
14811fcced4cSJordan Brown int rc;
14821fcced4cSJordan Brown
14831fcced4cSJordan Brown smb_tree_netinfo_init(tree, &info);
14841fcced4cSJordan Brown rc = smb_netconnectinfo_encode(&info, buf, buflen, nbytes);
14851fcced4cSJordan Brown smb_tree_netinfo_fini(&info);
14861fcced4cSJordan Brown
14871fcced4cSJordan Brown return (rc);
14881fcced4cSJordan Brown }
14891fcced4cSJordan Brown
14903b13a1efSThomas Keiser static void
smb_tree_netinfo_username(smb_tree_t * tree,char ** namestr,uint32_t * namelen)14913b13a1efSThomas Keiser smb_tree_netinfo_username(smb_tree_t *tree, char **namestr, uint32_t *namelen)
14923b13a1efSThomas Keiser {
14933b13a1efSThomas Keiser smb_user_t *user = tree->t_owner;
14943b13a1efSThomas Keiser
14953b13a1efSThomas Keiser /*
14963b13a1efSThomas Keiser * u_domain_len and u_name_len include the '\0' in their
14973b13a1efSThomas Keiser * lengths, hence the sum of the two lengths gives us room
14983b13a1efSThomas Keiser * for both the '\\' and '\0' chars.
14993b13a1efSThomas Keiser */
15003b13a1efSThomas Keiser ASSERT(namestr);
15013b13a1efSThomas Keiser ASSERT(namelen);
15023b13a1efSThomas Keiser ASSERT(user->u_domain_len > 0);
15033b13a1efSThomas Keiser ASSERT(user->u_name_len > 0);
15043b13a1efSThomas Keiser *namelen = user->u_domain_len + user->u_name_len;
15053b13a1efSThomas Keiser *namestr = kmem_alloc(*namelen, KM_SLEEP);
15063b13a1efSThomas Keiser (void) snprintf(*namestr, *namelen, "%s\\%s", user->u_domain,
15073b13a1efSThomas Keiser user->u_name);
15083b13a1efSThomas Keiser }
15093b13a1efSThomas Keiser
15101fcced4cSJordan Brown /*
15111fcced4cSJordan Brown * Note: ci_numusers should be the number of users connected to
15121fcced4cSJordan Brown * the share rather than the number of references on the tree but
15131fcced4cSJordan Brown * we don't have a mechanism to track users/share in smbsrv yet.
15141fcced4cSJordan Brown */
15151fcced4cSJordan Brown static void
smb_tree_netinfo_init(smb_tree_t * tree,smb_netconnectinfo_t * info)15161fcced4cSJordan Brown smb_tree_netinfo_init(smb_tree_t *tree, smb_netconnectinfo_t *info)
15171fcced4cSJordan Brown {
15181fcced4cSJordan Brown ASSERT(tree);
15191fcced4cSJordan Brown
15201fcced4cSJordan Brown info->ci_id = tree->t_tid;
15211fcced4cSJordan Brown info->ci_type = tree->t_res_type;
15221fcced4cSJordan Brown info->ci_numopens = tree->t_open_files;
15231fcced4cSJordan Brown info->ci_numusers = tree->t_refcnt;
15241fcced4cSJordan Brown info->ci_time = gethrestime_sec() - tree->t_connect_time;
15251fcced4cSJordan Brown
15261fcced4cSJordan Brown info->ci_sharelen = strlen(tree->t_sharename) + 1;
15279fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States info->ci_share = smb_mem_strdup(tree->t_sharename);
15281fcced4cSJordan Brown
15293b13a1efSThomas Keiser smb_tree_netinfo_username(tree, &info->ci_username, &info->ci_namelen);
15301fcced4cSJordan Brown }
15311fcced4cSJordan Brown
15321fcced4cSJordan Brown static void
smb_tree_netinfo_fini(smb_netconnectinfo_t * info)15331fcced4cSJordan Brown smb_tree_netinfo_fini(smb_netconnectinfo_t *info)
15341fcced4cSJordan Brown {
15351fcced4cSJordan Brown if (info == NULL)
15361fcced4cSJordan Brown return;
15371fcced4cSJordan Brown
15381fcced4cSJordan Brown if (info->ci_username)
15391fcced4cSJordan Brown kmem_free(info->ci_username, info->ci_namelen);
15401fcced4cSJordan Brown if (info->ci_share)
15419fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_mem_free(info->ci_share);
15421fcced4cSJordan Brown
15431fcced4cSJordan Brown bzero(info, sizeof (smb_netconnectinfo_t));
15441fcced4cSJordan Brown }
1545