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. 243b13a1efSThomas Keiser * Copyright 2012 Nexenta Systems, Inc. All rights reserved. 25da6c28aaSamw */ 26da6c28aaSamw 27da6c28aaSamw /* 28da6c28aaSamw * General Structures Layout 29da6c28aaSamw * ------------------------- 30da6c28aaSamw * 31da6c28aaSamw * This is a simplified diagram showing the relationship between most of the 32da6c28aaSamw * main structures. 33da6c28aaSamw * 34da6c28aaSamw * +-------------------+ 35da6c28aaSamw * | SMB_INFO | 36da6c28aaSamw * +-------------------+ 37da6c28aaSamw * | 38da6c28aaSamw * | 39da6c28aaSamw * v 40da6c28aaSamw * +-------------------+ +-------------------+ +-------------------+ 41da6c28aaSamw * | SESSION |<----->| SESSION |......| SESSION | 42da6c28aaSamw * +-------------------+ +-------------------+ +-------------------+ 433b13a1efSThomas Keiser * | | 443b13a1efSThomas Keiser * | | 453b13a1efSThomas Keiser * | v 463b13a1efSThomas Keiser * | +-------------------+ +-------------------+ +-------------------+ 473b13a1efSThomas Keiser * | | USER |<--->| USER |...| USER | 483b13a1efSThomas Keiser * | +-------------------+ +-------------------+ +-------------------+ 49da6c28aaSamw * | 50da6c28aaSamw * | 51da6c28aaSamw * v 52da6c28aaSamw * +-------------------+ +-------------------+ +-------------------+ 53da6c28aaSamw * | TREE |<----->| TREE |......| TREE | 54da6c28aaSamw * +-------------------+ +-------------------+ +-------------------+ 55da6c28aaSamw * | | 56da6c28aaSamw * | | 57da6c28aaSamw * | v 58da6c28aaSamw * | +-------+ +-------+ +-------+ 59da6c28aaSamw * | | OFILE |<----->| OFILE |......| OFILE | 60da6c28aaSamw * | +-------+ +-------+ +-------+ 61da6c28aaSamw * | 62da6c28aaSamw * | 63da6c28aaSamw * v 64da6c28aaSamw * +-------+ +------+ +------+ 65da6c28aaSamw * | ODIR |<----->| ODIR |......| ODIR | 66da6c28aaSamw * +-------+ +------+ +------+ 67da6c28aaSamw * 68da6c28aaSamw * 69da6c28aaSamw * Tree State Machine 70da6c28aaSamw * ------------------ 71da6c28aaSamw * 72da6c28aaSamw * +-----------------------------+ T0 73da6c28aaSamw * | SMB_TREE_STATE_CONNECTED |<----------- Creation/Allocation 74da6c28aaSamw * +-----------------------------+ 75da6c28aaSamw * | 76da6c28aaSamw * | T1 77da6c28aaSamw * | 78da6c28aaSamw * v 79da6c28aaSamw * +------------------------------+ 80da6c28aaSamw * | SMB_TREE_STATE_DISCONNECTING | 81da6c28aaSamw * +------------------------------+ 82da6c28aaSamw * | 83da6c28aaSamw * | T2 84da6c28aaSamw * | 85da6c28aaSamw * v 86da6c28aaSamw * +-----------------------------+ T3 87da6c28aaSamw * | SMB_TREE_STATE_DISCONNECTED |----------> Deletion/Free 88da6c28aaSamw * +-----------------------------+ 89da6c28aaSamw * 90da6c28aaSamw * SMB_TREE_STATE_CONNECTED 91da6c28aaSamw * 92da6c28aaSamw * While in this state: 93da6c28aaSamw * - The tree is queued in the list of trees of its user. 94da6c28aaSamw * - References will be given out if the tree is looked up. 95da6c28aaSamw * - Files under that tree can be accessed. 96da6c28aaSamw * 97da6c28aaSamw * SMB_TREE_STATE_DISCONNECTING 98da6c28aaSamw * 99da6c28aaSamw * While in this state: 100da6c28aaSamw * - The tree is queued in the list of trees of its user. 101da6c28aaSamw * - References will not be given out if the tree is looked up. 102da6c28aaSamw * - The files and directories open under the tree are being closed. 103da6c28aaSamw * - The resources associated with the tree remain. 104da6c28aaSamw * 105da6c28aaSamw * SMB_TREE_STATE_DISCONNECTED 106da6c28aaSamw * 107da6c28aaSamw * While in this state: 108da6c28aaSamw * - The tree is queued in the list of trees of its user. 109da6c28aaSamw * - References will not be given out if the tree is looked up. 110da6c28aaSamw * - The tree has no more files and directories opened. 111da6c28aaSamw * - The resources associated with the tree remain. 112da6c28aaSamw * 113da6c28aaSamw * Transition T0 114da6c28aaSamw * 115da6c28aaSamw * This transition occurs in smb_tree_connect(). A new tree is created and 116da6c28aaSamw * added to the list of trees of a user. 117da6c28aaSamw * 118da6c28aaSamw * Transition T1 119da6c28aaSamw * 120da6c28aaSamw * This transition occurs in smb_tree_disconnect(). 121da6c28aaSamw * 122da6c28aaSamw * Transition T2 123da6c28aaSamw * 124da6c28aaSamw * This transition occurs in smb_tree_release(). The resources associated 125da6c28aaSamw * with the tree are freed as well as the tree structure. For the transition 126da6c28aaSamw * to occur, the tree must be in the SMB_TREE_STATE_DISCONNECTED state and 127da6c28aaSamw * the reference count be zero. 128da6c28aaSamw * 129da6c28aaSamw * Comments 130da6c28aaSamw * -------- 131da6c28aaSamw * 132da6c28aaSamw * The state machine of the tree structures is controlled by 3 elements: 133da6c28aaSamw * - The list of trees of the user it belongs to. 134da6c28aaSamw * - The mutex embedded in the structure itself. 135da6c28aaSamw * - The reference count. 136da6c28aaSamw * 137da6c28aaSamw * There's a mutex embedded in the tree structure used to protect its fields 138da6c28aaSamw * and there's a lock embedded in the list of trees of a user. To 139da6c28aaSamw * increment or to decrement the reference count the mutex must be entered. 140da6c28aaSamw * To insert the tree into the list of trees of the user and to remove 141da6c28aaSamw * the tree from it, the lock must be entered in RW_WRITER mode. 142da6c28aaSamw * 143da6c28aaSamw * Rules of access to a tree structure: 144da6c28aaSamw * 145da6c28aaSamw * 1) In order to avoid deadlocks, when both (mutex and lock of the user 146da6c28aaSamw * list) have to be entered, the lock must be entered first. 147da6c28aaSamw * 148da6c28aaSamw * 2) All actions applied to a tree require a reference count. 149da6c28aaSamw * 150c8ec8eeaSjose borrego * 3) There are 2 ways of getting a reference count: when a tree is 151c8ec8eeaSjose borrego * connected and when a tree is looked up. 152da6c28aaSamw * 153da6c28aaSamw * It should be noted that the reference count of a tree registers the 154da6c28aaSamw * number of references to the tree in other structures (such as an smb 155da6c28aaSamw * request). The reference count is not incremented in these 2 instances: 156da6c28aaSamw * 157da6c28aaSamw * 1) The tree is connected. An tree is anchored by his state. If there's 158da6c28aaSamw * no activity involving a tree currently connected, the reference 159da6c28aaSamw * count of that tree is zero. 160da6c28aaSamw * 161da6c28aaSamw * 2) The tree is queued in the list of trees of the user. The fact of 162da6c28aaSamw * being queued in that list is NOT registered by incrementing the 163da6c28aaSamw * reference count. 164da6c28aaSamw */ 165148c5f43SAlan Wright 166c8ec8eeaSjose borrego #include <sys/refstr_impl.h> 167bbf6f00cSJordan Brown #include <smbsrv/smb_kproto.h> 168148c5f43SAlan Wright #include <smbsrv/smb_ktypes.h> 169da6c28aaSamw #include <smbsrv/smb_fsops.h> 170cb174861Sjoyce mcintosh #include <smbsrv/smb_share.h> 171da6c28aaSamw 172c8ec8eeaSjose borrego int smb_tcon_mute = 0; 173c8ec8eeaSjose borrego 174cb174861Sjoyce mcintosh static smb_tree_t *smb_tree_connect_core(smb_request_t *); 175c8ec8eeaSjose borrego static smb_tree_t *smb_tree_connect_disk(smb_request_t *, const char *); 176148c5f43SAlan Wright static smb_tree_t *smb_tree_connect_printq(smb_request_t *, const char *); 177c8ec8eeaSjose borrego static smb_tree_t *smb_tree_connect_ipc(smb_request_t *, const char *); 1783b13a1efSThomas Keiser static smb_tree_t *smb_tree_alloc(smb_request_t *, const smb_kshare_t *, 179148c5f43SAlan Wright smb_node_t *, uint32_t, uint32_t); 1808b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States static boolean_t smb_tree_is_connected_locked(smb_tree_t *); 181c8ec8eeaSjose borrego static boolean_t smb_tree_is_disconnected(smb_tree_t *); 182c8ec8eeaSjose borrego static const char *smb_tree_get_sharename(const char *); 183148c5f43SAlan Wright static int smb_tree_getattr(const smb_kshare_t *, smb_node_t *, smb_tree_t *); 184c8ec8eeaSjose borrego static void smb_tree_get_volname(vfs_t *, smb_tree_t *); 185148c5f43SAlan Wright static void smb_tree_get_flags(const smb_kshare_t *, vfs_t *, smb_tree_t *); 186c8ec8eeaSjose borrego static void smb_tree_log(smb_request_t *, const char *, const char *, ...); 1877f667e74Sjose borrego static void smb_tree_close_odirs(smb_tree_t *, uint16_t); 1881fcced4cSJordan Brown static smb_ofile_t *smb_tree_get_ofile(smb_tree_t *, smb_ofile_t *); 1897f667e74Sjose borrego static smb_odir_t *smb_tree_get_odir(smb_tree_t *, smb_odir_t *); 190148c5f43SAlan Wright static void smb_tree_set_execinfo(smb_tree_t *, smb_shr_execinfo_t *, int); 1911fcced4cSJordan Brown static int smb_tree_enum_private(smb_tree_t *, smb_svcenum_t *); 1921fcced4cSJordan Brown static int smb_tree_netinfo_encode(smb_tree_t *, uint8_t *, size_t, uint32_t *); 1931fcced4cSJordan Brown static void smb_tree_netinfo_init(smb_tree_t *tree, smb_netconnectinfo_t *); 1941fcced4cSJordan Brown static void smb_tree_netinfo_fini(smb_netconnectinfo_t *); 195da6c28aaSamw 196cb174861Sjoyce mcintosh smb_tree_t * 197cb174861Sjoyce mcintosh smb_tree_connect(smb_request_t *sr) 198cb174861Sjoyce mcintosh { 199cb174861Sjoyce mcintosh smb_tree_t *tree; 200cb174861Sjoyce mcintosh smb_server_t *sv = sr->sr_server; 201cb174861Sjoyce mcintosh 202cb174861Sjoyce mcintosh if (smb_threshold_enter(&sv->sv_tcon_ct) != 0) { 203cb174861Sjoyce mcintosh smbsr_error(sr, RPC_NT_SERVER_TOO_BUSY, 0, 0); 204cb174861Sjoyce mcintosh return (NULL); 205cb174861Sjoyce mcintosh } 206cb174861Sjoyce mcintosh 207cb174861Sjoyce mcintosh tree = smb_tree_connect_core(sr); 208cb174861Sjoyce mcintosh smb_threshold_exit(&sv->sv_tcon_ct, sv); 209cb174861Sjoyce mcintosh return (tree); 210cb174861Sjoyce mcintosh } 211cb174861Sjoyce mcintosh 212da6c28aaSamw /* 213148c5f43SAlan Wright * Lookup the share name dispatch the appropriate stype handler. 214c8ec8eeaSjose borrego * Share names are case insensitive so we map the share name to 215c8ec8eeaSjose borrego * lower-case as a convenience for internal processing. 216148c5f43SAlan Wright * 217148c5f43SAlan Wright * Valid service values are: 218148c5f43SAlan Wright * A: Disk share 219148c5f43SAlan Wright * LPT1: Printer 220148c5f43SAlan Wright * IPC Named pipe (IPC$ is reserved as the named pipe share). 221148c5f43SAlan Wright * COMM Communications device 222148c5f43SAlan Wright * ????? Any type of device (wildcard) 223da6c28aaSamw */ 224cb174861Sjoyce mcintosh static smb_tree_t * 225cb174861Sjoyce mcintosh smb_tree_connect_core(smb_request_t *sr) 226c8ec8eeaSjose borrego { 227148c5f43SAlan Wright char *unc_path = sr->sr_tcon.path; 228c8ec8eeaSjose borrego smb_tree_t *tree = NULL; 229148c5f43SAlan Wright smb_kshare_t *si; 230c8ec8eeaSjose borrego const char *name; 231c8ec8eeaSjose borrego 232bbf6f00cSJordan Brown (void) smb_strlwr(unc_path); 233c8ec8eeaSjose borrego 234c8ec8eeaSjose borrego if ((name = smb_tree_get_sharename(unc_path)) == NULL) { 235488bda50SGordon Ross smb_tree_log(sr, unc_path, "invalid UNC path"); 236c8ec8eeaSjose borrego smbsr_error(sr, 0, ERRSRV, ERRinvnetname); 237c8ec8eeaSjose borrego return (NULL); 238c8ec8eeaSjose borrego } 239c8ec8eeaSjose borrego 240*8622ec45SGordon Ross si = smb_kshare_lookup(sr->sr_server, name); 241*8622ec45SGordon Ross if (si == NULL) { 242148c5f43SAlan Wright smb_tree_log(sr, name, "share not found"); 243148c5f43SAlan Wright smbsr_error(sr, 0, ERRSRV, ERRinvnetname); 244c8ec8eeaSjose borrego return (NULL); 245c8ec8eeaSjose borrego } 246cb174861Sjoyce mcintosh 247cb174861Sjoyce mcintosh if (!strcasecmp(SMB_SHARE_PRINT, name)) { 248*8622ec45SGordon Ross smb_kshare_release(sr->sr_server, si); 249cb174861Sjoyce mcintosh smb_tree_log(sr, name, "access not permitted"); 250cb174861Sjoyce mcintosh smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRSRV, ERRaccess); 251cb174861Sjoyce mcintosh return (NULL); 252cb174861Sjoyce mcintosh } 253cb174861Sjoyce mcintosh 254148c5f43SAlan Wright sr->sr_tcon.si = si; 255c8ec8eeaSjose borrego 256148c5f43SAlan Wright switch (si->shr_type & STYPE_MASK) { 257c8ec8eeaSjose borrego case STYPE_DISKTREE: 258c8ec8eeaSjose borrego tree = smb_tree_connect_disk(sr, name); 259c8ec8eeaSjose borrego break; 260c8ec8eeaSjose borrego case STYPE_IPC: 261c8ec8eeaSjose borrego tree = smb_tree_connect_ipc(sr, name); 262c8ec8eeaSjose borrego break; 263148c5f43SAlan Wright case STYPE_PRINTQ: 264148c5f43SAlan Wright tree = smb_tree_connect_printq(sr, name); 265148c5f43SAlan Wright break; 266c8ec8eeaSjose borrego default: 267c8ec8eeaSjose borrego smbsr_error(sr, NT_STATUS_BAD_DEVICE_TYPE, 268c8ec8eeaSjose borrego ERRDOS, ERROR_BAD_DEV_TYPE); 269c8ec8eeaSjose borrego break; 270c8ec8eeaSjose borrego } 271c8ec8eeaSjose borrego 272*8622ec45SGordon Ross smb_kshare_release(sr->sr_server, si); 273c8ec8eeaSjose borrego return (tree); 274c8ec8eeaSjose borrego } 275c8ec8eeaSjose borrego 276c8ec8eeaSjose borrego /* 277c8ec8eeaSjose borrego * Disconnect a tree. 278c8ec8eeaSjose borrego */ 279c8ec8eeaSjose borrego void 28029bd2886SAlan Wright smb_tree_disconnect(smb_tree_t *tree, boolean_t do_exec) 281c8ec8eeaSjose borrego { 282148c5f43SAlan Wright smb_shr_execinfo_t execinfo; 28329bd2886SAlan Wright 284c8ec8eeaSjose borrego ASSERT(tree->t_magic == SMB_TREE_MAGIC); 285c8ec8eeaSjose borrego 286c8ec8eeaSjose borrego mutex_enter(&tree->t_mutex); 287c8ec8eeaSjose borrego ASSERT(tree->t_refcnt); 288c8ec8eeaSjose borrego 2898b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (smb_tree_is_connected_locked(tree)) { 290c8ec8eeaSjose borrego /* 291c8ec8eeaSjose borrego * Indicate that the disconnect process has started. 292c8ec8eeaSjose borrego */ 293c8ec8eeaSjose borrego tree->t_state = SMB_TREE_STATE_DISCONNECTING; 294c8ec8eeaSjose borrego mutex_exit(&tree->t_mutex); 295c8ec8eeaSjose borrego 29629bd2886SAlan Wright if (do_exec) { 297c8ec8eeaSjose borrego /* 298c8ec8eeaSjose borrego * The files opened under this tree are closed. 299c8ec8eeaSjose borrego */ 300c8ec8eeaSjose borrego smb_ofile_close_all(tree); 301c8ec8eeaSjose borrego /* 302c8ec8eeaSjose borrego * The directories opened under this tree are closed. 303c8ec8eeaSjose borrego */ 3047f667e74Sjose borrego smb_tree_close_odirs(tree, 0); 30529bd2886SAlan Wright } 30629bd2886SAlan Wright 307c8ec8eeaSjose borrego mutex_enter(&tree->t_mutex); 308c8ec8eeaSjose borrego tree->t_state = SMB_TREE_STATE_DISCONNECTED; 309148c5f43SAlan Wright smb_server_dec_trees(tree->t_server); 310c8ec8eeaSjose borrego } 311c8ec8eeaSjose borrego 312c8ec8eeaSjose borrego mutex_exit(&tree->t_mutex); 31329bd2886SAlan Wright 314148c5f43SAlan Wright if (do_exec && (tree->t_state == SMB_TREE_STATE_DISCONNECTED) && 315148c5f43SAlan Wright (tree->t_execflags & SMB_EXEC_UNMAP)) { 31629bd2886SAlan Wright 317148c5f43SAlan Wright smb_tree_set_execinfo(tree, &execinfo, SMB_EXEC_UNMAP); 318*8622ec45SGordon Ross (void) smb_kshare_exec(tree->t_server, &execinfo); 31929bd2886SAlan Wright } 320c8ec8eeaSjose borrego } 321c8ec8eeaSjose borrego 322c8ec8eeaSjose borrego /* 323c8ec8eeaSjose borrego * Take a reference on a tree. 324c8ec8eeaSjose borrego */ 325c8ec8eeaSjose borrego boolean_t 326c8ec8eeaSjose borrego smb_tree_hold( 327c8ec8eeaSjose borrego smb_tree_t *tree) 328c8ec8eeaSjose borrego { 329c8ec8eeaSjose borrego ASSERT(tree); 330c8ec8eeaSjose borrego ASSERT(tree->t_magic == SMB_TREE_MAGIC); 331c8ec8eeaSjose borrego 332c8ec8eeaSjose borrego mutex_enter(&tree->t_mutex); 333c8ec8eeaSjose borrego 3348b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (smb_tree_is_connected_locked(tree)) { 335c8ec8eeaSjose borrego tree->t_refcnt++; 336c8ec8eeaSjose borrego mutex_exit(&tree->t_mutex); 337c8ec8eeaSjose borrego return (B_TRUE); 338c8ec8eeaSjose borrego } 339c8ec8eeaSjose borrego 340c8ec8eeaSjose borrego mutex_exit(&tree->t_mutex); 341c8ec8eeaSjose borrego return (B_FALSE); 342c8ec8eeaSjose borrego } 343c8ec8eeaSjose borrego 344c8ec8eeaSjose borrego /* 345c8ec8eeaSjose borrego * Release a reference on a tree. If the tree is disconnected and the 3469fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * reference count falls to zero, post the object for deletion. 3479fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Object deletion is deferred to avoid modifying a list while an 3489fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * iteration may be in progress. 349c8ec8eeaSjose borrego */ 350c8ec8eeaSjose borrego void 351c8ec8eeaSjose borrego smb_tree_release( 352c8ec8eeaSjose borrego smb_tree_t *tree) 353c8ec8eeaSjose borrego { 3549fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_TREE_VALID(tree); 355c8ec8eeaSjose borrego 356c8ec8eeaSjose borrego mutex_enter(&tree->t_mutex); 357c8ec8eeaSjose borrego ASSERT(tree->t_refcnt); 358c8ec8eeaSjose borrego tree->t_refcnt--; 359c8ec8eeaSjose borrego 360c5866007SKeyur Desai /* flush the ofile and odir lists' delete queues */ 361c5866007SKeyur Desai smb_llist_flush(&tree->t_ofile_list); 362c5866007SKeyur Desai smb_llist_flush(&tree->t_odir_list); 363c5866007SKeyur Desai 3649fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (smb_tree_is_disconnected(tree) && (tree->t_refcnt == 0)) 3653b13a1efSThomas Keiser smb_session_post_tree(tree->t_session, tree); 366c8ec8eeaSjose borrego 367c8ec8eeaSjose borrego mutex_exit(&tree->t_mutex); 368c8ec8eeaSjose borrego } 369c8ec8eeaSjose borrego 3709fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States void 3719fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_tree_post_ofile(smb_tree_t *tree, smb_ofile_t *of) 3729fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States { 3739fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_TREE_VALID(tree); 3749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_OFILE_VALID(of); 3759fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ASSERT(of->f_refcnt == 0); 3769fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ASSERT(of->f_state == SMB_OFILE_STATE_CLOSED); 3779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ASSERT(of->f_tree == tree); 3789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 3799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_llist_post(&tree->t_ofile_list, of, smb_ofile_delete); 3809fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States } 3819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 3829fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States void 3839fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_tree_post_odir(smb_tree_t *tree, smb_odir_t *od) 3849fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States { 3859fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_TREE_VALID(tree); 3869fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_ODIR_VALID(od); 3879fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ASSERT(od->d_refcnt == 0); 3889fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ASSERT(od->d_state == SMB_ODIR_STATE_CLOSED); 3899fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ASSERT(od->d_tree == tree); 3909fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 3919fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_llist_post(&tree->t_odir_list, od, smb_odir_delete); 3929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States } 3939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 394c8ec8eeaSjose borrego /* 395c8ec8eeaSjose borrego * Close ofiles and odirs that match pid. 396c8ec8eeaSjose borrego */ 397c8ec8eeaSjose borrego void 398c8ec8eeaSjose borrego smb_tree_close_pid( 399c8ec8eeaSjose borrego smb_tree_t *tree, 400c8ec8eeaSjose borrego uint16_t pid) 401c8ec8eeaSjose borrego { 402c8ec8eeaSjose borrego ASSERT(tree); 403c8ec8eeaSjose borrego ASSERT(tree->t_magic == SMB_TREE_MAGIC); 404c8ec8eeaSjose borrego 405c8ec8eeaSjose borrego smb_ofile_close_all_by_pid(tree, pid); 4067f667e74Sjose borrego smb_tree_close_odirs(tree, pid); 407c8ec8eeaSjose borrego } 408c8ec8eeaSjose borrego 409c8ec8eeaSjose borrego /* 410c8ec8eeaSjose borrego * Check whether or not a tree supports the features identified by flags. 411c8ec8eeaSjose borrego */ 412c8ec8eeaSjose borrego boolean_t 413c8ec8eeaSjose borrego smb_tree_has_feature(smb_tree_t *tree, uint32_t flags) 414c8ec8eeaSjose borrego { 415c8ec8eeaSjose borrego ASSERT(tree); 416c8ec8eeaSjose borrego ASSERT(tree->t_magic == SMB_TREE_MAGIC); 417c8ec8eeaSjose borrego 418c8ec8eeaSjose borrego return ((tree->t_flags & flags) == flags); 419c8ec8eeaSjose borrego } 420c8ec8eeaSjose borrego 4211fcced4cSJordan Brown /* 4221fcced4cSJordan Brown * If the enumeration request is for tree data, handle the request 4231fcced4cSJordan Brown * here. Otherwise, pass it on to the ofiles. 4241fcced4cSJordan Brown * 4251fcced4cSJordan Brown * This function should be called with a hold on the tree. 4261fcced4cSJordan Brown */ 4271fcced4cSJordan Brown int 4281fcced4cSJordan Brown smb_tree_enum(smb_tree_t *tree, smb_svcenum_t *svcenum) 4291fcced4cSJordan Brown { 4301fcced4cSJordan Brown smb_ofile_t *of; 4311fcced4cSJordan Brown smb_ofile_t *next; 4323b13a1efSThomas Keiser int rc = 0; 4331fcced4cSJordan Brown 4341fcced4cSJordan Brown ASSERT(tree); 4351fcced4cSJordan Brown ASSERT(tree->t_magic == SMB_TREE_MAGIC); 4361fcced4cSJordan Brown 4371fcced4cSJordan Brown if (svcenum->se_type == SMB_SVCENUM_TYPE_TREE) 4381fcced4cSJordan Brown return (smb_tree_enum_private(tree, svcenum)); 4391fcced4cSJordan Brown 4401fcced4cSJordan Brown of = smb_tree_get_ofile(tree, NULL); 4411fcced4cSJordan Brown while (of) { 4421fcced4cSJordan Brown ASSERT(of->f_tree == tree); 4431fcced4cSJordan Brown 4441fcced4cSJordan Brown rc = smb_ofile_enum(of, svcenum); 4451fcced4cSJordan Brown if (rc != 0) { 4461fcced4cSJordan Brown smb_ofile_release(of); 4471fcced4cSJordan Brown break; 4481fcced4cSJordan Brown } 4491fcced4cSJordan Brown 4501fcced4cSJordan Brown next = smb_tree_get_ofile(tree, of); 4511fcced4cSJordan Brown smb_ofile_release(of); 4521fcced4cSJordan Brown of = next; 4531fcced4cSJordan Brown } 4541fcced4cSJordan Brown 4551fcced4cSJordan Brown return (rc); 4561fcced4cSJordan Brown } 4571fcced4cSJordan Brown 4581fcced4cSJordan Brown /* 4591fcced4cSJordan Brown * Close a file by its unique id. 4601fcced4cSJordan Brown */ 4611fcced4cSJordan Brown int 4621fcced4cSJordan Brown smb_tree_fclose(smb_tree_t *tree, uint32_t uniqid) 4631fcced4cSJordan Brown { 4641fcced4cSJordan Brown smb_ofile_t *of; 4651fcced4cSJordan Brown 4661fcced4cSJordan Brown ASSERT(tree); 4671fcced4cSJordan Brown ASSERT(tree->t_magic == SMB_TREE_MAGIC); 4681fcced4cSJordan Brown 4691fcced4cSJordan Brown if ((of = smb_ofile_lookup_by_uniqid(tree, uniqid)) == NULL) 4701fcced4cSJordan Brown return (ENOENT); 4711fcced4cSJordan Brown 4721fcced4cSJordan Brown if (smb_ofile_disallow_fclose(of)) { 4731fcced4cSJordan Brown smb_ofile_release(of); 4741fcced4cSJordan Brown return (EACCES); 4751fcced4cSJordan Brown } 4761fcced4cSJordan Brown 4771fcced4cSJordan Brown smb_ofile_close(of, 0); 4781fcced4cSJordan Brown smb_ofile_release(of); 4791fcced4cSJordan Brown return (0); 4801fcced4cSJordan Brown } 481743a77edSAlan Wright 482c8ec8eeaSjose borrego /* *************************** Static Functions ***************************** */ 4831fcced4cSJordan Brown 484743a77edSAlan Wright #define SHARES_DIR ".zfs/shares/" 485148c5f43SAlan Wright 486148c5f43SAlan Wright /* 487148c5f43SAlan Wright * Calculates permissions given by the share's ACL to the 488148c5f43SAlan Wright * user in the passed request. The default is full access. 489148c5f43SAlan Wright * If any error occurs, full access is granted. 490148c5f43SAlan Wright * 491148c5f43SAlan Wright * Using the vnode of the share path find the root directory 492148c5f43SAlan Wright * of the mounted file system. Then look to see if there is a 493148c5f43SAlan Wright * .zfs/shares directory and if there is, lookup the file with 494148c5f43SAlan Wright * the same name as the share name in it. The ACL set for this 495148c5f43SAlan Wright * file is the share's ACL which is used for access check here. 496148c5f43SAlan Wright */ 497148c5f43SAlan Wright static uint32_t 498148c5f43SAlan Wright smb_tree_acl_access(smb_request_t *sr, const smb_kshare_t *si, vnode_t *pathvp) 499743a77edSAlan Wright { 500fe1c642dSBill Krier smb_user_t *user; 501fe1c642dSBill Krier cred_t *cred; 502743a77edSAlan Wright int rc; 503743a77edSAlan Wright vfs_t *vfsp; 504743a77edSAlan Wright vnode_t *root = NULL; 505743a77edSAlan Wright vnode_t *sharevp = NULL; 506743a77edSAlan Wright char *sharepath; 507743a77edSAlan Wright struct pathname pnp; 508743a77edSAlan Wright size_t size; 509148c5f43SAlan Wright uint32_t access; 510743a77edSAlan Wright 511fe1c642dSBill Krier user = sr->uid_user; 512fe1c642dSBill Krier cred = user->u_cred; 513148c5f43SAlan Wright access = ACE_ALL_PERMS; 514743a77edSAlan Wright 515fe1c642dSBill Krier if (si->shr_flags & SMB_SHRF_AUTOHOME) { 516fe1c642dSBill Krier /* 517fe1c642dSBill Krier * An autohome share owner gets full access to the share. 518fe1c642dSBill Krier * Everyone else is denied access. 519fe1c642dSBill Krier */ 520c5866007SKeyur Desai if (si->shr_uid != crgetuid(cred)) 521148c5f43SAlan Wright access = 0; 522148c5f43SAlan Wright 523148c5f43SAlan Wright return (access); 524fe1c642dSBill Krier } 525fe1c642dSBill Krier 526743a77edSAlan Wright /* 527148c5f43SAlan Wright * The hold on 'root' is released by the lookuppnvp() that follows 528743a77edSAlan Wright */ 529743a77edSAlan Wright vfsp = pathvp->v_vfsp; 530743a77edSAlan Wright if (vfsp != NULL) 531743a77edSAlan Wright rc = VFS_ROOT(vfsp, &root); 532743a77edSAlan Wright else 533743a77edSAlan Wright rc = ENOENT; 534743a77edSAlan Wright 535743a77edSAlan Wright if (rc != 0) 536148c5f43SAlan Wright return (access); 537743a77edSAlan Wright 538743a77edSAlan Wright 539fe1c642dSBill Krier size = sizeof (SHARES_DIR) + strlen(si->shr_name) + 1; 540148c5f43SAlan Wright sharepath = smb_srm_alloc(sr, size); 541fe1c642dSBill Krier (void) sprintf(sharepath, "%s%s", SHARES_DIR, si->shr_name); 542743a77edSAlan Wright 543743a77edSAlan Wright pn_alloc(&pnp); 544743a77edSAlan Wright (void) pn_set(&pnp, sharepath); 545148c5f43SAlan Wright rc = lookuppnvp(&pnp, NULL, NO_FOLLOW, NULL, &sharevp, rootdir, root, 546*8622ec45SGordon Ross zone_kcred()); 547743a77edSAlan Wright pn_free(&pnp); 548743a77edSAlan Wright 549743a77edSAlan Wright /* 550148c5f43SAlan Wright * Now get the effective access value based on cred and ACL values. 551743a77edSAlan Wright */ 552037cac00Sjoyce mcintosh if (rc == 0) { 553148c5f43SAlan Wright smb_vop_eaccess(sharevp, (int *)&access, V_ACE_MASK, NULL, 554148c5f43SAlan Wright cred); 555037cac00Sjoyce mcintosh VN_RELE(sharevp); 556037cac00Sjoyce mcintosh } 557148c5f43SAlan Wright 558148c5f43SAlan Wright return (access); 559148c5f43SAlan Wright } 560148c5f43SAlan Wright 561148c5f43SAlan Wright /* 562148c5f43SAlan Wright * Performs the following access checks for a disk share: 563148c5f43SAlan Wright * 564148c5f43SAlan Wright * - No IPC/anonymous user is allowed 565148c5f43SAlan Wright * 566148c5f43SAlan Wright * - If user is Guest, guestok property of the share should be 567148c5f43SAlan Wright * enabled 568148c5f43SAlan Wright * 569148c5f43SAlan Wright * - If this is an Admin share, the user should have administrative 570148c5f43SAlan Wright * privileges 571148c5f43SAlan Wright * 572148c5f43SAlan Wright * - Host based access control lists 573148c5f43SAlan Wright * 574148c5f43SAlan Wright * - Share ACL 575148c5f43SAlan Wright * 576148c5f43SAlan Wright * Returns the access allowed or 0 if access is denied. 577148c5f43SAlan Wright */ 578148c5f43SAlan Wright static uint32_t 579148c5f43SAlan Wright smb_tree_chkaccess(smb_request_t *sr, smb_kshare_t *shr, vnode_t *vp) 580148c5f43SAlan Wright { 581148c5f43SAlan Wright smb_user_t *user = sr->uid_user; 582148c5f43SAlan Wright char *sharename = shr->shr_name; 583148c5f43SAlan Wright uint32_t host_access; 584148c5f43SAlan Wright uint32_t acl_access; 585148c5f43SAlan Wright uint32_t access; 586148c5f43SAlan Wright 587148c5f43SAlan Wright if (user->u_flags & SMB_USER_FLAG_IPC) { 588148c5f43SAlan Wright smb_tree_log(sr, sharename, "access denied: IPC only"); 589148c5f43SAlan Wright return (0); 590148c5f43SAlan Wright } 591148c5f43SAlan Wright 592148c5f43SAlan Wright if ((user->u_flags & SMB_USER_FLAG_GUEST) && 593148c5f43SAlan Wright ((shr->shr_flags & SMB_SHRF_GUEST_OK) == 0)) { 594148c5f43SAlan Wright smb_tree_log(sr, sharename, "access denied: guest disabled"); 595148c5f43SAlan Wright return (0); 596148c5f43SAlan Wright } 597148c5f43SAlan Wright 598148c5f43SAlan Wright if ((shr->shr_flags & SMB_SHRF_ADMIN) && !smb_user_is_admin(user)) { 599148c5f43SAlan Wright smb_tree_log(sr, sharename, "access denied: not admin"); 600148c5f43SAlan Wright return (0); 601148c5f43SAlan Wright } 602148c5f43SAlan Wright 603*8622ec45SGordon Ross host_access = smb_kshare_hostaccess(shr, sr->session); 604148c5f43SAlan Wright if ((host_access & ACE_ALL_PERMS) == 0) { 605148c5f43SAlan Wright smb_tree_log(sr, sharename, "access denied: host access"); 606148c5f43SAlan Wright return (0); 607148c5f43SAlan Wright } 608148c5f43SAlan Wright 609148c5f43SAlan Wright acl_access = smb_tree_acl_access(sr, shr, vp); 610148c5f43SAlan Wright if ((acl_access & ACE_ALL_PERMS) == 0) { 611148c5f43SAlan Wright smb_tree_log(sr, sharename, "access denied: share ACL"); 612148c5f43SAlan Wright return (0); 613148c5f43SAlan Wright } 614148c5f43SAlan Wright 615148c5f43SAlan Wright access = host_access & acl_access; 616148c5f43SAlan Wright if ((access & ACE_ALL_PERMS) == 0) { 617148c5f43SAlan Wright smb_tree_log(sr, sharename, "access denied"); 618148c5f43SAlan Wright return (0); 619148c5f43SAlan Wright } 620148c5f43SAlan Wright 621148c5f43SAlan Wright return (access); 622743a77edSAlan Wright } 623c8ec8eeaSjose borrego 624c8ec8eeaSjose borrego /* 625c8ec8eeaSjose borrego * Connect a share for use with files and directories. 626c8ec8eeaSjose borrego */ 627c8ec8eeaSjose borrego static smb_tree_t * 628c8ec8eeaSjose borrego smb_tree_connect_disk(smb_request_t *sr, const char *sharename) 629c8ec8eeaSjose borrego { 630148c5f43SAlan Wright const char *any = "?????"; 631c8ec8eeaSjose borrego smb_user_t *user = sr->uid_user; 6321fcced4cSJordan Brown smb_node_t *dnode = NULL; 633c8ec8eeaSjose borrego smb_node_t *snode = NULL; 634148c5f43SAlan Wright smb_kshare_t *si = sr->sr_tcon.si; 635148c5f43SAlan Wright char *service = sr->sr_tcon.service; 636c8ec8eeaSjose borrego char last_component[MAXNAMELEN]; 637c8ec8eeaSjose borrego smb_tree_t *tree; 638c8ec8eeaSjose borrego int rc; 639148c5f43SAlan Wright uint32_t access; 640148c5f43SAlan Wright smb_shr_execinfo_t execinfo; 641c8ec8eeaSjose borrego 642c8ec8eeaSjose borrego ASSERT(user); 643148c5f43SAlan Wright ASSERT(user->u_cred); 644c8ec8eeaSjose borrego 645148c5f43SAlan Wright if ((strcmp(service, any) != 0) && (strcasecmp(service, "A:") != 0)) { 646148c5f43SAlan Wright smb_tree_log(sr, sharename, "invalid service (%s)", service); 647148c5f43SAlan Wright smbsr_error(sr, NT_STATUS_BAD_DEVICE_TYPE, 648148c5f43SAlan Wright ERRDOS, ERROR_BAD_DEV_TYPE); 649b89a8333Snatalie li - Sun Microsystems - Irvine United States return (NULL); 650b89a8333Snatalie li - Sun Microsystems - Irvine United States } 651b89a8333Snatalie li - Sun Microsystems - Irvine United States 652c8ec8eeaSjose borrego /* 653c8ec8eeaSjose borrego * Check that the shared directory exists. 654c8ec8eeaSjose borrego */ 655148c5f43SAlan Wright rc = smb_pathname_reduce(sr, user->u_cred, si->shr_path, 0, 0, &dnode, 656c8ec8eeaSjose borrego last_component); 657c8ec8eeaSjose borrego 658c8ec8eeaSjose borrego if (rc == 0) { 659148c5f43SAlan Wright rc = smb_fsop_lookup(sr, user->u_cred, SMB_FOLLOW_LINKS, 6601fcced4cSJordan Brown sr->sr_server->si_root_smb_node, dnode, last_component, 661037cac00Sjoyce mcintosh &snode); 662c8ec8eeaSjose borrego 6631fcced4cSJordan Brown smb_node_release(dnode); 664c8ec8eeaSjose borrego } 665c8ec8eeaSjose borrego 666c8ec8eeaSjose borrego if (rc) { 667c8ec8eeaSjose borrego if (snode) 668c8ec8eeaSjose borrego smb_node_release(snode); 669c8ec8eeaSjose borrego 670b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_tree_log(sr, sharename, "bad path: %s", si->shr_path); 671c8ec8eeaSjose borrego smbsr_error(sr, 0, ERRSRV, ERRinvnetname); 672c8ec8eeaSjose borrego return (NULL); 673c8ec8eeaSjose borrego } 674c8ec8eeaSjose borrego 675148c5f43SAlan Wright if ((access = smb_tree_chkaccess(sr, si, snode->vp)) == 0) { 676148c5f43SAlan Wright smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRSRV, ERRaccess); 677743a77edSAlan Wright smb_node_release(snode); 678743a77edSAlan Wright return (NULL); 679743a77edSAlan Wright } 680743a77edSAlan Wright 681743a77edSAlan Wright /* 682148c5f43SAlan Wright * Set up the OptionalSupport for this share. 683743a77edSAlan Wright */ 684148c5f43SAlan Wright sr->sr_tcon.optional_support = SMB_SUPPORT_SEARCH_BITS; 6852c2961f8Sjose borrego 686148c5f43SAlan Wright switch (si->shr_flags & SMB_SHRF_CSC_MASK) { 687148c5f43SAlan Wright case SMB_SHRF_CSC_DISABLED: 688148c5f43SAlan Wright sr->sr_tcon.optional_support |= SMB_CSC_CACHE_NONE; 689148c5f43SAlan Wright break; 690148c5f43SAlan Wright case SMB_SHRF_CSC_AUTO: 691148c5f43SAlan Wright sr->sr_tcon.optional_support |= SMB_CSC_CACHE_AUTO_REINT; 692148c5f43SAlan Wright break; 693148c5f43SAlan Wright case SMB_SHRF_CSC_VDO: 694148c5f43SAlan Wright sr->sr_tcon.optional_support |= SMB_CSC_CACHE_VDO; 695148c5f43SAlan Wright break; 696148c5f43SAlan Wright case SMB_SHRF_CSC_MANUAL: 697148c5f43SAlan Wright default: 698148c5f43SAlan Wright /* 699148c5f43SAlan Wright * Default to SMB_CSC_CACHE_MANUAL_REINT. 700148c5f43SAlan Wright */ 701148c5f43SAlan Wright break; 702148c5f43SAlan Wright } 703148c5f43SAlan Wright 704148c5f43SAlan Wright /* ABE support */ 705148c5f43SAlan Wright if (si->shr_flags & SMB_SHRF_ABE) 706148c5f43SAlan Wright sr->sr_tcon.optional_support |= 707148c5f43SAlan Wright SHI1005_FLAGS_ACCESS_BASED_DIRECTORY_ENUM; 708148c5f43SAlan Wright 709148c5f43SAlan Wright if (si->shr_flags & SMB_SHRF_DFSROOT) 710148c5f43SAlan Wright sr->sr_tcon.optional_support |= SMB_SHARE_IS_IN_DFS; 711148c5f43SAlan Wright 712cb174861Sjoyce mcintosh /* if 'smb' zfs property: shortnames=disabled */ 713cb174861Sjoyce mcintosh if (!smb_shortnames) 714cb174861Sjoyce mcintosh sr->arg.tcon.optional_support |= SMB_UNIQUE_FILE_NAME; 715cb174861Sjoyce mcintosh 7163b13a1efSThomas Keiser tree = smb_tree_alloc(sr, si, snode, access, sr->sr_cfg->skc_execflags); 717148c5f43SAlan Wright 718148c5f43SAlan Wright smb_node_release(snode); 719148c5f43SAlan Wright 720148c5f43SAlan Wright if (tree) { 721148c5f43SAlan Wright if (tree->t_execflags & SMB_EXEC_MAP) { 722148c5f43SAlan Wright smb_tree_set_execinfo(tree, &execinfo, SMB_EXEC_MAP); 723148c5f43SAlan Wright 724*8622ec45SGordon Ross rc = smb_kshare_exec(tree->t_server, &execinfo); 725148c5f43SAlan Wright 726148c5f43SAlan Wright if ((rc != 0) && (tree->t_execflags & SMB_EXEC_TERM)) { 727148c5f43SAlan Wright smb_tree_disconnect(tree, B_FALSE); 728148c5f43SAlan Wright smb_tree_release(tree); 729148c5f43SAlan Wright smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRSRV, 730148c5f43SAlan Wright ERRaccess); 731148c5f43SAlan Wright return (NULL); 732148c5f43SAlan Wright } 733148c5f43SAlan Wright } 734148c5f43SAlan Wright } else { 735148c5f43SAlan Wright smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRSRV, ERRaccess); 736148c5f43SAlan Wright } 737148c5f43SAlan Wright 738148c5f43SAlan Wright return (tree); 739148c5f43SAlan Wright } 740148c5f43SAlan Wright 741148c5f43SAlan Wright /* 742148c5f43SAlan Wright * Shares have both a share and host based access control. The access 743148c5f43SAlan Wright * granted will be minimum permissions based on both hostaccess 744148c5f43SAlan Wright * (permissions allowed by host based access) and aclaccess (from the 745148c5f43SAlan Wright * share ACL). 746148c5f43SAlan Wright */ 747148c5f43SAlan Wright static smb_tree_t * 748148c5f43SAlan Wright smb_tree_connect_printq(smb_request_t *sr, const char *sharename) 749148c5f43SAlan Wright { 750148c5f43SAlan Wright const char *any = "?????"; 751148c5f43SAlan Wright smb_user_t *user = sr->uid_user; 752148c5f43SAlan Wright smb_node_t *dnode = NULL; 753148c5f43SAlan Wright smb_node_t *snode = NULL; 754148c5f43SAlan Wright smb_kshare_t *si = sr->sr_tcon.si; 755148c5f43SAlan Wright char *service = sr->sr_tcon.service; 756148c5f43SAlan Wright char last_component[MAXNAMELEN]; 757148c5f43SAlan Wright smb_tree_t *tree; 758148c5f43SAlan Wright int rc; 759148c5f43SAlan Wright uint32_t access; 760148c5f43SAlan Wright 761148c5f43SAlan Wright ASSERT(user); 762148c5f43SAlan Wright ASSERT(user->u_cred); 763148c5f43SAlan Wright 764b7301bf5SGordon Ross if (sr->sr_server->sv_cfg.skc_print_enable == 0) { 765b7301bf5SGordon Ross smb_tree_log(sr, sharename, "printing disabled"); 766b7301bf5SGordon Ross smbsr_error(sr, 0, ERRSRV, ERRinvnetname); 767b7301bf5SGordon Ross return (NULL); 768b7301bf5SGordon Ross } 769b7301bf5SGordon Ross 770148c5f43SAlan Wright if ((strcmp(service, any) != 0) && 771148c5f43SAlan Wright (strcasecmp(service, "LPT1:") != 0)) { 772148c5f43SAlan Wright smb_tree_log(sr, sharename, "invalid service (%s)", service); 773148c5f43SAlan Wright smbsr_error(sr, NT_STATUS_BAD_DEVICE_TYPE, 774148c5f43SAlan Wright ERRDOS, ERROR_BAD_DEV_TYPE); 775148c5f43SAlan Wright return (NULL); 776148c5f43SAlan Wright } 777148c5f43SAlan Wright 778148c5f43SAlan Wright /* 779148c5f43SAlan Wright * Check that the shared directory exists. 780148c5f43SAlan Wright */ 781148c5f43SAlan Wright rc = smb_pathname_reduce(sr, user->u_cred, si->shr_path, 0, 0, &dnode, 782148c5f43SAlan Wright last_component); 783148c5f43SAlan Wright if (rc == 0) { 784148c5f43SAlan Wright rc = smb_fsop_lookup(sr, user->u_cred, SMB_FOLLOW_LINKS, 785148c5f43SAlan Wright sr->sr_server->si_root_smb_node, dnode, last_component, 786148c5f43SAlan Wright &snode); 787148c5f43SAlan Wright 788148c5f43SAlan Wright smb_node_release(dnode); 789148c5f43SAlan Wright } 790148c5f43SAlan Wright 791148c5f43SAlan Wright if (rc) { 792148c5f43SAlan Wright if (snode) 793148c5f43SAlan Wright smb_node_release(snode); 794148c5f43SAlan Wright 795148c5f43SAlan Wright smb_tree_log(sr, sharename, "bad path: %s", si->shr_path); 796148c5f43SAlan Wright smbsr_error(sr, 0, ERRSRV, ERRinvnetname); 797148c5f43SAlan Wright return (NULL); 798148c5f43SAlan Wright } 799148c5f43SAlan Wright 800148c5f43SAlan Wright if ((access = smb_tree_chkaccess(sr, si, snode->vp)) == 0) { 801148c5f43SAlan Wright smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRSRV, ERRaccess); 802148c5f43SAlan Wright smb_node_release(snode); 803148c5f43SAlan Wright return (NULL); 804148c5f43SAlan Wright } 805148c5f43SAlan Wright 806148c5f43SAlan Wright sr->sr_tcon.optional_support = SMB_SUPPORT_SEARCH_BITS; 807148c5f43SAlan Wright 8083b13a1efSThomas Keiser tree = smb_tree_alloc(sr, si, snode, access, sr->sr_cfg->skc_execflags); 809b89a8333Snatalie li - Sun Microsystems - Irvine United States 81029bd2886SAlan Wright smb_node_release(snode); 81129bd2886SAlan Wright 812c8ec8eeaSjose borrego if (tree == NULL) 813c8ec8eeaSjose borrego smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRSRV, ERRaccess); 81429bd2886SAlan Wright 815c8ec8eeaSjose borrego return (tree); 816c8ec8eeaSjose borrego } 817c8ec8eeaSjose borrego 818c8ec8eeaSjose borrego /* 819c8ec8eeaSjose borrego * Connect an IPC share for use with named pipes. 820c8ec8eeaSjose borrego */ 821c8ec8eeaSjose borrego static smb_tree_t * 822c8ec8eeaSjose borrego smb_tree_connect_ipc(smb_request_t *sr, const char *name) 823c8ec8eeaSjose borrego { 824148c5f43SAlan Wright const char *any = "?????"; 825c8ec8eeaSjose borrego smb_user_t *user = sr->uid_user; 826c8ec8eeaSjose borrego smb_tree_t *tree; 827148c5f43SAlan Wright smb_kshare_t *si = sr->sr_tcon.si; 828148c5f43SAlan Wright char *service = sr->sr_tcon.service; 829c8ec8eeaSjose borrego 830c8ec8eeaSjose borrego ASSERT(user); 831c8ec8eeaSjose borrego 832c8ec8eeaSjose borrego if ((user->u_flags & SMB_USER_FLAG_IPC) && 833c8ec8eeaSjose borrego sr->sr_cfg->skc_restrict_anon) { 834c8ec8eeaSjose borrego smb_tree_log(sr, name, "access denied: restrict anonymous"); 835c8ec8eeaSjose borrego smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRSRV, ERRaccess); 836c8ec8eeaSjose borrego return (NULL); 837c8ec8eeaSjose borrego } 838c8ec8eeaSjose borrego 839148c5f43SAlan Wright if ((strcmp(service, any) != 0) && (strcasecmp(service, "IPC") != 0)) { 840148c5f43SAlan Wright smb_tree_log(sr, name, "invalid service (%s)", service); 841148c5f43SAlan Wright smbsr_error(sr, NT_STATUS_BAD_DEVICE_TYPE, 842148c5f43SAlan Wright ERRDOS, ERROR_BAD_DEV_TYPE); 843148c5f43SAlan Wright return (NULL); 844148c5f43SAlan Wright } 8458d7e4166Sjose borrego 846148c5f43SAlan Wright sr->sr_tcon.optional_support = SMB_SUPPORT_SEARCH_BITS; 8478b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 8483b13a1efSThomas Keiser tree = smb_tree_alloc(sr, si, NULL, ACE_ALL_PERMS, 0); 849c8ec8eeaSjose borrego if (tree == NULL) { 850c8ec8eeaSjose borrego smb_tree_log(sr, name, "access denied"); 851c8ec8eeaSjose borrego smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRSRV, ERRaccess); 852c8ec8eeaSjose borrego } 853c8ec8eeaSjose borrego 854c8ec8eeaSjose borrego return (tree); 855c8ec8eeaSjose borrego } 856c8ec8eeaSjose borrego 857c8ec8eeaSjose borrego /* 858c8ec8eeaSjose borrego * Allocate a tree. 859c8ec8eeaSjose borrego */ 860c8ec8eeaSjose borrego static smb_tree_t * 8613b13a1efSThomas Keiser smb_tree_alloc(smb_request_t *sr, const smb_kshare_t *si, 8623b13a1efSThomas Keiser smb_node_t *snode, uint32_t access, uint32_t execflags) 863da6c28aaSamw { 8643b13a1efSThomas Keiser smb_session_t *session = sr->session; 865da6c28aaSamw smb_tree_t *tree; 866148c5f43SAlan Wright uint32_t stype = si->shr_type; 867da6c28aaSamw uint16_t tid; 868da6c28aaSamw 8693b13a1efSThomas Keiser if (smb_idpool_alloc(&session->s_tid_pool, &tid)) 870da6c28aaSamw return (NULL); 871da6c28aaSamw 872*8622ec45SGordon Ross tree = kmem_cache_alloc(smb_cache_tree, KM_SLEEP); 873da6c28aaSamw bzero(tree, sizeof (smb_tree_t)); 874da6c28aaSamw 8753b13a1efSThomas Keiser tree->t_session = session; 8763b13a1efSThomas Keiser tree->t_server = session->s_server; 8773b13a1efSThomas Keiser 8783b13a1efSThomas Keiser /* grab a ref for tree->t_owner */ 8793b13a1efSThomas Keiser smb_user_hold_internal(sr->uid_user); 8803b13a1efSThomas Keiser tree->t_owner = sr->uid_user; 881cb174861Sjoyce mcintosh 882148c5f43SAlan Wright if (STYPE_ISDSK(stype) || STYPE_ISPRN(stype)) { 8838b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (smb_tree_getattr(si, snode, tree) != 0) { 8843b13a1efSThomas Keiser smb_idpool_free(&session->s_tid_pool, tid); 885*8622ec45SGordon Ross kmem_cache_free(smb_cache_tree, tree); 886c8ec8eeaSjose borrego return (NULL); 887c8ec8eeaSjose borrego } 888c8ec8eeaSjose borrego } 889c8ec8eeaSjose borrego 890da6c28aaSamw if (smb_idpool_constructor(&tree->t_fid_pool)) { 8913b13a1efSThomas Keiser smb_idpool_free(&session->s_tid_pool, tid); 892*8622ec45SGordon Ross kmem_cache_free(smb_cache_tree, tree); 893da6c28aaSamw return (NULL); 894da6c28aaSamw } 895da6c28aaSamw 8967f667e74Sjose borrego if (smb_idpool_constructor(&tree->t_odid_pool)) { 897da6c28aaSamw smb_idpool_destructor(&tree->t_fid_pool); 8983b13a1efSThomas Keiser smb_idpool_free(&session->s_tid_pool, tid); 899*8622ec45SGordon Ross kmem_cache_free(smb_cache_tree, tree); 900da6c28aaSamw return (NULL); 901da6c28aaSamw } 902da6c28aaSamw 903da6c28aaSamw smb_llist_constructor(&tree->t_ofile_list, sizeof (smb_ofile_t), 904da6c28aaSamw offsetof(smb_ofile_t, f_lnd)); 905da6c28aaSamw 906da6c28aaSamw smb_llist_constructor(&tree->t_odir_list, sizeof (smb_odir_t), 907da6c28aaSamw offsetof(smb_odir_t, d_lnd)); 908da6c28aaSamw 9098b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States (void) strlcpy(tree->t_sharename, si->shr_name, 910da6c28aaSamw sizeof (tree->t_sharename)); 9118b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States (void) strlcpy(tree->t_resource, si->shr_path, 9128b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States sizeof (tree->t_resource)); 913da6c28aaSamw 914da6c28aaSamw mutex_init(&tree->t_mutex, NULL, MUTEX_DEFAULT, NULL); 915da6c28aaSamw 916da6c28aaSamw tree->t_refcnt = 1; 917da6c28aaSamw tree->t_tid = tid; 918da6c28aaSamw tree->t_res_type = stype; 919da6c28aaSamw tree->t_state = SMB_TREE_STATE_CONNECTED; 920da6c28aaSamw tree->t_magic = SMB_TREE_MAGIC; 921743a77edSAlan Wright tree->t_access = access; 9221fcced4cSJordan Brown tree->t_connect_time = gethrestime_sec(); 923148c5f43SAlan Wright tree->t_execflags = execflags; 924743a77edSAlan Wright 925743a77edSAlan Wright /* if FS is readonly, enforce that here */ 926743a77edSAlan Wright if (tree->t_flags & SMB_TREE_READONLY) 927743a77edSAlan Wright tree->t_access &= ~ACE_ALL_WRITE_PERMS; 928da6c28aaSamw 929148c5f43SAlan Wright if (STYPE_ISDSK(stype) || STYPE_ISPRN(stype)) { 930c8ec8eeaSjose borrego smb_node_ref(snode); 931c8ec8eeaSjose borrego tree->t_snode = snode; 932da6c28aaSamw tree->t_acltype = smb_fsop_acltype(snode); 933da6c28aaSamw } 934da6c28aaSamw 9353b13a1efSThomas Keiser smb_llist_enter(&session->s_tree_list, RW_WRITER); 9363b13a1efSThomas Keiser smb_llist_insert_head(&session->s_tree_list, tree); 9373b13a1efSThomas Keiser smb_llist_exit(&session->s_tree_list); 9383b13a1efSThomas Keiser atomic_inc_32(&session->s_tree_cnt); 9393b13a1efSThomas Keiser smb_server_inc_trees(session->s_server); 940da6c28aaSamw return (tree); 941da6c28aaSamw } 942da6c28aaSamw 943da6c28aaSamw /* 9449fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Deallocate a tree. The open file and open directory lists should be 9459fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * empty. 946da6c28aaSamw * 9479fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Remove the tree from the user's tree list before freeing resources 9489fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * associated with the tree. 949da6c28aaSamw */ 9509fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States void 9519fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_tree_dealloc(void *arg) 952da6c28aaSamw { 9533b13a1efSThomas Keiser smb_session_t *session; 9549fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_tree_t *tree = (smb_tree_t *)arg; 9559fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 9569fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_TREE_VALID(tree); 957da6c28aaSamw ASSERT(tree->t_state == SMB_TREE_STATE_DISCONNECTED); 958da6c28aaSamw ASSERT(tree->t_refcnt == 0); 959da6c28aaSamw 9603b13a1efSThomas Keiser session = tree->t_session; 9613b13a1efSThomas Keiser smb_llist_enter(&session->s_tree_list, RW_WRITER); 9623b13a1efSThomas Keiser smb_llist_remove(&session->s_tree_list, tree); 9633b13a1efSThomas Keiser smb_idpool_free(&session->s_tid_pool, tree->t_tid); 9643b13a1efSThomas Keiser atomic_dec_32(&session->s_tree_cnt); 9653b13a1efSThomas Keiser smb_llist_exit(&session->s_tree_list); 9669fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 9679fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States mutex_enter(&tree->t_mutex); 9689fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States mutex_exit(&tree->t_mutex); 969da6c28aaSamw 970da6c28aaSamw tree->t_magic = (uint32_t)~SMB_TREE_MAGIC; 971da6c28aaSamw 972c8ec8eeaSjose borrego if (tree->t_snode) 973da6c28aaSamw smb_node_release(tree->t_snode); 974c8ec8eeaSjose borrego 975da6c28aaSamw mutex_destroy(&tree->t_mutex); 976da6c28aaSamw smb_llist_destructor(&tree->t_ofile_list); 977da6c28aaSamw smb_llist_destructor(&tree->t_odir_list); 978da6c28aaSamw smb_idpool_destructor(&tree->t_fid_pool); 9797f667e74Sjose borrego smb_idpool_destructor(&tree->t_odid_pool); 9803b13a1efSThomas Keiser 9813b13a1efSThomas Keiser SMB_USER_VALID(tree->t_owner); 9823b13a1efSThomas Keiser smb_user_release(tree->t_owner); 9833b13a1efSThomas Keiser 984*8622ec45SGordon Ross kmem_cache_free(smb_cache_tree, tree); 985da6c28aaSamw } 986da6c28aaSamw 987da6c28aaSamw /* 988c8ec8eeaSjose borrego * Determine whether or not a tree is connected. 989c8ec8eeaSjose borrego * This function must be called with the tree mutex held. 990da6c28aaSamw */ 991c8ec8eeaSjose borrego static boolean_t 9928b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_tree_is_connected_locked(smb_tree_t *tree) 993da6c28aaSamw { 994c8ec8eeaSjose borrego switch (tree->t_state) { 995c8ec8eeaSjose borrego case SMB_TREE_STATE_CONNECTED: 996c8ec8eeaSjose borrego return (B_TRUE); 997da6c28aaSamw 998c8ec8eeaSjose borrego case SMB_TREE_STATE_DISCONNECTING: 999c8ec8eeaSjose borrego case SMB_TREE_STATE_DISCONNECTED: 1000c8ec8eeaSjose borrego /* 1001c8ec8eeaSjose borrego * The tree exists but being diconnected or destroyed. 1002c8ec8eeaSjose borrego */ 1003c8ec8eeaSjose borrego return (B_FALSE); 1004c8ec8eeaSjose borrego 1005c8ec8eeaSjose borrego default: 1006da6c28aaSamw ASSERT(0); 1007c8ec8eeaSjose borrego return (B_FALSE); 1008da6c28aaSamw } 1009da6c28aaSamw } 1010da6c28aaSamw 1011da6c28aaSamw /* 1012c8ec8eeaSjose borrego * Determine whether or not a tree is disconnected. 1013c8ec8eeaSjose borrego * This function must be called with the tree mutex held. 1014da6c28aaSamw */ 1015c8ec8eeaSjose borrego static boolean_t 1016c8ec8eeaSjose borrego smb_tree_is_disconnected(smb_tree_t *tree) 1017da6c28aaSamw { 1018c8ec8eeaSjose borrego switch (tree->t_state) { 1019c8ec8eeaSjose borrego case SMB_TREE_STATE_DISCONNECTED: 1020c8ec8eeaSjose borrego return (B_TRUE); 1021da6c28aaSamw 1022c8ec8eeaSjose borrego case SMB_TREE_STATE_CONNECTED: 1023c8ec8eeaSjose borrego case SMB_TREE_STATE_DISCONNECTING: 1024c8ec8eeaSjose borrego return (B_FALSE); 1025da6c28aaSamw 1026c8ec8eeaSjose borrego default: 1027da6c28aaSamw ASSERT(0); 1028c8ec8eeaSjose borrego return (B_FALSE); 1029da6c28aaSamw } 1030da6c28aaSamw } 1031da6c28aaSamw 1032c8ec8eeaSjose borrego /* 1033c8ec8eeaSjose borrego * Return a pointer to the share name within a share resource path. 1034c8ec8eeaSjose borrego * 1035c8ec8eeaSjose borrego * The share path may be a Uniform Naming Convention (UNC) string 1036c8ec8eeaSjose borrego * (\\server\share) or simply the share name. We validate the UNC 1037c8ec8eeaSjose borrego * format but we don't look at the server name. 1038c8ec8eeaSjose borrego */ 1039c8ec8eeaSjose borrego static const char * 1040c8ec8eeaSjose borrego smb_tree_get_sharename(const char *unc_path) 1041c8ec8eeaSjose borrego { 1042c8ec8eeaSjose borrego const char *sharename = unc_path; 1043c8ec8eeaSjose borrego 1044c8ec8eeaSjose borrego if (sharename[0] == '\\') { 1045c8ec8eeaSjose borrego /* 1046c8ec8eeaSjose borrego * Looks like a UNC path, validate the format. 1047c8ec8eeaSjose borrego */ 1048c8ec8eeaSjose borrego if (sharename[1] != '\\') 1049c8ec8eeaSjose borrego return (NULL); 1050c8ec8eeaSjose borrego 1051c8ec8eeaSjose borrego if ((sharename = strchr(sharename+2, '\\')) == NULL) 1052c8ec8eeaSjose borrego return (NULL); 1053c8ec8eeaSjose borrego 1054c8ec8eeaSjose borrego ++sharename; 1055c8ec8eeaSjose borrego } else if (strchr(sharename, '\\') != NULL) { 1056c8ec8eeaSjose borrego /* 1057c8ec8eeaSjose borrego * This should be a share name (no embedded \'s). 1058c8ec8eeaSjose borrego */ 1059c8ec8eeaSjose borrego return (NULL); 1060c8ec8eeaSjose borrego } 1061c8ec8eeaSjose borrego 1062c8ec8eeaSjose borrego return (sharename); 1063c8ec8eeaSjose borrego } 1064c8ec8eeaSjose borrego 1065c8ec8eeaSjose borrego /* 1066c8ec8eeaSjose borrego * Obtain the tree attributes: volume name, typename and flags. 1067c8ec8eeaSjose borrego */ 1068c8ec8eeaSjose borrego static int 1069148c5f43SAlan Wright smb_tree_getattr(const smb_kshare_t *si, smb_node_t *node, smb_tree_t *tree) 1070c8ec8eeaSjose borrego { 1071c8ec8eeaSjose borrego vfs_t *vfsp = SMB_NODE_VFS(node); 1072c8ec8eeaSjose borrego 1073c8ec8eeaSjose borrego ASSERT(vfsp); 1074c8ec8eeaSjose borrego 1075c8ec8eeaSjose borrego if (getvfs(&vfsp->vfs_fsid) != vfsp) 1076c8ec8eeaSjose borrego return (ESTALE); 1077c8ec8eeaSjose borrego 1078c8ec8eeaSjose borrego smb_tree_get_volname(vfsp, tree); 10798b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_tree_get_flags(si, vfsp, tree); 1080c8ec8eeaSjose borrego 1081c8ec8eeaSjose borrego VFS_RELE(vfsp); 1082c8ec8eeaSjose borrego return (0); 1083c8ec8eeaSjose borrego } 1084c8ec8eeaSjose borrego 1085c8ec8eeaSjose borrego /* 1086c8ec8eeaSjose borrego * Extract the volume name. 1087c8ec8eeaSjose borrego */ 1088c8ec8eeaSjose borrego static void 1089c8ec8eeaSjose borrego smb_tree_get_volname(vfs_t *vfsp, smb_tree_t *tree) 1090c8ec8eeaSjose borrego { 1091c8ec8eeaSjose borrego refstr_t *vfs_mntpoint; 1092c8ec8eeaSjose borrego const char *s; 1093c8ec8eeaSjose borrego char *name; 1094c8ec8eeaSjose borrego 1095c8ec8eeaSjose borrego vfs_mntpoint = vfs_getmntpoint(vfsp); 1096c8ec8eeaSjose borrego 1097c8ec8eeaSjose borrego s = vfs_mntpoint->rs_string; 1098c8ec8eeaSjose borrego s += strspn(s, "/"); 1099c8ec8eeaSjose borrego (void) strlcpy(tree->t_volume, s, SMB_VOLNAMELEN); 1100c8ec8eeaSjose borrego 1101c8ec8eeaSjose borrego refstr_rele(vfs_mntpoint); 1102c8ec8eeaSjose borrego 1103c8ec8eeaSjose borrego name = tree->t_volume; 1104c8ec8eeaSjose borrego (void) strsep((char **)&name, "/"); 1105c8ec8eeaSjose borrego } 1106c8ec8eeaSjose borrego 1107c8ec8eeaSjose borrego /* 1108c8ec8eeaSjose borrego * Always set ACL support because the VFS will fake ACLs for file systems 1109c8ec8eeaSjose borrego * that don't support them. 1110c8ec8eeaSjose borrego * 1111c8ec8eeaSjose borrego * Some flags are dependent on the typename, which is also set up here. 1112c8ec8eeaSjose borrego * File system types are hardcoded in uts/common/os/vfs_conf.c. 1113c8ec8eeaSjose borrego */ 1114c8ec8eeaSjose borrego static void 1115148c5f43SAlan Wright smb_tree_get_flags(const smb_kshare_t *si, vfs_t *vfsp, smb_tree_t *tree) 1116c8ec8eeaSjose borrego { 11175f1ef25cSAram Hăvărneanu smb_session_t *ssn = tree->t_session; 11185f1ef25cSAram Hăvărneanu 1119fc724630SAlan Wright typedef struct smb_mtype { 1120fc724630SAlan Wright char *mt_name; 1121fc724630SAlan Wright size_t mt_namelen; 1122fc724630SAlan Wright uint32_t mt_flags; 1123fc724630SAlan Wright } smb_mtype_t; 1124fc724630SAlan Wright 1125fc724630SAlan Wright static smb_mtype_t smb_mtype[] = { 1126fd9ee8b5Sjoyce mcintosh { "zfs", 3, SMB_TREE_UNICODE_ON_DISK | 1127fd9ee8b5Sjoyce mcintosh SMB_TREE_QUOTA | SMB_TREE_SPARSE}, 1128fc724630SAlan Wright { "ufs", 3, SMB_TREE_UNICODE_ON_DISK }, 1129fc724630SAlan Wright { "nfs", 3, SMB_TREE_NFS_MOUNTED }, 1130fc724630SAlan Wright { "tmpfs", 5, SMB_TREE_NO_EXPORT } 1131fc724630SAlan Wright }; 1132fc724630SAlan Wright smb_mtype_t *mtype; 1133c8ec8eeaSjose borrego char *name; 1134fc724630SAlan Wright uint32_t flags = SMB_TREE_SUPPORTS_ACLS; 1135fc724630SAlan Wright int i; 1136c8ec8eeaSjose borrego 11379fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (si->shr_flags & SMB_SHRF_DFSROOT) 11389fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States flags |= SMB_TREE_DFSROOT; 11399fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 11408b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (si->shr_flags & SMB_SHRF_CATIA) 11418b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States flags |= SMB_TREE_CATIA; 11428b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 1143e3f2c991SKeyur Desai if (si->shr_flags & SMB_SHRF_ABE) 1144e3f2c991SKeyur Desai flags |= SMB_TREE_ABE; 1145e3f2c991SKeyur Desai 11465f1ef25cSAram Hăvărneanu if (ssn->s_cfg.skc_oplock_enable) { 1147cb174861Sjoyce mcintosh /* if 'smb' zfs property: oplocks=enabled */ 1148cb174861Sjoyce mcintosh flags |= SMB_TREE_OPLOCKS; 1149cb174861Sjoyce mcintosh } 1150cb174861Sjoyce mcintosh 11515f1ef25cSAram Hăvărneanu /* Global config option for now. Later make per-share. */ 11525f1ef25cSAram Hăvărneanu if (ssn->s_cfg.skc_traverse_mounts) 11535f1ef25cSAram Hăvărneanu flags |= SMB_TREE_TRAVERSE_MOUNTS; 11545f1ef25cSAram Hăvărneanu 1155cb174861Sjoyce mcintosh /* if 'smb' zfs property: shortnames=enabled */ 1156cb174861Sjoyce mcintosh if (smb_shortnames) 1157cb174861Sjoyce mcintosh flags |= SMB_TREE_SHORTNAMES; 1158cb174861Sjoyce mcintosh 1159c8ec8eeaSjose borrego if (vfsp->vfs_flag & VFS_RDONLY) 1160c8ec8eeaSjose borrego flags |= SMB_TREE_READONLY; 1161c8ec8eeaSjose borrego 1162c8ec8eeaSjose borrego if (vfsp->vfs_flag & VFS_XATTR) 1163c8ec8eeaSjose borrego flags |= SMB_TREE_STREAMS; 1164c8ec8eeaSjose borrego 1165c8ec8eeaSjose borrego name = vfssw[vfsp->vfs_fstype].vsw_name; 1166c8ec8eeaSjose borrego 1167fc724630SAlan Wright for (i = 0; i < sizeof (smb_mtype) / sizeof (smb_mtype[0]); ++i) { 1168fc724630SAlan Wright mtype = &smb_mtype[i]; 1169fc724630SAlan Wright if (strncasecmp(name, mtype->mt_name, mtype->mt_namelen) == 0) 1170fc724630SAlan Wright flags |= mtype->mt_flags; 1171fc724630SAlan Wright } 1172c8ec8eeaSjose borrego 1173c8ec8eeaSjose borrego (void) strlcpy(tree->t_typename, name, SMB_TYPENAMELEN); 1174bbf6f00cSJordan Brown (void) smb_strupr((char *)tree->t_typename); 1175c8ec8eeaSjose borrego 1176c8ec8eeaSjose borrego if (vfs_has_feature(vfsp, VFSFT_XVATTR)) 1177c8ec8eeaSjose borrego flags |= SMB_TREE_XVATTR; 1178c8ec8eeaSjose borrego 1179c8ec8eeaSjose borrego if (vfs_has_feature(vfsp, VFSFT_CASEINSENSITIVE)) 1180c8ec8eeaSjose borrego flags |= SMB_TREE_CASEINSENSITIVE; 1181c8ec8eeaSjose borrego 1182c8ec8eeaSjose borrego if (vfs_has_feature(vfsp, VFSFT_NOCASESENSITIVE)) 1183c8ec8eeaSjose borrego flags |= SMB_TREE_NO_CASESENSITIVE; 1184c8ec8eeaSjose borrego 1185c8ec8eeaSjose borrego if (vfs_has_feature(vfsp, VFSFT_DIRENTFLAGS)) 1186c8ec8eeaSjose borrego flags |= SMB_TREE_DIRENTFLAGS; 1187c8ec8eeaSjose borrego 1188c8ec8eeaSjose borrego if (vfs_has_feature(vfsp, VFSFT_ACLONCREATE)) 1189c8ec8eeaSjose borrego flags |= SMB_TREE_ACLONCREATE; 1190c8ec8eeaSjose borrego 1191c8ec8eeaSjose borrego if (vfs_has_feature(vfsp, VFSFT_ACEMASKONACCESS)) 1192c8ec8eeaSjose borrego flags |= SMB_TREE_ACEMASKONACCESS; 1193c8ec8eeaSjose borrego 1194fc724630SAlan Wright DTRACE_PROBE2(smb__tree__flags, uint32_t, flags, char *, name); 1195fc724630SAlan Wright 1196c8ec8eeaSjose borrego 1197c8ec8eeaSjose borrego tree->t_flags = flags; 1198c8ec8eeaSjose borrego } 1199c8ec8eeaSjose borrego 1200c8ec8eeaSjose borrego /* 1201c8ec8eeaSjose borrego * Report share access result to syslog. 1202c8ec8eeaSjose borrego */ 1203c8ec8eeaSjose borrego static void 1204c8ec8eeaSjose borrego smb_tree_log(smb_request_t *sr, const char *sharename, const char *fmt, ...) 1205c8ec8eeaSjose borrego { 1206c8ec8eeaSjose borrego va_list ap; 1207c8ec8eeaSjose borrego char buf[128]; 1208c8ec8eeaSjose borrego smb_user_t *user = sr->uid_user; 1209c8ec8eeaSjose borrego 1210c8ec8eeaSjose borrego ASSERT(user); 1211c8ec8eeaSjose borrego 1212c8ec8eeaSjose borrego if (smb_tcon_mute) 1213c8ec8eeaSjose borrego return; 1214c8ec8eeaSjose borrego 1215c8ec8eeaSjose borrego if ((user->u_name) && (strcasecmp(sharename, "IPC$") == 0)) { 1216c8ec8eeaSjose borrego /* 1217c8ec8eeaSjose borrego * Only report normal users, i.e. ignore W2K misuse 1218c8ec8eeaSjose borrego * of the IPC connection by filtering out internal 1219c8ec8eeaSjose borrego * names such as nobody and root. 1220c8ec8eeaSjose borrego */ 1221c8ec8eeaSjose borrego if ((strcmp(user->u_name, "root") == 0) || 1222c8ec8eeaSjose borrego (strcmp(user->u_name, "nobody") == 0)) { 1223c8ec8eeaSjose borrego return; 1224c8ec8eeaSjose borrego } 1225c8ec8eeaSjose borrego } 1226c8ec8eeaSjose borrego 1227c8ec8eeaSjose borrego va_start(ap, fmt); 1228c8ec8eeaSjose borrego (void) vsnprintf(buf, 128, fmt, ap); 1229c8ec8eeaSjose borrego va_end(ap); 1230c8ec8eeaSjose borrego 1231c8ec8eeaSjose borrego cmn_err(CE_NOTE, "smbd[%s\\%s]: %s %s", 1232c8ec8eeaSjose borrego user->u_domain, user->u_name, sharename, buf); 1233da6c28aaSamw } 12347f667e74Sjose borrego 12357f667e74Sjose borrego /* 12367f667e74Sjose borrego * smb_tree_lookup_odir 12377f667e74Sjose borrego * 12387f667e74Sjose borrego * Find the specified odir in the tree's list of odirs, and 12397f667e74Sjose borrego * attempt to obtain a hold on the odir. 12407f667e74Sjose borrego * 12417f667e74Sjose borrego * Returns NULL if odir not found or a hold cannot be obtained. 12427f667e74Sjose borrego */ 12437f667e74Sjose borrego smb_odir_t * 12443b13a1efSThomas Keiser smb_tree_lookup_odir(smb_request_t *sr, uint16_t odid) 12457f667e74Sjose borrego { 12467f667e74Sjose borrego smb_odir_t *od; 12477f667e74Sjose borrego smb_llist_t *od_list; 12483b13a1efSThomas Keiser smb_tree_t *tree = sr->tid_tree; 12497f667e74Sjose borrego 12507f667e74Sjose borrego ASSERT(tree->t_magic == SMB_TREE_MAGIC); 12517f667e74Sjose borrego 12527f667e74Sjose borrego od_list = &tree->t_odir_list; 12537f667e74Sjose borrego 12543b13a1efSThomas Keiser smb_llist_enter(od_list, RW_READER); 12557f667e74Sjose borrego od = smb_llist_head(od_list); 12567f667e74Sjose borrego while (od) { 12573b13a1efSThomas Keiser if (od->d_odid == odid) 12587f667e74Sjose borrego break; 12597f667e74Sjose borrego od = smb_llist_next(od_list, od); 12607f667e74Sjose borrego } 12613b13a1efSThomas Keiser if (od == NULL) 12623b13a1efSThomas Keiser goto out; 12637f667e74Sjose borrego 12643b13a1efSThomas Keiser /* 12653b13a1efSThomas Keiser * Only allow use of a given Search ID with the same UID that 12663b13a1efSThomas Keiser * was used to create it. MS-CIFS 3.3.5.14 12673b13a1efSThomas Keiser */ 12683b13a1efSThomas Keiser if (od->d_user != sr->uid_user) { 12693b13a1efSThomas Keiser od = NULL; 12703b13a1efSThomas Keiser goto out; 12713b13a1efSThomas Keiser } 12723b13a1efSThomas Keiser if (!smb_odir_hold(od)) 12733b13a1efSThomas Keiser od = NULL; 12743b13a1efSThomas Keiser 12753b13a1efSThomas Keiser out: 12767f667e74Sjose borrego smb_llist_exit(od_list); 12777f667e74Sjose borrego return (od); 12787f667e74Sjose borrego } 12797f667e74Sjose borrego 12808b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States boolean_t 12818b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_tree_is_connected(smb_tree_t *tree) 12828b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States { 12838b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States boolean_t rb; 12848b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 12858b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States mutex_enter(&tree->t_mutex); 12868b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States rb = smb_tree_is_connected_locked(tree); 12878b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States mutex_exit(&tree->t_mutex); 12888b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States return (rb); 12898b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States } 12908b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 12917f667e74Sjose borrego /* 12921fcced4cSJordan Brown * Get the next open ofile in the list. A reference is taken on 12931fcced4cSJordan Brown * the ofile, which can be released later with smb_ofile_release(). 12941fcced4cSJordan Brown * 12951fcced4cSJordan Brown * If the specified ofile is NULL, search from the beginning of the 12961fcced4cSJordan Brown * list. Otherwise, the search starts just after that ofile. 12971fcced4cSJordan Brown * 12981fcced4cSJordan Brown * Returns NULL if there are no open files in the list. 12991fcced4cSJordan Brown */ 13001fcced4cSJordan Brown static smb_ofile_t * 13011fcced4cSJordan Brown smb_tree_get_ofile(smb_tree_t *tree, smb_ofile_t *of) 13021fcced4cSJordan Brown { 13031fcced4cSJordan Brown smb_llist_t *ofile_list; 13041fcced4cSJordan Brown 13051fcced4cSJordan Brown ASSERT(tree); 13061fcced4cSJordan Brown ASSERT(tree->t_magic == SMB_TREE_MAGIC); 13071fcced4cSJordan Brown 13081fcced4cSJordan Brown ofile_list = &tree->t_ofile_list; 13091fcced4cSJordan Brown smb_llist_enter(ofile_list, RW_READER); 13101fcced4cSJordan Brown 13111fcced4cSJordan Brown if (of) { 13121fcced4cSJordan Brown ASSERT(of->f_magic == SMB_OFILE_MAGIC); 13131fcced4cSJordan Brown of = smb_llist_next(ofile_list, of); 13141fcced4cSJordan Brown } else { 13151fcced4cSJordan Brown of = smb_llist_head(ofile_list); 13161fcced4cSJordan Brown } 13171fcced4cSJordan Brown 13181fcced4cSJordan Brown while (of) { 13191fcced4cSJordan Brown if (smb_ofile_hold(of)) 13201fcced4cSJordan Brown break; 13211fcced4cSJordan Brown 13221fcced4cSJordan Brown of = smb_llist_next(ofile_list, of); 13231fcced4cSJordan Brown } 13241fcced4cSJordan Brown 13251fcced4cSJordan Brown smb_llist_exit(ofile_list); 13261fcced4cSJordan Brown return (of); 13271fcced4cSJordan Brown } 13281fcced4cSJordan Brown 13291fcced4cSJordan Brown /* 13307f667e74Sjose borrego * smb_tree_get_odir 13317f667e74Sjose borrego * 1332a1511e6bSjoyce mcintosh * Find the next odir in the tree's list of odirs, and obtain a 1333a1511e6bSjoyce mcintosh * hold on it. 13347f667e74Sjose borrego * If the specified odir is NULL the search starts at the beginning 13357f667e74Sjose borrego * of the tree's odir list, otherwise the search starts after the 13367f667e74Sjose borrego * specified odir. 13377f667e74Sjose borrego */ 13387f667e74Sjose borrego static smb_odir_t * 13397f667e74Sjose borrego smb_tree_get_odir(smb_tree_t *tree, smb_odir_t *od) 13407f667e74Sjose borrego { 13417f667e74Sjose borrego smb_llist_t *od_list; 13427f667e74Sjose borrego 13437f667e74Sjose borrego ASSERT(tree); 13447f667e74Sjose borrego ASSERT(tree->t_magic == SMB_TREE_MAGIC); 13457f667e74Sjose borrego 13467f667e74Sjose borrego od_list = &tree->t_odir_list; 13477f667e74Sjose borrego smb_llist_enter(od_list, RW_READER); 13487f667e74Sjose borrego 13497f667e74Sjose borrego if (od) { 13507f667e74Sjose borrego ASSERT(od->d_magic == SMB_ODIR_MAGIC); 13517f667e74Sjose borrego od = smb_llist_next(od_list, od); 13527f667e74Sjose borrego } else { 13537f667e74Sjose borrego od = smb_llist_head(od_list); 13547f667e74Sjose borrego } 13557f667e74Sjose borrego 13567f667e74Sjose borrego while (od) { 13577f667e74Sjose borrego ASSERT(od->d_magic == SMB_ODIR_MAGIC); 13587f667e74Sjose borrego 13597f667e74Sjose borrego if (smb_odir_hold(od)) 13607f667e74Sjose borrego break; 13617f667e74Sjose borrego od = smb_llist_next(od_list, od); 13627f667e74Sjose borrego } 13637f667e74Sjose borrego 13647f667e74Sjose borrego smb_llist_exit(od_list); 13657f667e74Sjose borrego return (od); 13667f667e74Sjose borrego } 13677f667e74Sjose borrego 13687f667e74Sjose borrego /* 13697f667e74Sjose borrego * smb_tree_close_odirs 13707f667e74Sjose borrego * 13717f667e74Sjose borrego * Close all open odirs in the tree's list which were opened by 13727f667e74Sjose borrego * the process identified by pid. 13737f667e74Sjose borrego * If pid is zero, close all open odirs in the tree's list. 13747f667e74Sjose borrego */ 13757f667e74Sjose borrego static void 13767f667e74Sjose borrego smb_tree_close_odirs(smb_tree_t *tree, uint16_t pid) 13777f667e74Sjose borrego { 13787f667e74Sjose borrego smb_odir_t *od, *next_od; 13797f667e74Sjose borrego 13807f667e74Sjose borrego ASSERT(tree); 13817f667e74Sjose borrego ASSERT(tree->t_magic == SMB_TREE_MAGIC); 13827f667e74Sjose borrego 13837f667e74Sjose borrego od = smb_tree_get_odir(tree, NULL); 13847f667e74Sjose borrego while (od) { 13857f667e74Sjose borrego ASSERT(od->d_magic == SMB_ODIR_MAGIC); 13867f667e74Sjose borrego ASSERT(od->d_tree == tree); 13877f667e74Sjose borrego 13887f667e74Sjose borrego next_od = smb_tree_get_odir(tree, od); 13897f667e74Sjose borrego if ((pid == 0) || (od->d_opened_by_pid == pid)) 13907f667e74Sjose borrego smb_odir_close(od); 13917f667e74Sjose borrego smb_odir_release(od); 13927f667e74Sjose borrego 13937f667e74Sjose borrego od = next_od; 13947f667e74Sjose borrego } 13957f667e74Sjose borrego } 139629bd2886SAlan Wright 139729bd2886SAlan Wright static void 13983b13a1efSThomas Keiser smb_tree_set_execinfo(smb_tree_t *tree, smb_shr_execinfo_t *exec, 13993b13a1efSThomas Keiser int exec_type) 140029bd2886SAlan Wright { 1401148c5f43SAlan Wright exec->e_sharename = tree->t_sharename; 14023b13a1efSThomas Keiser exec->e_winname = tree->t_owner->u_name; 14033b13a1efSThomas Keiser exec->e_userdom = tree->t_owner->u_domain; 1404148c5f43SAlan Wright exec->e_srv_ipaddr = tree->t_session->local_ipaddr; 1405148c5f43SAlan Wright exec->e_cli_ipaddr = tree->t_session->ipaddr; 1406148c5f43SAlan Wright exec->e_cli_netbiosname = tree->t_session->workstation; 14073b13a1efSThomas Keiser exec->e_uid = crgetuid(tree->t_owner->u_cred); 1408148c5f43SAlan Wright exec->e_type = exec_type; 140929bd2886SAlan Wright } 14101fcced4cSJordan Brown 14111fcced4cSJordan Brown /* 14121fcced4cSJordan Brown * Private function to support smb_tree_enum. 14131fcced4cSJordan Brown */ 14141fcced4cSJordan Brown static int 14151fcced4cSJordan Brown smb_tree_enum_private(smb_tree_t *tree, smb_svcenum_t *svcenum) 14161fcced4cSJordan Brown { 14171fcced4cSJordan Brown uint8_t *pb; 14181fcced4cSJordan Brown uint_t nbytes; 14191fcced4cSJordan Brown int rc; 14201fcced4cSJordan Brown 14211fcced4cSJordan Brown if (svcenum->se_nskip > 0) { 14221fcced4cSJordan Brown svcenum->se_nskip--; 14231fcced4cSJordan Brown return (0); 14241fcced4cSJordan Brown } 14251fcced4cSJordan Brown 14261fcced4cSJordan Brown if (svcenum->se_nitems >= svcenum->se_nlimit) { 14271fcced4cSJordan Brown svcenum->se_nitems = svcenum->se_nlimit; 14281fcced4cSJordan Brown return (0); 14291fcced4cSJordan Brown } 14301fcced4cSJordan Brown 14311fcced4cSJordan Brown pb = &svcenum->se_buf[svcenum->se_bused]; 14321fcced4cSJordan Brown rc = smb_tree_netinfo_encode(tree, pb, svcenum->se_bavail, &nbytes); 14331fcced4cSJordan Brown if (rc == 0) { 14341fcced4cSJordan Brown svcenum->se_bavail -= nbytes; 14351fcced4cSJordan Brown svcenum->se_bused += nbytes; 14361fcced4cSJordan Brown svcenum->se_nitems++; 14371fcced4cSJordan Brown } 14381fcced4cSJordan Brown 14391fcced4cSJordan Brown return (rc); 14401fcced4cSJordan Brown } 14411fcced4cSJordan Brown 14421fcced4cSJordan Brown /* 14431fcced4cSJordan Brown * Encode connection information into a buffer: connection information 14441fcced4cSJordan Brown * needed in user space to support RPC requests. 14451fcced4cSJordan Brown */ 14461fcced4cSJordan Brown static int 14471fcced4cSJordan Brown smb_tree_netinfo_encode(smb_tree_t *tree, uint8_t *buf, size_t buflen, 14481fcced4cSJordan Brown uint32_t *nbytes) 14491fcced4cSJordan Brown { 14501fcced4cSJordan Brown smb_netconnectinfo_t info; 14511fcced4cSJordan Brown int rc; 14521fcced4cSJordan Brown 14531fcced4cSJordan Brown smb_tree_netinfo_init(tree, &info); 14541fcced4cSJordan Brown rc = smb_netconnectinfo_encode(&info, buf, buflen, nbytes); 14551fcced4cSJordan Brown smb_tree_netinfo_fini(&info); 14561fcced4cSJordan Brown 14571fcced4cSJordan Brown return (rc); 14581fcced4cSJordan Brown } 14591fcced4cSJordan Brown 14603b13a1efSThomas Keiser static void 14613b13a1efSThomas Keiser smb_tree_netinfo_username(smb_tree_t *tree, char **namestr, uint32_t *namelen) 14623b13a1efSThomas Keiser { 14633b13a1efSThomas Keiser smb_user_t *user = tree->t_owner; 14643b13a1efSThomas Keiser 14653b13a1efSThomas Keiser /* 14663b13a1efSThomas Keiser * u_domain_len and u_name_len include the '\0' in their 14673b13a1efSThomas Keiser * lengths, hence the sum of the two lengths gives us room 14683b13a1efSThomas Keiser * for both the '\\' and '\0' chars. 14693b13a1efSThomas Keiser */ 14703b13a1efSThomas Keiser ASSERT(namestr); 14713b13a1efSThomas Keiser ASSERT(namelen); 14723b13a1efSThomas Keiser ASSERT(user->u_domain_len > 0); 14733b13a1efSThomas Keiser ASSERT(user->u_name_len > 0); 14743b13a1efSThomas Keiser *namelen = user->u_domain_len + user->u_name_len; 14753b13a1efSThomas Keiser *namestr = kmem_alloc(*namelen, KM_SLEEP); 14763b13a1efSThomas Keiser (void) snprintf(*namestr, *namelen, "%s\\%s", user->u_domain, 14773b13a1efSThomas Keiser user->u_name); 14783b13a1efSThomas Keiser } 14793b13a1efSThomas Keiser 14801fcced4cSJordan Brown /* 14811fcced4cSJordan Brown * Note: ci_numusers should be the number of users connected to 14821fcced4cSJordan Brown * the share rather than the number of references on the tree but 14831fcced4cSJordan Brown * we don't have a mechanism to track users/share in smbsrv yet. 14841fcced4cSJordan Brown */ 14851fcced4cSJordan Brown static void 14861fcced4cSJordan Brown smb_tree_netinfo_init(smb_tree_t *tree, smb_netconnectinfo_t *info) 14871fcced4cSJordan Brown { 14881fcced4cSJordan Brown ASSERT(tree); 14891fcced4cSJordan Brown 14901fcced4cSJordan Brown info->ci_id = tree->t_tid; 14911fcced4cSJordan Brown info->ci_type = tree->t_res_type; 14921fcced4cSJordan Brown info->ci_numopens = tree->t_open_files; 14931fcced4cSJordan Brown info->ci_numusers = tree->t_refcnt; 14941fcced4cSJordan Brown info->ci_time = gethrestime_sec() - tree->t_connect_time; 14951fcced4cSJordan Brown 14961fcced4cSJordan Brown info->ci_sharelen = strlen(tree->t_sharename) + 1; 14979fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States info->ci_share = smb_mem_strdup(tree->t_sharename); 14981fcced4cSJordan Brown 14993b13a1efSThomas Keiser smb_tree_netinfo_username(tree, &info->ci_username, &info->ci_namelen); 15001fcced4cSJordan Brown } 15011fcced4cSJordan Brown 15021fcced4cSJordan Brown static void 15031fcced4cSJordan Brown smb_tree_netinfo_fini(smb_netconnectinfo_t *info) 15041fcced4cSJordan Brown { 15051fcced4cSJordan Brown if (info == NULL) 15061fcced4cSJordan Brown return; 15071fcced4cSJordan Brown 15081fcced4cSJordan Brown if (info->ci_username) 15091fcced4cSJordan Brown kmem_free(info->ci_username, info->ci_namelen); 15101fcced4cSJordan Brown if (info->ci_share) 15119fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_mem_free(info->ci_share); 15121fcced4cSJordan Brown 15131fcced4cSJordan Brown bzero(info, sizeof (smb_netconnectinfo_t)); 15141fcced4cSJordan Brown } 1515