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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 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 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 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 * 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 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 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 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 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 * 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 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 * 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 * 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 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 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 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 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 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 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 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