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 */ 21da6c28aaSamw /* 22faa1795aSjb * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23da6c28aaSamw * Use is subject to license terms. 24da6c28aaSamw */ 25da6c28aaSamw 26*c8ec8eeaSjose borrego #pragma ident "@(#)smb_tree.c 1.5 08/08/07 SMI" 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 * +-------------------+ +-------------------+ +-------------------+ 44da6c28aaSamw * | 45da6c28aaSamw * | 46da6c28aaSamw * v 47da6c28aaSamw * +-------------------+ +-------------------+ +-------------------+ 48da6c28aaSamw * | USER |<----->| USER |......| USER | 49da6c28aaSamw * +-------------------+ +-------------------+ +-------------------+ 50da6c28aaSamw * | 51da6c28aaSamw * | 52da6c28aaSamw * 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 * 125da6c28aaSamw * This transition occurs in smb_tree_release(). The resources associated 126da6c28aaSamw * with the tree are freed as well as the tree structure. For the transition 127da6c28aaSamw * to occur, the tree must be in the SMB_TREE_STATE_DISCONNECTED state and 128da6c28aaSamw * the reference count be zero. 129da6c28aaSamw * 130da6c28aaSamw * Comments 131da6c28aaSamw * -------- 132da6c28aaSamw * 133da6c28aaSamw * The state machine of the tree structures is controlled by 3 elements: 134da6c28aaSamw * - The list of trees of the user it belongs to. 135da6c28aaSamw * - The mutex embedded in the structure itself. 136da6c28aaSamw * - The reference count. 137da6c28aaSamw * 138da6c28aaSamw * There's a mutex embedded in the tree structure used to protect its fields 139da6c28aaSamw * and there's a lock embedded in the list of trees of a user. To 140da6c28aaSamw * increment or to decrement the reference count the mutex must be entered. 141da6c28aaSamw * To insert the tree into the list of trees of the user and to remove 142da6c28aaSamw * the tree from it, the lock must be entered in RW_WRITER mode. 143da6c28aaSamw * 144da6c28aaSamw * Rules of access to a tree structure: 145da6c28aaSamw * 146da6c28aaSamw * 1) In order to avoid deadlocks, when both (mutex and lock of the user 147da6c28aaSamw * list) have to be entered, the lock must be entered first. 148da6c28aaSamw * 149da6c28aaSamw * 2) All actions applied to a tree require a reference count. 150da6c28aaSamw * 151*c8ec8eeaSjose borrego * 3) There are 2 ways of getting a reference count: when a tree is 152*c8ec8eeaSjose borrego * connected and when a tree is looked up. 153da6c28aaSamw * 154da6c28aaSamw * It should be noted that the reference count of a tree registers the 155da6c28aaSamw * number of references to the tree in other structures (such as an smb 156da6c28aaSamw * request). The reference count is not incremented in these 2 instances: 157da6c28aaSamw * 158da6c28aaSamw * 1) The tree is connected. An tree is anchored by his state. If there's 159da6c28aaSamw * no activity involving a tree currently connected, the reference 160da6c28aaSamw * count of that tree is zero. 161da6c28aaSamw * 162da6c28aaSamw * 2) The tree is queued in the list of trees of the user. The fact of 163da6c28aaSamw * being queued in that list is NOT registered by incrementing the 164da6c28aaSamw * reference count. 165da6c28aaSamw */ 166*c8ec8eeaSjose borrego #include <sys/types.h> 167*c8ec8eeaSjose borrego #include <sys/refstr_impl.h> 168*c8ec8eeaSjose borrego #include <sys/feature_tests.h> 169*c8ec8eeaSjose borrego #include <sys/sunddi.h> 17055bf511dSas #include <sys/fsid.h> 171*c8ec8eeaSjose borrego #include <sys/vfs.h> 172*c8ec8eeaSjose borrego #include <sys/stat.h> 173*c8ec8eeaSjose borrego #include <sys/varargs.h> 174da6c28aaSamw #include <smbsrv/smb_incl.h> 175*c8ec8eeaSjose borrego #include <smbsrv/lmerr.h> 176*c8ec8eeaSjose borrego #include <smbsrv/mlsvc.h> 177da6c28aaSamw #include <smbsrv/smb_fsops.h> 178*c8ec8eeaSjose borrego #include <smbsrv/smb_door_svc.h> 179*c8ec8eeaSjose borrego #include <smbsrv/smb_share.h> 180*c8ec8eeaSjose borrego 181*c8ec8eeaSjose borrego int smb_tcon_mute = 0; 182*c8ec8eeaSjose borrego 183*c8ec8eeaSjose borrego static smb_tree_t *smb_tree_connect_disk(smb_request_t *, const char *); 184*c8ec8eeaSjose borrego static smb_tree_t *smb_tree_connect_ipc(smb_request_t *, const char *); 185*c8ec8eeaSjose borrego static smb_tree_t *smb_tree_alloc(smb_user_t *, const char *, const char *, 186*c8ec8eeaSjose borrego int32_t, smb_node_t *); 187*c8ec8eeaSjose borrego static void smb_tree_dealloc(smb_tree_t *); 188*c8ec8eeaSjose borrego static boolean_t smb_tree_is_connected(smb_tree_t *); 189*c8ec8eeaSjose borrego static boolean_t smb_tree_is_disconnected(smb_tree_t *); 190*c8ec8eeaSjose borrego static const char *smb_tree_get_sharename(const char *); 191*c8ec8eeaSjose borrego static int smb_tree_get_stype(const char *, const char *, int32_t *); 192*c8ec8eeaSjose borrego static int smb_tree_getattr(smb_node_t *, smb_tree_t *); 193*c8ec8eeaSjose borrego static void smb_tree_get_volname(vfs_t *, smb_tree_t *); 194*c8ec8eeaSjose borrego static void smb_tree_get_flags(vfs_t *, smb_tree_t *); 195*c8ec8eeaSjose borrego static void smb_tree_log(smb_request_t *, const char *, const char *, ...); 196da6c28aaSamw 197da6c28aaSamw /* 198*c8ec8eeaSjose borrego * Extract the share name and share type and connect as appropriate. 199*c8ec8eeaSjose borrego * Share names are case insensitive so we map the share name to 200*c8ec8eeaSjose borrego * lower-case as a convenience for internal processing. 201da6c28aaSamw */ 202da6c28aaSamw smb_tree_t * 203*c8ec8eeaSjose borrego smb_tree_connect(smb_request_t *sr) 204da6c28aaSamw { 205*c8ec8eeaSjose borrego char *unc_path = sr->arg.tcon.path; 206*c8ec8eeaSjose borrego char *service = sr->arg.tcon.service; 207*c8ec8eeaSjose borrego smb_tree_t *tree = NULL; 208*c8ec8eeaSjose borrego const char *name; 209*c8ec8eeaSjose borrego int32_t stype; 210da6c28aaSamw 211*c8ec8eeaSjose borrego (void) utf8_strlwr(unc_path); 212da6c28aaSamw 213*c8ec8eeaSjose borrego if ((name = smb_tree_get_sharename(unc_path)) == NULL) { 214*c8ec8eeaSjose borrego smbsr_error(sr, 0, ERRSRV, ERRinvnetname); 215da6c28aaSamw return (NULL); 216da6c28aaSamw } 217da6c28aaSamw 218*c8ec8eeaSjose borrego if (smb_tree_get_stype(name, service, &stype) != 0) { 219*c8ec8eeaSjose borrego smbsr_error(sr, NT_STATUS_BAD_DEVICE_TYPE, 220*c8ec8eeaSjose borrego ERRDOS, ERROR_BAD_DEV_TYPE); 221da6c28aaSamw return (NULL); 222da6c28aaSamw } 223da6c28aaSamw 224da6c28aaSamw switch (stype & STYPE_MASK) { 225da6c28aaSamw case STYPE_DISKTREE: 226*c8ec8eeaSjose borrego tree = smb_tree_connect_disk(sr, name); 227da6c28aaSamw break; 228da6c28aaSamw 229da6c28aaSamw case STYPE_IPC: 230*c8ec8eeaSjose borrego tree = smb_tree_connect_ipc(sr, name); 231*c8ec8eeaSjose borrego break; 232*c8ec8eeaSjose borrego 233da6c28aaSamw default: 234*c8ec8eeaSjose borrego smbsr_error(sr, NT_STATUS_BAD_DEVICE_TYPE, 235*c8ec8eeaSjose borrego ERRDOS, ERROR_BAD_DEV_TYPE); 236da6c28aaSamw break; 237da6c28aaSamw } 238da6c28aaSamw 239da6c28aaSamw return (tree); 240da6c28aaSamw } 241da6c28aaSamw 242da6c28aaSamw /* 243*c8ec8eeaSjose borrego * Disconnect a tree. 244da6c28aaSamw */ 245da6c28aaSamw void 246da6c28aaSamw smb_tree_disconnect( 247da6c28aaSamw smb_tree_t *tree) 248da6c28aaSamw { 249da6c28aaSamw ASSERT(tree->t_magic == SMB_TREE_MAGIC); 250da6c28aaSamw 251da6c28aaSamw mutex_enter(&tree->t_mutex); 252da6c28aaSamw ASSERT(tree->t_refcnt); 253*c8ec8eeaSjose borrego 254*c8ec8eeaSjose borrego if (smb_tree_is_connected(tree)) { 255da6c28aaSamw /* 256*c8ec8eeaSjose borrego * Indicate that the disconnect process has started. 257da6c28aaSamw */ 258da6c28aaSamw tree->t_state = SMB_TREE_STATE_DISCONNECTING; 259da6c28aaSamw mutex_exit(&tree->t_mutex); 260faa1795aSjb atomic_dec_32(&tree->t_server->sv_open_trees); 261*c8ec8eeaSjose borrego 262da6c28aaSamw /* 263da6c28aaSamw * The files opened under this tree are closed. 264da6c28aaSamw */ 265da6c28aaSamw smb_ofile_close_all(tree); 266da6c28aaSamw /* 267da6c28aaSamw * The directories opened under this tree are closed. 268da6c28aaSamw */ 269da6c28aaSamw smb_odir_close_all(tree); 270da6c28aaSamw mutex_enter(&tree->t_mutex); 271da6c28aaSamw tree->t_state = SMB_TREE_STATE_DISCONNECTED; 272da6c28aaSamw } 273da6c28aaSamw 274da6c28aaSamw mutex_exit(&tree->t_mutex); 275da6c28aaSamw } 276da6c28aaSamw 277da6c28aaSamw /* 278*c8ec8eeaSjose borrego * Take a reference on a tree. 279da6c28aaSamw */ 280*c8ec8eeaSjose borrego boolean_t 281*c8ec8eeaSjose borrego smb_tree_hold( 282*c8ec8eeaSjose borrego smb_tree_t *tree) 283da6c28aaSamw { 284*c8ec8eeaSjose borrego ASSERT(tree); 285*c8ec8eeaSjose borrego ASSERT(tree->t_magic == SMB_TREE_MAGIC); 286da6c28aaSamw 287*c8ec8eeaSjose borrego mutex_enter(&tree->t_mutex); 288*c8ec8eeaSjose borrego 289*c8ec8eeaSjose borrego if (smb_tree_is_connected(tree)) { 290*c8ec8eeaSjose borrego tree->t_refcnt++; 291*c8ec8eeaSjose borrego mutex_exit(&tree->t_mutex); 292*c8ec8eeaSjose borrego return (B_TRUE); 293da6c28aaSamw } 294*c8ec8eeaSjose borrego 295*c8ec8eeaSjose borrego mutex_exit(&tree->t_mutex); 296*c8ec8eeaSjose borrego return (B_FALSE); 297da6c28aaSamw } 298da6c28aaSamw 299da6c28aaSamw /* 300*c8ec8eeaSjose borrego * Release a reference on a tree. If the tree is disconnected and the 301*c8ec8eeaSjose borrego * reference count falls to zero, the tree will be deallocated. 302da6c28aaSamw */ 303da6c28aaSamw void 304*c8ec8eeaSjose borrego smb_tree_release( 305*c8ec8eeaSjose borrego smb_tree_t *tree) 306da6c28aaSamw { 307*c8ec8eeaSjose borrego ASSERT(tree); 308*c8ec8eeaSjose borrego ASSERT(tree->t_magic == SMB_TREE_MAGIC); 309da6c28aaSamw 310*c8ec8eeaSjose borrego mutex_enter(&tree->t_mutex); 311*c8ec8eeaSjose borrego ASSERT(tree->t_refcnt); 312*c8ec8eeaSjose borrego tree->t_refcnt--; 313*c8ec8eeaSjose borrego 314*c8ec8eeaSjose borrego if (smb_tree_is_disconnected(tree) && (tree->t_refcnt == 0)) { 315*c8ec8eeaSjose borrego mutex_exit(&tree->t_mutex); 316*c8ec8eeaSjose borrego smb_tree_dealloc(tree); 317*c8ec8eeaSjose borrego return; 318da6c28aaSamw } 319*c8ec8eeaSjose borrego 320*c8ec8eeaSjose borrego mutex_exit(&tree->t_mutex); 321da6c28aaSamw } 322da6c28aaSamw 323da6c28aaSamw /* 324*c8ec8eeaSjose borrego * Close ofiles and odirs that match pid. 325da6c28aaSamw */ 326da6c28aaSamw void 327*c8ec8eeaSjose borrego smb_tree_close_pid( 328*c8ec8eeaSjose borrego smb_tree_t *tree, 329*c8ec8eeaSjose borrego uint16_t pid) 330da6c28aaSamw { 331da6c28aaSamw ASSERT(tree); 332da6c28aaSamw ASSERT(tree->t_magic == SMB_TREE_MAGIC); 333da6c28aaSamw 334*c8ec8eeaSjose borrego smb_ofile_close_all_by_pid(tree, pid); 335*c8ec8eeaSjose borrego smb_odir_close_all_by_pid(tree, pid); 336*c8ec8eeaSjose borrego } 337da6c28aaSamw 338*c8ec8eeaSjose borrego /* 339*c8ec8eeaSjose borrego * Check whether or not a tree supports the features identified by flags. 340*c8ec8eeaSjose borrego */ 341*c8ec8eeaSjose borrego boolean_t 342*c8ec8eeaSjose borrego smb_tree_has_feature(smb_tree_t *tree, uint32_t flags) 343*c8ec8eeaSjose borrego { 344*c8ec8eeaSjose borrego ASSERT(tree); 345*c8ec8eeaSjose borrego ASSERT(tree->t_magic == SMB_TREE_MAGIC); 346da6c28aaSamw 347*c8ec8eeaSjose borrego return ((tree->t_flags & flags) == flags); 348da6c28aaSamw } 349da6c28aaSamw 350*c8ec8eeaSjose borrego /* *************************** Static Functions ***************************** */ 351*c8ec8eeaSjose borrego 352da6c28aaSamw /* 353*c8ec8eeaSjose borrego * Connect a share for use with files and directories. 354da6c28aaSamw */ 355*c8ec8eeaSjose borrego static smb_tree_t * 356*c8ec8eeaSjose borrego smb_tree_connect_disk(smb_request_t *sr, const char *sharename) 357da6c28aaSamw { 358*c8ec8eeaSjose borrego smb_user_t *user = sr->uid_user; 359*c8ec8eeaSjose borrego smb_node_t *dir_snode = NULL; 360*c8ec8eeaSjose borrego smb_node_t *snode = NULL; 361*c8ec8eeaSjose borrego char last_component[MAXNAMELEN]; 362*c8ec8eeaSjose borrego smb_tree_t *tree; 363*c8ec8eeaSjose borrego smb_share_t si; 364*c8ec8eeaSjose borrego smb_attr_t attr; 365*c8ec8eeaSjose borrego cred_t *u_cred; 366*c8ec8eeaSjose borrego int rc; 367da6c28aaSamw 368da6c28aaSamw ASSERT(user); 369*c8ec8eeaSjose borrego u_cred = user->u_cred; 370*c8ec8eeaSjose borrego ASSERT(u_cred); 371*c8ec8eeaSjose borrego 372*c8ec8eeaSjose borrego bzero(&si, sizeof (smb_share_t)); 373*c8ec8eeaSjose borrego 374*c8ec8eeaSjose borrego if (user->u_flags & SMB_USER_FLAG_IPC) { 375*c8ec8eeaSjose borrego smb_tree_log(sr, sharename, "access denied: IPC only"); 376*c8ec8eeaSjose borrego smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRSRV, ERRaccess); 377*c8ec8eeaSjose borrego return (NULL); 378*c8ec8eeaSjose borrego } 379*c8ec8eeaSjose borrego 380*c8ec8eeaSjose borrego if (smb_kshare_getinfo(sr->sr_server->sv_lmshrd, sharename, &si) != 381*c8ec8eeaSjose borrego NERR_Success) { 382*c8ec8eeaSjose borrego smb_tree_log(sr, sharename, "share not found"); 383*c8ec8eeaSjose borrego smbsr_error(sr, 0, ERRSRV, ERRinvnetname); 384*c8ec8eeaSjose borrego return (NULL); 385*c8ec8eeaSjose borrego } 386*c8ec8eeaSjose borrego 387*c8ec8eeaSjose borrego /* 388*c8ec8eeaSjose borrego * Handle the default administration shares: C$, D$ etc. 389*c8ec8eeaSjose borrego * Only a user with admin rights is allowed to map these 390*c8ec8eeaSjose borrego * shares. 391*c8ec8eeaSjose borrego */ 392*c8ec8eeaSjose borrego if (si.shr_flags & SMB_SHRF_ADMIN) { 393*c8ec8eeaSjose borrego if (!smb_user_is_admin(user)) { 394*c8ec8eeaSjose borrego smb_tree_log(sr, sharename, "access denied: not admin"); 395*c8ec8eeaSjose borrego smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 396*c8ec8eeaSjose borrego ERRSRV, ERRaccess); 397*c8ec8eeaSjose borrego return (NULL); 398da6c28aaSamw } 399da6c28aaSamw } 400*c8ec8eeaSjose borrego 401*c8ec8eeaSjose borrego /* 402*c8ec8eeaSjose borrego * Check that the shared directory exists. 403*c8ec8eeaSjose borrego */ 404*c8ec8eeaSjose borrego rc = smb_pathname_reduce(sr, u_cred, si.shr_path, 0, 0, &dir_snode, 405*c8ec8eeaSjose borrego last_component); 406*c8ec8eeaSjose borrego 407*c8ec8eeaSjose borrego if (rc == 0) { 408*c8ec8eeaSjose borrego rc = smb_fsop_lookup(sr, u_cred, SMB_FOLLOW_LINKS, 0, 409*c8ec8eeaSjose borrego dir_snode, last_component, &snode, &attr, 0, 0); 410*c8ec8eeaSjose borrego 411*c8ec8eeaSjose borrego smb_node_release(dir_snode); 412*c8ec8eeaSjose borrego } 413*c8ec8eeaSjose borrego 414*c8ec8eeaSjose borrego if (rc) { 415*c8ec8eeaSjose borrego if (snode) 416*c8ec8eeaSjose borrego smb_node_release(snode); 417*c8ec8eeaSjose borrego 418*c8ec8eeaSjose borrego smb_tree_log(sr, sharename, "bad path: %s", si.shr_path); 419*c8ec8eeaSjose borrego smbsr_error(sr, 0, ERRSRV, ERRinvnetname); 420*c8ec8eeaSjose borrego return (NULL); 421*c8ec8eeaSjose borrego } 422*c8ec8eeaSjose borrego 423*c8ec8eeaSjose borrego tree = smb_tree_alloc(user, sharename, si.shr_path, STYPE_DISKTREE, 424*c8ec8eeaSjose borrego snode); 425*c8ec8eeaSjose borrego if (tree == NULL) 426*c8ec8eeaSjose borrego smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRSRV, ERRaccess); 427*c8ec8eeaSjose borrego 428*c8ec8eeaSjose borrego smb_node_release(snode); 429*c8ec8eeaSjose borrego return (tree); 430da6c28aaSamw } 431da6c28aaSamw 432da6c28aaSamw /* 433*c8ec8eeaSjose borrego * Connect an IPC share for use with named pipes. 434da6c28aaSamw */ 435*c8ec8eeaSjose borrego static smb_tree_t * 436*c8ec8eeaSjose borrego smb_tree_connect_ipc(smb_request_t *sr, const char *name) 437da6c28aaSamw { 438*c8ec8eeaSjose borrego smb_user_t *user = sr->uid_user; 439*c8ec8eeaSjose borrego smb_tree_t *tree; 440da6c28aaSamw 441*c8ec8eeaSjose borrego ASSERT(user); 442da6c28aaSamw 443*c8ec8eeaSjose borrego if ((user->u_flags & SMB_USER_FLAG_IPC) && 444*c8ec8eeaSjose borrego sr->sr_cfg->skc_restrict_anon) { 445*c8ec8eeaSjose borrego smb_tree_log(sr, name, "access denied: restrict anonymous"); 446*c8ec8eeaSjose borrego smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRSRV, ERRaccess); 447*c8ec8eeaSjose borrego return (NULL); 448da6c28aaSamw } 449da6c28aaSamw 450*c8ec8eeaSjose borrego tree = smb_tree_alloc(user, name, name, STYPE_IPC, NULL); 451*c8ec8eeaSjose borrego if (tree == NULL) { 452*c8ec8eeaSjose borrego smb_tree_log(sr, name, "access denied"); 453*c8ec8eeaSjose borrego smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRSRV, ERRaccess); 454da6c28aaSamw } 455*c8ec8eeaSjose borrego 456*c8ec8eeaSjose borrego return (tree); 457da6c28aaSamw } 458da6c28aaSamw 459da6c28aaSamw /* 460*c8ec8eeaSjose borrego * Allocate a tree. 461da6c28aaSamw */ 462*c8ec8eeaSjose borrego static smb_tree_t * 463*c8ec8eeaSjose borrego smb_tree_alloc( 464da6c28aaSamw smb_user_t *user, 465*c8ec8eeaSjose borrego const char *sharename, 466*c8ec8eeaSjose borrego const char *resource, 467*c8ec8eeaSjose borrego int32_t stype, 468*c8ec8eeaSjose borrego smb_node_t *snode) 469da6c28aaSamw { 470*c8ec8eeaSjose borrego smb_tree_t *tree; 471*c8ec8eeaSjose borrego uint16_t tid; 472da6c28aaSamw 473*c8ec8eeaSjose borrego if (smb_idpool_alloc(&user->u_tid_pool, &tid)) 474*c8ec8eeaSjose borrego return (NULL); 475da6c28aaSamw 476*c8ec8eeaSjose borrego tree = kmem_cache_alloc(user->u_server->si_cache_tree, KM_SLEEP); 477*c8ec8eeaSjose borrego bzero(tree, sizeof (smb_tree_t)); 478da6c28aaSamw 479*c8ec8eeaSjose borrego if (STYPE_ISDSK(stype)) { 480*c8ec8eeaSjose borrego if (smb_tree_getattr(snode, tree) != 0) { 481*c8ec8eeaSjose borrego smb_idpool_free(&user->u_tid_pool, tid); 482*c8ec8eeaSjose borrego kmem_cache_free(user->u_server->si_cache_tree, tree); 483*c8ec8eeaSjose borrego return (NULL); 484da6c28aaSamw } 485da6c28aaSamw } 486*c8ec8eeaSjose borrego 487*c8ec8eeaSjose borrego if (smb_idpool_constructor(&tree->t_fid_pool)) { 488*c8ec8eeaSjose borrego smb_idpool_free(&user->u_tid_pool, tid); 489*c8ec8eeaSjose borrego kmem_cache_free(user->u_server->si_cache_tree, tree); 490*c8ec8eeaSjose borrego return (NULL); 491*c8ec8eeaSjose borrego } 492*c8ec8eeaSjose borrego 493*c8ec8eeaSjose borrego if (smb_idpool_constructor(&tree->t_sid_pool)) { 494*c8ec8eeaSjose borrego smb_idpool_destructor(&tree->t_fid_pool); 495*c8ec8eeaSjose borrego smb_idpool_free(&user->u_tid_pool, tid); 496*c8ec8eeaSjose borrego kmem_cache_free(user->u_server->si_cache_tree, tree); 497*c8ec8eeaSjose borrego return (NULL); 498*c8ec8eeaSjose borrego } 499*c8ec8eeaSjose borrego 500*c8ec8eeaSjose borrego smb_llist_constructor(&tree->t_ofile_list, sizeof (smb_ofile_t), 501*c8ec8eeaSjose borrego offsetof(smb_ofile_t, f_lnd)); 502*c8ec8eeaSjose borrego 503*c8ec8eeaSjose borrego smb_llist_constructor(&tree->t_odir_list, sizeof (smb_odir_t), 504*c8ec8eeaSjose borrego offsetof(smb_odir_t, d_lnd)); 505*c8ec8eeaSjose borrego 506*c8ec8eeaSjose borrego (void) strlcpy(tree->t_sharename, sharename, 507*c8ec8eeaSjose borrego sizeof (tree->t_sharename)); 508*c8ec8eeaSjose borrego (void) strlcpy(tree->t_resource, resource, sizeof (tree->t_resource)); 509*c8ec8eeaSjose borrego 510*c8ec8eeaSjose borrego mutex_init(&tree->t_mutex, NULL, MUTEX_DEFAULT, NULL); 511*c8ec8eeaSjose borrego 512*c8ec8eeaSjose borrego tree->t_user = user; 513*c8ec8eeaSjose borrego tree->t_session = user->u_session; 514*c8ec8eeaSjose borrego tree->t_server = user->u_server; 515*c8ec8eeaSjose borrego tree->t_refcnt = 1; 516*c8ec8eeaSjose borrego tree->t_tid = tid; 517*c8ec8eeaSjose borrego tree->t_res_type = stype; 518*c8ec8eeaSjose borrego tree->t_state = SMB_TREE_STATE_CONNECTED; 519*c8ec8eeaSjose borrego tree->t_magic = SMB_TREE_MAGIC; 520*c8ec8eeaSjose borrego 521*c8ec8eeaSjose borrego if (STYPE_ISDSK(stype)) { 522*c8ec8eeaSjose borrego smb_node_ref(snode); 523*c8ec8eeaSjose borrego tree->t_snode = snode; 524*c8ec8eeaSjose borrego tree->t_acltype = smb_fsop_acltype(snode); 525*c8ec8eeaSjose borrego } 526*c8ec8eeaSjose borrego 527*c8ec8eeaSjose borrego smb_llist_enter(&user->u_tree_list, RW_WRITER); 528*c8ec8eeaSjose borrego smb_llist_insert_head(&user->u_tree_list, tree); 529da6c28aaSamw smb_llist_exit(&user->u_tree_list); 530*c8ec8eeaSjose borrego atomic_inc_32(&user->u_session->s_tree_cnt); 531*c8ec8eeaSjose borrego atomic_inc_32(&user->u_server->sv_open_trees); 532da6c28aaSamw 533*c8ec8eeaSjose borrego return (tree); 534*c8ec8eeaSjose borrego } 535da6c28aaSamw 536da6c28aaSamw /* 537*c8ec8eeaSjose borrego * Deallocate a tree: release all resources associated with a tree and 538*c8ec8eeaSjose borrego * remove the tree from the user's tree list. 539*c8ec8eeaSjose borrego * 540*c8ec8eeaSjose borrego * The tree being destroyed must be in the "destroying" state and the 541*c8ec8eeaSjose borrego * reference count must be zero. This function assumes it's single threaded 542*c8ec8eeaSjose borrego * i.e. only one thread will attempt to destroy a specific tree, which 543*c8ec8eeaSjose borrego * should be the case if the tree is in disconnected and has a reference 544*c8ec8eeaSjose borrego * count of zero. 545da6c28aaSamw */ 546da6c28aaSamw static void 547*c8ec8eeaSjose borrego smb_tree_dealloc(smb_tree_t *tree) 548da6c28aaSamw { 549da6c28aaSamw ASSERT(tree); 550da6c28aaSamw ASSERT(tree->t_magic == SMB_TREE_MAGIC); 551da6c28aaSamw ASSERT(tree->t_state == SMB_TREE_STATE_DISCONNECTED); 552da6c28aaSamw ASSERT(tree->t_refcnt == 0); 553da6c28aaSamw 554da6c28aaSamw /* 555*c8ec8eeaSjose borrego * Remove the tree from the user's tree list. This must be done 556*c8ec8eeaSjose borrego * before any resources associated with the tree are released. 557da6c28aaSamw */ 558da6c28aaSamw smb_llist_enter(&tree->t_user->u_tree_list, RW_WRITER); 559da6c28aaSamw smb_llist_remove(&tree->t_user->u_tree_list, tree); 560da6c28aaSamw smb_llist_exit(&tree->t_user->u_tree_list); 561da6c28aaSamw 562da6c28aaSamw tree->t_magic = (uint32_t)~SMB_TREE_MAGIC; 563da6c28aaSamw smb_idpool_free(&tree->t_user->u_tid_pool, tree->t_tid); 564da6c28aaSamw atomic_dec_32(&tree->t_session->s_tree_cnt); 565da6c28aaSamw 566*c8ec8eeaSjose borrego if (tree->t_snode) 567da6c28aaSamw smb_node_release(tree->t_snode); 568*c8ec8eeaSjose borrego 569da6c28aaSamw mutex_destroy(&tree->t_mutex); 570*c8ec8eeaSjose borrego 571da6c28aaSamw /* 572da6c28aaSamw * The list of open files and open directories should be empty. 573da6c28aaSamw */ 574da6c28aaSamw smb_llist_destructor(&tree->t_ofile_list); 575da6c28aaSamw smb_llist_destructor(&tree->t_odir_list); 576da6c28aaSamw smb_idpool_destructor(&tree->t_fid_pool); 577da6c28aaSamw smb_idpool_destructor(&tree->t_sid_pool); 578faa1795aSjb kmem_cache_free(tree->t_server->si_cache_tree, tree); 579da6c28aaSamw } 580da6c28aaSamw 581da6c28aaSamw /* 582*c8ec8eeaSjose borrego * Determine whether or not a tree is connected. 583*c8ec8eeaSjose borrego * This function must be called with the tree mutex held. 584*c8ec8eeaSjose borrego */ 585*c8ec8eeaSjose borrego static boolean_t 586*c8ec8eeaSjose borrego smb_tree_is_connected(smb_tree_t *tree) 587*c8ec8eeaSjose borrego { 588*c8ec8eeaSjose borrego switch (tree->t_state) { 589*c8ec8eeaSjose borrego case SMB_TREE_STATE_CONNECTED: 590*c8ec8eeaSjose borrego return (B_TRUE); 591*c8ec8eeaSjose borrego 592*c8ec8eeaSjose borrego case SMB_TREE_STATE_DISCONNECTING: 593*c8ec8eeaSjose borrego case SMB_TREE_STATE_DISCONNECTED: 594*c8ec8eeaSjose borrego /* 595*c8ec8eeaSjose borrego * The tree exists but being diconnected or destroyed. 596*c8ec8eeaSjose borrego */ 597*c8ec8eeaSjose borrego return (B_FALSE); 598*c8ec8eeaSjose borrego 599*c8ec8eeaSjose borrego default: 600*c8ec8eeaSjose borrego ASSERT(0); 601*c8ec8eeaSjose borrego return (B_FALSE); 602*c8ec8eeaSjose borrego } 603*c8ec8eeaSjose borrego } 604*c8ec8eeaSjose borrego 605*c8ec8eeaSjose borrego /* 606*c8ec8eeaSjose borrego * Determine whether or not a tree is disconnected. 607*c8ec8eeaSjose borrego * This function must be called with the tree mutex held. 608*c8ec8eeaSjose borrego */ 609*c8ec8eeaSjose borrego static boolean_t 610*c8ec8eeaSjose borrego smb_tree_is_disconnected(smb_tree_t *tree) 611*c8ec8eeaSjose borrego { 612*c8ec8eeaSjose borrego switch (tree->t_state) { 613*c8ec8eeaSjose borrego case SMB_TREE_STATE_DISCONNECTED: 614*c8ec8eeaSjose borrego return (B_TRUE); 615*c8ec8eeaSjose borrego 616*c8ec8eeaSjose borrego case SMB_TREE_STATE_CONNECTED: 617*c8ec8eeaSjose borrego case SMB_TREE_STATE_DISCONNECTING: 618*c8ec8eeaSjose borrego return (B_FALSE); 619*c8ec8eeaSjose borrego 620*c8ec8eeaSjose borrego default: 621*c8ec8eeaSjose borrego ASSERT(0); 622*c8ec8eeaSjose borrego return (B_FALSE); 623*c8ec8eeaSjose borrego } 624*c8ec8eeaSjose borrego } 625*c8ec8eeaSjose borrego 626*c8ec8eeaSjose borrego /* 627*c8ec8eeaSjose borrego * Return a pointer to the share name within a share resource path. 628da6c28aaSamw * 629*c8ec8eeaSjose borrego * The share path may be a Uniform Naming Convention (UNC) string 630*c8ec8eeaSjose borrego * (\\server\share) or simply the share name. We validate the UNC 631*c8ec8eeaSjose borrego * format but we don't look at the server name. 632*c8ec8eeaSjose borrego */ 633*c8ec8eeaSjose borrego static const char * 634*c8ec8eeaSjose borrego smb_tree_get_sharename(const char *unc_path) 635*c8ec8eeaSjose borrego { 636*c8ec8eeaSjose borrego const char *sharename = unc_path; 637*c8ec8eeaSjose borrego 638*c8ec8eeaSjose borrego if (sharename[0] == '\\') { 639*c8ec8eeaSjose borrego /* 640*c8ec8eeaSjose borrego * Looks like a UNC path, validate the format. 641*c8ec8eeaSjose borrego */ 642*c8ec8eeaSjose borrego if (sharename[1] != '\\') 643*c8ec8eeaSjose borrego return (NULL); 644*c8ec8eeaSjose borrego 645*c8ec8eeaSjose borrego if ((sharename = strchr(sharename+2, '\\')) == NULL) 646*c8ec8eeaSjose borrego return (NULL); 647*c8ec8eeaSjose borrego 648*c8ec8eeaSjose borrego ++sharename; 649*c8ec8eeaSjose borrego } else if (strchr(sharename, '\\') != NULL) { 650*c8ec8eeaSjose borrego /* 651*c8ec8eeaSjose borrego * This should be a share name (no embedded \'s). 652*c8ec8eeaSjose borrego */ 653*c8ec8eeaSjose borrego return (NULL); 654*c8ec8eeaSjose borrego } 655*c8ec8eeaSjose borrego 656*c8ec8eeaSjose borrego return (sharename); 657*c8ec8eeaSjose borrego } 658*c8ec8eeaSjose borrego 659*c8ec8eeaSjose borrego /* 660*c8ec8eeaSjose borrego * Map the service to a resource type. Valid values for service are: 661da6c28aaSamw * 662*c8ec8eeaSjose borrego * A: Disk share 663*c8ec8eeaSjose borrego * LPT1: Printer 664*c8ec8eeaSjose borrego * IPC Named pipe 665*c8ec8eeaSjose borrego * COMM Communications device 666*c8ec8eeaSjose borrego * ????? Any type of device (wildcard) 667da6c28aaSamw * 668*c8ec8eeaSjose borrego * We support IPC and disk shares; anything else is currently treated 669*c8ec8eeaSjose borrego * as an error. IPC$ is reserved as the named pipe share. 670da6c28aaSamw */ 671*c8ec8eeaSjose borrego static int 672*c8ec8eeaSjose borrego smb_tree_get_stype(const char *sharename, const char *service, 673*c8ec8eeaSjose borrego int32_t *stype_ret) 674da6c28aaSamw { 675*c8ec8eeaSjose borrego const char *any = "?????"; 676da6c28aaSamw 677*c8ec8eeaSjose borrego if ((strcmp(service, any) == 0) || (strcasecmp(service, "IPC") == 0)) { 678*c8ec8eeaSjose borrego if (strcasecmp(sharename, "IPC$") == 0) { 679*c8ec8eeaSjose borrego *stype_ret = STYPE_IPC; 680*c8ec8eeaSjose borrego return (0); 681da6c28aaSamw } 682da6c28aaSamw } 683da6c28aaSamw 684*c8ec8eeaSjose borrego if ((strcmp(service, any) == 0) || (strcasecmp(service, "A:") == 0)) { 685*c8ec8eeaSjose borrego if (strcasecmp(sharename, "IPC$") == 0) 686*c8ec8eeaSjose borrego return (-1); 687*c8ec8eeaSjose borrego 688*c8ec8eeaSjose borrego *stype_ret = STYPE_DISKTREE; 689*c8ec8eeaSjose borrego return (0); 690*c8ec8eeaSjose borrego } 691*c8ec8eeaSjose borrego 692*c8ec8eeaSjose borrego return (-1); 693da6c28aaSamw } 694da6c28aaSamw 695da6c28aaSamw /* 696*c8ec8eeaSjose borrego * Obtain the tree attributes: volume name, typename and flags. 697*c8ec8eeaSjose borrego */ 698*c8ec8eeaSjose borrego static int 699*c8ec8eeaSjose borrego smb_tree_getattr(smb_node_t *node, smb_tree_t *tree) 700*c8ec8eeaSjose borrego { 701*c8ec8eeaSjose borrego vfs_t *vfsp = SMB_NODE_VFS(node); 702*c8ec8eeaSjose borrego 703*c8ec8eeaSjose borrego ASSERT(vfsp); 704*c8ec8eeaSjose borrego 705*c8ec8eeaSjose borrego if (getvfs(&vfsp->vfs_fsid) != vfsp) 706*c8ec8eeaSjose borrego return (ESTALE); 707*c8ec8eeaSjose borrego 708*c8ec8eeaSjose borrego smb_tree_get_volname(vfsp, tree); 709*c8ec8eeaSjose borrego smb_tree_get_flags(vfsp, tree); 710*c8ec8eeaSjose borrego 711*c8ec8eeaSjose borrego VFS_RELE(vfsp); 712*c8ec8eeaSjose borrego return (0); 713*c8ec8eeaSjose borrego } 714*c8ec8eeaSjose borrego 715*c8ec8eeaSjose borrego /* 716*c8ec8eeaSjose borrego * Extract the volume name. 717*c8ec8eeaSjose borrego */ 718*c8ec8eeaSjose borrego static void 719*c8ec8eeaSjose borrego smb_tree_get_volname(vfs_t *vfsp, smb_tree_t *tree) 720*c8ec8eeaSjose borrego { 721*c8ec8eeaSjose borrego refstr_t *vfs_mntpoint; 722*c8ec8eeaSjose borrego const char *s; 723*c8ec8eeaSjose borrego char *name; 724*c8ec8eeaSjose borrego 725*c8ec8eeaSjose borrego vfs_mntpoint = vfs_getmntpoint(vfsp); 726*c8ec8eeaSjose borrego 727*c8ec8eeaSjose borrego s = vfs_mntpoint->rs_string; 728*c8ec8eeaSjose borrego s += strspn(s, "/"); 729*c8ec8eeaSjose borrego (void) strlcpy(tree->t_volume, s, SMB_VOLNAMELEN); 730*c8ec8eeaSjose borrego 731*c8ec8eeaSjose borrego refstr_rele(vfs_mntpoint); 732*c8ec8eeaSjose borrego 733*c8ec8eeaSjose borrego name = tree->t_volume; 734*c8ec8eeaSjose borrego (void) strsep((char **)&name, "/"); 735*c8ec8eeaSjose borrego } 736*c8ec8eeaSjose borrego 737*c8ec8eeaSjose borrego /* 738*c8ec8eeaSjose borrego * Always set ACL support because the VFS will fake ACLs for file systems 739*c8ec8eeaSjose borrego * that don't support them. 740da6c28aaSamw * 741*c8ec8eeaSjose borrego * Some flags are dependent on the typename, which is also set up here. 742*c8ec8eeaSjose borrego * File system types are hardcoded in uts/common/os/vfs_conf.c. 743da6c28aaSamw */ 744*c8ec8eeaSjose borrego static void 745*c8ec8eeaSjose borrego smb_tree_get_flags(vfs_t *vfsp, smb_tree_t *tree) 746da6c28aaSamw { 747*c8ec8eeaSjose borrego uint32_t flags = SMB_TREE_SUPPORTS_ACLS; 748*c8ec8eeaSjose borrego char *name; 749da6c28aaSamw 750*c8ec8eeaSjose borrego if (vfsp->vfs_flag & VFS_RDONLY) 751*c8ec8eeaSjose borrego flags |= SMB_TREE_READONLY; 752*c8ec8eeaSjose borrego 753*c8ec8eeaSjose borrego if (vfsp->vfs_flag & VFS_XATTR) 754*c8ec8eeaSjose borrego flags |= SMB_TREE_STREAMS; 755*c8ec8eeaSjose borrego 756*c8ec8eeaSjose borrego if (vfs_optionisset(vfsp, MNTOPT_NOATIME, NULL)) 757*c8ec8eeaSjose borrego flags |= SMB_TREE_NO_ATIME; 758*c8ec8eeaSjose borrego 759*c8ec8eeaSjose borrego name = vfssw[vfsp->vfs_fstype].vsw_name; 760*c8ec8eeaSjose borrego 761*c8ec8eeaSjose borrego if (strcmp(name, "tmpfs") == 0) 762*c8ec8eeaSjose borrego flags |= SMB_TREE_NO_EXPORT; 763*c8ec8eeaSjose borrego 764*c8ec8eeaSjose borrego if (strncasecmp(name, NFS, sizeof (NFS)) == 0) 765*c8ec8eeaSjose borrego flags |= SMB_TREE_NFS_MOUNTED; 766*c8ec8eeaSjose borrego 767*c8ec8eeaSjose borrego if (strncasecmp(name, "UFS", sizeof ("UFS")) == 0) 768*c8ec8eeaSjose borrego flags |= SMB_TREE_UFS; 769*c8ec8eeaSjose borrego 770*c8ec8eeaSjose borrego (void) strlcpy(tree->t_typename, name, SMB_TYPENAMELEN); 771*c8ec8eeaSjose borrego (void) utf8_strupr((char *)tree->t_typename); 772da6c28aaSamw 773*c8ec8eeaSjose borrego if (vfs_has_feature(vfsp, VFSFT_XVATTR)) 774*c8ec8eeaSjose borrego flags |= SMB_TREE_XVATTR; 775*c8ec8eeaSjose borrego 776*c8ec8eeaSjose borrego if (vfs_has_feature(vfsp, VFSFT_CASEINSENSITIVE)) 777*c8ec8eeaSjose borrego flags |= SMB_TREE_CASEINSENSITIVE; 778*c8ec8eeaSjose borrego 779*c8ec8eeaSjose borrego if (vfs_has_feature(vfsp, VFSFT_NOCASESENSITIVE)) 780*c8ec8eeaSjose borrego flags |= SMB_TREE_NO_CASESENSITIVE; 781*c8ec8eeaSjose borrego 782*c8ec8eeaSjose borrego if (vfs_has_feature(vfsp, VFSFT_DIRENTFLAGS)) 783*c8ec8eeaSjose borrego flags |= SMB_TREE_DIRENTFLAGS; 784*c8ec8eeaSjose borrego 785*c8ec8eeaSjose borrego if (vfs_has_feature(vfsp, VFSFT_ACLONCREATE)) 786*c8ec8eeaSjose borrego flags |= SMB_TREE_ACLONCREATE; 787*c8ec8eeaSjose borrego 788*c8ec8eeaSjose borrego if (vfs_has_feature(vfsp, VFSFT_ACEMASKONACCESS)) 789*c8ec8eeaSjose borrego flags |= SMB_TREE_ACEMASKONACCESS; 790*c8ec8eeaSjose borrego 791*c8ec8eeaSjose borrego DTRACE_PROBE1(smb__tree__flags, uint32_t, flags); 792*c8ec8eeaSjose borrego 793*c8ec8eeaSjose borrego tree->t_flags = flags; 794*c8ec8eeaSjose borrego } 795*c8ec8eeaSjose borrego 796*c8ec8eeaSjose borrego /* 797*c8ec8eeaSjose borrego * Report share access result to syslog. 798*c8ec8eeaSjose borrego */ 799*c8ec8eeaSjose borrego static void 800*c8ec8eeaSjose borrego smb_tree_log(smb_request_t *sr, const char *sharename, const char *fmt, ...) 801*c8ec8eeaSjose borrego { 802*c8ec8eeaSjose borrego va_list ap; 803*c8ec8eeaSjose borrego char buf[128]; 804*c8ec8eeaSjose borrego smb_user_t *user = sr->uid_user; 805*c8ec8eeaSjose borrego 806*c8ec8eeaSjose borrego ASSERT(user); 807*c8ec8eeaSjose borrego 808*c8ec8eeaSjose borrego if (smb_tcon_mute) 809*c8ec8eeaSjose borrego return; 810*c8ec8eeaSjose borrego 811*c8ec8eeaSjose borrego if ((user->u_name) && (strcasecmp(sharename, "IPC$") == 0)) { 812*c8ec8eeaSjose borrego /* 813*c8ec8eeaSjose borrego * Only report normal users, i.e. ignore W2K misuse 814*c8ec8eeaSjose borrego * of the IPC connection by filtering out internal 815*c8ec8eeaSjose borrego * names such as nobody and root. 816*c8ec8eeaSjose borrego */ 817*c8ec8eeaSjose borrego if ((strcmp(user->u_name, "root") == 0) || 818*c8ec8eeaSjose borrego (strcmp(user->u_name, "nobody") == 0)) { 819*c8ec8eeaSjose borrego return; 820da6c28aaSamw } 821da6c28aaSamw } 822da6c28aaSamw 823*c8ec8eeaSjose borrego va_start(ap, fmt); 824*c8ec8eeaSjose borrego (void) vsnprintf(buf, 128, fmt, ap); 825*c8ec8eeaSjose borrego va_end(ap); 826*c8ec8eeaSjose borrego 827*c8ec8eeaSjose borrego cmn_err(CE_NOTE, "smbd[%s\\%s]: %s %s", 828*c8ec8eeaSjose borrego user->u_domain, user->u_name, sharename, buf); 829da6c28aaSamw } 830