1da6c28aaSamw /* 2da6c28aaSamw * CDDL HEADER START 3da6c28aaSamw * 4da6c28aaSamw * The contents of this file are subject to the terms of the 5da6c28aaSamw * Common Development and Distribution License (the "License"). 6da6c28aaSamw * You may not use this file except in compliance with the License. 7da6c28aaSamw * 8da6c28aaSamw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9da6c28aaSamw * or http://www.opensolaris.org/os/licensing. 10da6c28aaSamw * See the License for the specific language governing permissions 11da6c28aaSamw * and limitations under the License. 12da6c28aaSamw * 13da6c28aaSamw * When distributing Covered Code, include this CDDL HEADER in each 14da6c28aaSamw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15da6c28aaSamw * If applicable, add the following below this CDDL HEADER, with the 16da6c28aaSamw * fields enclosed by brackets "[]" replaced with your own identifying 17da6c28aaSamw * information: Portions Copyright [yyyy] [name of copyright owner] 18da6c28aaSamw * 19da6c28aaSamw * CDDL HEADER END 20da6c28aaSamw */ 21148c5f43SAlan Wright 22da6c28aaSamw /* 23c5866007SKeyur Desai * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 2448bbca81SDaniel Hoffman * Copyright (c) 2016 by Delphix. All rights reserved. 25*af536d7dSGordon Ross * Copyright 2021 Tintri by DDN, Inc. All rights reserved. 26da6c28aaSamw */ 27da6c28aaSamw 28da6c28aaSamw /* 29da6c28aaSamw * General Structures Layout 30da6c28aaSamw * ------------------------- 31da6c28aaSamw * 32da6c28aaSamw * This is a simplified diagram showing the relationship between most of the 33da6c28aaSamw * main structures. 34da6c28aaSamw * 35da6c28aaSamw * +-------------------+ 36da6c28aaSamw * | SMB_INFO | 37da6c28aaSamw * +-------------------+ 38da6c28aaSamw * | 39da6c28aaSamw * | 40da6c28aaSamw * v 41da6c28aaSamw * +-------------------+ +-------------------+ +-------------------+ 42da6c28aaSamw * | SESSION |<----->| SESSION |......| SESSION | 43da6c28aaSamw * +-------------------+ +-------------------+ +-------------------+ 443b13a1efSThomas Keiser * | | 453b13a1efSThomas Keiser * | | 463b13a1efSThomas Keiser * | v 473b13a1efSThomas Keiser * | +-------------------+ +-------------------+ +-------------------+ 483b13a1efSThomas Keiser * | | USER |<--->| USER |...| USER | 493b13a1efSThomas Keiser * | +-------------------+ +-------------------+ +-------------------+ 503b13a1efSThomas Keiser * | 513b13a1efSThomas Keiser * | 523b13a1efSThomas Keiser * v 53da6c28aaSamw * +-------------------+ +-------------------+ +-------------------+ 54da6c28aaSamw * | TREE |<----->| TREE |......| TREE | 55da6c28aaSamw * +-------------------+ +-------------------+ +-------------------+ 56da6c28aaSamw * | | 57da6c28aaSamw * | | 58da6c28aaSamw * | v 59da6c28aaSamw * | +-------+ +-------+ +-------+ 60da6c28aaSamw * | | OFILE |<----->| OFILE |......| OFILE | 61da6c28aaSamw * | +-------+ +-------+ +-------+ 62da6c28aaSamw * | 63da6c28aaSamw * | 64da6c28aaSamw * v 65da6c28aaSamw * +-------+ +------+ +------+ 66da6c28aaSamw * | ODIR |<----->| ODIR |......| ODIR | 67da6c28aaSamw * +-------+ +------+ +------+ 68da6c28aaSamw * 69da6c28aaSamw * 70da6c28aaSamw * Tree State Machine 71da6c28aaSamw * ------------------ 72da6c28aaSamw * 73da6c28aaSamw * +-----------------------------+ T0 74da6c28aaSamw * | SMB_TREE_STATE_CONNECTED |<----------- Creation/Allocation 75da6c28aaSamw * +-----------------------------+ 76da6c28aaSamw * | 77da6c28aaSamw * | T1 78da6c28aaSamw * | 79da6c28aaSamw * v 80da6c28aaSamw * +------------------------------+ 81da6c28aaSamw * | SMB_TREE_STATE_DISCONNECTING | 82da6c28aaSamw * +------------------------------+ 83da6c28aaSamw * | 84da6c28aaSamw * | T2 85da6c28aaSamw * | 86da6c28aaSamw * v 87da6c28aaSamw * +-----------------------------+ T3 88da6c28aaSamw * | SMB_TREE_STATE_DISCONNECTED |----------> Deletion/Free 89da6c28aaSamw * +-----------------------------+ 90da6c28aaSamw * 91da6c28aaSamw * SMB_TREE_STATE_CONNECTED 92da6c28aaSamw * 93da6c28aaSamw * While in this state: 94da6c28aaSamw * - The tree is queued in the list of trees of its user. 95da6c28aaSamw * - References will be given out if the tree is looked up. 96da6c28aaSamw * - Files under that tree can be accessed. 97da6c28aaSamw * 98da6c28aaSamw * SMB_TREE_STATE_DISCONNECTING 99da6c28aaSamw * 100da6c28aaSamw * While in this state: 101da6c28aaSamw * - The tree is queued in the list of trees of its user. 102da6c28aaSamw * - References will not be given out if the tree is looked up. 103da6c28aaSamw * - The files and directories open under the tree are being closed. 104da6c28aaSamw * - The resources associated with the tree remain. 105da6c28aaSamw * 106da6c28aaSamw * SMB_TREE_STATE_DISCONNECTED 107da6c28aaSamw * 108da6c28aaSamw * While in this state: 109da6c28aaSamw * - The tree is queued in the list of trees of its user. 110da6c28aaSamw * - References will not be given out if the tree is looked up. 111da6c28aaSamw * - The tree has no more files and directories opened. 112da6c28aaSamw * - The resources associated with the tree remain. 113da6c28aaSamw * 114da6c28aaSamw * Transition T0 115da6c28aaSamw * 116da6c28aaSamw * This transition occurs in smb_tree_connect(). A new tree is created and 117da6c28aaSamw * added to the list of trees of a user. 118da6c28aaSamw * 119da6c28aaSamw * Transition T1 120da6c28aaSamw * 121da6c28aaSamw * This transition occurs in smb_tree_disconnect(). 122da6c28aaSamw * 123da6c28aaSamw * Transition T2 124da6c28aaSamw * 125811599a4SMatt Barden * This transition occurs in smb_tree_disconnect() 126811599a4SMatt Barden * 127811599a4SMatt Barden * Transition T3 128811599a4SMatt Barden * 129da6c28aaSamw * This transition occurs in smb_tree_release(). The resources associated 130da6c28aaSamw * with the tree are freed as well as the tree structure. For the transition 131811599a4SMatt Barden * to occur, the tree must be in the SMB_TREE_STATE_DISCONNECTED and the 132811599a4SMatt Barden * reference count must be zero. 133da6c28aaSamw * 134da6c28aaSamw * Comments 135da6c28aaSamw * -------- 136da6c28aaSamw * 137da6c28aaSamw * The state machine of the tree structures is controlled by 3 elements: 138da6c28aaSamw * - The list of trees of the user it belongs to. 139da6c28aaSamw * - The mutex embedded in the structure itself. 140da6c28aaSamw * - The reference count. 141da6c28aaSamw * 142da6c28aaSamw * There's a mutex embedded in the tree structure used to protect its fields 143da6c28aaSamw * and there's a lock embedded in the list of trees of a user. To 144da6c28aaSamw * increment or to decrement the reference count the mutex must be entered. 145da6c28aaSamw * To insert the tree into the list of trees of the user and to remove 146da6c28aaSamw * the tree from it, the lock must be entered in RW_WRITER mode. 147da6c28aaSamw * 148da6c28aaSamw * Rules of access to a tree structure: 149da6c28aaSamw * 150da6c28aaSamw * 1) In order to avoid deadlocks, when both (mutex and lock of the user 151811599a4SMatt Barden * list) have to be entered, the lock must be entered first. Additionally, 152811599a4SMatt Barden * when both the (mutex and lock of the ofile list) have to be entered, 153811599a4SMatt Barden * the mutex must be entered first. However, the ofile list lock must NOT 154811599a4SMatt Barden * be dropped while the mutex is held in such a way that the ofile deleteq 155811599a4SMatt Barden * is flushed. 156da6c28aaSamw * 157da6c28aaSamw * 2) All actions applied to a tree require a reference count. 158da6c28aaSamw * 159c8ec8eeaSjose borrego * 3) There are 2 ways of getting a reference count: when a tree is 160c8ec8eeaSjose borrego * connected and when a tree is looked up. 161da6c28aaSamw * 162da6c28aaSamw * It should be noted that the reference count of a tree registers the 163da6c28aaSamw * number of references to the tree in other structures (such as an smb 164da6c28aaSamw * request). The reference count is not incremented in these 2 instances: 165da6c28aaSamw * 16648bbca81SDaniel Hoffman * 1) The tree is connected. An tree is anchored by its state. If there's 167da6c28aaSamw * no activity involving a tree currently connected, the reference 168da6c28aaSamw * count of that tree is zero. 169da6c28aaSamw * 170da6c28aaSamw * 2) The tree is queued in the list of trees of the user. The fact of 171da6c28aaSamw * being queued in that list is NOT registered by incrementing the 172da6c28aaSamw * reference count. 173da6c28aaSamw */ 174148c5f43SAlan Wright 175c8ec8eeaSjose borrego #include <sys/refstr_impl.h> 176bbf6f00cSJordan Brown #include <smbsrv/smb_kproto.h> 177148c5f43SAlan Wright #include <smbsrv/smb_ktypes.h> 178da6c28aaSamw #include <smbsrv/smb_fsops.h> 179cb174861Sjoyce mcintosh #include <smbsrv/smb_share.h> 180c8ec8eeaSjose borrego 181c8ec8eeaSjose borrego int smb_tcon_mute = 0; 182c8ec8eeaSjose borrego 183a90cf9f2SGordon Ross uint32_t smb_tree_connect_core(smb_request_t *); 184a90cf9f2SGordon Ross uint32_t smb_tree_connect_disk(smb_request_t *, smb_arg_tcon_t *); 185a90cf9f2SGordon Ross uint32_t smb_tree_connect_printq(smb_request_t *, smb_arg_tcon_t *); 186a90cf9f2SGordon Ross uint32_t smb_tree_connect_ipc(smb_request_t *, smb_arg_tcon_t *); 187811599a4SMatt Barden static void smb_tree_dealloc(void *); 1888b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States static boolean_t smb_tree_is_connected_locked(smb_tree_t *); 189a90cf9f2SGordon Ross static char *smb_tree_get_sharename(char *); 190148c5f43SAlan Wright static int smb_tree_getattr(const smb_kshare_t *, smb_node_t *, smb_tree_t *); 19125a9a7aaSGordon Ross static void smb_tree_get_creation(smb_node_t *, smb_tree_t *); 192c8ec8eeaSjose borrego static void smb_tree_get_volname(vfs_t *, smb_tree_t *); 193148c5f43SAlan Wright static void smb_tree_get_flags(const smb_kshare_t *, vfs_t *, smb_tree_t *); 194c8ec8eeaSjose borrego static void smb_tree_log(smb_request_t *, const char *, const char *, ...); 1958d94f651SGordon Ross static void smb_tree_close_odirs(smb_tree_t *, uint32_t); 196148c5f43SAlan Wright static void smb_tree_set_execinfo(smb_tree_t *, smb_shr_execinfo_t *, int); 1971fcced4cSJordan Brown static int smb_tree_enum_private(smb_tree_t *, smb_svcenum_t *); 1981fcced4cSJordan Brown static int smb_tree_netinfo_encode(smb_tree_t *, uint8_t *, size_t, uint32_t *); 1991fcced4cSJordan Brown static void smb_tree_netinfo_init(smb_tree_t *tree, smb_netconnectinfo_t *); 2001fcced4cSJordan Brown static void smb_tree_netinfo_fini(smb_netconnectinfo_t *); 201da6c28aaSamw 202a90cf9f2SGordon Ross uint32_t 203cb174861Sjoyce mcintosh smb_tree_connect(smb_request_t *sr) 204cb174861Sjoyce mcintosh { 205cb174861Sjoyce mcintosh smb_server_t *sv = sr->sr_server; 206a90cf9f2SGordon Ross uint32_t status; 207cb174861Sjoyce mcintosh 208cb174861Sjoyce mcintosh if (smb_threshold_enter(&sv->sv_tcon_ct) != 0) { 209a90cf9f2SGordon Ross return (NT_STATUS_INSUFF_SERVER_RESOURCES); 210cb174861Sjoyce mcintosh } 211cb174861Sjoyce mcintosh 212a90cf9f2SGordon Ross status = smb_tree_connect_core(sr); 213856399cfSGordon Ross smb_threshold_exit(&sv->sv_tcon_ct); 214a90cf9f2SGordon Ross return (status); 215cb174861Sjoyce mcintosh } 216cb174861Sjoyce mcintosh 217da6c28aaSamw /* 218148c5f43SAlan Wright * Lookup the share name dispatch the appropriate stype handler. 219c8ec8eeaSjose borrego * Share names are case insensitive so we map the share name to 220c8ec8eeaSjose borrego * lower-case as a convenience for internal processing. 221148c5f43SAlan Wright * 222148c5f43SAlan Wright * Valid service values are: 223148c5f43SAlan Wright * A: Disk share 224148c5f43SAlan Wright * LPT1: Printer 225148c5f43SAlan Wright * IPC Named pipe (IPC$ is reserved as the named pipe share). 226148c5f43SAlan Wright * COMM Communications device 227148c5f43SAlan Wright * ????? Any type of device (wildcard) 228da6c28aaSamw */ 229a90cf9f2SGordon Ross uint32_t 230cb174861Sjoyce mcintosh smb_tree_connect_core(smb_request_t *sr) 231da6c28aaSamw { 232a90cf9f2SGordon Ross smb_arg_tcon_t *tcon = &sr->sr_tcon; 233148c5f43SAlan Wright smb_kshare_t *si; 234a90cf9f2SGordon Ross char *name; 235a90cf9f2SGordon Ross uint32_t status; 236da6c28aaSamw 237a90cf9f2SGordon Ross (void) smb_strlwr(tcon->path); 238da6c28aaSamw 239a90cf9f2SGordon Ross if ((name = smb_tree_get_sharename(tcon->path)) == NULL) { 240a90cf9f2SGordon Ross smb_tree_log(sr, tcon->path, "invalid UNC path"); 241a90cf9f2SGordon Ross return (NT_STATUS_BAD_NETWORK_NAME); 242da6c28aaSamw } 243da6c28aaSamw 2448622ec45SGordon Ross si = smb_kshare_lookup(sr->sr_server, name); 2458622ec45SGordon Ross if (si == NULL) { 246148c5f43SAlan Wright smb_tree_log(sr, name, "share not found"); 247a90cf9f2SGordon Ross return (NT_STATUS_BAD_NETWORK_NAME); 248da6c28aaSamw } 249cb174861Sjoyce mcintosh 250cb174861Sjoyce mcintosh if (!strcasecmp(SMB_SHARE_PRINT, name)) { 2518622ec45SGordon Ross smb_kshare_release(sr->sr_server, si); 252cb174861Sjoyce mcintosh smb_tree_log(sr, name, "access not permitted"); 253a90cf9f2SGordon Ross return (NT_STATUS_ACCESS_DENIED); 254cb174861Sjoyce mcintosh } 255cb174861Sjoyce mcintosh 256a90cf9f2SGordon Ross /* NB: name points into tcon->path - don't free it. */ 257a90cf9f2SGordon Ross tcon->name = name; 258148c5f43SAlan Wright sr->sr_tcon.si = si; 259da6c28aaSamw 2601160dcf7SMatt Barden /* 2611160dcf7SMatt Barden * [MS-SMB2] 3.3.5.7 Receiving an SMB2 TREE_CONNECT Request 2621160dcf7SMatt Barden * 2631160dcf7SMatt Barden * If we support 3.x, RejectUnencryptedAccess is TRUE, 2641160dcf7SMatt Barden * if Tcon.EncryptData is TRUE or global EncryptData is TRUE, 2651160dcf7SMatt Barden * and the connection doesn't support encryption, 2661160dcf7SMatt Barden * return ACCESS_DENIED. 2671160dcf7SMatt Barden * 2681160dcf7SMatt Barden * If RejectUnencryptedAccess is TRUE, we force max_protocol 2691160dcf7SMatt Barden * to at least 3.0. Additionally, if the tree requires encryption, 2701160dcf7SMatt Barden * we don't care what we support, we still enforce encryption. 2711160dcf7SMatt Barden */ 2721160dcf7SMatt Barden if ((sr->sr_server->sv_cfg.skc_encrypt == SMB_CONFIG_REQUIRED || 2731160dcf7SMatt Barden si->shr_encrypt == SMB_CONFIG_REQUIRED) && 2741160dcf7SMatt Barden (sr->session->srv_cap & SMB2_CAP_ENCRYPTION) == 0) { 2751160dcf7SMatt Barden status = NT_STATUS_ACCESS_DENIED; 2761160dcf7SMatt Barden goto out; 2771160dcf7SMatt Barden } 2781160dcf7SMatt Barden 279148c5f43SAlan Wright switch (si->shr_type & STYPE_MASK) { 280da6c28aaSamw case STYPE_DISKTREE: 281a90cf9f2SGordon Ross status = smb_tree_connect_disk(sr, &sr->sr_tcon); 282da6c28aaSamw break; 283da6c28aaSamw case STYPE_IPC: 284a90cf9f2SGordon Ross status = smb_tree_connect_ipc(sr, &sr->sr_tcon); 285c8ec8eeaSjose borrego break; 286148c5f43SAlan Wright case STYPE_PRINTQ: 287a90cf9f2SGordon Ross status = smb_tree_connect_printq(sr, &sr->sr_tcon); 288148c5f43SAlan Wright break; 289da6c28aaSamw default: 290a90cf9f2SGordon Ross status = NT_STATUS_BAD_DEVICE_TYPE; 291da6c28aaSamw break; 292da6c28aaSamw } 293da6c28aaSamw 2941160dcf7SMatt Barden out: 2958622ec45SGordon Ross smb_kshare_release(sr->sr_server, si); 296a90cf9f2SGordon Ross sr->sr_tcon.si = NULL; 297a90cf9f2SGordon Ross 298a90cf9f2SGordon Ross return (status); 299da6c28aaSamw } 300da6c28aaSamw 301da6c28aaSamw /* 302c8ec8eeaSjose borrego * Disconnect a tree. 3038d94f651SGordon Ross * 3048d94f651SGordon Ross * The "do_exec" arg is obsolete and ignored. 305da6c28aaSamw */ 306da6c28aaSamw void 30729bd2886SAlan Wright smb_tree_disconnect(smb_tree_t *tree, boolean_t do_exec) 308da6c28aaSamw { 3098d94f651SGordon Ross _NOTE(ARGUNUSED(do_exec)) 310148c5f43SAlan Wright smb_shr_execinfo_t execinfo; 31129bd2886SAlan Wright 312da6c28aaSamw ASSERT(tree->t_magic == SMB_TREE_MAGIC); 313da6c28aaSamw 314da6c28aaSamw mutex_enter(&tree->t_mutex); 315da6c28aaSamw ASSERT(tree->t_refcnt); 316c8ec8eeaSjose borrego 3178d94f651SGordon Ross if (!smb_tree_is_connected_locked(tree)) { 318da6c28aaSamw mutex_exit(&tree->t_mutex); 3198d94f651SGordon Ross return; 320da6c28aaSamw } 321da6c28aaSamw 3228d94f651SGordon Ross /* 3238d94f651SGordon Ross * Indicate that the disconnect process has started. 3248d94f651SGordon Ross */ 3258d94f651SGordon Ross tree->t_state = SMB_TREE_STATE_DISCONNECTING; 326da6c28aaSamw mutex_exit(&tree->t_mutex); 32729bd2886SAlan Wright 3288d94f651SGordon Ross /* 3298d94f651SGordon Ross * The files opened under this tree are closed. 3308d94f651SGordon Ross */ 3318d94f651SGordon Ross smb_ofile_close_all(tree, 0); 3328d94f651SGordon Ross /* 3338d94f651SGordon Ross * The directories opened under this tree are closed. 3348d94f651SGordon Ross */ 3358d94f651SGordon Ross smb_tree_close_odirs(tree, 0); 33629bd2886SAlan Wright 3378d94f651SGordon Ross if ((tree->t_execflags & SMB_EXEC_UNMAP) != 0) { 338148c5f43SAlan Wright smb_tree_set_execinfo(tree, &execinfo, SMB_EXEC_UNMAP); 3398622ec45SGordon Ross (void) smb_kshare_exec(tree->t_server, &execinfo); 34029bd2886SAlan Wright } 341da6c28aaSamw } 342da6c28aaSamw 343da6c28aaSamw /* 344c8ec8eeaSjose borrego * Take a reference on a tree. 345da6c28aaSamw */ 346c8ec8eeaSjose borrego boolean_t 347c8ec8eeaSjose borrego smb_tree_hold( 348c8ec8eeaSjose borrego smb_tree_t *tree) 349da6c28aaSamw { 350a90cf9f2SGordon Ross SMB_TREE_VALID(tree); 351da6c28aaSamw 352c8ec8eeaSjose borrego mutex_enter(&tree->t_mutex); 353c8ec8eeaSjose borrego 3548b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (smb_tree_is_connected_locked(tree)) { 355c8ec8eeaSjose borrego tree->t_refcnt++; 356c8ec8eeaSjose borrego mutex_exit(&tree->t_mutex); 357c8ec8eeaSjose borrego return (B_TRUE); 358da6c28aaSamw } 359c8ec8eeaSjose borrego 360c8ec8eeaSjose borrego mutex_exit(&tree->t_mutex); 361c8ec8eeaSjose borrego return (B_FALSE); 362da6c28aaSamw } 363da6c28aaSamw 364a90cf9f2SGordon Ross /* 365a90cf9f2SGordon Ross * Bump the hold count regardless of the tree state. This is used in 366a90cf9f2SGordon Ross * some internal code paths where we've already checked that we had a 367a90cf9f2SGordon Ross * valid tree connection, and don't want to deal with the possiblity 368a90cf9f2SGordon Ross * that the tree state might have changed to disconnecting after our 369a90cf9f2SGordon Ross * original hold was taken. It's correct to continue processing a 370a90cf9f2SGordon Ross * request even when new requests cannot lookup that tree anymore. 371a90cf9f2SGordon Ross */ 372a90cf9f2SGordon Ross void 373a90cf9f2SGordon Ross smb_tree_hold_internal( 374a90cf9f2SGordon Ross smb_tree_t *tree) 375a90cf9f2SGordon Ross { 376a90cf9f2SGordon Ross SMB_TREE_VALID(tree); 377a90cf9f2SGordon Ross 378a90cf9f2SGordon Ross mutex_enter(&tree->t_mutex); 379a90cf9f2SGordon Ross tree->t_refcnt++; 380a90cf9f2SGordon Ross mutex_exit(&tree->t_mutex); 381a90cf9f2SGordon Ross } 382a90cf9f2SGordon Ross 383da6c28aaSamw /* 384c8ec8eeaSjose borrego * Release a reference on a tree. If the tree is disconnected and the 3859fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * reference count falls to zero, post the object for deletion. 3869fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Object deletion is deferred to avoid modifying a list while an 3879fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * iteration may be in progress. 388da6c28aaSamw */ 389da6c28aaSamw void 390c8ec8eeaSjose borrego smb_tree_release( 391c8ec8eeaSjose borrego smb_tree_t *tree) 392da6c28aaSamw { 3939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_TREE_VALID(tree); 394da6c28aaSamw 395c5866007SKeyur Desai /* flush the ofile and odir lists' delete queues */ 396c5866007SKeyur Desai smb_llist_flush(&tree->t_ofile_list); 397c5866007SKeyur Desai smb_llist_flush(&tree->t_odir_list); 398c5866007SKeyur Desai 399811599a4SMatt Barden mutex_enter(&tree->t_mutex); 400811599a4SMatt Barden ASSERT(tree->t_refcnt); 401811599a4SMatt Barden tree->t_refcnt--; 4029fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 403811599a4SMatt Barden switch (tree->t_state) { 4048d94f651SGordon Ross case SMB_TREE_STATE_DISCONNECTING: 405811599a4SMatt Barden if (tree->t_refcnt == 0) { 406811599a4SMatt Barden smb_session_t *ssn = tree->t_session; 407811599a4SMatt Barden tree->t_state = SMB_TREE_STATE_DISCONNECTED; 408811599a4SMatt Barden smb_llist_post(&ssn->s_tree_list, tree, 409811599a4SMatt Barden smb_tree_dealloc); 410811599a4SMatt Barden } 411811599a4SMatt Barden break; 412811599a4SMatt Barden case SMB_TREE_STATE_CONNECTED: 413811599a4SMatt Barden break; 414811599a4SMatt Barden default: 415811599a4SMatt Barden ASSERT(0); 416811599a4SMatt Barden break; 417811599a4SMatt Barden } 4189fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 419811599a4SMatt Barden mutex_exit(&tree->t_mutex); 4209fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States } 4219fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 422da6c28aaSamw /* 423c8ec8eeaSjose borrego * Close ofiles and odirs that match pid. 424da6c28aaSamw */ 425da6c28aaSamw void 426c8ec8eeaSjose borrego smb_tree_close_pid( 427c8ec8eeaSjose borrego smb_tree_t *tree, 428a90cf9f2SGordon Ross uint32_t pid) 429da6c28aaSamw { 430da6c28aaSamw ASSERT(tree); 431da6c28aaSamw ASSERT(tree->t_magic == SMB_TREE_MAGIC); 432da6c28aaSamw 433811599a4SMatt Barden smb_ofile_close_all(tree, pid); 4347f667e74Sjose borrego smb_tree_close_odirs(tree, pid); 435c8ec8eeaSjose borrego } 436da6c28aaSamw 437c8ec8eeaSjose borrego /* 438c8ec8eeaSjose borrego * Check whether or not a tree supports the features identified by flags. 439c8ec8eeaSjose borrego */ 440c8ec8eeaSjose borrego boolean_t 441c8ec8eeaSjose borrego smb_tree_has_feature(smb_tree_t *tree, uint32_t flags) 442c8ec8eeaSjose borrego { 443c8ec8eeaSjose borrego ASSERT(tree); 444c8ec8eeaSjose borrego ASSERT(tree->t_magic == SMB_TREE_MAGIC); 445da6c28aaSamw 446c8ec8eeaSjose borrego return ((tree->t_flags & flags) == flags); 447da6c28aaSamw } 448da6c28aaSamw 4491fcced4cSJordan Brown /* 4501fcced4cSJordan Brown * If the enumeration request is for tree data, handle the request 4511fcced4cSJordan Brown * here. Otherwise, pass it on to the ofiles. 4521fcced4cSJordan Brown * 4531fcced4cSJordan Brown * This function should be called with a hold on the tree. 4541fcced4cSJordan Brown */ 4551fcced4cSJordan Brown int 4561fcced4cSJordan Brown smb_tree_enum(smb_tree_t *tree, smb_svcenum_t *svcenum) 4571fcced4cSJordan Brown { 4588d94f651SGordon Ross smb_llist_t *of_list; 4591fcced4cSJordan Brown smb_ofile_t *of; 4603b13a1efSThomas Keiser int rc = 0; 4611fcced4cSJordan Brown 4621fcced4cSJordan Brown if (svcenum->se_type == SMB_SVCENUM_TYPE_TREE) 4631fcced4cSJordan Brown return (smb_tree_enum_private(tree, svcenum)); 4641fcced4cSJordan Brown 4658d94f651SGordon Ross of_list = &tree->t_ofile_list; 4668d94f651SGordon Ross smb_llist_enter(of_list, RW_READER); 4671fcced4cSJordan Brown 4688d94f651SGordon Ross of = smb_llist_head(of_list); 4698d94f651SGordon Ross while (of) { 4708d94f651SGordon Ross if (smb_ofile_hold(of)) { 4718d94f651SGordon Ross rc = smb_ofile_enum(of, svcenum); 4721fcced4cSJordan Brown smb_ofile_release(of); 4731fcced4cSJordan Brown } 4748d94f651SGordon Ross if (rc != 0) 4758d94f651SGordon Ross break; 4768d94f651SGordon Ross of = smb_llist_next(of_list, of); 4771fcced4cSJordan Brown } 4781fcced4cSJordan Brown 4798d94f651SGordon Ross smb_llist_exit(of_list); 4808d94f651SGordon Ross 4811fcced4cSJordan Brown return (rc); 4821fcced4cSJordan Brown } 4831fcced4cSJordan Brown 4841fcced4cSJordan Brown /* 4851fcced4cSJordan Brown * Close a file by its unique id. 4861fcced4cSJordan Brown */ 4871fcced4cSJordan Brown int 4881fcced4cSJordan Brown smb_tree_fclose(smb_tree_t *tree, uint32_t uniqid) 4891fcced4cSJordan Brown { 4901fcced4cSJordan Brown smb_ofile_t *of; 4911fcced4cSJordan Brown 4921fcced4cSJordan Brown ASSERT(tree); 4931fcced4cSJordan Brown ASSERT(tree->t_magic == SMB_TREE_MAGIC); 4941fcced4cSJordan Brown 495811599a4SMatt Barden /* 496811599a4SMatt Barden * Note that ORPHANED ofiles aren't fclosable, as they have 497811599a4SMatt Barden * no session, user, or tree by which they might be found. 498811599a4SMatt Barden * They will eventually expire. 499811599a4SMatt Barden */ 5001fcced4cSJordan Brown if ((of = smb_ofile_lookup_by_uniqid(tree, uniqid)) == NULL) 5011fcced4cSJordan Brown return (ENOENT); 5021fcced4cSJordan Brown 5031fcced4cSJordan Brown if (smb_ofile_disallow_fclose(of)) { 5041fcced4cSJordan Brown smb_ofile_release(of); 5051fcced4cSJordan Brown return (EACCES); 5061fcced4cSJordan Brown } 5071fcced4cSJordan Brown 5081fcced4cSJordan Brown smb_ofile_close(of, 0); 5091fcced4cSJordan Brown smb_ofile_release(of); 5101fcced4cSJordan Brown return (0); 5111fcced4cSJordan Brown } 512743a77edSAlan Wright 513c8ec8eeaSjose borrego /* *************************** Static Functions ***************************** */ 5141fcced4cSJordan Brown 515743a77edSAlan Wright #define SHARES_DIR ".zfs/shares/" 516148c5f43SAlan Wright 517148c5f43SAlan Wright /* 518148c5f43SAlan Wright * Calculates permissions given by the share's ACL to the 519148c5f43SAlan Wright * user in the passed request. The default is full access. 520148c5f43SAlan Wright * If any error occurs, full access is granted. 521148c5f43SAlan Wright * 522148c5f43SAlan Wright * Using the vnode of the share path find the root directory 523148c5f43SAlan Wright * of the mounted file system. Then look to see if there is a 524148c5f43SAlan Wright * .zfs/shares directory and if there is, lookup the file with 525148c5f43SAlan Wright * the same name as the share name in it. The ACL set for this 526148c5f43SAlan Wright * file is the share's ACL which is used for access check here. 527148c5f43SAlan Wright */ 528148c5f43SAlan Wright static uint32_t 529148c5f43SAlan Wright smb_tree_acl_access(smb_request_t *sr, const smb_kshare_t *si, vnode_t *pathvp) 530743a77edSAlan Wright { 531fe1c642dSBill Krier smb_user_t *user; 532fe1c642dSBill Krier cred_t *cred; 533fe1c642dSBill Krier int rc; 534fe1c642dSBill Krier vfs_t *vfsp; 535fe1c642dSBill Krier vnode_t *root = NULL; 536fe1c642dSBill Krier vnode_t *sharevp = NULL; 537fe1c642dSBill Krier char *sharepath; 538fe1c642dSBill Krier struct pathname pnp; 539fe1c642dSBill Krier size_t size; 540148c5f43SAlan Wright uint32_t access; 541fe1c642dSBill Krier 542fe1c642dSBill Krier user = sr->uid_user; 543fe1c642dSBill Krier cred = user->u_cred; 544148c5f43SAlan Wright access = ACE_ALL_PERMS; 545743a77edSAlan Wright 546fe1c642dSBill Krier if (si->shr_flags & SMB_SHRF_AUTOHOME) { 547fe1c642dSBill Krier /* 548fe1c642dSBill Krier * An autohome share owner gets full access to the share. 549fe1c642dSBill Krier * Everyone else is denied access. 550fe1c642dSBill Krier */ 551c5866007SKeyur Desai if (si->shr_uid != crgetuid(cred)) 552148c5f43SAlan Wright access = 0; 553148c5f43SAlan Wright 554148c5f43SAlan Wright return (access); 555fe1c642dSBill Krier } 556fe1c642dSBill Krier 557743a77edSAlan Wright /* 558148c5f43SAlan Wright * The hold on 'root' is released by the lookuppnvp() that follows 559743a77edSAlan Wright */ 560743a77edSAlan Wright vfsp = pathvp->v_vfsp; 561743a77edSAlan Wright if (vfsp != NULL) 562743a77edSAlan Wright rc = VFS_ROOT(vfsp, &root); 563743a77edSAlan Wright else 564743a77edSAlan Wright rc = ENOENT; 565743a77edSAlan Wright 566743a77edSAlan Wright if (rc != 0) 567148c5f43SAlan Wright return (access); 568743a77edSAlan Wright 569743a77edSAlan Wright 570fe1c642dSBill Krier size = sizeof (SHARES_DIR) + strlen(si->shr_name) + 1; 571148c5f43SAlan Wright sharepath = smb_srm_alloc(sr, size); 572b819cea2SGordon Ross (void) snprintf(sharepath, size, "%s%s", SHARES_DIR, si->shr_name); 573743a77edSAlan Wright 574743a77edSAlan Wright pn_alloc(&pnp); 575743a77edSAlan Wright (void) pn_set(&pnp, sharepath); 576148c5f43SAlan Wright rc = lookuppnvp(&pnp, NULL, NO_FOLLOW, NULL, &sharevp, rootdir, root, 5778622ec45SGordon Ross zone_kcred()); 578743a77edSAlan Wright pn_free(&pnp); 579743a77edSAlan Wright 580743a77edSAlan Wright /* 581148c5f43SAlan Wright * Now get the effective access value based on cred and ACL values. 582743a77edSAlan Wright */ 583037cac00Sjoyce mcintosh if (rc == 0) { 584148c5f43SAlan Wright smb_vop_eaccess(sharevp, (int *)&access, V_ACE_MASK, NULL, 585148c5f43SAlan Wright cred); 586037cac00Sjoyce mcintosh VN_RELE(sharevp); 587037cac00Sjoyce mcintosh } 588148c5f43SAlan Wright 589148c5f43SAlan Wright return (access); 590743a77edSAlan Wright } 591c8ec8eeaSjose borrego 592da6c28aaSamw /* 593148c5f43SAlan Wright * Performs the following access checks for a disk share: 594148c5f43SAlan Wright * 595148c5f43SAlan Wright * - No IPC/anonymous user is allowed 596148c5f43SAlan Wright * 597148c5f43SAlan Wright * - If user is Guest, guestok property of the share should be 598148c5f43SAlan Wright * enabled 599148c5f43SAlan Wright * 600148c5f43SAlan Wright * - If this is an Admin share, the user should have administrative 601148c5f43SAlan Wright * privileges 602148c5f43SAlan Wright * 603148c5f43SAlan Wright * - Host based access control lists 604148c5f43SAlan Wright * 605148c5f43SAlan Wright * - Share ACL 606148c5f43SAlan Wright * 607148c5f43SAlan Wright * Returns the access allowed or 0 if access is denied. 608da6c28aaSamw */ 609148c5f43SAlan Wright static uint32_t 610148c5f43SAlan Wright smb_tree_chkaccess(smb_request_t *sr, smb_kshare_t *shr, vnode_t *vp) 611148c5f43SAlan Wright { 612148c5f43SAlan Wright smb_user_t *user = sr->uid_user; 613148c5f43SAlan Wright char *sharename = shr->shr_name; 614148c5f43SAlan Wright uint32_t host_access; 615148c5f43SAlan Wright uint32_t acl_access; 616148c5f43SAlan Wright uint32_t access; 617743a77edSAlan Wright 618a90cf9f2SGordon Ross if (user->u_flags & SMB_USER_FLAG_ANON) { 619148c5f43SAlan Wright smb_tree_log(sr, sharename, "access denied: IPC only"); 620148c5f43SAlan Wright return (0); 621148c5f43SAlan Wright } 622148c5f43SAlan Wright 623148c5f43SAlan Wright if ((user->u_flags & SMB_USER_FLAG_GUEST) && 624148c5f43SAlan Wright ((shr->shr_flags & SMB_SHRF_GUEST_OK) == 0)) { 625148c5f43SAlan Wright smb_tree_log(sr, sharename, "access denied: guest disabled"); 626148c5f43SAlan Wright return (0); 627148c5f43SAlan Wright } 628148c5f43SAlan Wright 629148c5f43SAlan Wright if ((shr->shr_flags & SMB_SHRF_ADMIN) && !smb_user_is_admin(user)) { 630148c5f43SAlan Wright smb_tree_log(sr, sharename, "access denied: not admin"); 631148c5f43SAlan Wright return (0); 632148c5f43SAlan Wright } 633148c5f43SAlan Wright 6348622ec45SGordon Ross host_access = smb_kshare_hostaccess(shr, sr->session); 635148c5f43SAlan Wright if ((host_access & ACE_ALL_PERMS) == 0) { 636148c5f43SAlan Wright smb_tree_log(sr, sharename, "access denied: host access"); 637148c5f43SAlan Wright return (0); 638148c5f43SAlan Wright } 639148c5f43SAlan Wright 640148c5f43SAlan Wright acl_access = smb_tree_acl_access(sr, shr, vp); 641148c5f43SAlan Wright if ((acl_access & ACE_ALL_PERMS) == 0) { 642148c5f43SAlan Wright smb_tree_log(sr, sharename, "access denied: share ACL"); 643148c5f43SAlan Wright return (0); 644148c5f43SAlan Wright } 645148c5f43SAlan Wright 646148c5f43SAlan Wright access = host_access & acl_access; 647148c5f43SAlan Wright if ((access & ACE_ALL_PERMS) == 0) { 648148c5f43SAlan Wright smb_tree_log(sr, sharename, "access denied"); 649148c5f43SAlan Wright return (0); 650148c5f43SAlan Wright } 651148c5f43SAlan Wright 652148c5f43SAlan Wright return (access); 653148c5f43SAlan Wright } 654148c5f43SAlan Wright 6558d94f651SGordon Ross /* How long should tree connect wait for DH import to complete? */ 6568d94f651SGordon Ross int smb_tcon_import_wait = 20; /* sec. */ 6578d94f651SGordon Ross 658148c5f43SAlan Wright /* 659148c5f43SAlan Wright * Connect a share for use with files and directories. 660148c5f43SAlan Wright */ 661a90cf9f2SGordon Ross uint32_t 662a90cf9f2SGordon Ross smb_tree_connect_disk(smb_request_t *sr, smb_arg_tcon_t *tcon) 663da6c28aaSamw { 664a90cf9f2SGordon Ross char *sharename = tcon->path; 665148c5f43SAlan Wright const char *any = "?????"; 666c8ec8eeaSjose borrego smb_user_t *user = sr->uid_user; 667c8ec8eeaSjose borrego smb_node_t *snode = NULL; 668811599a4SMatt Barden smb_kshare_t *si = tcon->si; 669a90cf9f2SGordon Ross char *service = tcon->service; 670c8ec8eeaSjose borrego smb_tree_t *tree; 671c8ec8eeaSjose borrego int rc; 672148c5f43SAlan Wright uint32_t access; 673148c5f43SAlan Wright smb_shr_execinfo_t execinfo; 6748d94f651SGordon Ross clock_t time; 675da6c28aaSamw 676da6c28aaSamw ASSERT(user); 677148c5f43SAlan Wright ASSERT(user->u_cred); 678c8ec8eeaSjose borrego 679a90cf9f2SGordon Ross if (service != NULL && 680a90cf9f2SGordon Ross strcmp(service, any) != 0 && 681a90cf9f2SGordon Ross strcasecmp(service, "A:") != 0) { 682148c5f43SAlan Wright smb_tree_log(sr, sharename, "invalid service (%s)", service); 683a90cf9f2SGordon Ross return (NT_STATUS_BAD_DEVICE_TYPE); 684c8ec8eeaSjose borrego } 685c8ec8eeaSjose borrego 686148c5f43SAlan Wright /* 687148c5f43SAlan Wright * Check that the shared directory exists. 688148c5f43SAlan Wright */ 6898d94f651SGordon Ross snode = si->shr_root_node; 6908d94f651SGordon Ross if (snode == NULL) { 691148c5f43SAlan Wright smb_tree_log(sr, sharename, "bad path: %s", si->shr_path); 692a90cf9f2SGordon Ross return (NT_STATUS_BAD_NETWORK_NAME); 69329bd2886SAlan Wright } 69429bd2886SAlan Wright 695148c5f43SAlan Wright if ((access = smb_tree_chkaccess(sr, si, snode->vp)) == 0) { 696a90cf9f2SGordon Ross return (NT_STATUS_ACCESS_DENIED); 697da6c28aaSamw } 698c8ec8eeaSjose borrego 6998d94f651SGordon Ross /* 7008d94f651SGordon Ross * Wait for DH import of persistent handles to finish. 7018d94f651SGordon Ross * If we timeout, it's not clear what status to return, 7028d94f651SGordon Ross * but as the share is not really available yet, let's 7038d94f651SGordon Ross * return the status for "no such share". 7048d94f651SGordon Ross */ 7058d94f651SGordon Ross time = SEC_TO_TICK(smb_tcon_import_wait) + ddi_get_lbolt(); 7068d94f651SGordon Ross mutex_enter(&si->shr_mutex); 7078d94f651SGordon Ross while (si->shr_import_busy != NULL) { 7088d94f651SGordon Ross if (cv_timedwait(&si->shr_cv, &si->shr_mutex, time) < 0) { 7098d94f651SGordon Ross mutex_exit(&si->shr_mutex); 7108d94f651SGordon Ross return (NT_STATUS_BAD_NETWORK_NAME); 7118d94f651SGordon Ross } 7128d94f651SGordon Ross } 7138d94f651SGordon Ross mutex_exit(&si->shr_mutex); 7148d94f651SGordon Ross 7158d7e4166Sjose borrego /* 7168d7e4166Sjose borrego * Set up the OptionalSupport for this share. 7178d7e4166Sjose borrego */ 718a90cf9f2SGordon Ross tcon->optional_support = SMB_SUPPORT_SEARCH_BITS; 7198d7e4166Sjose borrego 7208d7e4166Sjose borrego switch (si->shr_flags & SMB_SHRF_CSC_MASK) { 7218d7e4166Sjose borrego case SMB_SHRF_CSC_DISABLED: 722a90cf9f2SGordon Ross tcon->optional_support |= SMB_CSC_CACHE_NONE; 7238d7e4166Sjose borrego break; 7248d7e4166Sjose borrego case SMB_SHRF_CSC_AUTO: 725a90cf9f2SGordon Ross tcon->optional_support |= SMB_CSC_CACHE_AUTO_REINT; 7268d7e4166Sjose borrego break; 7278d7e4166Sjose borrego case SMB_SHRF_CSC_VDO: 728a90cf9f2SGordon Ross tcon->optional_support |= SMB_CSC_CACHE_VDO; 7298d7e4166Sjose borrego break; 7308d7e4166Sjose borrego case SMB_SHRF_CSC_MANUAL: 7318d7e4166Sjose borrego default: 7328d7e4166Sjose borrego /* 7338d7e4166Sjose borrego * Default to SMB_CSC_CACHE_MANUAL_REINT. 7348d7e4166Sjose borrego */ 7358d7e4166Sjose borrego break; 7368d7e4166Sjose borrego } 7378d7e4166Sjose borrego 738e3f2c991SKeyur Desai /* ABE support */ 739e3f2c991SKeyur Desai if (si->shr_flags & SMB_SHRF_ABE) 740a90cf9f2SGordon Ross tcon->optional_support |= 741e3f2c991SKeyur Desai SHI1005_FLAGS_ACCESS_BASED_DIRECTORY_ENUM; 742e3f2c991SKeyur Desai 7439fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (si->shr_flags & SMB_SHRF_DFSROOT) 744a90cf9f2SGordon Ross tcon->optional_support |= SMB_SHARE_IS_IN_DFS; 7459fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 746cb174861Sjoyce mcintosh /* if 'smb' zfs property: shortnames=disabled */ 747cb174861Sjoyce mcintosh if (!smb_shortnames) 748cb174861Sjoyce mcintosh sr->arg.tcon.optional_support |= SMB_UNIQUE_FILE_NAME; 749cb174861Sjoyce mcintosh 7503b13a1efSThomas Keiser tree = smb_tree_alloc(sr, si, snode, access, sr->sr_cfg->skc_execflags); 751b89a8333Snatalie li - Sun Microsystems - Irvine United States 752a90cf9f2SGordon Ross if (tree == NULL) 753a90cf9f2SGordon Ross return (NT_STATUS_INSUFF_SERVER_RESOURCES); 754a90cf9f2SGordon Ross 755a90cf9f2SGordon Ross if (tree->t_execflags & SMB_EXEC_MAP) { 756a90cf9f2SGordon Ross smb_tree_set_execinfo(tree, &execinfo, SMB_EXEC_MAP); 757148c5f43SAlan Wright 758a90cf9f2SGordon Ross rc = smb_kshare_exec(tree->t_server, &execinfo); 759148c5f43SAlan Wright 760a90cf9f2SGordon Ross if ((rc != 0) && (tree->t_execflags & SMB_EXEC_TERM)) { 7618d94f651SGordon Ross /* 7628d94f651SGordon Ross * Inline parts of: smb_tree_disconnect() 7638d94f651SGordon Ross * Not using smb_tree_disconnect() for cleanup 7648d94f651SGordon Ross * here because: we don't want an exec up-call, 7658d94f651SGordon Ross * and there can't be any opens as we never 7668d94f651SGordon Ross * returned this TID to the client. 7678d94f651SGordon Ross */ 7688d94f651SGordon Ross mutex_enter(&tree->t_mutex); 7698d94f651SGordon Ross tree->t_state = SMB_TREE_STATE_DISCONNECTING; 7708d94f651SGordon Ross mutex_exit(&tree->t_mutex); 7718d94f651SGordon Ross 772a90cf9f2SGordon Ross smb_tree_release(tree); 773a90cf9f2SGordon Ross return (NT_STATUS_ACCESS_DENIED); 774148c5f43SAlan Wright } 775148c5f43SAlan Wright } 776148c5f43SAlan Wright 777a90cf9f2SGordon Ross sr->tid_tree = tree; 778a90cf9f2SGordon Ross sr->smb_tid = tree->t_tid; 779a90cf9f2SGordon Ross 780a90cf9f2SGordon Ross return (0); 781148c5f43SAlan Wright } 782148c5f43SAlan Wright 783148c5f43SAlan Wright /* 784148c5f43SAlan Wright * Shares have both a share and host based access control. The access 785148c5f43SAlan Wright * granted will be minimum permissions based on both hostaccess 786148c5f43SAlan Wright * (permissions allowed by host based access) and aclaccess (from the 787148c5f43SAlan Wright * share ACL). 788148c5f43SAlan Wright */ 789a90cf9f2SGordon Ross uint32_t 790a90cf9f2SGordon Ross smb_tree_connect_printq(smb_request_t *sr, smb_arg_tcon_t *tcon) 791148c5f43SAlan Wright { 792a90cf9f2SGordon Ross char *sharename = tcon->path; 793148c5f43SAlan Wright const char *any = "?????"; 794148c5f43SAlan Wright smb_user_t *user = sr->uid_user; 795148c5f43SAlan Wright smb_node_t *dnode = NULL; 796148c5f43SAlan Wright smb_node_t *snode = NULL; 797811599a4SMatt Barden smb_kshare_t *si = tcon->si; 798a90cf9f2SGordon Ross char *service = tcon->service; 799148c5f43SAlan Wright char last_component[MAXNAMELEN]; 800148c5f43SAlan Wright smb_tree_t *tree; 801148c5f43SAlan Wright int rc; 802148c5f43SAlan Wright uint32_t access; 803148c5f43SAlan Wright 804148c5f43SAlan Wright ASSERT(user); 805148c5f43SAlan Wright ASSERT(user->u_cred); 806148c5f43SAlan Wright 807b7301bf5SGordon Ross if (sr->sr_server->sv_cfg.skc_print_enable == 0) { 808b7301bf5SGordon Ross smb_tree_log(sr, sharename, "printing disabled"); 809a90cf9f2SGordon Ross return (NT_STATUS_BAD_NETWORK_NAME); 810b7301bf5SGordon Ross } 811b7301bf5SGordon Ross 812a90cf9f2SGordon Ross if (service != NULL && 813a90cf9f2SGordon Ross strcmp(service, any) != 0 && 814a90cf9f2SGordon Ross strcasecmp(service, "LPT1:") != 0) { 815148c5f43SAlan Wright smb_tree_log(sr, sharename, "invalid service (%s)", service); 816a90cf9f2SGordon Ross return (NT_STATUS_BAD_DEVICE_TYPE); 817b89a8333Snatalie li - Sun Microsystems - Irvine United States } 818b89a8333Snatalie li - Sun Microsystems - Irvine United States 819c8ec8eeaSjose borrego /* 820c8ec8eeaSjose borrego * Check that the shared directory exists. 821c8ec8eeaSjose borrego */ 822148c5f43SAlan Wright rc = smb_pathname_reduce(sr, user->u_cred, si->shr_path, 0, 0, &dnode, 823c8ec8eeaSjose borrego last_component); 824c8ec8eeaSjose borrego if (rc == 0) { 825148c5f43SAlan Wright rc = smb_fsop_lookup(sr, user->u_cred, SMB_FOLLOW_LINKS, 8261fcced4cSJordan Brown sr->sr_server->si_root_smb_node, dnode, last_component, 827037cac00Sjoyce mcintosh &snode); 828c8ec8eeaSjose borrego 8291fcced4cSJordan Brown smb_node_release(dnode); 830c8ec8eeaSjose borrego } 831c8ec8eeaSjose borrego 832c8ec8eeaSjose borrego if (rc) { 833c8ec8eeaSjose borrego if (snode) 834c8ec8eeaSjose borrego smb_node_release(snode); 835c8ec8eeaSjose borrego 836b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_tree_log(sr, sharename, "bad path: %s", si->shr_path); 837a90cf9f2SGordon Ross return (NT_STATUS_BAD_NETWORK_NAME); 838c8ec8eeaSjose borrego } 839c8ec8eeaSjose borrego 840148c5f43SAlan Wright if ((access = smb_tree_chkaccess(sr, si, snode->vp)) == 0) { 841037cac00Sjoyce mcintosh smb_node_release(snode); 842a90cf9f2SGordon Ross return (NT_STATUS_ACCESS_DENIED); 843743a77edSAlan Wright } 844743a77edSAlan Wright 845a90cf9f2SGordon Ross tcon->optional_support = SMB_SUPPORT_SEARCH_BITS; 8462c2961f8Sjose borrego 8473b13a1efSThomas Keiser tree = smb_tree_alloc(sr, si, snode, access, sr->sr_cfg->skc_execflags); 848b89a8333Snatalie li - Sun Microsystems - Irvine United States 84929bd2886SAlan Wright smb_node_release(snode); 85029bd2886SAlan Wright 851c8ec8eeaSjose borrego if (tree == NULL) 852a90cf9f2SGordon Ross return (NT_STATUS_INSUFF_SERVER_RESOURCES); 85329bd2886SAlan Wright 854a90cf9f2SGordon Ross sr->tid_tree = tree; 855a90cf9f2SGordon Ross sr->smb_tid = tree->t_tid; 856a90cf9f2SGordon Ross 857a90cf9f2SGordon Ross return (0); 858da6c28aaSamw } 859da6c28aaSamw 860da6c28aaSamw /* 861c8ec8eeaSjose borrego * Connect an IPC share for use with named pipes. 862da6c28aaSamw */ 863a90cf9f2SGordon Ross uint32_t 864a90cf9f2SGordon Ross smb_tree_connect_ipc(smb_request_t *sr, smb_arg_tcon_t *tcon) 865da6c28aaSamw { 866a90cf9f2SGordon Ross char *name = tcon->path; 867148c5f43SAlan Wright const char *any = "?????"; 8688b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_user_t *user = sr->uid_user; 8698b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_tree_t *tree; 870a90cf9f2SGordon Ross smb_kshare_t *si = tcon->si; 871a90cf9f2SGordon Ross char *service = tcon->service; 872da6c28aaSamw 873c8ec8eeaSjose borrego ASSERT(user); 874da6c28aaSamw 875a90cf9f2SGordon Ross if (service != NULL && 876a90cf9f2SGordon Ross strcmp(service, any) != 0 && 877a90cf9f2SGordon Ross strcasecmp(service, "IPC") != 0) { 878a90cf9f2SGordon Ross smb_tree_log(sr, name, "invalid service (%s)", service); 879a90cf9f2SGordon Ross return (NT_STATUS_BAD_DEVICE_TYPE); 880da6c28aaSamw } 881da6c28aaSamw 882a90cf9f2SGordon Ross if ((user->u_flags & SMB_USER_FLAG_ANON) && 883a90cf9f2SGordon Ross sr->sr_cfg->skc_restrict_anon) { 884a90cf9f2SGordon Ross smb_tree_log(sr, name, "access denied: restrict anonymous"); 885a90cf9f2SGordon Ross return (NT_STATUS_ACCESS_DENIED); 886148c5f43SAlan Wright } 8878d7e4166Sjose borrego 888a90cf9f2SGordon Ross tcon->optional_support = SMB_SUPPORT_SEARCH_BITS; 8898b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 8903b13a1efSThomas Keiser tree = smb_tree_alloc(sr, si, NULL, ACE_ALL_PERMS, 0); 891a90cf9f2SGordon Ross if (tree == NULL) 892a90cf9f2SGordon Ross return (NT_STATUS_INSUFF_SERVER_RESOURCES); 893c8ec8eeaSjose borrego 894a90cf9f2SGordon Ross sr->tid_tree = tree; 895a90cf9f2SGordon Ross sr->smb_tid = tree->t_tid; 896a90cf9f2SGordon Ross 897a90cf9f2SGordon Ross return (0); 898da6c28aaSamw } 899da6c28aaSamw 900da6c28aaSamw /* 901c8ec8eeaSjose borrego * Allocate a tree. 902da6c28aaSamw */ 9038d94f651SGordon Ross smb_tree_t * 9043b13a1efSThomas Keiser smb_tree_alloc(smb_request_t *sr, const smb_kshare_t *si, 9053b13a1efSThomas Keiser smb_node_t *snode, uint32_t access, uint32_t execflags) 906da6c28aaSamw { 9073b13a1efSThomas Keiser smb_session_t *session = sr->session; 908c8ec8eeaSjose borrego smb_tree_t *tree; 909148c5f43SAlan Wright uint32_t stype = si->shr_type; 910c8ec8eeaSjose borrego uint16_t tid; 911da6c28aaSamw 9123b13a1efSThomas Keiser if (smb_idpool_alloc(&session->s_tid_pool, &tid)) 913c8ec8eeaSjose borrego return (NULL); 914da6c28aaSamw 9158622ec45SGordon Ross tree = kmem_cache_alloc(smb_cache_tree, KM_SLEEP); 916c8ec8eeaSjose borrego bzero(tree, sizeof (smb_tree_t)); 917da6c28aaSamw 9183b13a1efSThomas Keiser tree->t_session = session; 9193b13a1efSThomas Keiser tree->t_server = session->s_server; 9203b13a1efSThomas Keiser 921148c5f43SAlan Wright if (STYPE_ISDSK(stype) || STYPE_ISPRN(stype)) { 9228b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (smb_tree_getattr(si, snode, tree) != 0) { 9233b13a1efSThomas Keiser smb_idpool_free(&session->s_tid_pool, tid); 9248622ec45SGordon Ross kmem_cache_free(smb_cache_tree, tree); 925c8ec8eeaSjose borrego return (NULL); 926da6c28aaSamw } 927da6c28aaSamw } 928c8ec8eeaSjose borrego 929c8ec8eeaSjose borrego if (smb_idpool_constructor(&tree->t_fid_pool)) { 9303b13a1efSThomas Keiser smb_idpool_free(&session->s_tid_pool, tid); 9318622ec45SGordon Ross kmem_cache_free(smb_cache_tree, tree); 932c8ec8eeaSjose borrego return (NULL); 933c8ec8eeaSjose borrego } 934c8ec8eeaSjose borrego 9357f667e74Sjose borrego if (smb_idpool_constructor(&tree->t_odid_pool)) { 936c8ec8eeaSjose borrego smb_idpool_destructor(&tree->t_fid_pool); 9373b13a1efSThomas Keiser smb_idpool_free(&session->s_tid_pool, tid); 9388622ec45SGordon Ross kmem_cache_free(smb_cache_tree, tree); 939c8ec8eeaSjose borrego return (NULL); 940c8ec8eeaSjose borrego } 941c8ec8eeaSjose borrego 942c8ec8eeaSjose borrego smb_llist_constructor(&tree->t_ofile_list, sizeof (smb_ofile_t), 943811599a4SMatt Barden offsetof(smb_ofile_t, f_tree_lnd)); 944c8ec8eeaSjose borrego 945c8ec8eeaSjose borrego smb_llist_constructor(&tree->t_odir_list, sizeof (smb_odir_t), 946c8ec8eeaSjose borrego offsetof(smb_odir_t, d_lnd)); 947c8ec8eeaSjose borrego 9488b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States (void) strlcpy(tree->t_sharename, si->shr_name, 949c8ec8eeaSjose borrego sizeof (tree->t_sharename)); 9508b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States (void) strlcpy(tree->t_resource, si->shr_path, 9518b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States sizeof (tree->t_resource)); 952c8ec8eeaSjose borrego 953c8ec8eeaSjose borrego mutex_init(&tree->t_mutex, NULL, MUTEX_DEFAULT, NULL); 954c8ec8eeaSjose borrego 955c8ec8eeaSjose borrego tree->t_refcnt = 1; 956c8ec8eeaSjose borrego tree->t_tid = tid; 957c8ec8eeaSjose borrego tree->t_res_type = stype; 958c8ec8eeaSjose borrego tree->t_state = SMB_TREE_STATE_CONNECTED; 959c8ec8eeaSjose borrego tree->t_magic = SMB_TREE_MAGIC; 960743a77edSAlan Wright tree->t_access = access; 9611fcced4cSJordan Brown tree->t_connect_time = gethrestime_sec(); 962148c5f43SAlan Wright tree->t_execflags = execflags; 963743a77edSAlan Wright 964*af536d7dSGordon Ross /* grab a ref for tree->t_owner */ 965*af536d7dSGordon Ross smb_user_hold_internal(sr->uid_user); 966*af536d7dSGordon Ross tree->t_owner = sr->uid_user; 967*af536d7dSGordon Ross 968743a77edSAlan Wright /* if FS is readonly, enforce that here */ 969743a77edSAlan Wright if (tree->t_flags & SMB_TREE_READONLY) 970743a77edSAlan Wright tree->t_access &= ~ACE_ALL_WRITE_PERMS; 971c8ec8eeaSjose borrego 972148c5f43SAlan Wright if (STYPE_ISDSK(stype) || STYPE_ISPRN(stype)) { 973c8ec8eeaSjose borrego smb_node_ref(snode); 974c8ec8eeaSjose borrego tree->t_snode = snode; 975c8ec8eeaSjose borrego tree->t_acltype = smb_fsop_acltype(snode); 976c8ec8eeaSjose borrego } 977c8ec8eeaSjose borrego 9783b13a1efSThomas Keiser smb_llist_enter(&session->s_tree_list, RW_WRITER); 9793b13a1efSThomas Keiser smb_llist_insert_head(&session->s_tree_list, tree); 9803b13a1efSThomas Keiser smb_llist_exit(&session->s_tree_list); 9813b13a1efSThomas Keiser atomic_inc_32(&session->s_tree_cnt); 9823b13a1efSThomas Keiser smb_server_inc_trees(session->s_server); 983c8ec8eeaSjose borrego return (tree); 984c8ec8eeaSjose borrego } 985da6c28aaSamw 986da6c28aaSamw /* 9879fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Deallocate a tree. The open file and open directory lists should be 9889fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * empty. 989c8ec8eeaSjose borrego * 9909fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Remove the tree from the user's tree list before freeing resources 9919fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * associated with the tree. 992da6c28aaSamw */ 993811599a4SMatt Barden static void 9949fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_tree_dealloc(void *arg) 995da6c28aaSamw { 9963b13a1efSThomas Keiser smb_session_t *session; 9979fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_tree_t *tree = (smb_tree_t *)arg; 9989fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 9999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_TREE_VALID(tree); 1000da6c28aaSamw ASSERT(tree->t_state == SMB_TREE_STATE_DISCONNECTED); 1001da6c28aaSamw ASSERT(tree->t_refcnt == 0); 1002da6c28aaSamw 10038d94f651SGordon Ross smb_server_dec_trees(tree->t_server); 10048d94f651SGordon Ross 10053b13a1efSThomas Keiser session = tree->t_session; 10063b13a1efSThomas Keiser smb_llist_enter(&session->s_tree_list, RW_WRITER); 10073b13a1efSThomas Keiser smb_llist_remove(&session->s_tree_list, tree); 10083b13a1efSThomas Keiser smb_idpool_free(&session->s_tid_pool, tree->t_tid); 10093b13a1efSThomas Keiser atomic_dec_32(&session->s_tree_cnt); 10103b13a1efSThomas Keiser smb_llist_exit(&session->s_tree_list); 10119fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 1012811599a4SMatt Barden /* 1013811599a4SMatt Barden * This tree is no longer on s_tree_list, however... 1014811599a4SMatt Barden * 1015811599a4SMatt Barden * This is called via smb_llist_post, which means it may run 1016811599a4SMatt Barden * BEFORE smb_tree_release drops t_mutex (if another thread 1017811599a4SMatt Barden * flushes the delete queue before we do). Synchronize. 1018811599a4SMatt Barden */ 10199fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States mutex_enter(&tree->t_mutex); 10209fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States mutex_exit(&tree->t_mutex); 1021da6c28aaSamw 1022da6c28aaSamw tree->t_magic = (uint32_t)~SMB_TREE_MAGIC; 1023da6c28aaSamw 1024c8ec8eeaSjose borrego if (tree->t_snode) 1025da6c28aaSamw smb_node_release(tree->t_snode); 1026c8ec8eeaSjose borrego 1027da6c28aaSamw mutex_destroy(&tree->t_mutex); 1028da6c28aaSamw smb_llist_destructor(&tree->t_ofile_list); 1029da6c28aaSamw smb_llist_destructor(&tree->t_odir_list); 1030da6c28aaSamw smb_idpool_destructor(&tree->t_fid_pool); 10317f667e74Sjose borrego smb_idpool_destructor(&tree->t_odid_pool); 10323b13a1efSThomas Keiser 10333b13a1efSThomas Keiser SMB_USER_VALID(tree->t_owner); 10343b13a1efSThomas Keiser smb_user_release(tree->t_owner); 10353b13a1efSThomas Keiser 10368622ec45SGordon Ross kmem_cache_free(smb_cache_tree, tree); 1037da6c28aaSamw } 1038da6c28aaSamw 1039da6c28aaSamw /* 1040c8ec8eeaSjose borrego * Determine whether or not a tree is connected. 1041c8ec8eeaSjose borrego * This function must be called with the tree mutex held. 1042c8ec8eeaSjose borrego */ 1043c8ec8eeaSjose borrego static boolean_t 10448b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_tree_is_connected_locked(smb_tree_t *tree) 1045c8ec8eeaSjose borrego { 1046c8ec8eeaSjose borrego switch (tree->t_state) { 1047c8ec8eeaSjose borrego case SMB_TREE_STATE_CONNECTED: 1048c8ec8eeaSjose borrego return (B_TRUE); 1049c8ec8eeaSjose borrego 1050c8ec8eeaSjose borrego case SMB_TREE_STATE_DISCONNECTING: 1051c8ec8eeaSjose borrego case SMB_TREE_STATE_DISCONNECTED: 1052c8ec8eeaSjose borrego /* 1053811599a4SMatt Barden * The tree exists but is being disconnected or destroyed. 1054c8ec8eeaSjose borrego */ 1055c8ec8eeaSjose borrego return (B_FALSE); 1056c8ec8eeaSjose borrego 1057c8ec8eeaSjose borrego default: 1058c8ec8eeaSjose borrego ASSERT(0); 1059c8ec8eeaSjose borrego return (B_FALSE); 1060c8ec8eeaSjose borrego } 1061c8ec8eeaSjose borrego } 1062c8ec8eeaSjose borrego 1063c8ec8eeaSjose borrego /* 1064c8ec8eeaSjose borrego * Return a pointer to the share name within a share resource path. 1065da6c28aaSamw * 1066c8ec8eeaSjose borrego * The share path may be a Uniform Naming Convention (UNC) string 1067c8ec8eeaSjose borrego * (\\server\share) or simply the share name. We validate the UNC 1068c8ec8eeaSjose borrego * format but we don't look at the server name. 1069c8ec8eeaSjose borrego */ 1070a90cf9f2SGordon Ross static char * 1071a90cf9f2SGordon Ross smb_tree_get_sharename(char *unc_path) 1072c8ec8eeaSjose borrego { 1073a90cf9f2SGordon Ross char *sharename = unc_path; 1074c8ec8eeaSjose borrego 1075c8ec8eeaSjose borrego if (sharename[0] == '\\') { 1076c8ec8eeaSjose borrego /* 1077c8ec8eeaSjose borrego * Looks like a UNC path, validate the format. 1078c8ec8eeaSjose borrego */ 1079c8ec8eeaSjose borrego if (sharename[1] != '\\') 1080c8ec8eeaSjose borrego return (NULL); 1081c8ec8eeaSjose borrego 1082c8ec8eeaSjose borrego if ((sharename = strchr(sharename+2, '\\')) == NULL) 1083c8ec8eeaSjose borrego return (NULL); 1084c8ec8eeaSjose borrego 1085c8ec8eeaSjose borrego ++sharename; 1086c8ec8eeaSjose borrego } else if (strchr(sharename, '\\') != NULL) { 1087c8ec8eeaSjose borrego /* 1088c8ec8eeaSjose borrego * This should be a share name (no embedded \'s). 1089c8ec8eeaSjose borrego */ 1090c8ec8eeaSjose borrego return (NULL); 1091c8ec8eeaSjose borrego } 1092c8ec8eeaSjose borrego 1093c8ec8eeaSjose borrego return (sharename); 1094c8ec8eeaSjose borrego } 1095c8ec8eeaSjose borrego 1096da6c28aaSamw /* 1097c8ec8eeaSjose borrego * Obtain the tree attributes: volume name, typename and flags. 1098c8ec8eeaSjose borrego */ 1099c8ec8eeaSjose borrego static int 1100148c5f43SAlan Wright smb_tree_getattr(const smb_kshare_t *si, smb_node_t *node, smb_tree_t *tree) 1101c8ec8eeaSjose borrego { 1102c8ec8eeaSjose borrego vfs_t *vfsp = SMB_NODE_VFS(node); 1103*af536d7dSGordon Ross vfs_t *realvfsp; 11041160dcf7SMatt Barden smb_cfg_val_t srv_encrypt; 1105c8ec8eeaSjose borrego 1106c8ec8eeaSjose borrego ASSERT(vfsp); 1107c8ec8eeaSjose borrego 110825a9a7aaSGordon Ross smb_tree_get_creation(node, tree); 1109c8ec8eeaSjose borrego smb_tree_get_volname(vfsp, tree); 1110*af536d7dSGordon Ross 1111*af536d7dSGordon Ross /* 1112*af536d7dSGordon Ross * In the case of an lofs mount, we need to ask the (real) 1113*af536d7dSGordon Ross * underlying filesystem about capabilities, where the 1114*af536d7dSGordon Ross * passed in vfs_t will be from lofs. 1115*af536d7dSGordon Ross */ 1116*af536d7dSGordon Ross realvfsp = getvfs(&vfsp->vfs_fsid); 1117*af536d7dSGordon Ross if (realvfsp != NULL) { 1118*af536d7dSGordon Ross smb_tree_get_flags(si, realvfsp, tree); 1119*af536d7dSGordon Ross VFS_RELE(realvfsp); 1120*af536d7dSGordon Ross } else { 1121*af536d7dSGordon Ross cmn_err(CE_NOTE, "Failed getting info for share: %s", 1122*af536d7dSGordon Ross si->shr_name); 1123*af536d7dSGordon Ross /* do the best we can without realvfsp */ 1124*af536d7dSGordon Ross smb_tree_get_flags(si, vfsp, tree); 1125*af536d7dSGordon Ross } 1126c8ec8eeaSjose borrego 11271160dcf7SMatt Barden srv_encrypt = tree->t_session->s_server->sv_cfg.skc_encrypt; 11281160dcf7SMatt Barden if (tree->t_session->dialect >= SMB_VERS_3_0) { 11291160dcf7SMatt Barden if (si->shr_encrypt == SMB_CONFIG_REQUIRED || 11301160dcf7SMatt Barden srv_encrypt == SMB_CONFIG_REQUIRED) 11311160dcf7SMatt Barden tree->t_encrypt = SMB_CONFIG_REQUIRED; 11321160dcf7SMatt Barden else if (si->shr_encrypt == SMB_CONFIG_ENABLED || 11331160dcf7SMatt Barden srv_encrypt == SMB_CONFIG_ENABLED) 11341160dcf7SMatt Barden tree->t_encrypt = SMB_CONFIG_ENABLED; 11351160dcf7SMatt Barden else 11361160dcf7SMatt Barden tree->t_encrypt = SMB_CONFIG_DISABLED; 11371160dcf7SMatt Barden } else 11381160dcf7SMatt Barden tree->t_encrypt = SMB_CONFIG_DISABLED; 11391160dcf7SMatt Barden 1140c8ec8eeaSjose borrego return (0); 1141c8ec8eeaSjose borrego } 1142c8ec8eeaSjose borrego 114325a9a7aaSGordon Ross /* 114425a9a7aaSGordon Ross * File volume creation time 114525a9a7aaSGordon Ross */ 114625a9a7aaSGordon Ross static void 114725a9a7aaSGordon Ross smb_tree_get_creation(smb_node_t *node, smb_tree_t *tree) 114825a9a7aaSGordon Ross { 114925a9a7aaSGordon Ross smb_attr_t attr; 115025a9a7aaSGordon Ross cred_t *kcr = zone_kcred(); 115125a9a7aaSGordon Ross 115225a9a7aaSGordon Ross bzero(&attr, sizeof (attr)); 115325a9a7aaSGordon Ross attr.sa_mask = SMB_AT_CRTIME; 115425a9a7aaSGordon Ross (void) smb_node_getattr(NULL, node, kcr, NULL, &attr); 115525a9a7aaSGordon Ross /* On failure we'll have time zero, which is OK */ 115625a9a7aaSGordon Ross 115725a9a7aaSGordon Ross tree->t_create_time = attr.sa_crtime; 115825a9a7aaSGordon Ross } 115925a9a7aaSGordon Ross 1160c8ec8eeaSjose borrego /* 1161c8ec8eeaSjose borrego * Extract the volume name. 1162c8ec8eeaSjose borrego */ 1163c8ec8eeaSjose borrego static void 1164c8ec8eeaSjose borrego smb_tree_get_volname(vfs_t *vfsp, smb_tree_t *tree) 1165c8ec8eeaSjose borrego { 1166a90cf9f2SGordon Ross #ifdef _FAKE_KERNEL 1167a90cf9f2SGordon Ross _NOTE(ARGUNUSED(vfsp)) 1168a90cf9f2SGordon Ross (void) strlcpy(tree->t_volume, "fake", SMB_VOLNAMELEN); 1169a90cf9f2SGordon Ross #else /* _FAKE_KERNEL */ 1170c8ec8eeaSjose borrego refstr_t *vfs_mntpoint; 1171c8ec8eeaSjose borrego const char *s; 1172c8ec8eeaSjose borrego char *name; 1173c8ec8eeaSjose borrego 1174c8ec8eeaSjose borrego vfs_mntpoint = vfs_getmntpoint(vfsp); 1175c8ec8eeaSjose borrego 1176b819cea2SGordon Ross s = refstr_value(vfs_mntpoint); 1177c8ec8eeaSjose borrego s += strspn(s, "/"); 1178c8ec8eeaSjose borrego (void) strlcpy(tree->t_volume, s, SMB_VOLNAMELEN); 1179c8ec8eeaSjose borrego 1180c8ec8eeaSjose borrego refstr_rele(vfs_mntpoint); 1181c8ec8eeaSjose borrego 1182c8ec8eeaSjose borrego name = tree->t_volume; 1183c8ec8eeaSjose borrego (void) strsep((char **)&name, "/"); 1184a90cf9f2SGordon Ross #endif /* _FAKE_KERNEL */ 1185c8ec8eeaSjose borrego } 1186c8ec8eeaSjose borrego 1187c8ec8eeaSjose borrego /* 1188a90cf9f2SGordon Ross * Always set "unicode on disk" because we always use utf8 names locally. 1189c8ec8eeaSjose borrego * Always set ACL support because the VFS will fake ACLs for file systems 1190c8ec8eeaSjose borrego * that don't support them. 1191da6c28aaSamw * 1192c8ec8eeaSjose borrego * Some flags are dependent on the typename, which is also set up here. 1193c8ec8eeaSjose borrego * File system types are hardcoded in uts/common/os/vfs_conf.c. 1194da6c28aaSamw */ 1195c8ec8eeaSjose borrego static void 1196148c5f43SAlan Wright smb_tree_get_flags(const smb_kshare_t *si, vfs_t *vfsp, smb_tree_t *tree) 1197da6c28aaSamw { 11985f1ef25cSAram Hăvărneanu smb_session_t *ssn = tree->t_session; 1199b819cea2SGordon Ross struct vfssw *vswp; 12005f1ef25cSAram Hăvărneanu 1201fc724630SAlan Wright typedef struct smb_mtype { 1202fc724630SAlan Wright char *mt_name; 1203fc724630SAlan Wright size_t mt_namelen; 1204fc724630SAlan Wright uint32_t mt_flags; 1205fc724630SAlan Wright } smb_mtype_t; 1206fc724630SAlan Wright 1207fc724630SAlan Wright static smb_mtype_t smb_mtype[] = { 120855f0a249SGordon Ross #ifdef _FAKE_KERNEL 120955f0a249SGordon Ross /* See libfksmbsrv:fake_vfs.c */ 121055f0a249SGordon Ross { "fake", 3, SMB_TREE_SPARSE}, 121155f0a249SGordon Ross #endif /* _FAKE_KERNEL */ 1212a90cf9f2SGordon Ross { "zfs", 3, SMB_TREE_QUOTA | SMB_TREE_SPARSE}, 1213a90cf9f2SGordon Ross { "ufs", 3, 0 }, 12149fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States { "nfs", 3, SMB_TREE_NFS_MOUNTED }, 12159fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States { "tmpfs", 5, SMB_TREE_NO_EXPORT } 1216fc724630SAlan Wright }; 1217fc724630SAlan Wright smb_mtype_t *mtype; 1218fc724630SAlan Wright char *name; 1219a90cf9f2SGordon Ross uint32_t flags = 1220a90cf9f2SGordon Ross SMB_TREE_SUPPORTS_ACLS | 1221a90cf9f2SGordon Ross SMB_TREE_UNICODE_ON_DISK; 1222fc724630SAlan Wright int i; 1223da6c28aaSamw 12249fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (si->shr_flags & SMB_SHRF_DFSROOT) 12259fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States flags |= SMB_TREE_DFSROOT; 12269fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 12278b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (si->shr_flags & SMB_SHRF_CATIA) 12288b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States flags |= SMB_TREE_CATIA; 12298b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 1230e3f2c991SKeyur Desai if (si->shr_flags & SMB_SHRF_ABE) 1231e3f2c991SKeyur Desai flags |= SMB_TREE_ABE; 1232e3f2c991SKeyur Desai 12338d94f651SGordon Ross if (si->shr_flags & SMB_SHRF_CA) 12348d94f651SGordon Ross flags |= SMB_TREE_CA; 12358d94f651SGordon Ross 123694047d49SGordon Ross if (si->shr_flags & SMB_SHRF_FSO) 123794047d49SGordon Ross flags |= SMB_TREE_FORCE_L2_OPLOCK; 123894047d49SGordon Ross 12395f1ef25cSAram Hăvărneanu if (ssn->s_cfg.skc_oplock_enable) { 1240cb174861Sjoyce mcintosh /* if 'smb' zfs property: oplocks=enabled */ 1241cb174861Sjoyce mcintosh flags |= SMB_TREE_OPLOCKS; 1242cb174861Sjoyce mcintosh } 1243cb174861Sjoyce mcintosh 12445f1ef25cSAram Hăvărneanu /* Global config option for now. Later make per-share. */ 12455f1ef25cSAram Hăvărneanu if (ssn->s_cfg.skc_traverse_mounts) 12465f1ef25cSAram Hăvărneanu flags |= SMB_TREE_TRAVERSE_MOUNTS; 12475f1ef25cSAram Hăvărneanu 1248cb174861Sjoyce mcintosh /* if 'smb' zfs property: shortnames=enabled */ 1249cb174861Sjoyce mcintosh if (smb_shortnames) 1250cb174861Sjoyce mcintosh flags |= SMB_TREE_SHORTNAMES; 1251cb174861Sjoyce mcintosh 1252c8ec8eeaSjose borrego if (vfsp->vfs_flag & VFS_RDONLY) 1253c8ec8eeaSjose borrego flags |= SMB_TREE_READONLY; 1254c8ec8eeaSjose borrego 1255c8ec8eeaSjose borrego if (vfsp->vfs_flag & VFS_XATTR) 1256c8ec8eeaSjose borrego flags |= SMB_TREE_STREAMS; 1257c8ec8eeaSjose borrego 1258b819cea2SGordon Ross vswp = vfs_getvfsswbyvfsops(vfs_getops(vfsp)); 1259b819cea2SGordon Ross if (vswp != NULL) { 1260b819cea2SGordon Ross name = vswp->vsw_name; 1261b819cea2SGordon Ross vfs_unrefvfssw(vswp); 1262b819cea2SGordon Ross } else { 1263b819cea2SGordon Ross name = "?"; 1264b819cea2SGordon Ross } 1265c8ec8eeaSjose borrego 1266fc724630SAlan Wright for (i = 0; i < sizeof (smb_mtype) / sizeof (smb_mtype[0]); ++i) { 1267fc724630SAlan Wright mtype = &smb_mtype[i]; 1268fc724630SAlan Wright if (strncasecmp(name, mtype->mt_name, mtype->mt_namelen) == 0) 1269fc724630SAlan Wright flags |= mtype->mt_flags; 1270fc724630SAlan Wright } 1271c8ec8eeaSjose borrego 1272ca5fb90aSGordon Ross /* 1273ca5fb90aSGordon Ross * SMB_TREE_QUOTA will be on here if the FS is ZFS. We want to 1274ca5fb90aSGordon Ross * turn it OFF when the share property says false. 1275ca5fb90aSGordon Ross */ 1276ca5fb90aSGordon Ross if ((si->shr_flags & SMB_SHRF_QUOTAS) == 0) 1277ca5fb90aSGordon Ross flags &= ~SMB_TREE_QUOTA; 1278ca5fb90aSGordon Ross 1279c8ec8eeaSjose borrego (void) strlcpy(tree->t_typename, name, SMB_TYPENAMELEN); 1280bbf6f00cSJordan Brown (void) smb_strupr((char *)tree->t_typename); 1281da6c28aaSamw 1282c8ec8eeaSjose borrego if (vfs_has_feature(vfsp, VFSFT_XVATTR)) 1283c8ec8eeaSjose borrego flags |= SMB_TREE_XVATTR; 1284c8ec8eeaSjose borrego 1285c8ec8eeaSjose borrego if (vfs_has_feature(vfsp, VFSFT_CASEINSENSITIVE)) 1286c8ec8eeaSjose borrego flags |= SMB_TREE_CASEINSENSITIVE; 1287c8ec8eeaSjose borrego 1288c8ec8eeaSjose borrego if (vfs_has_feature(vfsp, VFSFT_NOCASESENSITIVE)) 1289c8ec8eeaSjose borrego flags |= SMB_TREE_NO_CASESENSITIVE; 1290c8ec8eeaSjose borrego 1291c8ec8eeaSjose borrego if (vfs_has_feature(vfsp, VFSFT_DIRENTFLAGS)) 1292c8ec8eeaSjose borrego flags |= SMB_TREE_DIRENTFLAGS; 1293c8ec8eeaSjose borrego 1294c8ec8eeaSjose borrego if (vfs_has_feature(vfsp, VFSFT_ACLONCREATE)) 1295c8ec8eeaSjose borrego flags |= SMB_TREE_ACLONCREATE; 1296c8ec8eeaSjose borrego 1297c8ec8eeaSjose borrego if (vfs_has_feature(vfsp, VFSFT_ACEMASKONACCESS)) 1298c8ec8eeaSjose borrego flags |= SMB_TREE_ACEMASKONACCESS; 1299c8ec8eeaSjose borrego 1300fc724630SAlan Wright DTRACE_PROBE2(smb__tree__flags, uint32_t, flags, char *, name); 1301fc724630SAlan Wright 1302c8ec8eeaSjose borrego 1303c8ec8eeaSjose borrego tree->t_flags = flags; 1304c8ec8eeaSjose borrego } 1305c8ec8eeaSjose borrego 1306c8ec8eeaSjose borrego /* 1307c8ec8eeaSjose borrego * Report share access result to syslog. 1308c8ec8eeaSjose borrego */ 1309c8ec8eeaSjose borrego static void 1310c8ec8eeaSjose borrego smb_tree_log(smb_request_t *sr, const char *sharename, const char *fmt, ...) 1311c8ec8eeaSjose borrego { 1312c8ec8eeaSjose borrego va_list ap; 1313c8ec8eeaSjose borrego char buf[128]; 1314c8ec8eeaSjose borrego smb_user_t *user = sr->uid_user; 1315c8ec8eeaSjose borrego 1316c8ec8eeaSjose borrego ASSERT(user); 1317c8ec8eeaSjose borrego 1318c8ec8eeaSjose borrego if (smb_tcon_mute) 1319c8ec8eeaSjose borrego return; 1320c8ec8eeaSjose borrego 1321c8ec8eeaSjose borrego if ((user->u_name) && (strcasecmp(sharename, "IPC$") == 0)) { 1322c8ec8eeaSjose borrego /* 1323c8ec8eeaSjose borrego * Only report normal users, i.e. ignore W2K misuse 1324c8ec8eeaSjose borrego * of the IPC connection by filtering out internal 1325c8ec8eeaSjose borrego * names such as nobody and root. 1326c8ec8eeaSjose borrego */ 1327c8ec8eeaSjose borrego if ((strcmp(user->u_name, "root") == 0) || 1328c8ec8eeaSjose borrego (strcmp(user->u_name, "nobody") == 0)) { 1329c8ec8eeaSjose borrego return; 1330da6c28aaSamw } 1331da6c28aaSamw } 1332da6c28aaSamw 1333c8ec8eeaSjose borrego va_start(ap, fmt); 1334c8ec8eeaSjose borrego (void) vsnprintf(buf, 128, fmt, ap); 1335c8ec8eeaSjose borrego va_end(ap); 1336c8ec8eeaSjose borrego 1337c8ec8eeaSjose borrego cmn_err(CE_NOTE, "smbd[%s\\%s]: %s %s", 1338c8ec8eeaSjose borrego user->u_domain, user->u_name, sharename, buf); 1339da6c28aaSamw } 13407f667e74Sjose borrego 13417f667e74Sjose borrego /* 13427f667e74Sjose borrego * smb_tree_lookup_odir 13437f667e74Sjose borrego * 13447f667e74Sjose borrego * Find the specified odir in the tree's list of odirs, and 13457f667e74Sjose borrego * attempt to obtain a hold on the odir. 13467f667e74Sjose borrego * 13477f667e74Sjose borrego * Returns NULL if odir not found or a hold cannot be obtained. 13487f667e74Sjose borrego */ 13497f667e74Sjose borrego smb_odir_t * 13503b13a1efSThomas Keiser smb_tree_lookup_odir(smb_request_t *sr, uint16_t odid) 13517f667e74Sjose borrego { 13527f667e74Sjose borrego smb_odir_t *od; 13537f667e74Sjose borrego smb_llist_t *od_list; 13543b13a1efSThomas Keiser smb_tree_t *tree = sr->tid_tree; 13557f667e74Sjose borrego 13567f667e74Sjose borrego ASSERT(tree->t_magic == SMB_TREE_MAGIC); 13577f667e74Sjose borrego 13587f667e74Sjose borrego od_list = &tree->t_odir_list; 13597f667e74Sjose borrego 13603b13a1efSThomas Keiser smb_llist_enter(od_list, RW_READER); 13617f667e74Sjose borrego od = smb_llist_head(od_list); 13627f667e74Sjose borrego while (od) { 13633b13a1efSThomas Keiser if (od->d_odid == odid) 13647f667e74Sjose borrego break; 13657f667e74Sjose borrego od = smb_llist_next(od_list, od); 13667f667e74Sjose borrego } 13673b13a1efSThomas Keiser if (od == NULL) 13683b13a1efSThomas Keiser goto out; 13693b13a1efSThomas Keiser 13703b13a1efSThomas Keiser /* 13713b13a1efSThomas Keiser * Only allow use of a given Search ID with the same UID that 13723b13a1efSThomas Keiser * was used to create it. MS-CIFS 3.3.5.14 13733b13a1efSThomas Keiser */ 13743b13a1efSThomas Keiser if (od->d_user != sr->uid_user) { 13753b13a1efSThomas Keiser od = NULL; 13763b13a1efSThomas Keiser goto out; 13773b13a1efSThomas Keiser } 13783b13a1efSThomas Keiser if (!smb_odir_hold(od)) 13793b13a1efSThomas Keiser od = NULL; 13807f667e74Sjose borrego 13813b13a1efSThomas Keiser out: 13827f667e74Sjose borrego smb_llist_exit(od_list); 13837f667e74Sjose borrego return (od); 13847f667e74Sjose borrego } 13857f667e74Sjose borrego 13868b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States boolean_t 13878b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_tree_is_connected(smb_tree_t *tree) 13888b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States { 13898b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States boolean_t rb; 13908b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 13918b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States mutex_enter(&tree->t_mutex); 13928b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States rb = smb_tree_is_connected_locked(tree); 13938b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States mutex_exit(&tree->t_mutex); 13948b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States return (rb); 13958b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States } 13968b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 13977f667e74Sjose borrego /* 13987f667e74Sjose borrego * smb_tree_close_odirs 13997f667e74Sjose borrego * 14007f667e74Sjose borrego * Close all open odirs in the tree's list which were opened by 14017f667e74Sjose borrego * the process identified by pid. 14027f667e74Sjose borrego * If pid is zero, close all open odirs in the tree's list. 14037f667e74Sjose borrego */ 14047f667e74Sjose borrego static void 14058d94f651SGordon Ross smb_tree_close_odirs(smb_tree_t *tree, uint32_t pid) 14067f667e74Sjose borrego { 14078d94f651SGordon Ross smb_llist_t *od_list; 14088d94f651SGordon Ross smb_odir_t *od; 14097f667e74Sjose borrego 14107f667e74Sjose borrego ASSERT(tree); 14117f667e74Sjose borrego ASSERT(tree->t_magic == SMB_TREE_MAGIC); 14127f667e74Sjose borrego 14138d94f651SGordon Ross od_list = &tree->t_odir_list; 14148d94f651SGordon Ross smb_llist_enter(od_list, RW_READER); 14158d94f651SGordon Ross 14168d94f651SGordon Ross for (od = smb_llist_head(od_list); 14178d94f651SGordon Ross od != NULL; 14188d94f651SGordon Ross od = smb_llist_next(od_list, od)) { 14198d94f651SGordon Ross 14207f667e74Sjose borrego ASSERT(od->d_magic == SMB_ODIR_MAGIC); 14217f667e74Sjose borrego ASSERT(od->d_tree == tree); 14227f667e74Sjose borrego 14238d94f651SGordon Ross if (pid != 0 && od->d_opened_by_pid != pid) 14248d94f651SGordon Ross continue; 14257f667e74Sjose borrego 14268d94f651SGordon Ross if (smb_odir_hold(od)) { 14278d94f651SGordon Ross smb_odir_close(od); 14288d94f651SGordon Ross smb_odir_release(od); 14298d94f651SGordon Ross } 14307f667e74Sjose borrego } 14318d94f651SGordon Ross 14328d94f651SGordon Ross smb_llist_exit(od_list); 14337f667e74Sjose borrego } 143429bd2886SAlan Wright 143529bd2886SAlan Wright static void 14363b13a1efSThomas Keiser smb_tree_set_execinfo(smb_tree_t *tree, smb_shr_execinfo_t *exec, 14373b13a1efSThomas Keiser int exec_type) 143829bd2886SAlan Wright { 1439148c5f43SAlan Wright exec->e_sharename = tree->t_sharename; 14403b13a1efSThomas Keiser exec->e_winname = tree->t_owner->u_name; 14413b13a1efSThomas Keiser exec->e_userdom = tree->t_owner->u_domain; 1442148c5f43SAlan Wright exec->e_srv_ipaddr = tree->t_session->local_ipaddr; 1443148c5f43SAlan Wright exec->e_cli_ipaddr = tree->t_session->ipaddr; 1444148c5f43SAlan Wright exec->e_cli_netbiosname = tree->t_session->workstation; 14453b13a1efSThomas Keiser exec->e_uid = crgetuid(tree->t_owner->u_cred); 1446148c5f43SAlan Wright exec->e_type = exec_type; 144729bd2886SAlan Wright } 14481fcced4cSJordan Brown 14491fcced4cSJordan Brown /* 14501fcced4cSJordan Brown * Private function to support smb_tree_enum. 14511fcced4cSJordan Brown */ 14521fcced4cSJordan Brown static int 14531fcced4cSJordan Brown smb_tree_enum_private(smb_tree_t *tree, smb_svcenum_t *svcenum) 14541fcced4cSJordan Brown { 14551fcced4cSJordan Brown uint8_t *pb; 14561fcced4cSJordan Brown uint_t nbytes; 14571fcced4cSJordan Brown int rc; 14581fcced4cSJordan Brown 14591fcced4cSJordan Brown if (svcenum->se_nskip > 0) { 14601fcced4cSJordan Brown svcenum->se_nskip--; 14611fcced4cSJordan Brown return (0); 14621fcced4cSJordan Brown } 14631fcced4cSJordan Brown 14641fcced4cSJordan Brown if (svcenum->se_nitems >= svcenum->se_nlimit) { 14651fcced4cSJordan Brown svcenum->se_nitems = svcenum->se_nlimit; 14661fcced4cSJordan Brown return (0); 14671fcced4cSJordan Brown } 14681fcced4cSJordan Brown 14691fcced4cSJordan Brown pb = &svcenum->se_buf[svcenum->se_bused]; 14701fcced4cSJordan Brown rc = smb_tree_netinfo_encode(tree, pb, svcenum->se_bavail, &nbytes); 14711fcced4cSJordan Brown if (rc == 0) { 14721fcced4cSJordan Brown svcenum->se_bavail -= nbytes; 14731fcced4cSJordan Brown svcenum->se_bused += nbytes; 14741fcced4cSJordan Brown svcenum->se_nitems++; 14751fcced4cSJordan Brown } 14761fcced4cSJordan Brown 14771fcced4cSJordan Brown return (rc); 14781fcced4cSJordan Brown } 14791fcced4cSJordan Brown 14801fcced4cSJordan Brown /* 14811fcced4cSJordan Brown * Encode connection information into a buffer: connection information 14821fcced4cSJordan Brown * needed in user space to support RPC requests. 14831fcced4cSJordan Brown */ 14841fcced4cSJordan Brown static int 14851fcced4cSJordan Brown smb_tree_netinfo_encode(smb_tree_t *tree, uint8_t *buf, size_t buflen, 14861fcced4cSJordan Brown uint32_t *nbytes) 14871fcced4cSJordan Brown { 14881fcced4cSJordan Brown smb_netconnectinfo_t info; 14891fcced4cSJordan Brown int rc; 14901fcced4cSJordan Brown 14911fcced4cSJordan Brown smb_tree_netinfo_init(tree, &info); 14921fcced4cSJordan Brown rc = smb_netconnectinfo_encode(&info, buf, buflen, nbytes); 14931fcced4cSJordan Brown smb_tree_netinfo_fini(&info); 14941fcced4cSJordan Brown 14951fcced4cSJordan Brown return (rc); 14961fcced4cSJordan Brown } 14971fcced4cSJordan Brown 14983b13a1efSThomas Keiser static void 14993b13a1efSThomas Keiser smb_tree_netinfo_username(smb_tree_t *tree, char **namestr, uint32_t *namelen) 15003b13a1efSThomas Keiser { 15013b13a1efSThomas Keiser smb_user_t *user = tree->t_owner; 15023b13a1efSThomas Keiser 15033b13a1efSThomas Keiser /* 15043b13a1efSThomas Keiser * u_domain_len and u_name_len include the '\0' in their 15053b13a1efSThomas Keiser * lengths, hence the sum of the two lengths gives us room 15063b13a1efSThomas Keiser * for both the '\\' and '\0' chars. 15073b13a1efSThomas Keiser */ 15083b13a1efSThomas Keiser ASSERT(namestr); 15093b13a1efSThomas Keiser ASSERT(namelen); 15103b13a1efSThomas Keiser ASSERT(user->u_domain_len > 0); 15113b13a1efSThomas Keiser ASSERT(user->u_name_len > 0); 15123b13a1efSThomas Keiser *namelen = user->u_domain_len + user->u_name_len; 15133b13a1efSThomas Keiser *namestr = kmem_alloc(*namelen, KM_SLEEP); 15143b13a1efSThomas Keiser (void) snprintf(*namestr, *namelen, "%s\\%s", user->u_domain, 15153b13a1efSThomas Keiser user->u_name); 15163b13a1efSThomas Keiser } 15173b13a1efSThomas Keiser 15181fcced4cSJordan Brown /* 15191fcced4cSJordan Brown * Note: ci_numusers should be the number of users connected to 15201fcced4cSJordan Brown * the share rather than the number of references on the tree but 15211fcced4cSJordan Brown * we don't have a mechanism to track users/share in smbsrv yet. 15221fcced4cSJordan Brown */ 15231fcced4cSJordan Brown static void 15241fcced4cSJordan Brown smb_tree_netinfo_init(smb_tree_t *tree, smb_netconnectinfo_t *info) 15251fcced4cSJordan Brown { 15261fcced4cSJordan Brown ASSERT(tree); 15271fcced4cSJordan Brown 15281fcced4cSJordan Brown info->ci_id = tree->t_tid; 15291fcced4cSJordan Brown info->ci_type = tree->t_res_type; 15301fcced4cSJordan Brown info->ci_numopens = tree->t_open_files; 15311fcced4cSJordan Brown info->ci_numusers = tree->t_refcnt; 15321fcced4cSJordan Brown info->ci_time = gethrestime_sec() - tree->t_connect_time; 15331fcced4cSJordan Brown 15341fcced4cSJordan Brown info->ci_sharelen = strlen(tree->t_sharename) + 1; 15359fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States info->ci_share = smb_mem_strdup(tree->t_sharename); 15361fcced4cSJordan Brown 15373b13a1efSThomas Keiser smb_tree_netinfo_username(tree, &info->ci_username, &info->ci_namelen); 15381fcced4cSJordan Brown } 15391fcced4cSJordan Brown 15401fcced4cSJordan Brown static void 15411fcced4cSJordan Brown smb_tree_netinfo_fini(smb_netconnectinfo_t *info) 15421fcced4cSJordan Brown { 15431fcced4cSJordan Brown if (info == NULL) 15441fcced4cSJordan Brown return; 15451fcced4cSJordan Brown 15461fcced4cSJordan Brown if (info->ci_username) 15471fcced4cSJordan Brown kmem_free(info->ci_username, info->ci_namelen); 15481fcced4cSJordan Brown if (info->ci_share) 15499fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_mem_free(info->ci_share); 15501fcced4cSJordan Brown 15511fcced4cSJordan Brown bzero(info, sizeof (smb_netconnectinfo_t)); 15521fcced4cSJordan Brown } 1553