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. 24*811599a4SMatt Barden * Copyright 2018 Nexenta Systems, Inc. All rights reserved. 2548bbca81SDaniel Hoffman * Copyright (c) 2016 by Delphix. 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 * 125*811599a4SMatt Barden * This transition occurs in smb_tree_disconnect() 126*811599a4SMatt Barden * 127*811599a4SMatt Barden * Transition T3 128*811599a4SMatt 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 131*811599a4SMatt Barden * to occur, the tree must be in the SMB_TREE_STATE_DISCONNECTED and the 132*811599a4SMatt 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 151*811599a4SMatt Barden * list) have to be entered, the lock must be entered first. Additionally, 152*811599a4SMatt Barden * when both the (mutex and lock of the ofile list) have to be entered, 153*811599a4SMatt Barden * the mutex must be entered first. However, the ofile list lock must NOT 154*811599a4SMatt Barden * be dropped while the mutex is held in such a way that the ofile deleteq 155*811599a4SMatt 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 *); 1873b13a1efSThomas Keiser static smb_tree_t *smb_tree_alloc(smb_request_t *, const smb_kshare_t *, 188148c5f43SAlan Wright smb_node_t *, uint32_t, uint32_t); 189*811599a4SMatt Barden static void smb_tree_dealloc(void *); 1908b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States static boolean_t smb_tree_is_connected_locked(smb_tree_t *); 191a90cf9f2SGordon Ross static char *smb_tree_get_sharename(char *); 192148c5f43SAlan Wright static int smb_tree_getattr(const smb_kshare_t *, smb_node_t *, smb_tree_t *); 193c8ec8eeaSjose borrego static void smb_tree_get_volname(vfs_t *, smb_tree_t *); 194148c5f43SAlan Wright static void smb_tree_get_flags(const smb_kshare_t *, vfs_t *, smb_tree_t *); 195c8ec8eeaSjose borrego static void smb_tree_log(smb_request_t *, const char *, const char *, ...); 1967f667e74Sjose borrego static void smb_tree_close_odirs(smb_tree_t *, uint16_t); 1971fcced4cSJordan Brown static smb_ofile_t *smb_tree_get_ofile(smb_tree_t *, smb_ofile_t *); 1987f667e74Sjose borrego static smb_odir_t *smb_tree_get_odir(smb_tree_t *, smb_odir_t *); 199148c5f43SAlan Wright static void smb_tree_set_execinfo(smb_tree_t *, smb_shr_execinfo_t *, int); 2001fcced4cSJordan Brown static int smb_tree_enum_private(smb_tree_t *, smb_svcenum_t *); 2011fcced4cSJordan Brown static int smb_tree_netinfo_encode(smb_tree_t *, uint8_t *, size_t, uint32_t *); 2021fcced4cSJordan Brown static void smb_tree_netinfo_init(smb_tree_t *tree, smb_netconnectinfo_t *); 2031fcced4cSJordan Brown static void smb_tree_netinfo_fini(smb_netconnectinfo_t *); 204da6c28aaSamw 205a90cf9f2SGordon Ross uint32_t 206cb174861Sjoyce mcintosh smb_tree_connect(smb_request_t *sr) 207cb174861Sjoyce mcintosh { 208cb174861Sjoyce mcintosh smb_server_t *sv = sr->sr_server; 209a90cf9f2SGordon Ross uint32_t status; 210cb174861Sjoyce mcintosh 211cb174861Sjoyce mcintosh if (smb_threshold_enter(&sv->sv_tcon_ct) != 0) { 212a90cf9f2SGordon Ross return (NT_STATUS_INSUFF_SERVER_RESOURCES); 213cb174861Sjoyce mcintosh } 214cb174861Sjoyce mcintosh 215a90cf9f2SGordon Ross status = smb_tree_connect_core(sr); 216856399cfSGordon Ross smb_threshold_exit(&sv->sv_tcon_ct); 217a90cf9f2SGordon Ross return (status); 218cb174861Sjoyce mcintosh } 219cb174861Sjoyce mcintosh 220da6c28aaSamw /* 221148c5f43SAlan Wright * Lookup the share name dispatch the appropriate stype handler. 222c8ec8eeaSjose borrego * Share names are case insensitive so we map the share name to 223c8ec8eeaSjose borrego * lower-case as a convenience for internal processing. 224148c5f43SAlan Wright * 225148c5f43SAlan Wright * Valid service values are: 226148c5f43SAlan Wright * A: Disk share 227148c5f43SAlan Wright * LPT1: Printer 228148c5f43SAlan Wright * IPC Named pipe (IPC$ is reserved as the named pipe share). 229148c5f43SAlan Wright * COMM Communications device 230148c5f43SAlan Wright * ????? Any type of device (wildcard) 231da6c28aaSamw */ 232a90cf9f2SGordon Ross uint32_t 233cb174861Sjoyce mcintosh smb_tree_connect_core(smb_request_t *sr) 234da6c28aaSamw { 235a90cf9f2SGordon Ross smb_arg_tcon_t *tcon = &sr->sr_tcon; 236148c5f43SAlan Wright smb_kshare_t *si; 237a90cf9f2SGordon Ross char *name; 238a90cf9f2SGordon Ross uint32_t status; 239da6c28aaSamw 240a90cf9f2SGordon Ross (void) smb_strlwr(tcon->path); 241da6c28aaSamw 242a90cf9f2SGordon Ross if ((name = smb_tree_get_sharename(tcon->path)) == NULL) { 243a90cf9f2SGordon Ross smb_tree_log(sr, tcon->path, "invalid UNC path"); 244a90cf9f2SGordon Ross return (NT_STATUS_BAD_NETWORK_NAME); 245da6c28aaSamw } 246da6c28aaSamw 2478622ec45SGordon Ross si = smb_kshare_lookup(sr->sr_server, name); 2488622ec45SGordon Ross if (si == NULL) { 249148c5f43SAlan Wright smb_tree_log(sr, name, "share not found"); 250a90cf9f2SGordon Ross return (NT_STATUS_BAD_NETWORK_NAME); 251da6c28aaSamw } 252cb174861Sjoyce mcintosh 253cb174861Sjoyce mcintosh if (!strcasecmp(SMB_SHARE_PRINT, name)) { 2548622ec45SGordon Ross smb_kshare_release(sr->sr_server, si); 255cb174861Sjoyce mcintosh smb_tree_log(sr, name, "access not permitted"); 256a90cf9f2SGordon Ross return (NT_STATUS_ACCESS_DENIED); 257cb174861Sjoyce mcintosh } 258cb174861Sjoyce mcintosh 259a90cf9f2SGordon Ross /* NB: name points into tcon->path - don't free it. */ 260a90cf9f2SGordon Ross tcon->name = name; 261148c5f43SAlan Wright sr->sr_tcon.si = si; 262da6c28aaSamw 263148c5f43SAlan Wright switch (si->shr_type & STYPE_MASK) { 264da6c28aaSamw case STYPE_DISKTREE: 265a90cf9f2SGordon Ross status = smb_tree_connect_disk(sr, &sr->sr_tcon); 266da6c28aaSamw break; 267da6c28aaSamw case STYPE_IPC: 268a90cf9f2SGordon Ross status = smb_tree_connect_ipc(sr, &sr->sr_tcon); 269c8ec8eeaSjose borrego break; 270148c5f43SAlan Wright case STYPE_PRINTQ: 271a90cf9f2SGordon Ross status = smb_tree_connect_printq(sr, &sr->sr_tcon); 272148c5f43SAlan Wright break; 273da6c28aaSamw default: 274a90cf9f2SGordon Ross status = NT_STATUS_BAD_DEVICE_TYPE; 275da6c28aaSamw break; 276da6c28aaSamw } 277da6c28aaSamw 2788622ec45SGordon Ross smb_kshare_release(sr->sr_server, si); 279a90cf9f2SGordon Ross sr->sr_tcon.si = NULL; 280a90cf9f2SGordon Ross 281a90cf9f2SGordon Ross return (status); 282da6c28aaSamw } 283da6c28aaSamw 284da6c28aaSamw /* 285c8ec8eeaSjose borrego * Disconnect a tree. 286da6c28aaSamw */ 287da6c28aaSamw void 28829bd2886SAlan Wright smb_tree_disconnect(smb_tree_t *tree, boolean_t do_exec) 289da6c28aaSamw { 290148c5f43SAlan Wright smb_shr_execinfo_t execinfo; 29129bd2886SAlan Wright 292da6c28aaSamw ASSERT(tree->t_magic == SMB_TREE_MAGIC); 293da6c28aaSamw 294da6c28aaSamw mutex_enter(&tree->t_mutex); 295da6c28aaSamw ASSERT(tree->t_refcnt); 296c8ec8eeaSjose borrego 2978b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (smb_tree_is_connected_locked(tree)) { 298da6c28aaSamw /* 299c8ec8eeaSjose borrego * Indicate that the disconnect process has started. 300da6c28aaSamw */ 301da6c28aaSamw tree->t_state = SMB_TREE_STATE_DISCONNECTING; 302da6c28aaSamw mutex_exit(&tree->t_mutex); 303c8ec8eeaSjose borrego 30429bd2886SAlan Wright if (do_exec) { 30529bd2886SAlan Wright /* 30629bd2886SAlan Wright * The files opened under this tree are closed. 30729bd2886SAlan Wright */ 308*811599a4SMatt Barden smb_ofile_close_all(tree, 0); 30929bd2886SAlan Wright /* 31029bd2886SAlan Wright * The directories opened under this tree are closed. 31129bd2886SAlan Wright */ 31229bd2886SAlan Wright smb_tree_close_odirs(tree, 0); 31329bd2886SAlan Wright } 31429bd2886SAlan Wright 315da6c28aaSamw mutex_enter(&tree->t_mutex); 316da6c28aaSamw tree->t_state = SMB_TREE_STATE_DISCONNECTED; 317148c5f43SAlan Wright smb_server_dec_trees(tree->t_server); 318da6c28aaSamw } 319da6c28aaSamw 320da6c28aaSamw mutex_exit(&tree->t_mutex); 32129bd2886SAlan Wright 322148c5f43SAlan Wright if (do_exec && (tree->t_state == SMB_TREE_STATE_DISCONNECTED) && 323148c5f43SAlan Wright (tree->t_execflags & SMB_EXEC_UNMAP)) { 32429bd2886SAlan Wright 325148c5f43SAlan Wright smb_tree_set_execinfo(tree, &execinfo, SMB_EXEC_UNMAP); 3268622ec45SGordon Ross (void) smb_kshare_exec(tree->t_server, &execinfo); 32729bd2886SAlan Wright } 328da6c28aaSamw } 329da6c28aaSamw 330da6c28aaSamw /* 331c8ec8eeaSjose borrego * Take a reference on a tree. 332da6c28aaSamw */ 333c8ec8eeaSjose borrego boolean_t 334c8ec8eeaSjose borrego smb_tree_hold( 335c8ec8eeaSjose borrego smb_tree_t *tree) 336da6c28aaSamw { 337a90cf9f2SGordon Ross SMB_TREE_VALID(tree); 338da6c28aaSamw 339c8ec8eeaSjose borrego mutex_enter(&tree->t_mutex); 340c8ec8eeaSjose borrego 3418b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (smb_tree_is_connected_locked(tree)) { 342c8ec8eeaSjose borrego tree->t_refcnt++; 343c8ec8eeaSjose borrego mutex_exit(&tree->t_mutex); 344c8ec8eeaSjose borrego return (B_TRUE); 345da6c28aaSamw } 346c8ec8eeaSjose borrego 347c8ec8eeaSjose borrego mutex_exit(&tree->t_mutex); 348c8ec8eeaSjose borrego return (B_FALSE); 349da6c28aaSamw } 350da6c28aaSamw 351a90cf9f2SGordon Ross /* 352a90cf9f2SGordon Ross * Bump the hold count regardless of the tree state. This is used in 353a90cf9f2SGordon Ross * some internal code paths where we've already checked that we had a 354a90cf9f2SGordon Ross * valid tree connection, and don't want to deal with the possiblity 355a90cf9f2SGordon Ross * that the tree state might have changed to disconnecting after our 356a90cf9f2SGordon Ross * original hold was taken. It's correct to continue processing a 357a90cf9f2SGordon Ross * request even when new requests cannot lookup that tree anymore. 358a90cf9f2SGordon Ross */ 359a90cf9f2SGordon Ross void 360a90cf9f2SGordon Ross smb_tree_hold_internal( 361a90cf9f2SGordon Ross smb_tree_t *tree) 362a90cf9f2SGordon Ross { 363a90cf9f2SGordon Ross SMB_TREE_VALID(tree); 364a90cf9f2SGordon Ross 365a90cf9f2SGordon Ross mutex_enter(&tree->t_mutex); 366a90cf9f2SGordon Ross tree->t_refcnt++; 367a90cf9f2SGordon Ross mutex_exit(&tree->t_mutex); 368a90cf9f2SGordon Ross } 369a90cf9f2SGordon Ross 370da6c28aaSamw /* 371c8ec8eeaSjose borrego * Release a reference on a tree. If the tree is disconnected and the 3729fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * reference count falls to zero, post the object for deletion. 3739fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Object deletion is deferred to avoid modifying a list while an 3749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * iteration may be in progress. 375da6c28aaSamw */ 376da6c28aaSamw void 377c8ec8eeaSjose borrego smb_tree_release( 378c8ec8eeaSjose borrego smb_tree_t *tree) 379da6c28aaSamw { 3809fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_TREE_VALID(tree); 381da6c28aaSamw 382c5866007SKeyur Desai /* flush the ofile and odir lists' delete queues */ 383c5866007SKeyur Desai smb_llist_flush(&tree->t_ofile_list); 384c5866007SKeyur Desai smb_llist_flush(&tree->t_odir_list); 385c5866007SKeyur Desai 386*811599a4SMatt Barden mutex_enter(&tree->t_mutex); 387*811599a4SMatt Barden ASSERT(tree->t_refcnt); 388*811599a4SMatt Barden tree->t_refcnt--; 3899fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 390*811599a4SMatt Barden switch (tree->t_state) { 391*811599a4SMatt Barden case SMB_TREE_STATE_DISCONNECTED: 392*811599a4SMatt Barden if (tree->t_refcnt == 0) { 393*811599a4SMatt Barden smb_session_t *ssn = tree->t_session; 394*811599a4SMatt Barden tree->t_state = SMB_TREE_STATE_DISCONNECTED; 395*811599a4SMatt Barden smb_llist_post(&ssn->s_tree_list, tree, 396*811599a4SMatt Barden smb_tree_dealloc); 397*811599a4SMatt Barden } 398*811599a4SMatt Barden break; 399*811599a4SMatt Barden case SMB_TREE_STATE_CONNECTED: 400*811599a4SMatt Barden case SMB_TREE_STATE_DISCONNECTING: 401*811599a4SMatt Barden break; 402*811599a4SMatt Barden default: 403*811599a4SMatt Barden ASSERT(0); 404*811599a4SMatt Barden break; 405*811599a4SMatt Barden } 4069fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 407*811599a4SMatt Barden mutex_exit(&tree->t_mutex); 4089fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States } 4099fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 410da6c28aaSamw /* 411c8ec8eeaSjose borrego * Close ofiles and odirs that match pid. 412da6c28aaSamw */ 413da6c28aaSamw void 414c8ec8eeaSjose borrego smb_tree_close_pid( 415c8ec8eeaSjose borrego smb_tree_t *tree, 416a90cf9f2SGordon Ross uint32_t pid) 417da6c28aaSamw { 418da6c28aaSamw ASSERT(tree); 419da6c28aaSamw ASSERT(tree->t_magic == SMB_TREE_MAGIC); 420da6c28aaSamw 421*811599a4SMatt Barden smb_ofile_close_all(tree, pid); 4227f667e74Sjose borrego smb_tree_close_odirs(tree, pid); 423c8ec8eeaSjose borrego } 424da6c28aaSamw 425c8ec8eeaSjose borrego /* 426c8ec8eeaSjose borrego * Check whether or not a tree supports the features identified by flags. 427c8ec8eeaSjose borrego */ 428c8ec8eeaSjose borrego boolean_t 429c8ec8eeaSjose borrego smb_tree_has_feature(smb_tree_t *tree, uint32_t flags) 430c8ec8eeaSjose borrego { 431c8ec8eeaSjose borrego ASSERT(tree); 432c8ec8eeaSjose borrego ASSERT(tree->t_magic == SMB_TREE_MAGIC); 433da6c28aaSamw 434c8ec8eeaSjose borrego return ((tree->t_flags & flags) == flags); 435da6c28aaSamw } 436da6c28aaSamw 4371fcced4cSJordan Brown /* 4381fcced4cSJordan Brown * If the enumeration request is for tree data, handle the request 4391fcced4cSJordan Brown * here. Otherwise, pass it on to the ofiles. 4401fcced4cSJordan Brown * 4411fcced4cSJordan Brown * This function should be called with a hold on the tree. 4421fcced4cSJordan Brown */ 4431fcced4cSJordan Brown int 4441fcced4cSJordan Brown smb_tree_enum(smb_tree_t *tree, smb_svcenum_t *svcenum) 4451fcced4cSJordan Brown { 4461fcced4cSJordan Brown smb_ofile_t *of; 4471fcced4cSJordan Brown smb_ofile_t *next; 4483b13a1efSThomas Keiser int rc = 0; 4491fcced4cSJordan Brown 4501fcced4cSJordan Brown ASSERT(tree); 4511fcced4cSJordan Brown ASSERT(tree->t_magic == SMB_TREE_MAGIC); 4521fcced4cSJordan Brown 4531fcced4cSJordan Brown if (svcenum->se_type == SMB_SVCENUM_TYPE_TREE) 4541fcced4cSJordan Brown return (smb_tree_enum_private(tree, svcenum)); 4551fcced4cSJordan Brown 4561fcced4cSJordan Brown of = smb_tree_get_ofile(tree, NULL); 4571fcced4cSJordan Brown while (of) { 4581fcced4cSJordan Brown ASSERT(of->f_tree == tree); 4591fcced4cSJordan Brown 4601fcced4cSJordan Brown rc = smb_ofile_enum(of, svcenum); 4611fcced4cSJordan Brown if (rc != 0) { 4621fcced4cSJordan Brown smb_ofile_release(of); 4631fcced4cSJordan Brown break; 4641fcced4cSJordan Brown } 4651fcced4cSJordan Brown 4661fcced4cSJordan Brown next = smb_tree_get_ofile(tree, of); 4671fcced4cSJordan Brown smb_ofile_release(of); 4681fcced4cSJordan Brown of = next; 4691fcced4cSJordan Brown } 4701fcced4cSJordan Brown 4711fcced4cSJordan Brown return (rc); 4721fcced4cSJordan Brown } 4731fcced4cSJordan Brown 4741fcced4cSJordan Brown /* 4751fcced4cSJordan Brown * Close a file by its unique id. 4761fcced4cSJordan Brown */ 4771fcced4cSJordan Brown int 4781fcced4cSJordan Brown smb_tree_fclose(smb_tree_t *tree, uint32_t uniqid) 4791fcced4cSJordan Brown { 4801fcced4cSJordan Brown smb_ofile_t *of; 4811fcced4cSJordan Brown 4821fcced4cSJordan Brown ASSERT(tree); 4831fcced4cSJordan Brown ASSERT(tree->t_magic == SMB_TREE_MAGIC); 4841fcced4cSJordan Brown 485*811599a4SMatt Barden /* 486*811599a4SMatt Barden * Note that ORPHANED ofiles aren't fclosable, as they have 487*811599a4SMatt Barden * no session, user, or tree by which they might be found. 488*811599a4SMatt Barden * They will eventually expire. 489*811599a4SMatt Barden */ 4901fcced4cSJordan Brown if ((of = smb_ofile_lookup_by_uniqid(tree, uniqid)) == NULL) 4911fcced4cSJordan Brown return (ENOENT); 4921fcced4cSJordan Brown 4931fcced4cSJordan Brown if (smb_ofile_disallow_fclose(of)) { 4941fcced4cSJordan Brown smb_ofile_release(of); 4951fcced4cSJordan Brown return (EACCES); 4961fcced4cSJordan Brown } 4971fcced4cSJordan Brown 4981fcced4cSJordan Brown smb_ofile_close(of, 0); 4991fcced4cSJordan Brown smb_ofile_release(of); 5001fcced4cSJordan Brown return (0); 5011fcced4cSJordan Brown } 502743a77edSAlan Wright 503c8ec8eeaSjose borrego /* *************************** Static Functions ***************************** */ 5041fcced4cSJordan Brown 505743a77edSAlan Wright #define SHARES_DIR ".zfs/shares/" 506148c5f43SAlan Wright 507148c5f43SAlan Wright /* 508148c5f43SAlan Wright * Calculates permissions given by the share's ACL to the 509148c5f43SAlan Wright * user in the passed request. The default is full access. 510148c5f43SAlan Wright * If any error occurs, full access is granted. 511148c5f43SAlan Wright * 512148c5f43SAlan Wright * Using the vnode of the share path find the root directory 513148c5f43SAlan Wright * of the mounted file system. Then look to see if there is a 514148c5f43SAlan Wright * .zfs/shares directory and if there is, lookup the file with 515148c5f43SAlan Wright * the same name as the share name in it. The ACL set for this 516148c5f43SAlan Wright * file is the share's ACL which is used for access check here. 517148c5f43SAlan Wright */ 518148c5f43SAlan Wright static uint32_t 519148c5f43SAlan Wright smb_tree_acl_access(smb_request_t *sr, const smb_kshare_t *si, vnode_t *pathvp) 520743a77edSAlan Wright { 521fe1c642dSBill Krier smb_user_t *user; 522fe1c642dSBill Krier cred_t *cred; 523fe1c642dSBill Krier int rc; 524fe1c642dSBill Krier vfs_t *vfsp; 525fe1c642dSBill Krier vnode_t *root = NULL; 526fe1c642dSBill Krier vnode_t *sharevp = NULL; 527fe1c642dSBill Krier char *sharepath; 528fe1c642dSBill Krier struct pathname pnp; 529fe1c642dSBill Krier size_t size; 530148c5f43SAlan Wright uint32_t access; 531fe1c642dSBill Krier 532fe1c642dSBill Krier user = sr->uid_user; 533fe1c642dSBill Krier cred = user->u_cred; 534148c5f43SAlan Wright access = ACE_ALL_PERMS; 535743a77edSAlan Wright 536fe1c642dSBill Krier if (si->shr_flags & SMB_SHRF_AUTOHOME) { 537fe1c642dSBill Krier /* 538fe1c642dSBill Krier * An autohome share owner gets full access to the share. 539fe1c642dSBill Krier * Everyone else is denied access. 540fe1c642dSBill Krier */ 541c5866007SKeyur Desai if (si->shr_uid != crgetuid(cred)) 542148c5f43SAlan Wright access = 0; 543148c5f43SAlan Wright 544148c5f43SAlan Wright return (access); 545fe1c642dSBill Krier } 546fe1c642dSBill Krier 547743a77edSAlan Wright /* 548148c5f43SAlan Wright * The hold on 'root' is released by the lookuppnvp() that follows 549743a77edSAlan Wright */ 550743a77edSAlan Wright vfsp = pathvp->v_vfsp; 551743a77edSAlan Wright if (vfsp != NULL) 552743a77edSAlan Wright rc = VFS_ROOT(vfsp, &root); 553743a77edSAlan Wright else 554743a77edSAlan Wright rc = ENOENT; 555743a77edSAlan Wright 556743a77edSAlan Wright if (rc != 0) 557148c5f43SAlan Wright return (access); 558743a77edSAlan Wright 559743a77edSAlan Wright 560fe1c642dSBill Krier size = sizeof (SHARES_DIR) + strlen(si->shr_name) + 1; 561148c5f43SAlan Wright sharepath = smb_srm_alloc(sr, size); 562b819cea2SGordon Ross (void) snprintf(sharepath, size, "%s%s", SHARES_DIR, si->shr_name); 563743a77edSAlan Wright 564743a77edSAlan Wright pn_alloc(&pnp); 565743a77edSAlan Wright (void) pn_set(&pnp, sharepath); 566148c5f43SAlan Wright rc = lookuppnvp(&pnp, NULL, NO_FOLLOW, NULL, &sharevp, rootdir, root, 5678622ec45SGordon Ross zone_kcred()); 568743a77edSAlan Wright pn_free(&pnp); 569743a77edSAlan Wright 570743a77edSAlan Wright /* 571148c5f43SAlan Wright * Now get the effective access value based on cred and ACL values. 572743a77edSAlan Wright */ 573037cac00Sjoyce mcintosh if (rc == 0) { 574148c5f43SAlan Wright smb_vop_eaccess(sharevp, (int *)&access, V_ACE_MASK, NULL, 575148c5f43SAlan Wright cred); 576037cac00Sjoyce mcintosh VN_RELE(sharevp); 577037cac00Sjoyce mcintosh } 578148c5f43SAlan Wright 579148c5f43SAlan Wright return (access); 580743a77edSAlan Wright } 581c8ec8eeaSjose borrego 582da6c28aaSamw /* 583148c5f43SAlan Wright * Performs the following access checks for a disk share: 584148c5f43SAlan Wright * 585148c5f43SAlan Wright * - No IPC/anonymous user is allowed 586148c5f43SAlan Wright * 587148c5f43SAlan Wright * - If user is Guest, guestok property of the share should be 588148c5f43SAlan Wright * enabled 589148c5f43SAlan Wright * 590148c5f43SAlan Wright * - If this is an Admin share, the user should have administrative 591148c5f43SAlan Wright * privileges 592148c5f43SAlan Wright * 593148c5f43SAlan Wright * - Host based access control lists 594148c5f43SAlan Wright * 595148c5f43SAlan Wright * - Share ACL 596148c5f43SAlan Wright * 597148c5f43SAlan Wright * Returns the access allowed or 0 if access is denied. 598da6c28aaSamw */ 599148c5f43SAlan Wright static uint32_t 600148c5f43SAlan Wright smb_tree_chkaccess(smb_request_t *sr, smb_kshare_t *shr, vnode_t *vp) 601148c5f43SAlan Wright { 602148c5f43SAlan Wright smb_user_t *user = sr->uid_user; 603148c5f43SAlan Wright char *sharename = shr->shr_name; 604148c5f43SAlan Wright uint32_t host_access; 605148c5f43SAlan Wright uint32_t acl_access; 606148c5f43SAlan Wright uint32_t access; 607743a77edSAlan Wright 608a90cf9f2SGordon Ross if (user->u_flags & SMB_USER_FLAG_ANON) { 609148c5f43SAlan Wright smb_tree_log(sr, sharename, "access denied: IPC only"); 610148c5f43SAlan Wright return (0); 611148c5f43SAlan Wright } 612148c5f43SAlan Wright 613148c5f43SAlan Wright if ((user->u_flags & SMB_USER_FLAG_GUEST) && 614148c5f43SAlan Wright ((shr->shr_flags & SMB_SHRF_GUEST_OK) == 0)) { 615148c5f43SAlan Wright smb_tree_log(sr, sharename, "access denied: guest disabled"); 616148c5f43SAlan Wright return (0); 617148c5f43SAlan Wright } 618148c5f43SAlan Wright 619148c5f43SAlan Wright if ((shr->shr_flags & SMB_SHRF_ADMIN) && !smb_user_is_admin(user)) { 620148c5f43SAlan Wright smb_tree_log(sr, sharename, "access denied: not admin"); 621148c5f43SAlan Wright return (0); 622148c5f43SAlan Wright } 623148c5f43SAlan Wright 6248622ec45SGordon Ross host_access = smb_kshare_hostaccess(shr, sr->session); 625148c5f43SAlan Wright if ((host_access & ACE_ALL_PERMS) == 0) { 626148c5f43SAlan Wright smb_tree_log(sr, sharename, "access denied: host access"); 627148c5f43SAlan Wright return (0); 628148c5f43SAlan Wright } 629148c5f43SAlan Wright 630148c5f43SAlan Wright acl_access = smb_tree_acl_access(sr, shr, vp); 631148c5f43SAlan Wright if ((acl_access & ACE_ALL_PERMS) == 0) { 632148c5f43SAlan Wright smb_tree_log(sr, sharename, "access denied: share ACL"); 633148c5f43SAlan Wright return (0); 634148c5f43SAlan Wright } 635148c5f43SAlan Wright 636148c5f43SAlan Wright access = host_access & acl_access; 637148c5f43SAlan Wright if ((access & ACE_ALL_PERMS) == 0) { 638148c5f43SAlan Wright smb_tree_log(sr, sharename, "access denied"); 639148c5f43SAlan Wright return (0); 640148c5f43SAlan Wright } 641148c5f43SAlan Wright 642148c5f43SAlan Wright return (access); 643148c5f43SAlan Wright } 644148c5f43SAlan Wright 645148c5f43SAlan Wright /* 646148c5f43SAlan Wright * Connect a share for use with files and directories. 647148c5f43SAlan Wright */ 648a90cf9f2SGordon Ross uint32_t 649a90cf9f2SGordon Ross smb_tree_connect_disk(smb_request_t *sr, smb_arg_tcon_t *tcon) 650da6c28aaSamw { 651a90cf9f2SGordon Ross char *sharename = tcon->path; 652148c5f43SAlan Wright const char *any = "?????"; 653c8ec8eeaSjose borrego smb_user_t *user = sr->uid_user; 6541fcced4cSJordan Brown smb_node_t *dnode = NULL; 655c8ec8eeaSjose borrego smb_node_t *snode = NULL; 656*811599a4SMatt Barden smb_kshare_t *si = tcon->si; 657a90cf9f2SGordon Ross char *service = tcon->service; 658c8ec8eeaSjose borrego char last_component[MAXNAMELEN]; 659c8ec8eeaSjose borrego smb_tree_t *tree; 660c01771d0SDaniel Borek cred_t *kcr; 661c8ec8eeaSjose borrego int rc; 662148c5f43SAlan Wright uint32_t access; 663148c5f43SAlan Wright smb_shr_execinfo_t execinfo; 664da6c28aaSamw 665da6c28aaSamw ASSERT(user); 666148c5f43SAlan Wright ASSERT(user->u_cred); 667c8ec8eeaSjose borrego 668a90cf9f2SGordon Ross if (service != NULL && 669a90cf9f2SGordon Ross strcmp(service, any) != 0 && 670a90cf9f2SGordon Ross strcasecmp(service, "A:") != 0) { 671148c5f43SAlan Wright smb_tree_log(sr, sharename, "invalid service (%s)", service); 672a90cf9f2SGordon Ross return (NT_STATUS_BAD_DEVICE_TYPE); 673c8ec8eeaSjose borrego } 674c8ec8eeaSjose borrego 675148c5f43SAlan Wright /* 676148c5f43SAlan Wright * Check that the shared directory exists. 677c01771d0SDaniel Borek * Client might not have access to the path _leading_ to the share, 678c01771d0SDaniel Borek * so we use "kcred" to get to the share root. 679148c5f43SAlan Wright */ 680c01771d0SDaniel Borek kcr = zone_kcred(); 681c01771d0SDaniel Borek rc = smb_pathname_reduce(sr, kcr, si->shr_path, 0, 0, &dnode, 682148c5f43SAlan Wright last_component); 683148c5f43SAlan Wright if (rc == 0) { 684c01771d0SDaniel Borek rc = smb_fsop_lookup(sr, kcr, SMB_FOLLOW_LINKS, 685148c5f43SAlan Wright sr->sr_server->si_root_smb_node, dnode, last_component, 686148c5f43SAlan Wright &snode); 687148c5f43SAlan Wright 688148c5f43SAlan Wright smb_node_release(dnode); 689c8ec8eeaSjose borrego } 690c8ec8eeaSjose borrego 691148c5f43SAlan Wright if (rc) { 692148c5f43SAlan Wright if (snode) 693148c5f43SAlan Wright smb_node_release(snode); 694148c5f43SAlan Wright 695148c5f43SAlan Wright smb_tree_log(sr, sharename, "bad path: %s", si->shr_path); 696a90cf9f2SGordon Ross return (NT_STATUS_BAD_NETWORK_NAME); 69729bd2886SAlan Wright } 69829bd2886SAlan Wright 699148c5f43SAlan Wright if ((access = smb_tree_chkaccess(sr, si, snode->vp)) == 0) { 700148c5f43SAlan Wright smb_node_release(snode); 701a90cf9f2SGordon Ross return (NT_STATUS_ACCESS_DENIED); 702da6c28aaSamw } 703c8ec8eeaSjose borrego 7048d7e4166Sjose borrego /* 7058d7e4166Sjose borrego * Set up the OptionalSupport for this share. 7068d7e4166Sjose borrego */ 707a90cf9f2SGordon Ross tcon->optional_support = SMB_SUPPORT_SEARCH_BITS; 7088d7e4166Sjose borrego 7098d7e4166Sjose borrego switch (si->shr_flags & SMB_SHRF_CSC_MASK) { 7108d7e4166Sjose borrego case SMB_SHRF_CSC_DISABLED: 711a90cf9f2SGordon Ross tcon->optional_support |= SMB_CSC_CACHE_NONE; 7128d7e4166Sjose borrego break; 7138d7e4166Sjose borrego case SMB_SHRF_CSC_AUTO: 714a90cf9f2SGordon Ross tcon->optional_support |= SMB_CSC_CACHE_AUTO_REINT; 7158d7e4166Sjose borrego break; 7168d7e4166Sjose borrego case SMB_SHRF_CSC_VDO: 717a90cf9f2SGordon Ross tcon->optional_support |= SMB_CSC_CACHE_VDO; 7188d7e4166Sjose borrego break; 7198d7e4166Sjose borrego case SMB_SHRF_CSC_MANUAL: 7208d7e4166Sjose borrego default: 7218d7e4166Sjose borrego /* 7228d7e4166Sjose borrego * Default to SMB_CSC_CACHE_MANUAL_REINT. 7238d7e4166Sjose borrego */ 7248d7e4166Sjose borrego break; 7258d7e4166Sjose borrego } 7268d7e4166Sjose borrego 727e3f2c991SKeyur Desai /* ABE support */ 728e3f2c991SKeyur Desai if (si->shr_flags & SMB_SHRF_ABE) 729a90cf9f2SGordon Ross tcon->optional_support |= 730e3f2c991SKeyur Desai SHI1005_FLAGS_ACCESS_BASED_DIRECTORY_ENUM; 731e3f2c991SKeyur Desai 7329fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (si->shr_flags & SMB_SHRF_DFSROOT) 733a90cf9f2SGordon Ross tcon->optional_support |= SMB_SHARE_IS_IN_DFS; 7349fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 735cb174861Sjoyce mcintosh /* if 'smb' zfs property: shortnames=disabled */ 736cb174861Sjoyce mcintosh if (!smb_shortnames) 737cb174861Sjoyce mcintosh sr->arg.tcon.optional_support |= SMB_UNIQUE_FILE_NAME; 738cb174861Sjoyce mcintosh 7393b13a1efSThomas Keiser tree = smb_tree_alloc(sr, si, snode, access, sr->sr_cfg->skc_execflags); 740b89a8333Snatalie li - Sun Microsystems - Irvine United States 741148c5f43SAlan Wright smb_node_release(snode); 742148c5f43SAlan Wright 743a90cf9f2SGordon Ross if (tree == NULL) 744a90cf9f2SGordon Ross return (NT_STATUS_INSUFF_SERVER_RESOURCES); 745a90cf9f2SGordon Ross 746a90cf9f2SGordon Ross if (tree->t_execflags & SMB_EXEC_MAP) { 747a90cf9f2SGordon Ross smb_tree_set_execinfo(tree, &execinfo, SMB_EXEC_MAP); 748148c5f43SAlan Wright 749a90cf9f2SGordon Ross rc = smb_kshare_exec(tree->t_server, &execinfo); 750148c5f43SAlan Wright 751a90cf9f2SGordon Ross if ((rc != 0) && (tree->t_execflags & SMB_EXEC_TERM)) { 752a90cf9f2SGordon Ross smb_tree_disconnect(tree, B_FALSE); 753a90cf9f2SGordon Ross smb_tree_release(tree); 754a90cf9f2SGordon Ross return (NT_STATUS_ACCESS_DENIED); 755148c5f43SAlan Wright } 756148c5f43SAlan Wright } 757148c5f43SAlan Wright 758a90cf9f2SGordon Ross sr->tid_tree = tree; 759a90cf9f2SGordon Ross sr->smb_tid = tree->t_tid; 760a90cf9f2SGordon Ross 761a90cf9f2SGordon Ross return (0); 762148c5f43SAlan Wright } 763148c5f43SAlan Wright 764148c5f43SAlan Wright /* 765148c5f43SAlan Wright * Shares have both a share and host based access control. The access 766148c5f43SAlan Wright * granted will be minimum permissions based on both hostaccess 767148c5f43SAlan Wright * (permissions allowed by host based access) and aclaccess (from the 768148c5f43SAlan Wright * share ACL). 769148c5f43SAlan Wright */ 770a90cf9f2SGordon Ross uint32_t 771a90cf9f2SGordon Ross smb_tree_connect_printq(smb_request_t *sr, smb_arg_tcon_t *tcon) 772148c5f43SAlan Wright { 773a90cf9f2SGordon Ross char *sharename = tcon->path; 774148c5f43SAlan Wright const char *any = "?????"; 775148c5f43SAlan Wright smb_user_t *user = sr->uid_user; 776148c5f43SAlan Wright smb_node_t *dnode = NULL; 777148c5f43SAlan Wright smb_node_t *snode = NULL; 778*811599a4SMatt Barden smb_kshare_t *si = tcon->si; 779a90cf9f2SGordon Ross char *service = tcon->service; 780148c5f43SAlan Wright char last_component[MAXNAMELEN]; 781148c5f43SAlan Wright smb_tree_t *tree; 782148c5f43SAlan Wright int rc; 783148c5f43SAlan Wright uint32_t access; 784148c5f43SAlan Wright 785148c5f43SAlan Wright ASSERT(user); 786148c5f43SAlan Wright ASSERT(user->u_cred); 787148c5f43SAlan Wright 788b7301bf5SGordon Ross if (sr->sr_server->sv_cfg.skc_print_enable == 0) { 789b7301bf5SGordon Ross smb_tree_log(sr, sharename, "printing disabled"); 790a90cf9f2SGordon Ross return (NT_STATUS_BAD_NETWORK_NAME); 791b7301bf5SGordon Ross } 792b7301bf5SGordon Ross 793a90cf9f2SGordon Ross if (service != NULL && 794a90cf9f2SGordon Ross strcmp(service, any) != 0 && 795a90cf9f2SGordon Ross strcasecmp(service, "LPT1:") != 0) { 796148c5f43SAlan Wright smb_tree_log(sr, sharename, "invalid service (%s)", service); 797a90cf9f2SGordon Ross return (NT_STATUS_BAD_DEVICE_TYPE); 798b89a8333Snatalie li - Sun Microsystems - Irvine United States } 799b89a8333Snatalie li - Sun Microsystems - Irvine United States 800c8ec8eeaSjose borrego /* 801c8ec8eeaSjose borrego * Check that the shared directory exists. 802c8ec8eeaSjose borrego */ 803148c5f43SAlan Wright rc = smb_pathname_reduce(sr, user->u_cred, si->shr_path, 0, 0, &dnode, 804c8ec8eeaSjose borrego last_component); 805c8ec8eeaSjose borrego if (rc == 0) { 806148c5f43SAlan Wright rc = smb_fsop_lookup(sr, user->u_cred, SMB_FOLLOW_LINKS, 8071fcced4cSJordan Brown sr->sr_server->si_root_smb_node, dnode, last_component, 808037cac00Sjoyce mcintosh &snode); 809c8ec8eeaSjose borrego 8101fcced4cSJordan Brown smb_node_release(dnode); 811c8ec8eeaSjose borrego } 812c8ec8eeaSjose borrego 813c8ec8eeaSjose borrego if (rc) { 814c8ec8eeaSjose borrego if (snode) 815c8ec8eeaSjose borrego smb_node_release(snode); 816c8ec8eeaSjose borrego 817b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_tree_log(sr, sharename, "bad path: %s", si->shr_path); 818a90cf9f2SGordon Ross return (NT_STATUS_BAD_NETWORK_NAME); 819c8ec8eeaSjose borrego } 820c8ec8eeaSjose borrego 821148c5f43SAlan Wright if ((access = smb_tree_chkaccess(sr, si, snode->vp)) == 0) { 822037cac00Sjoyce mcintosh smb_node_release(snode); 823a90cf9f2SGordon Ross return (NT_STATUS_ACCESS_DENIED); 824743a77edSAlan Wright } 825743a77edSAlan Wright 826a90cf9f2SGordon Ross tcon->optional_support = SMB_SUPPORT_SEARCH_BITS; 8272c2961f8Sjose borrego 8283b13a1efSThomas Keiser tree = smb_tree_alloc(sr, si, snode, access, sr->sr_cfg->skc_execflags); 829b89a8333Snatalie li - Sun Microsystems - Irvine United States 83029bd2886SAlan Wright smb_node_release(snode); 83129bd2886SAlan Wright 832c8ec8eeaSjose borrego if (tree == NULL) 833a90cf9f2SGordon Ross return (NT_STATUS_INSUFF_SERVER_RESOURCES); 83429bd2886SAlan Wright 835a90cf9f2SGordon Ross sr->tid_tree = tree; 836a90cf9f2SGordon Ross sr->smb_tid = tree->t_tid; 837a90cf9f2SGordon Ross 838a90cf9f2SGordon Ross return (0); 839da6c28aaSamw } 840da6c28aaSamw 841da6c28aaSamw /* 842c8ec8eeaSjose borrego * Connect an IPC share for use with named pipes. 843da6c28aaSamw */ 844a90cf9f2SGordon Ross uint32_t 845a90cf9f2SGordon Ross smb_tree_connect_ipc(smb_request_t *sr, smb_arg_tcon_t *tcon) 846da6c28aaSamw { 847a90cf9f2SGordon Ross char *name = tcon->path; 848148c5f43SAlan Wright const char *any = "?????"; 8498b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_user_t *user = sr->uid_user; 8508b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_tree_t *tree; 851a90cf9f2SGordon Ross smb_kshare_t *si = tcon->si; 852a90cf9f2SGordon Ross char *service = tcon->service; 853da6c28aaSamw 854c8ec8eeaSjose borrego ASSERT(user); 855da6c28aaSamw 856a90cf9f2SGordon Ross if (service != NULL && 857a90cf9f2SGordon Ross strcmp(service, any) != 0 && 858a90cf9f2SGordon Ross strcasecmp(service, "IPC") != 0) { 859a90cf9f2SGordon Ross smb_tree_log(sr, name, "invalid service (%s)", service); 860a90cf9f2SGordon Ross return (NT_STATUS_BAD_DEVICE_TYPE); 861da6c28aaSamw } 862da6c28aaSamw 863a90cf9f2SGordon Ross if ((user->u_flags & SMB_USER_FLAG_ANON) && 864a90cf9f2SGordon Ross sr->sr_cfg->skc_restrict_anon) { 865a90cf9f2SGordon Ross smb_tree_log(sr, name, "access denied: restrict anonymous"); 866a90cf9f2SGordon Ross return (NT_STATUS_ACCESS_DENIED); 867148c5f43SAlan Wright } 8688d7e4166Sjose borrego 869a90cf9f2SGordon Ross tcon->optional_support = SMB_SUPPORT_SEARCH_BITS; 8708b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 8713b13a1efSThomas Keiser tree = smb_tree_alloc(sr, si, NULL, ACE_ALL_PERMS, 0); 872a90cf9f2SGordon Ross if (tree == NULL) 873a90cf9f2SGordon Ross return (NT_STATUS_INSUFF_SERVER_RESOURCES); 874c8ec8eeaSjose borrego 875a90cf9f2SGordon Ross sr->tid_tree = tree; 876a90cf9f2SGordon Ross sr->smb_tid = tree->t_tid; 877a90cf9f2SGordon Ross 878a90cf9f2SGordon Ross return (0); 879da6c28aaSamw } 880da6c28aaSamw 881da6c28aaSamw /* 882c8ec8eeaSjose borrego * Allocate a tree. 883da6c28aaSamw */ 884c8ec8eeaSjose borrego static smb_tree_t * 8853b13a1efSThomas Keiser smb_tree_alloc(smb_request_t *sr, const smb_kshare_t *si, 8863b13a1efSThomas Keiser smb_node_t *snode, uint32_t access, uint32_t execflags) 887da6c28aaSamw { 8883b13a1efSThomas Keiser smb_session_t *session = sr->session; 889c8ec8eeaSjose borrego smb_tree_t *tree; 890148c5f43SAlan Wright uint32_t stype = si->shr_type; 891c8ec8eeaSjose borrego uint16_t tid; 892da6c28aaSamw 8933b13a1efSThomas Keiser if (smb_idpool_alloc(&session->s_tid_pool, &tid)) 894c8ec8eeaSjose borrego return (NULL); 895da6c28aaSamw 8968622ec45SGordon Ross tree = kmem_cache_alloc(smb_cache_tree, KM_SLEEP); 897c8ec8eeaSjose borrego bzero(tree, sizeof (smb_tree_t)); 898da6c28aaSamw 8993b13a1efSThomas Keiser tree->t_session = session; 9003b13a1efSThomas Keiser tree->t_server = session->s_server; 9013b13a1efSThomas Keiser 9023b13a1efSThomas Keiser /* grab a ref for tree->t_owner */ 9033b13a1efSThomas Keiser smb_user_hold_internal(sr->uid_user); 9043b13a1efSThomas Keiser tree->t_owner = sr->uid_user; 905cb174861Sjoyce mcintosh 906148c5f43SAlan Wright if (STYPE_ISDSK(stype) || STYPE_ISPRN(stype)) { 9078b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (smb_tree_getattr(si, snode, tree) != 0) { 9083b13a1efSThomas Keiser smb_idpool_free(&session->s_tid_pool, tid); 9098622ec45SGordon Ross kmem_cache_free(smb_cache_tree, tree); 910c8ec8eeaSjose borrego return (NULL); 911da6c28aaSamw } 912da6c28aaSamw } 913c8ec8eeaSjose borrego 914c8ec8eeaSjose borrego if (smb_idpool_constructor(&tree->t_fid_pool)) { 9153b13a1efSThomas Keiser smb_idpool_free(&session->s_tid_pool, tid); 9168622ec45SGordon Ross kmem_cache_free(smb_cache_tree, tree); 917c8ec8eeaSjose borrego return (NULL); 918c8ec8eeaSjose borrego } 919c8ec8eeaSjose borrego 9207f667e74Sjose borrego if (smb_idpool_constructor(&tree->t_odid_pool)) { 921c8ec8eeaSjose borrego smb_idpool_destructor(&tree->t_fid_pool); 9223b13a1efSThomas Keiser smb_idpool_free(&session->s_tid_pool, tid); 9238622ec45SGordon Ross kmem_cache_free(smb_cache_tree, tree); 924c8ec8eeaSjose borrego return (NULL); 925c8ec8eeaSjose borrego } 926c8ec8eeaSjose borrego 927c8ec8eeaSjose borrego smb_llist_constructor(&tree->t_ofile_list, sizeof (smb_ofile_t), 928*811599a4SMatt Barden offsetof(smb_ofile_t, f_tree_lnd)); 929c8ec8eeaSjose borrego 930c8ec8eeaSjose borrego smb_llist_constructor(&tree->t_odir_list, sizeof (smb_odir_t), 931c8ec8eeaSjose borrego offsetof(smb_odir_t, d_lnd)); 932c8ec8eeaSjose borrego 9338b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States (void) strlcpy(tree->t_sharename, si->shr_name, 934c8ec8eeaSjose borrego sizeof (tree->t_sharename)); 9358b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States (void) strlcpy(tree->t_resource, si->shr_path, 9368b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States sizeof (tree->t_resource)); 937c8ec8eeaSjose borrego 938c8ec8eeaSjose borrego mutex_init(&tree->t_mutex, NULL, MUTEX_DEFAULT, NULL); 939c8ec8eeaSjose borrego 940c8ec8eeaSjose borrego tree->t_refcnt = 1; 941c8ec8eeaSjose borrego tree->t_tid = tid; 942c8ec8eeaSjose borrego tree->t_res_type = stype; 943c8ec8eeaSjose borrego tree->t_state = SMB_TREE_STATE_CONNECTED; 944c8ec8eeaSjose borrego tree->t_magic = SMB_TREE_MAGIC; 945743a77edSAlan Wright tree->t_access = access; 9461fcced4cSJordan Brown tree->t_connect_time = gethrestime_sec(); 947148c5f43SAlan Wright tree->t_execflags = execflags; 948743a77edSAlan Wright 949743a77edSAlan Wright /* if FS is readonly, enforce that here */ 950743a77edSAlan Wright if (tree->t_flags & SMB_TREE_READONLY) 951743a77edSAlan Wright tree->t_access &= ~ACE_ALL_WRITE_PERMS; 952c8ec8eeaSjose borrego 953148c5f43SAlan Wright if (STYPE_ISDSK(stype) || STYPE_ISPRN(stype)) { 954c8ec8eeaSjose borrego smb_node_ref(snode); 955c8ec8eeaSjose borrego tree->t_snode = snode; 956c8ec8eeaSjose borrego tree->t_acltype = smb_fsop_acltype(snode); 957c8ec8eeaSjose borrego } 958c8ec8eeaSjose borrego 9593b13a1efSThomas Keiser smb_llist_enter(&session->s_tree_list, RW_WRITER); 9603b13a1efSThomas Keiser smb_llist_insert_head(&session->s_tree_list, tree); 9613b13a1efSThomas Keiser smb_llist_exit(&session->s_tree_list); 9623b13a1efSThomas Keiser atomic_inc_32(&session->s_tree_cnt); 9633b13a1efSThomas Keiser smb_server_inc_trees(session->s_server); 964c8ec8eeaSjose borrego return (tree); 965c8ec8eeaSjose borrego } 966da6c28aaSamw 967da6c28aaSamw /* 9689fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Deallocate a tree. The open file and open directory lists should be 9699fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * empty. 970c8ec8eeaSjose borrego * 9719fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Remove the tree from the user's tree list before freeing resources 9729fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * associated with the tree. 973da6c28aaSamw */ 974*811599a4SMatt Barden static void 9759fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_tree_dealloc(void *arg) 976da6c28aaSamw { 9773b13a1efSThomas Keiser smb_session_t *session; 9789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_tree_t *tree = (smb_tree_t *)arg; 9799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 9809fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_TREE_VALID(tree); 981da6c28aaSamw ASSERT(tree->t_state == SMB_TREE_STATE_DISCONNECTED); 982da6c28aaSamw ASSERT(tree->t_refcnt == 0); 983da6c28aaSamw 9843b13a1efSThomas Keiser session = tree->t_session; 9853b13a1efSThomas Keiser smb_llist_enter(&session->s_tree_list, RW_WRITER); 9863b13a1efSThomas Keiser smb_llist_remove(&session->s_tree_list, tree); 9873b13a1efSThomas Keiser smb_idpool_free(&session->s_tid_pool, tree->t_tid); 9883b13a1efSThomas Keiser atomic_dec_32(&session->s_tree_cnt); 9893b13a1efSThomas Keiser smb_llist_exit(&session->s_tree_list); 9909fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 991*811599a4SMatt Barden /* 992*811599a4SMatt Barden * This tree is no longer on s_tree_list, however... 993*811599a4SMatt Barden * 994*811599a4SMatt Barden * This is called via smb_llist_post, which means it may run 995*811599a4SMatt Barden * BEFORE smb_tree_release drops t_mutex (if another thread 996*811599a4SMatt Barden * flushes the delete queue before we do). Synchronize. 997*811599a4SMatt Barden */ 9989fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States mutex_enter(&tree->t_mutex); 9999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States mutex_exit(&tree->t_mutex); 1000da6c28aaSamw 1001da6c28aaSamw tree->t_magic = (uint32_t)~SMB_TREE_MAGIC; 1002da6c28aaSamw 1003c8ec8eeaSjose borrego if (tree->t_snode) 1004da6c28aaSamw smb_node_release(tree->t_snode); 1005c8ec8eeaSjose borrego 1006da6c28aaSamw mutex_destroy(&tree->t_mutex); 1007da6c28aaSamw smb_llist_destructor(&tree->t_ofile_list); 1008da6c28aaSamw smb_llist_destructor(&tree->t_odir_list); 1009da6c28aaSamw smb_idpool_destructor(&tree->t_fid_pool); 10107f667e74Sjose borrego smb_idpool_destructor(&tree->t_odid_pool); 10113b13a1efSThomas Keiser 10123b13a1efSThomas Keiser SMB_USER_VALID(tree->t_owner); 10133b13a1efSThomas Keiser smb_user_release(tree->t_owner); 10143b13a1efSThomas Keiser 10158622ec45SGordon Ross kmem_cache_free(smb_cache_tree, tree); 1016da6c28aaSamw } 1017da6c28aaSamw 1018da6c28aaSamw /* 1019c8ec8eeaSjose borrego * Determine whether or not a tree is connected. 1020c8ec8eeaSjose borrego * This function must be called with the tree mutex held. 1021c8ec8eeaSjose borrego */ 1022c8ec8eeaSjose borrego static boolean_t 10238b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_tree_is_connected_locked(smb_tree_t *tree) 1024c8ec8eeaSjose borrego { 1025c8ec8eeaSjose borrego switch (tree->t_state) { 1026c8ec8eeaSjose borrego case SMB_TREE_STATE_CONNECTED: 1027c8ec8eeaSjose borrego return (B_TRUE); 1028c8ec8eeaSjose borrego 1029c8ec8eeaSjose borrego case SMB_TREE_STATE_DISCONNECTING: 1030c8ec8eeaSjose borrego case SMB_TREE_STATE_DISCONNECTED: 1031c8ec8eeaSjose borrego /* 1032*811599a4SMatt Barden * The tree exists but is being disconnected or destroyed. 1033c8ec8eeaSjose borrego */ 1034c8ec8eeaSjose borrego return (B_FALSE); 1035c8ec8eeaSjose borrego 1036c8ec8eeaSjose borrego default: 1037c8ec8eeaSjose borrego ASSERT(0); 1038c8ec8eeaSjose borrego return (B_FALSE); 1039c8ec8eeaSjose borrego } 1040c8ec8eeaSjose borrego } 1041c8ec8eeaSjose borrego 1042c8ec8eeaSjose borrego /* 1043c8ec8eeaSjose borrego * Return a pointer to the share name within a share resource path. 1044da6c28aaSamw * 1045c8ec8eeaSjose borrego * The share path may be a Uniform Naming Convention (UNC) string 1046c8ec8eeaSjose borrego * (\\server\share) or simply the share name. We validate the UNC 1047c8ec8eeaSjose borrego * format but we don't look at the server name. 1048c8ec8eeaSjose borrego */ 1049a90cf9f2SGordon Ross static char * 1050a90cf9f2SGordon Ross smb_tree_get_sharename(char *unc_path) 1051c8ec8eeaSjose borrego { 1052a90cf9f2SGordon Ross char *sharename = unc_path; 1053c8ec8eeaSjose borrego 1054c8ec8eeaSjose borrego if (sharename[0] == '\\') { 1055c8ec8eeaSjose borrego /* 1056c8ec8eeaSjose borrego * Looks like a UNC path, validate the format. 1057c8ec8eeaSjose borrego */ 1058c8ec8eeaSjose borrego if (sharename[1] != '\\') 1059c8ec8eeaSjose borrego return (NULL); 1060c8ec8eeaSjose borrego 1061c8ec8eeaSjose borrego if ((sharename = strchr(sharename+2, '\\')) == NULL) 1062c8ec8eeaSjose borrego return (NULL); 1063c8ec8eeaSjose borrego 1064c8ec8eeaSjose borrego ++sharename; 1065c8ec8eeaSjose borrego } else if (strchr(sharename, '\\') != NULL) { 1066c8ec8eeaSjose borrego /* 1067c8ec8eeaSjose borrego * This should be a share name (no embedded \'s). 1068c8ec8eeaSjose borrego */ 1069c8ec8eeaSjose borrego return (NULL); 1070c8ec8eeaSjose borrego } 1071c8ec8eeaSjose borrego 1072c8ec8eeaSjose borrego return (sharename); 1073c8ec8eeaSjose borrego } 1074c8ec8eeaSjose borrego 1075da6c28aaSamw /* 1076c8ec8eeaSjose borrego * Obtain the tree attributes: volume name, typename and flags. 1077c8ec8eeaSjose borrego */ 1078c8ec8eeaSjose borrego static int 1079148c5f43SAlan Wright smb_tree_getattr(const smb_kshare_t *si, smb_node_t *node, smb_tree_t *tree) 1080c8ec8eeaSjose borrego { 1081c8ec8eeaSjose borrego vfs_t *vfsp = SMB_NODE_VFS(node); 1082c8ec8eeaSjose borrego 1083c8ec8eeaSjose borrego ASSERT(vfsp); 1084c8ec8eeaSjose borrego 1085c8ec8eeaSjose borrego if (getvfs(&vfsp->vfs_fsid) != vfsp) 1086c8ec8eeaSjose borrego return (ESTALE); 1087c8ec8eeaSjose borrego 1088c8ec8eeaSjose borrego smb_tree_get_volname(vfsp, tree); 10898b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_tree_get_flags(si, vfsp, tree); 1090c8ec8eeaSjose borrego 1091c8ec8eeaSjose borrego VFS_RELE(vfsp); 1092c8ec8eeaSjose borrego return (0); 1093c8ec8eeaSjose borrego } 1094c8ec8eeaSjose borrego 1095c8ec8eeaSjose borrego /* 1096c8ec8eeaSjose borrego * Extract the volume name. 1097c8ec8eeaSjose borrego */ 1098c8ec8eeaSjose borrego static void 1099c8ec8eeaSjose borrego smb_tree_get_volname(vfs_t *vfsp, smb_tree_t *tree) 1100c8ec8eeaSjose borrego { 1101a90cf9f2SGordon Ross #ifdef _FAKE_KERNEL 1102a90cf9f2SGordon Ross _NOTE(ARGUNUSED(vfsp)) 1103a90cf9f2SGordon Ross (void) strlcpy(tree->t_volume, "fake", SMB_VOLNAMELEN); 1104a90cf9f2SGordon Ross #else /* _FAKE_KERNEL */ 1105c8ec8eeaSjose borrego refstr_t *vfs_mntpoint; 1106c8ec8eeaSjose borrego const char *s; 1107c8ec8eeaSjose borrego char *name; 1108c8ec8eeaSjose borrego 1109c8ec8eeaSjose borrego vfs_mntpoint = vfs_getmntpoint(vfsp); 1110c8ec8eeaSjose borrego 1111b819cea2SGordon Ross s = refstr_value(vfs_mntpoint); 1112c8ec8eeaSjose borrego s += strspn(s, "/"); 1113c8ec8eeaSjose borrego (void) strlcpy(tree->t_volume, s, SMB_VOLNAMELEN); 1114c8ec8eeaSjose borrego 1115c8ec8eeaSjose borrego refstr_rele(vfs_mntpoint); 1116c8ec8eeaSjose borrego 1117c8ec8eeaSjose borrego name = tree->t_volume; 1118c8ec8eeaSjose borrego (void) strsep((char **)&name, "/"); 1119a90cf9f2SGordon Ross #endif /* _FAKE_KERNEL */ 1120c8ec8eeaSjose borrego } 1121c8ec8eeaSjose borrego 1122c8ec8eeaSjose borrego /* 1123a90cf9f2SGordon Ross * Always set "unicode on disk" because we always use utf8 names locally. 1124c8ec8eeaSjose borrego * Always set ACL support because the VFS will fake ACLs for file systems 1125c8ec8eeaSjose borrego * that don't support them. 1126da6c28aaSamw * 1127c8ec8eeaSjose borrego * Some flags are dependent on the typename, which is also set up here. 1128c8ec8eeaSjose borrego * File system types are hardcoded in uts/common/os/vfs_conf.c. 1129da6c28aaSamw */ 1130c8ec8eeaSjose borrego static void 1131148c5f43SAlan Wright smb_tree_get_flags(const smb_kshare_t *si, vfs_t *vfsp, smb_tree_t *tree) 1132da6c28aaSamw { 11335f1ef25cSAram Hăvărneanu smb_session_t *ssn = tree->t_session; 1134b819cea2SGordon Ross struct vfssw *vswp; 11355f1ef25cSAram Hăvărneanu 1136fc724630SAlan Wright typedef struct smb_mtype { 1137fc724630SAlan Wright char *mt_name; 1138fc724630SAlan Wright size_t mt_namelen; 1139fc724630SAlan Wright uint32_t mt_flags; 1140fc724630SAlan Wright } smb_mtype_t; 1141fc724630SAlan Wright 1142fc724630SAlan Wright static smb_mtype_t smb_mtype[] = { 1143a90cf9f2SGordon Ross { "zfs", 3, SMB_TREE_QUOTA | SMB_TREE_SPARSE}, 1144a90cf9f2SGordon Ross { "ufs", 3, 0 }, 11459fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States { "nfs", 3, SMB_TREE_NFS_MOUNTED }, 11469fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States { "tmpfs", 5, SMB_TREE_NO_EXPORT } 1147fc724630SAlan Wright }; 1148fc724630SAlan Wright smb_mtype_t *mtype; 1149fc724630SAlan Wright char *name; 1150a90cf9f2SGordon Ross uint32_t flags = 1151a90cf9f2SGordon Ross SMB_TREE_SUPPORTS_ACLS | 1152a90cf9f2SGordon Ross SMB_TREE_UNICODE_ON_DISK; 1153fc724630SAlan Wright int i; 1154da6c28aaSamw 11559fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (si->shr_flags & SMB_SHRF_DFSROOT) 11569fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States flags |= SMB_TREE_DFSROOT; 11579fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 11588b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (si->shr_flags & SMB_SHRF_CATIA) 11598b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States flags |= SMB_TREE_CATIA; 11608b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 1161e3f2c991SKeyur Desai if (si->shr_flags & SMB_SHRF_ABE) 1162e3f2c991SKeyur Desai flags |= SMB_TREE_ABE; 1163e3f2c991SKeyur Desai 11645f1ef25cSAram Hăvărneanu if (ssn->s_cfg.skc_oplock_enable) { 1165cb174861Sjoyce mcintosh /* if 'smb' zfs property: oplocks=enabled */ 1166cb174861Sjoyce mcintosh flags |= SMB_TREE_OPLOCKS; 1167cb174861Sjoyce mcintosh } 1168cb174861Sjoyce mcintosh 11695f1ef25cSAram Hăvărneanu /* Global config option for now. Later make per-share. */ 11705f1ef25cSAram Hăvărneanu if (ssn->s_cfg.skc_traverse_mounts) 11715f1ef25cSAram Hăvărneanu flags |= SMB_TREE_TRAVERSE_MOUNTS; 11725f1ef25cSAram Hăvărneanu 1173cb174861Sjoyce mcintosh /* if 'smb' zfs property: shortnames=enabled */ 1174cb174861Sjoyce mcintosh if (smb_shortnames) 1175cb174861Sjoyce mcintosh flags |= SMB_TREE_SHORTNAMES; 1176cb174861Sjoyce mcintosh 1177c8ec8eeaSjose borrego if (vfsp->vfs_flag & VFS_RDONLY) 1178c8ec8eeaSjose borrego flags |= SMB_TREE_READONLY; 1179c8ec8eeaSjose borrego 1180c8ec8eeaSjose borrego if (vfsp->vfs_flag & VFS_XATTR) 1181c8ec8eeaSjose borrego flags |= SMB_TREE_STREAMS; 1182c8ec8eeaSjose borrego 1183b819cea2SGordon Ross vswp = vfs_getvfsswbyvfsops(vfs_getops(vfsp)); 1184b819cea2SGordon Ross if (vswp != NULL) { 1185b819cea2SGordon Ross name = vswp->vsw_name; 1186b819cea2SGordon Ross vfs_unrefvfssw(vswp); 1187b819cea2SGordon Ross } else { 1188b819cea2SGordon Ross name = "?"; 1189b819cea2SGordon Ross } 1190c8ec8eeaSjose borrego 1191fc724630SAlan Wright for (i = 0; i < sizeof (smb_mtype) / sizeof (smb_mtype[0]); ++i) { 1192fc724630SAlan Wright mtype = &smb_mtype[i]; 1193fc724630SAlan Wright if (strncasecmp(name, mtype->mt_name, mtype->mt_namelen) == 0) 1194fc724630SAlan Wright flags |= mtype->mt_flags; 1195fc724630SAlan Wright } 1196c8ec8eeaSjose borrego 1197ca5fb90aSGordon Ross /* 1198ca5fb90aSGordon Ross * SMB_TREE_QUOTA will be on here if the FS is ZFS. We want to 1199ca5fb90aSGordon Ross * turn it OFF when the share property says false. 1200ca5fb90aSGordon Ross */ 1201ca5fb90aSGordon Ross if ((si->shr_flags & SMB_SHRF_QUOTAS) == 0) 1202ca5fb90aSGordon Ross flags &= ~SMB_TREE_QUOTA; 1203ca5fb90aSGordon Ross 1204c8ec8eeaSjose borrego (void) strlcpy(tree->t_typename, name, SMB_TYPENAMELEN); 1205bbf6f00cSJordan Brown (void) smb_strupr((char *)tree->t_typename); 1206da6c28aaSamw 1207c8ec8eeaSjose borrego if (vfs_has_feature(vfsp, VFSFT_XVATTR)) 1208c8ec8eeaSjose borrego flags |= SMB_TREE_XVATTR; 1209c8ec8eeaSjose borrego 1210c8ec8eeaSjose borrego if (vfs_has_feature(vfsp, VFSFT_CASEINSENSITIVE)) 1211c8ec8eeaSjose borrego flags |= SMB_TREE_CASEINSENSITIVE; 1212c8ec8eeaSjose borrego 1213c8ec8eeaSjose borrego if (vfs_has_feature(vfsp, VFSFT_NOCASESENSITIVE)) 1214c8ec8eeaSjose borrego flags |= SMB_TREE_NO_CASESENSITIVE; 1215c8ec8eeaSjose borrego 1216c8ec8eeaSjose borrego if (vfs_has_feature(vfsp, VFSFT_DIRENTFLAGS)) 1217c8ec8eeaSjose borrego flags |= SMB_TREE_DIRENTFLAGS; 1218c8ec8eeaSjose borrego 1219c8ec8eeaSjose borrego if (vfs_has_feature(vfsp, VFSFT_ACLONCREATE)) 1220c8ec8eeaSjose borrego flags |= SMB_TREE_ACLONCREATE; 1221c8ec8eeaSjose borrego 1222c8ec8eeaSjose borrego if (vfs_has_feature(vfsp, VFSFT_ACEMASKONACCESS)) 1223c8ec8eeaSjose borrego flags |= SMB_TREE_ACEMASKONACCESS; 1224c8ec8eeaSjose borrego 1225fc724630SAlan Wright DTRACE_PROBE2(smb__tree__flags, uint32_t, flags, char *, name); 1226fc724630SAlan Wright 1227c8ec8eeaSjose borrego 1228c8ec8eeaSjose borrego tree->t_flags = flags; 1229c8ec8eeaSjose borrego } 1230c8ec8eeaSjose borrego 1231c8ec8eeaSjose borrego /* 1232c8ec8eeaSjose borrego * Report share access result to syslog. 1233c8ec8eeaSjose borrego */ 1234c8ec8eeaSjose borrego static void 1235c8ec8eeaSjose borrego smb_tree_log(smb_request_t *sr, const char *sharename, const char *fmt, ...) 1236c8ec8eeaSjose borrego { 1237c8ec8eeaSjose borrego va_list ap; 1238c8ec8eeaSjose borrego char buf[128]; 1239c8ec8eeaSjose borrego smb_user_t *user = sr->uid_user; 1240c8ec8eeaSjose borrego 1241c8ec8eeaSjose borrego ASSERT(user); 1242c8ec8eeaSjose borrego 1243c8ec8eeaSjose borrego if (smb_tcon_mute) 1244c8ec8eeaSjose borrego return; 1245c8ec8eeaSjose borrego 1246c8ec8eeaSjose borrego if ((user->u_name) && (strcasecmp(sharename, "IPC$") == 0)) { 1247c8ec8eeaSjose borrego /* 1248c8ec8eeaSjose borrego * Only report normal users, i.e. ignore W2K misuse 1249c8ec8eeaSjose borrego * of the IPC connection by filtering out internal 1250c8ec8eeaSjose borrego * names such as nobody and root. 1251c8ec8eeaSjose borrego */ 1252c8ec8eeaSjose borrego if ((strcmp(user->u_name, "root") == 0) || 1253c8ec8eeaSjose borrego (strcmp(user->u_name, "nobody") == 0)) { 1254c8ec8eeaSjose borrego return; 1255da6c28aaSamw } 1256da6c28aaSamw } 1257da6c28aaSamw 1258c8ec8eeaSjose borrego va_start(ap, fmt); 1259c8ec8eeaSjose borrego (void) vsnprintf(buf, 128, fmt, ap); 1260c8ec8eeaSjose borrego va_end(ap); 1261c8ec8eeaSjose borrego 1262c8ec8eeaSjose borrego cmn_err(CE_NOTE, "smbd[%s\\%s]: %s %s", 1263c8ec8eeaSjose borrego user->u_domain, user->u_name, sharename, buf); 1264da6c28aaSamw } 12657f667e74Sjose borrego 12667f667e74Sjose borrego /* 12677f667e74Sjose borrego * smb_tree_lookup_odir 12687f667e74Sjose borrego * 12697f667e74Sjose borrego * Find the specified odir in the tree's list of odirs, and 12707f667e74Sjose borrego * attempt to obtain a hold on the odir. 12717f667e74Sjose borrego * 12727f667e74Sjose borrego * Returns NULL if odir not found or a hold cannot be obtained. 12737f667e74Sjose borrego */ 12747f667e74Sjose borrego smb_odir_t * 12753b13a1efSThomas Keiser smb_tree_lookup_odir(smb_request_t *sr, uint16_t odid) 12767f667e74Sjose borrego { 12777f667e74Sjose borrego smb_odir_t *od; 12787f667e74Sjose borrego smb_llist_t *od_list; 12793b13a1efSThomas Keiser smb_tree_t *tree = sr->tid_tree; 12807f667e74Sjose borrego 12817f667e74Sjose borrego ASSERT(tree->t_magic == SMB_TREE_MAGIC); 12827f667e74Sjose borrego 12837f667e74Sjose borrego od_list = &tree->t_odir_list; 12847f667e74Sjose borrego 12853b13a1efSThomas Keiser smb_llist_enter(od_list, RW_READER); 12867f667e74Sjose borrego od = smb_llist_head(od_list); 12877f667e74Sjose borrego while (od) { 12883b13a1efSThomas Keiser if (od->d_odid == odid) 12897f667e74Sjose borrego break; 12907f667e74Sjose borrego od = smb_llist_next(od_list, od); 12917f667e74Sjose borrego } 12923b13a1efSThomas Keiser if (od == NULL) 12933b13a1efSThomas Keiser goto out; 12943b13a1efSThomas Keiser 12953b13a1efSThomas Keiser /* 12963b13a1efSThomas Keiser * Only allow use of a given Search ID with the same UID that 12973b13a1efSThomas Keiser * was used to create it. MS-CIFS 3.3.5.14 12983b13a1efSThomas Keiser */ 12993b13a1efSThomas Keiser if (od->d_user != sr->uid_user) { 13003b13a1efSThomas Keiser od = NULL; 13013b13a1efSThomas Keiser goto out; 13023b13a1efSThomas Keiser } 13033b13a1efSThomas Keiser if (!smb_odir_hold(od)) 13043b13a1efSThomas Keiser od = NULL; 13057f667e74Sjose borrego 13063b13a1efSThomas Keiser out: 13077f667e74Sjose borrego smb_llist_exit(od_list); 13087f667e74Sjose borrego return (od); 13097f667e74Sjose borrego } 13107f667e74Sjose borrego 13118b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States boolean_t 13128b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_tree_is_connected(smb_tree_t *tree) 13138b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States { 13148b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States boolean_t rb; 13158b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 13168b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States mutex_enter(&tree->t_mutex); 13178b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States rb = smb_tree_is_connected_locked(tree); 13188b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States mutex_exit(&tree->t_mutex); 13198b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States return (rb); 13208b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States } 13218b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 13221fcced4cSJordan Brown /* 13231fcced4cSJordan Brown * Get the next open ofile in the list. A reference is taken on 13241fcced4cSJordan Brown * the ofile, which can be released later with smb_ofile_release(). 13251fcced4cSJordan Brown * 13261fcced4cSJordan Brown * If the specified ofile is NULL, search from the beginning of the 13271fcced4cSJordan Brown * list. Otherwise, the search starts just after that ofile. 13281fcced4cSJordan Brown * 13291fcced4cSJordan Brown * Returns NULL if there are no open files in the list. 13301fcced4cSJordan Brown */ 13311fcced4cSJordan Brown static smb_ofile_t * 13321fcced4cSJordan Brown smb_tree_get_ofile(smb_tree_t *tree, smb_ofile_t *of) 13331fcced4cSJordan Brown { 13341fcced4cSJordan Brown smb_llist_t *ofile_list; 13351fcced4cSJordan Brown 13361fcced4cSJordan Brown ASSERT(tree); 13371fcced4cSJordan Brown ASSERT(tree->t_magic == SMB_TREE_MAGIC); 13381fcced4cSJordan Brown 13391fcced4cSJordan Brown ofile_list = &tree->t_ofile_list; 13401fcced4cSJordan Brown smb_llist_enter(ofile_list, RW_READER); 13411fcced4cSJordan Brown 13421fcced4cSJordan Brown if (of) { 13431fcced4cSJordan Brown ASSERT(of->f_magic == SMB_OFILE_MAGIC); 13441fcced4cSJordan Brown of = smb_llist_next(ofile_list, of); 13451fcced4cSJordan Brown } else { 13461fcced4cSJordan Brown of = smb_llist_head(ofile_list); 13471fcced4cSJordan Brown } 13481fcced4cSJordan Brown 13491fcced4cSJordan Brown while (of) { 13501fcced4cSJordan Brown if (smb_ofile_hold(of)) 13511fcced4cSJordan Brown break; 13521fcced4cSJordan Brown 13531fcced4cSJordan Brown of = smb_llist_next(ofile_list, of); 13541fcced4cSJordan Brown } 13551fcced4cSJordan Brown 13561fcced4cSJordan Brown smb_llist_exit(ofile_list); 13571fcced4cSJordan Brown return (of); 13581fcced4cSJordan Brown } 13591fcced4cSJordan Brown 13607f667e74Sjose borrego /* 13617f667e74Sjose borrego * smb_tree_get_odir 13627f667e74Sjose borrego * 1363a1511e6bSjoyce mcintosh * Find the next odir in the tree's list of odirs, and obtain a 1364a1511e6bSjoyce mcintosh * hold on it. 13657f667e74Sjose borrego * If the specified odir is NULL the search starts at the beginning 13667f667e74Sjose borrego * of the tree's odir list, otherwise the search starts after the 13677f667e74Sjose borrego * specified odir. 13687f667e74Sjose borrego */ 13697f667e74Sjose borrego static smb_odir_t * 13707f667e74Sjose borrego smb_tree_get_odir(smb_tree_t *tree, smb_odir_t *od) 13717f667e74Sjose borrego { 13727f667e74Sjose borrego smb_llist_t *od_list; 13737f667e74Sjose borrego 13747f667e74Sjose borrego ASSERT(tree); 13757f667e74Sjose borrego ASSERT(tree->t_magic == SMB_TREE_MAGIC); 13767f667e74Sjose borrego 13777f667e74Sjose borrego od_list = &tree->t_odir_list; 13787f667e74Sjose borrego smb_llist_enter(od_list, RW_READER); 13797f667e74Sjose borrego 13807f667e74Sjose borrego if (od) { 13817f667e74Sjose borrego ASSERT(od->d_magic == SMB_ODIR_MAGIC); 13827f667e74Sjose borrego od = smb_llist_next(od_list, od); 13837f667e74Sjose borrego } else { 13847f667e74Sjose borrego od = smb_llist_head(od_list); 13857f667e74Sjose borrego } 13867f667e74Sjose borrego 13877f667e74Sjose borrego while (od) { 13887f667e74Sjose borrego ASSERT(od->d_magic == SMB_ODIR_MAGIC); 13897f667e74Sjose borrego 13907f667e74Sjose borrego if (smb_odir_hold(od)) 13917f667e74Sjose borrego break; 13927f667e74Sjose borrego od = smb_llist_next(od_list, od); 13937f667e74Sjose borrego } 13947f667e74Sjose borrego 13957f667e74Sjose borrego smb_llist_exit(od_list); 13967f667e74Sjose borrego return (od); 13977f667e74Sjose borrego } 13987f667e74Sjose borrego 13997f667e74Sjose borrego /* 14007f667e74Sjose borrego * smb_tree_close_odirs 14017f667e74Sjose borrego * 14027f667e74Sjose borrego * Close all open odirs in the tree's list which were opened by 14037f667e74Sjose borrego * the process identified by pid. 14047f667e74Sjose borrego * If pid is zero, close all open odirs in the tree's list. 14057f667e74Sjose borrego */ 14067f667e74Sjose borrego static void 14077f667e74Sjose borrego smb_tree_close_odirs(smb_tree_t *tree, uint16_t pid) 14087f667e74Sjose borrego { 14097f667e74Sjose borrego smb_odir_t *od, *next_od; 14107f667e74Sjose borrego 14117f667e74Sjose borrego ASSERT(tree); 14127f667e74Sjose borrego ASSERT(tree->t_magic == SMB_TREE_MAGIC); 14137f667e74Sjose borrego 14147f667e74Sjose borrego od = smb_tree_get_odir(tree, NULL); 14157f667e74Sjose borrego while (od) { 14167f667e74Sjose borrego ASSERT(od->d_magic == SMB_ODIR_MAGIC); 14177f667e74Sjose borrego ASSERT(od->d_tree == tree); 14187f667e74Sjose borrego 14197f667e74Sjose borrego next_od = smb_tree_get_odir(tree, od); 14207f667e74Sjose borrego if ((pid == 0) || (od->d_opened_by_pid == pid)) 14219fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_odir_close(od); 14227f667e74Sjose borrego smb_odir_release(od); 14237f667e74Sjose borrego 14247f667e74Sjose borrego od = next_od; 14257f667e74Sjose borrego } 14267f667e74Sjose borrego } 142729bd2886SAlan Wright 142829bd2886SAlan Wright static void 14293b13a1efSThomas Keiser smb_tree_set_execinfo(smb_tree_t *tree, smb_shr_execinfo_t *exec, 14303b13a1efSThomas Keiser int exec_type) 143129bd2886SAlan Wright { 1432148c5f43SAlan Wright exec->e_sharename = tree->t_sharename; 14333b13a1efSThomas Keiser exec->e_winname = tree->t_owner->u_name; 14343b13a1efSThomas Keiser exec->e_userdom = tree->t_owner->u_domain; 1435148c5f43SAlan Wright exec->e_srv_ipaddr = tree->t_session->local_ipaddr; 1436148c5f43SAlan Wright exec->e_cli_ipaddr = tree->t_session->ipaddr; 1437148c5f43SAlan Wright exec->e_cli_netbiosname = tree->t_session->workstation; 14383b13a1efSThomas Keiser exec->e_uid = crgetuid(tree->t_owner->u_cred); 1439148c5f43SAlan Wright exec->e_type = exec_type; 144029bd2886SAlan Wright } 14411fcced4cSJordan Brown 14421fcced4cSJordan Brown /* 14431fcced4cSJordan Brown * Private function to support smb_tree_enum. 14441fcced4cSJordan Brown */ 14451fcced4cSJordan Brown static int 14461fcced4cSJordan Brown smb_tree_enum_private(smb_tree_t *tree, smb_svcenum_t *svcenum) 14471fcced4cSJordan Brown { 14481fcced4cSJordan Brown uint8_t *pb; 14491fcced4cSJordan Brown uint_t nbytes; 14501fcced4cSJordan Brown int rc; 14511fcced4cSJordan Brown 14521fcced4cSJordan Brown if (svcenum->se_nskip > 0) { 14531fcced4cSJordan Brown svcenum->se_nskip--; 14541fcced4cSJordan Brown return (0); 14551fcced4cSJordan Brown } 14561fcced4cSJordan Brown 14571fcced4cSJordan Brown if (svcenum->se_nitems >= svcenum->se_nlimit) { 14581fcced4cSJordan Brown svcenum->se_nitems = svcenum->se_nlimit; 14591fcced4cSJordan Brown return (0); 14601fcced4cSJordan Brown } 14611fcced4cSJordan Brown 14621fcced4cSJordan Brown pb = &svcenum->se_buf[svcenum->se_bused]; 14631fcced4cSJordan Brown rc = smb_tree_netinfo_encode(tree, pb, svcenum->se_bavail, &nbytes); 14641fcced4cSJordan Brown if (rc == 0) { 14651fcced4cSJordan Brown svcenum->se_bavail -= nbytes; 14661fcced4cSJordan Brown svcenum->se_bused += nbytes; 14671fcced4cSJordan Brown svcenum->se_nitems++; 14681fcced4cSJordan Brown } 14691fcced4cSJordan Brown 14701fcced4cSJordan Brown return (rc); 14711fcced4cSJordan Brown } 14721fcced4cSJordan Brown 14731fcced4cSJordan Brown /* 14741fcced4cSJordan Brown * Encode connection information into a buffer: connection information 14751fcced4cSJordan Brown * needed in user space to support RPC requests. 14761fcced4cSJordan Brown */ 14771fcced4cSJordan Brown static int 14781fcced4cSJordan Brown smb_tree_netinfo_encode(smb_tree_t *tree, uint8_t *buf, size_t buflen, 14791fcced4cSJordan Brown uint32_t *nbytes) 14801fcced4cSJordan Brown { 14811fcced4cSJordan Brown smb_netconnectinfo_t info; 14821fcced4cSJordan Brown int rc; 14831fcced4cSJordan Brown 14841fcced4cSJordan Brown smb_tree_netinfo_init(tree, &info); 14851fcced4cSJordan Brown rc = smb_netconnectinfo_encode(&info, buf, buflen, nbytes); 14861fcced4cSJordan Brown smb_tree_netinfo_fini(&info); 14871fcced4cSJordan Brown 14881fcced4cSJordan Brown return (rc); 14891fcced4cSJordan Brown } 14901fcced4cSJordan Brown 14913b13a1efSThomas Keiser static void 14923b13a1efSThomas Keiser smb_tree_netinfo_username(smb_tree_t *tree, char **namestr, uint32_t *namelen) 14933b13a1efSThomas Keiser { 14943b13a1efSThomas Keiser smb_user_t *user = tree->t_owner; 14953b13a1efSThomas Keiser 14963b13a1efSThomas Keiser /* 14973b13a1efSThomas Keiser * u_domain_len and u_name_len include the '\0' in their 14983b13a1efSThomas Keiser * lengths, hence the sum of the two lengths gives us room 14993b13a1efSThomas Keiser * for both the '\\' and '\0' chars. 15003b13a1efSThomas Keiser */ 15013b13a1efSThomas Keiser ASSERT(namestr); 15023b13a1efSThomas Keiser ASSERT(namelen); 15033b13a1efSThomas Keiser ASSERT(user->u_domain_len > 0); 15043b13a1efSThomas Keiser ASSERT(user->u_name_len > 0); 15053b13a1efSThomas Keiser *namelen = user->u_domain_len + user->u_name_len; 15063b13a1efSThomas Keiser *namestr = kmem_alloc(*namelen, KM_SLEEP); 15073b13a1efSThomas Keiser (void) snprintf(*namestr, *namelen, "%s\\%s", user->u_domain, 15083b13a1efSThomas Keiser user->u_name); 15093b13a1efSThomas Keiser } 15103b13a1efSThomas Keiser 15111fcced4cSJordan Brown /* 15121fcced4cSJordan Brown * Note: ci_numusers should be the number of users connected to 15131fcced4cSJordan Brown * the share rather than the number of references on the tree but 15141fcced4cSJordan Brown * we don't have a mechanism to track users/share in smbsrv yet. 15151fcced4cSJordan Brown */ 15161fcced4cSJordan Brown static void 15171fcced4cSJordan Brown smb_tree_netinfo_init(smb_tree_t *tree, smb_netconnectinfo_t *info) 15181fcced4cSJordan Brown { 15191fcced4cSJordan Brown ASSERT(tree); 15201fcced4cSJordan Brown 15211fcced4cSJordan Brown info->ci_id = tree->t_tid; 15221fcced4cSJordan Brown info->ci_type = tree->t_res_type; 15231fcced4cSJordan Brown info->ci_numopens = tree->t_open_files; 15241fcced4cSJordan Brown info->ci_numusers = tree->t_refcnt; 15251fcced4cSJordan Brown info->ci_time = gethrestime_sec() - tree->t_connect_time; 15261fcced4cSJordan Brown 15271fcced4cSJordan Brown info->ci_sharelen = strlen(tree->t_sharename) + 1; 15289fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States info->ci_share = smb_mem_strdup(tree->t_sharename); 15291fcced4cSJordan Brown 15303b13a1efSThomas Keiser smb_tree_netinfo_username(tree, &info->ci_username, &info->ci_namelen); 15311fcced4cSJordan Brown } 15321fcced4cSJordan Brown 15331fcced4cSJordan Brown static void 15341fcced4cSJordan Brown smb_tree_netinfo_fini(smb_netconnectinfo_t *info) 15351fcced4cSJordan Brown { 15361fcced4cSJordan Brown if (info == NULL) 15371fcced4cSJordan Brown return; 15381fcced4cSJordan Brown 15391fcced4cSJordan Brown if (info->ci_username) 15401fcced4cSJordan Brown kmem_free(info->ci_username, info->ci_namelen); 15411fcced4cSJordan Brown if (info->ci_share) 15429fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_mem_free(info->ci_share); 15431fcced4cSJordan Brown 15441fcced4cSJordan Brown bzero(info, sizeof (smb_netconnectinfo_t)); 15451fcced4cSJordan Brown } 1546