Print this page
NEX-18761 panic in smb_ofile_free with vdbench
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-9808 SMB3 persistent handles
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-15578 SMB2 durable handle redesign
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-5665 SMB2 oplock leases
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-9808 SMB3 persistent handles
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-15578 SMB2 durable handle redesign
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-5665 SMB2 oplock leases
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-5273 SMB 3 Encryption
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-6858 Non-admin users unable to mount CIFS shares
Reviewed by: Gordon Ross <gwr@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-6276 SMB sparse file support
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-5737 mutex_enter: bad mutex in smb2 causes panic in mutex_vector_enter
Reviewed by: Gordon Ross <gwr@nexenta.com>
NEX-3553 SMB2/3 durable handles
Reviewed by: Gordon Ross <gwr@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
NEX-5537 Want reference counts for users, trees...
Reviewed by: Gordon Ross <gwr@nexenta.com>
NEX-4313 want iops, bandwidth, and latency kstats for smb
Portions contributed by: Gordon Ross <gwr@nexenta.com>
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
NEX-3863 Would like an SMB share property to enable/disable quotas
Reviewed by: Bayard Bell <bayard.bell@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-3441 CLONE - PORT NEX-3398 Restore SMB map/unmap upcall feature
SMB-11 SMB2 message parse & dispatch
SMB-12 SMB2 Negotiate Protocol
SMB-13 SMB2 Session Setup
SMB-14 SMB2 Logoff
SMB-15 SMB2 Tree Connect
SMB-16 SMB2 Tree Disconnect
SMB-17 SMB2 Create
SMB-18 SMB2 Close
SMB-19 SMB2 Flush
SMB-20 SMB2 Read
SMB-21 SMB2 Write
SMB-22 SMB2 Lock/Unlock
SMB-23 SMB2 Ioctl
SMB-24 SMB2 Cancel
SMB-25 SMB2 Echo
SMB-26 SMB2 Query Dir
SMB-27 SMB2 Change Notify
SMB-28 SMB2 Query Info
SMB-29 SMB2 Set Info
SMB-30 SMB2 Oplocks
SMB-53 SMB2 Create Context options
(SMB2 code review cleanup 1, 2, 3)
SMB-74 Process oplock breaks as session requests (part two)
SMB-50 User-mode SMB server
 Includes work by these authors:
 Thomas Keiser <thomas.keiser@nexenta.com>
 Albert Lee <trisk@nexenta.com>
SMB-65 SMB server in non-global zones (use zone_kcred())
SUP-694 panic on bad mutex in smb_event_wait()
SMB-65 SMB server in non-global zones (data structure changes)
Many things move to the smb_server_t object, and
many functions gain an sv arg (which server).
SMB-65 SMB server in non-global zones (kmem_caches)
common kmem_cache instances across zones
separate GZ-only init from NGZ init
SMB-63 taskq_create_proc ... TQ_DYNAMIC puts tasks in p0
re #11974 CIFS Share - Tree connect fails from Windows 7 Clients
re #13470 rb4432 Sync some SMB differences from illumos
re #6813 rb1757 port 2976 Child folder visibility through shares
re #6812 rb1753 backport illumos 1604 smbd print_enable doesn't really work


   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  25  * Copyright (c) 2016 by Delphix. All rights reserved.
  26  */
  27 
  28 /*
  29  * General Structures Layout
  30  * -------------------------
  31  *
  32  * This is a simplified diagram showing the relationship between most of the
  33  * main structures.
  34  *
  35  * +-------------------+
  36  * |     SMB_INFO      |
  37  * +-------------------+
  38  *          |
  39  *          |
  40  *          v
  41  * +-------------------+       +-------------------+      +-------------------+
  42  * |     SESSION       |<----->|     SESSION       |......|      SESSION      |
  43  * +-------------------+       +-------------------+      +-------------------+
  44  *   |          |


 105  *
 106  * SMB_TREE_STATE_DISCONNECTED
 107  *
 108  *    While in this state:
 109  *      - The tree is queued in the list of trees of its user.
 110  *      - References will not be given out if the tree is looked up.
 111  *      - The tree has no more files and directories opened.
 112  *      - The resources associated with the tree remain.
 113  *
 114  * Transition T0
 115  *
 116  *    This transition occurs in smb_tree_connect(). A new tree is created and
 117  *    added to the list of trees of a user.
 118  *
 119  * Transition T1
 120  *
 121  *    This transition occurs in smb_tree_disconnect().
 122  *
 123  * Transition T2
 124  *




 125  *    This transition occurs in smb_tree_release(). The resources associated
 126  *    with the tree are freed as well as the tree structure. For the transition
 127  *    to occur, the tree must be in the SMB_TREE_STATE_DISCONNECTED state and
 128  *    the reference count be zero.
 129  *
 130  * Comments
 131  * --------
 132  *
 133  *    The state machine of the tree structures is controlled by 3 elements:
 134  *      - The list of trees of the user it belongs to.
 135  *      - The mutex embedded in the structure itself.
 136  *      - The reference count.
 137  *
 138  *    There's a mutex embedded in the tree structure used to protect its fields
 139  *    and there's a lock embedded in the list of trees of a user. To
 140  *    increment or to decrement the reference count the mutex must be entered.
 141  *    To insert the tree into the list of trees of the user and to remove
 142  *    the tree from it, the lock must be entered in RW_WRITER mode.
 143  *
 144  *    Rules of access to a tree structure:
 145  *
 146  *    1) In order to avoid deadlocks, when both (mutex and lock of the user
 147  *       list) have to be entered, the lock must be entered first.




 148  *
 149  *    2) All actions applied to a tree require a reference count.
 150  *
 151  *    3) There are 2 ways of getting a reference count: when a tree is
 152  *       connected and when a tree is looked up.
 153  *
 154  *    It should be noted that the reference count of a tree registers the
 155  *    number of references to the tree in other structures (such as an smb
 156  *    request). The reference count is not incremented in these 2 instances:
 157  *
 158  *    1) The tree is connected. An tree is anchored by its state. If there's
 159  *       no activity involving a tree currently connected, the reference
 160  *       count of that tree is zero.
 161  *
 162  *    2) The tree is queued in the list of trees of the user. The fact of
 163  *       being queued in that list is NOT registered by incrementing the
 164  *       reference count.
 165  */
 166 
 167 #include <sys/refstr_impl.h>
 168 #include <smbsrv/smb_kproto.h>
 169 #include <smbsrv/smb_ktypes.h>
 170 #include <smbsrv/smb_fsops.h>
 171 #include <smbsrv/smb_share.h>
 172 
 173 int smb_tcon_mute = 0;
 174 
 175 uint32_t        smb_tree_connect_core(smb_request_t *);
 176 uint32_t        smb_tree_connect_disk(smb_request_t *, smb_arg_tcon_t *);
 177 uint32_t        smb_tree_connect_printq(smb_request_t *, smb_arg_tcon_t *);
 178 uint32_t        smb_tree_connect_ipc(smb_request_t *, smb_arg_tcon_t *);
 179 static smb_tree_t *smb_tree_alloc(smb_request_t *, const smb_kshare_t *,
 180     smb_node_t *, uint32_t, uint32_t);
 181 static boolean_t smb_tree_is_connected_locked(smb_tree_t *);
 182 static boolean_t smb_tree_is_disconnected(smb_tree_t *);
 183 static char *smb_tree_get_sharename(char *);
 184 static int smb_tree_getattr(const smb_kshare_t *, smb_node_t *, smb_tree_t *);
 185 static void smb_tree_get_volname(vfs_t *, smb_tree_t *);
 186 static void smb_tree_get_flags(const smb_kshare_t *, vfs_t *, smb_tree_t *);
 187 static void smb_tree_log(smb_request_t *, const char *, const char *, ...);
 188 static void smb_tree_close_odirs(smb_tree_t *, uint16_t);
 189 static smb_ofile_t *smb_tree_get_ofile(smb_tree_t *, smb_ofile_t *);
 190 static smb_odir_t *smb_tree_get_odir(smb_tree_t *, smb_odir_t *);
 191 static void smb_tree_set_execinfo(smb_tree_t *, smb_shr_execinfo_t *, int);
 192 static int smb_tree_enum_private(smb_tree_t *, smb_svcenum_t *);
 193 static int smb_tree_netinfo_encode(smb_tree_t *, uint8_t *, size_t, uint32_t *);
 194 static void smb_tree_netinfo_init(smb_tree_t *tree, smb_netconnectinfo_t *);
 195 static void smb_tree_netinfo_fini(smb_netconnectinfo_t *);
 196 
 197 uint32_t
 198 smb_tree_connect(smb_request_t *sr)
 199 {
 200         smb_server_t    *sv = sr->sr_server;
 201         uint32_t status;
 202 
 203         if (smb_threshold_enter(&sv->sv_tcon_ct) != 0) {
 204                 return (NT_STATUS_INSUFF_SERVER_RESOURCES);
 205         }
 206 
 207         status = smb_tree_connect_core(sr);
 208         smb_threshold_exit(&sv->sv_tcon_ct);
 209         return (status);
 210 }


 235                 smb_tree_log(sr, tcon->path, "invalid UNC path");
 236                 return (NT_STATUS_BAD_NETWORK_NAME);
 237         }
 238 
 239         si = smb_kshare_lookup(sr->sr_server, name);
 240         if (si == NULL) {
 241                 smb_tree_log(sr, name, "share not found");
 242                 return (NT_STATUS_BAD_NETWORK_NAME);
 243         }
 244 
 245         if (!strcasecmp(SMB_SHARE_PRINT, name)) {
 246                 smb_kshare_release(sr->sr_server, si);
 247                 smb_tree_log(sr, name, "access not permitted");
 248                 return (NT_STATUS_ACCESS_DENIED);
 249         }
 250 
 251         /* NB: name points into tcon->path - don't free it. */
 252         tcon->name = name;
 253         sr->sr_tcon.si = si;
 254 



















 255         switch (si->shr_type & STYPE_MASK) {
 256         case STYPE_DISKTREE:
 257                 status = smb_tree_connect_disk(sr, &sr->sr_tcon);
 258                 break;
 259         case STYPE_IPC:
 260                 status = smb_tree_connect_ipc(sr, &sr->sr_tcon);
 261                 break;
 262         case STYPE_PRINTQ:
 263                 status = smb_tree_connect_printq(sr, &sr->sr_tcon);
 264                 break;
 265         default:
 266                 status = NT_STATUS_BAD_DEVICE_TYPE;
 267                 break;
 268         }
 269 










 270         smb_kshare_release(sr->sr_server, si);


 271         sr->sr_tcon.si = NULL;
 272 
 273         return (status);
 274 }
 275 
 276 /*
 277  * Disconnect a tree.


 278  */
 279 void
 280 smb_tree_disconnect(smb_tree_t *tree, boolean_t do_exec)
 281 {

 282         smb_shr_execinfo_t execinfo;
 283 
 284         ASSERT(tree->t_magic == SMB_TREE_MAGIC);
 285 
 286         mutex_enter(&tree->t_mutex);
 287         ASSERT(tree->t_refcnt);
 288 
 289         if (smb_tree_is_connected_locked(tree)) {




 290                 /*
 291                  * Indicate that the disconnect process has started.
 292                  */
 293                 tree->t_state = SMB_TREE_STATE_DISCONNECTING;
 294                 mutex_exit(&tree->t_mutex);
 295 
 296                 if (do_exec) {
 297                         /*
 298                          * The files opened under this tree are closed.
 299                          */
 300                         smb_ofile_close_all(tree);
 301                         /*
 302                          * The directories opened under this tree are closed.
 303                          */
 304                         smb_tree_close_odirs(tree, 0);
 305                 }
 306 
 307                 mutex_enter(&tree->t_mutex);
 308                 tree->t_state = SMB_TREE_STATE_DISCONNECTED;
 309                 smb_server_dec_trees(tree->t_server);
 310         }
 311 
 312         mutex_exit(&tree->t_mutex);
 313 
 314         if (do_exec && (tree->t_state == SMB_TREE_STATE_DISCONNECTED) &&
 315             (tree->t_execflags & SMB_EXEC_UNMAP)) {
 316 
 317                 smb_tree_set_execinfo(tree, &execinfo, SMB_EXEC_UNMAP);
 318                 (void) smb_kshare_exec(tree->t_server, &execinfo);
 319         }
 320 }
 321 
 322 /*
 323  * Take a reference on a tree.
 324  */
 325 boolean_t
 326 smb_tree_hold(
 327     smb_tree_t          *tree)
 328 {
 329         SMB_TREE_VALID(tree);
 330 
 331         mutex_enter(&tree->t_mutex);
 332 
 333         if (smb_tree_is_connected_locked(tree)) {
 334                 tree->t_refcnt++;
 335                 mutex_exit(&tree->t_mutex);
 336                 return (B_TRUE);


 354 {
 355         SMB_TREE_VALID(tree);
 356 
 357         mutex_enter(&tree->t_mutex);
 358         tree->t_refcnt++;
 359         mutex_exit(&tree->t_mutex);
 360 }
 361 
 362 /*
 363  * Release a reference on a tree.  If the tree is disconnected and the
 364  * reference count falls to zero, post the object for deletion.
 365  * Object deletion is deferred to avoid modifying a list while an
 366  * iteration may be in progress.
 367  */
 368 void
 369 smb_tree_release(
 370     smb_tree_t          *tree)
 371 {
 372         SMB_TREE_VALID(tree);
 373 
 374         mutex_enter(&tree->t_mutex);
 375         ASSERT(tree->t_refcnt);
 376         tree->t_refcnt--;
 377 
 378         /* flush the ofile and odir lists' delete queues */
 379         smb_llist_flush(&tree->t_ofile_list);
 380         smb_llist_flush(&tree->t_odir_list);
 381 
 382         if (smb_tree_is_disconnected(tree) && (tree->t_refcnt == 0))
 383                 smb_session_post_tree(tree->t_session, tree);

 384 
















 385         mutex_exit(&tree->t_mutex);
 386 }
 387 
 388 void
 389 smb_tree_post_ofile(smb_tree_t *tree, smb_ofile_t *of)
 390 {
 391         SMB_TREE_VALID(tree);
 392         SMB_OFILE_VALID(of);
 393         ASSERT(of->f_refcnt == 0);
 394         ASSERT(of->f_state == SMB_OFILE_STATE_CLOSED);
 395         ASSERT(of->f_tree == tree);
 396 
 397         smb_llist_post(&tree->t_ofile_list, of, smb_ofile_delete);
 398 }
 399 
 400 void
 401 smb_tree_post_odir(smb_tree_t *tree, smb_odir_t *od)
 402 {
 403         SMB_TREE_VALID(tree);
 404         SMB_ODIR_VALID(od);
 405         ASSERT(od->d_refcnt == 0);
 406         ASSERT(od->d_state == SMB_ODIR_STATE_CLOSED);
 407         ASSERT(od->d_tree == tree);
 408 
 409         smb_llist_post(&tree->t_odir_list, od, smb_odir_delete);
 410 }
 411 
 412 /*
 413  * Close ofiles and odirs that match pid.
 414  */
 415 void
 416 smb_tree_close_pid(
 417     smb_tree_t          *tree,
 418     uint32_t            pid)
 419 {
 420         ASSERT(tree);
 421         ASSERT(tree->t_magic == SMB_TREE_MAGIC);
 422 
 423         smb_ofile_close_all_by_pid(tree, pid);
 424         smb_tree_close_odirs(tree, pid);
 425 }
 426 
 427 /*
 428  * Check whether or not a tree supports the features identified by flags.
 429  */
 430 boolean_t
 431 smb_tree_has_feature(smb_tree_t *tree, uint32_t flags)
 432 {
 433         ASSERT(tree);
 434         ASSERT(tree->t_magic == SMB_TREE_MAGIC);
 435 
 436         return ((tree->t_flags & flags) == flags);
 437 }
 438 
 439 /*
 440  * If the enumeration request is for tree data, handle the request
 441  * here.  Otherwise, pass it on to the ofiles.
 442  *
 443  * This function should be called with a hold on the tree.
 444  */
 445 int
 446 smb_tree_enum(smb_tree_t *tree, smb_svcenum_t *svcenum)
 447 {

 448         smb_ofile_t     *of;
 449         smb_ofile_t     *next;
 450         int             rc = 0;
 451 
 452         ASSERT(tree);
 453         ASSERT(tree->t_magic == SMB_TREE_MAGIC);
 454 
 455         if (svcenum->se_type == SMB_SVCENUM_TYPE_TREE)
 456                 return (smb_tree_enum_private(tree, svcenum));
 457 
 458         of = smb_tree_get_ofile(tree, NULL);
 459         while (of) {
 460                 ASSERT(of->f_tree == tree);
 461 



 462                 rc = smb_ofile_enum(of, svcenum);
 463                 if (rc != 0) {
 464                         smb_ofile_release(of);


 465                         break;

 466                 }
 467 
 468                 next = smb_tree_get_ofile(tree, of);
 469                 smb_ofile_release(of);
 470                 of = next;
 471         }
 472 
 473         return (rc);
 474 }
 475 
 476 /*
 477  * Close a file by its unique id.
 478  */
 479 int
 480 smb_tree_fclose(smb_tree_t *tree, uint32_t uniqid)
 481 {
 482         smb_ofile_t     *of;
 483 
 484         ASSERT(tree);
 485         ASSERT(tree->t_magic == SMB_TREE_MAGIC);
 486 





 487         if ((of = smb_ofile_lookup_by_uniqid(tree, uniqid)) == NULL)
 488                 return (ENOENT);
 489 
 490         if (smb_ofile_disallow_fclose(of)) {
 491                 smb_ofile_release(of);
 492                 return (EACCES);
 493         }
 494 
 495         smb_ofile_close(of, 0);
 496         smb_ofile_release(of);
 497         return (0);
 498 }
 499 
 500 /* *************************** Static Functions ***************************** */
 501 
 502 #define SHARES_DIR      ".zfs/shares/"
 503 
 504 /*
 505  * Calculates permissions given by the share's ACL to the
 506  * user in the passed request.  The default is full access.


 622         if ((host_access & ACE_ALL_PERMS) == 0) {
 623                 smb_tree_log(sr, sharename, "access denied: host access");
 624                 return (0);
 625         }
 626 
 627         acl_access = smb_tree_acl_access(sr, shr, vp);
 628         if ((acl_access & ACE_ALL_PERMS) == 0) {
 629                 smb_tree_log(sr, sharename, "access denied: share ACL");
 630                 return (0);
 631         }
 632 
 633         access = host_access & acl_access;
 634         if ((access & ACE_ALL_PERMS) == 0) {
 635                 smb_tree_log(sr, sharename, "access denied");
 636                 return (0);
 637         }
 638 
 639         return (access);
 640 }
 641 



 642 /*
 643  * Connect a share for use with files and directories.
 644  */
 645 uint32_t
 646 smb_tree_connect_disk(smb_request_t *sr, smb_arg_tcon_t *tcon)
 647 {
 648         char                    *sharename = tcon->path;
 649         const char              *any = "?????";
 650         smb_user_t              *user = sr->uid_user;
 651         smb_node_t              *dnode = NULL;
 652         smb_node_t              *snode = NULL;
 653         smb_kshare_t            *si = tcon->si;
 654         char                    *service = tcon->service;
 655         char                    last_component[MAXNAMELEN];
 656         smb_tree_t              *tree;
 657         int                     rc;
 658         uint32_t                access;
 659         smb_shr_execinfo_t      execinfo;

 660 
 661         ASSERT(user);
 662         ASSERT(user->u_cred);
 663 
 664         if (service != NULL &&
 665             strcmp(service, any) != 0 &&
 666             strcasecmp(service, "A:") != 0) {
 667                 smb_tree_log(sr, sharename, "invalid service (%s)", service);
 668                 return (NT_STATUS_BAD_DEVICE_TYPE);
 669         }
 670 
 671         /*
 672          * Check that the shared directory exists.
 673          */
 674         rc = smb_pathname_reduce(sr, user->u_cred, si->shr_path, 0, 0, &dnode,
 675             last_component);
 676         if (rc == 0) {
 677                 rc = smb_fsop_lookup(sr, user->u_cred, SMB_FOLLOW_LINKS,
 678                     sr->sr_server->si_root_smb_node, dnode, last_component,
 679                     &snode);
 680 
 681                 smb_node_release(dnode);
 682         }
 683 
 684         if (rc) {
 685                 if (snode)
 686                         smb_node_release(snode);
 687 
 688                 smb_tree_log(sr, sharename, "bad path: %s", si->shr_path);
 689                 return (NT_STATUS_BAD_NETWORK_NAME);
 690         }
 691 
 692         if ((access = smb_tree_chkaccess(sr, si, snode->vp)) == 0) {
 693                 smb_node_release(snode);
 694                 return (NT_STATUS_ACCESS_DENIED);
 695         }
 696 
 697         /*
















 698          * Set up the OptionalSupport for this share.
 699          */
 700         tcon->optional_support = SMB_SUPPORT_SEARCH_BITS;
 701 
 702         switch (si->shr_flags & SMB_SHRF_CSC_MASK) {
 703         case SMB_SHRF_CSC_DISABLED:
 704                 tcon->optional_support |= SMB_CSC_CACHE_NONE;
 705                 break;
 706         case SMB_SHRF_CSC_AUTO:
 707                 tcon->optional_support |= SMB_CSC_CACHE_AUTO_REINT;
 708                 break;
 709         case SMB_SHRF_CSC_VDO:
 710                 tcon->optional_support |= SMB_CSC_CACHE_VDO;
 711                 break;
 712         case SMB_SHRF_CSC_MANUAL:
 713         default:
 714                 /*
 715                  * Default to SMB_CSC_CACHE_MANUAL_REINT.
 716                  */
 717                 break;
 718         }
 719 
 720         /* ABE support */
 721         if (si->shr_flags & SMB_SHRF_ABE)
 722                 tcon->optional_support |=
 723                     SHI1005_FLAGS_ACCESS_BASED_DIRECTORY_ENUM;
 724 
 725         if (si->shr_flags & SMB_SHRF_DFSROOT)
 726                 tcon->optional_support |= SMB_SHARE_IS_IN_DFS;
 727 
 728         /* if 'smb' zfs property: shortnames=disabled */
 729         if (!smb_shortnames)
 730                 sr->arg.tcon.optional_support |= SMB_UNIQUE_FILE_NAME;
 731 
 732         tree = smb_tree_alloc(sr, si, snode, access, sr->sr_cfg->skc_execflags);
 733 
 734         smb_node_release(snode);
 735 
 736         if (tree == NULL)
 737                 return (NT_STATUS_INSUFF_SERVER_RESOURCES);
 738 
 739         if (tree->t_execflags & SMB_EXEC_MAP) {
 740                 smb_tree_set_execinfo(tree, &execinfo, SMB_EXEC_MAP);
 741 
 742                 rc = smb_kshare_exec(tree->t_server, &execinfo);
 743 
 744                 if ((rc != 0) && (tree->t_execflags & SMB_EXEC_TERM)) {
 745                         smb_tree_disconnect(tree, B_FALSE);










 746                         smb_tree_release(tree);
 747                         return (NT_STATUS_ACCESS_DENIED);
 748                 }
 749         }
 750 
 751         sr->tid_tree = tree;
 752         sr->smb_tid  = tree->t_tid;
 753 
 754         return (0);
 755 }
 756 
 757 /*
 758  * Shares have both a share and host based access control.  The access
 759  * granted will be minimum permissions based on both hostaccess
 760  * (permissions allowed by host based access) and aclaccess (from the
 761  * share ACL).
 762  */
 763 uint32_t
 764 smb_tree_connect_printq(smb_request_t *sr, smb_arg_tcon_t *tcon)
 765 {


 857             sr->sr_cfg->skc_restrict_anon) {
 858                 smb_tree_log(sr, name, "access denied: restrict anonymous");
 859                 return (NT_STATUS_ACCESS_DENIED);
 860         }
 861 
 862         tcon->optional_support = SMB_SUPPORT_SEARCH_BITS;
 863 
 864         tree = smb_tree_alloc(sr, si, NULL, ACE_ALL_PERMS, 0);
 865         if (tree == NULL)
 866                 return (NT_STATUS_INSUFF_SERVER_RESOURCES);
 867 
 868         sr->tid_tree = tree;
 869         sr->smb_tid  = tree->t_tid;
 870 
 871         return (0);
 872 }
 873 
 874 /*
 875  * Allocate a tree.
 876  */
 877 static smb_tree_t *
 878 smb_tree_alloc(smb_request_t *sr, const smb_kshare_t *si,
 879     smb_node_t *snode, uint32_t access, uint32_t execflags)
 880 {
 881         smb_session_t   *session = sr->session;
 882         smb_tree_t      *tree;
 883         uint32_t        stype = si->shr_type;
 884         uint16_t        tid;
 885 
 886         if (smb_idpool_alloc(&session->s_tid_pool, &tid))
 887                 return (NULL);
 888 
 889         tree = kmem_cache_alloc(smb_cache_tree, KM_SLEEP);
 890         bzero(tree, sizeof (smb_tree_t));
 891 
 892         tree->t_session = session;
 893         tree->t_server = session->s_server;
 894 
 895         /* grab a ref for tree->t_owner */
 896         smb_user_hold_internal(sr->uid_user);
 897         tree->t_owner = sr->uid_user;


 901                         smb_idpool_free(&session->s_tid_pool, tid);
 902                         kmem_cache_free(smb_cache_tree, tree);
 903                         return (NULL);
 904                 }
 905         }
 906 
 907         if (smb_idpool_constructor(&tree->t_fid_pool)) {
 908                 smb_idpool_free(&session->s_tid_pool, tid);
 909                 kmem_cache_free(smb_cache_tree, tree);
 910                 return (NULL);
 911         }
 912 
 913         if (smb_idpool_constructor(&tree->t_odid_pool)) {
 914                 smb_idpool_destructor(&tree->t_fid_pool);
 915                 smb_idpool_free(&session->s_tid_pool, tid);
 916                 kmem_cache_free(smb_cache_tree, tree);
 917                 return (NULL);
 918         }
 919 
 920         smb_llist_constructor(&tree->t_ofile_list, sizeof (smb_ofile_t),
 921             offsetof(smb_ofile_t, f_lnd));
 922 
 923         smb_llist_constructor(&tree->t_odir_list, sizeof (smb_odir_t),
 924             offsetof(smb_odir_t, d_lnd));
 925 
 926         (void) strlcpy(tree->t_sharename, si->shr_name,
 927             sizeof (tree->t_sharename));
 928         (void) strlcpy(tree->t_resource, si->shr_path,
 929             sizeof (tree->t_resource));
 930 
 931         mutex_init(&tree->t_mutex, NULL, MUTEX_DEFAULT, NULL);
 932 
 933         tree->t_refcnt = 1;
 934         tree->t_tid = tid;
 935         tree->t_res_type = stype;
 936         tree->t_state = SMB_TREE_STATE_CONNECTED;
 937         tree->t_magic = SMB_TREE_MAGIC;
 938         tree->t_access = access;
 939         tree->t_connect_time = gethrestime_sec();
 940         tree->t_execflags = execflags;
 941 


 947                 smb_node_ref(snode);
 948                 tree->t_snode = snode;
 949                 tree->t_acltype = smb_fsop_acltype(snode);
 950         }
 951 
 952         smb_llist_enter(&session->s_tree_list, RW_WRITER);
 953         smb_llist_insert_head(&session->s_tree_list, tree);
 954         smb_llist_exit(&session->s_tree_list);
 955         atomic_inc_32(&session->s_tree_cnt);
 956         smb_server_inc_trees(session->s_server);
 957         return (tree);
 958 }
 959 
 960 /*
 961  * Deallocate a tree.  The open file and open directory lists should be
 962  * empty.
 963  *
 964  * Remove the tree from the user's tree list before freeing resources
 965  * associated with the tree.
 966  */
 967 void
 968 smb_tree_dealloc(void *arg)
 969 {
 970         smb_session_t   *session;
 971         smb_tree_t      *tree = (smb_tree_t *)arg;
 972 
 973         SMB_TREE_VALID(tree);
 974         ASSERT(tree->t_state == SMB_TREE_STATE_DISCONNECTED);
 975         ASSERT(tree->t_refcnt == 0);
 976 


 977         session = tree->t_session;
 978         smb_llist_enter(&session->s_tree_list, RW_WRITER);
 979         smb_llist_remove(&session->s_tree_list, tree);
 980         smb_idpool_free(&session->s_tid_pool, tree->t_tid);
 981         atomic_dec_32(&session->s_tree_cnt);
 982         smb_llist_exit(&session->s_tree_list);
 983 







 984         mutex_enter(&tree->t_mutex);
 985         mutex_exit(&tree->t_mutex);
 986 
 987         tree->t_magic = (uint32_t)~SMB_TREE_MAGIC;
 988 





 989         if (tree->t_snode)
 990                 smb_node_release(tree->t_snode);
 991 
 992         mutex_destroy(&tree->t_mutex);
 993         smb_llist_destructor(&tree->t_ofile_list);
 994         smb_llist_destructor(&tree->t_odir_list);
 995         smb_idpool_destructor(&tree->t_fid_pool);
 996         smb_idpool_destructor(&tree->t_odid_pool);
 997 
 998         SMB_USER_VALID(tree->t_owner);
 999         smb_user_release(tree->t_owner);
1000 
1001         kmem_cache_free(smb_cache_tree, tree);
1002 }
1003 
1004 /*
1005  * Determine whether or not a tree is connected.
1006  * This function must be called with the tree mutex held.
1007  */
1008 static boolean_t
1009 smb_tree_is_connected_locked(smb_tree_t *tree)
1010 {
1011         switch (tree->t_state) {
1012         case SMB_TREE_STATE_CONNECTED:
1013                 return (B_TRUE);
1014 
1015         case SMB_TREE_STATE_DISCONNECTING:
1016         case SMB_TREE_STATE_DISCONNECTED:
1017                 /*
1018                  * The tree exists but being diconnected or destroyed.
1019                  */
1020                 return (B_FALSE);
1021 
1022         default:
1023                 ASSERT(0);
1024                 return (B_FALSE);
1025         }
1026 }
1027 
1028 /*
1029  * Determine whether or not a tree is disconnected.
1030  * This function must be called with the tree mutex held.
1031  */
1032 static boolean_t
1033 smb_tree_is_disconnected(smb_tree_t *tree)
1034 {
1035         switch (tree->t_state) {
1036         case SMB_TREE_STATE_DISCONNECTED:
1037                 return (B_TRUE);
1038 
1039         case SMB_TREE_STATE_CONNECTED:
1040         case SMB_TREE_STATE_DISCONNECTING:
1041                 return (B_FALSE);
1042 
1043         default:
1044                 ASSERT(0);
1045                 return (B_FALSE);
1046         }
1047 }
1048 
1049 /*
1050  * Return a pointer to the share name within a share resource path.
1051  *
1052  * The share path may be a Uniform Naming Convention (UNC) string
1053  * (\\server\share) or simply the share name.  We validate the UNC
1054  * format but we don't look at the server name.
1055  */
1056 static char *
1057 smb_tree_get_sharename(char *unc_path)
1058 {
1059         char *sharename = unc_path;
1060 
1061         if (sharename[0] == '\\') {
1062                 /*
1063                  * Looks like a UNC path, validate the format.
1064                  */
1065                 if (sharename[1] != '\\')
1066                         return (NULL);
1067 
1068                 if ((sharename = strchr(sharename+2, '\\')) == NULL)
1069                         return (NULL);
1070 
1071                 ++sharename;
1072         } else if (strchr(sharename, '\\') != NULL) {
1073                 /*
1074                  * This should be a share name (no embedded \'s).
1075                  */
1076                 return (NULL);
1077         }
1078 
1079         return (sharename);
1080 }
1081 
1082 /*
1083  * Obtain the tree attributes: volume name, typename and flags.
1084  */
1085 static int
1086 smb_tree_getattr(const smb_kshare_t *si, smb_node_t *node, smb_tree_t *tree)
1087 {
1088         vfs_t *vfsp = SMB_NODE_VFS(node);

1089 
1090         ASSERT(vfsp);
1091 
1092         if (getvfs(&vfsp->vfs_fsid) != vfsp)
1093                 return (ESTALE);
1094 
1095         smb_tree_get_volname(vfsp, tree);
1096         smb_tree_get_flags(si, vfsp, tree);
1097 













1098         VFS_RELE(vfsp);
1099         return (0);
1100 }
1101 
1102 /*
1103  * Extract the volume name.
1104  */
1105 static void
1106 smb_tree_get_volname(vfs_t *vfsp, smb_tree_t *tree)
1107 {
1108 #ifdef  _FAKE_KERNEL
1109         _NOTE(ARGUNUSED(vfsp))
1110         (void) strlcpy(tree->t_volume, "fake", SMB_VOLNAMELEN);
1111 #else   /* _FAKE_KERNEL */
1112         refstr_t *vfs_mntpoint;
1113         const char *s;
1114         char *name;
1115 
1116         vfs_mntpoint = vfs_getmntpoint(vfsp);
1117 


1130  * Always set "unicode on disk" because we always use utf8 names locally.
1131  * Always set ACL support because the VFS will fake ACLs for file systems
1132  * that don't support them.
1133  *
1134  * Some flags are dependent on the typename, which is also set up here.
1135  * File system types are hardcoded in uts/common/os/vfs_conf.c.
1136  */
1137 static void
1138 smb_tree_get_flags(const smb_kshare_t *si, vfs_t *vfsp, smb_tree_t *tree)
1139 {
1140         smb_session_t *ssn = tree->t_session;
1141         struct vfssw    *vswp;
1142 
1143         typedef struct smb_mtype {
1144                 char            *mt_name;
1145                 size_t          mt_namelen;
1146                 uint32_t        mt_flags;
1147         } smb_mtype_t;
1148 
1149         static smb_mtype_t smb_mtype[] = {




1150                 { "zfs",    3,  SMB_TREE_QUOTA | SMB_TREE_SPARSE},
1151                 { "ufs",    3,  0 },
1152                 { "nfs",    3,  SMB_TREE_NFS_MOUNTED },
1153                 { "tmpfs",  5,  SMB_TREE_NO_EXPORT }
1154         };
1155         smb_mtype_t     *mtype;
1156         char            *name;
1157         uint32_t        flags =
1158             SMB_TREE_SUPPORTS_ACLS |
1159             SMB_TREE_UNICODE_ON_DISK;
1160         int             i;
1161 
1162         if (si->shr_flags & SMB_SHRF_DFSROOT)
1163                 flags |= SMB_TREE_DFSROOT;
1164 
1165         if (si->shr_flags & SMB_SHRF_CATIA)
1166                 flags |= SMB_TREE_CATIA;
1167 
1168         if (si->shr_flags & SMB_SHRF_ABE)
1169                 flags |= SMB_TREE_ABE;
1170 






1171         if (ssn->s_cfg.skc_oplock_enable) {
1172                 /* if 'smb' zfs property: oplocks=enabled */
1173                 flags |= SMB_TREE_OPLOCKS;
1174         }
1175 
1176         /* Global config option for now.  Later make per-share. */
1177         if (ssn->s_cfg.skc_traverse_mounts)
1178                 flags |= SMB_TREE_TRAVERSE_MOUNTS;
1179 
1180         /* if 'smb' zfs property: shortnames=enabled */
1181         if (smb_shortnames)
1182                 flags |= SMB_TREE_SHORTNAMES;
1183 
1184         if (vfsp->vfs_flag & VFS_RDONLY)
1185                 flags |= SMB_TREE_READONLY;
1186 
1187         if (vfsp->vfs_flag & VFS_XATTR)
1188                 flags |= SMB_TREE_STREAMS;
1189 
1190         vswp = vfs_getvfsswbyvfsops(vfs_getops(vfsp));
1191         if (vswp != NULL) {
1192                 name = vswp->vsw_name;
1193                 vfs_unrefvfssw(vswp);
1194         } else {
1195                 name = "?";
1196         }
1197 
1198         for (i = 0; i < sizeof (smb_mtype) / sizeof (smb_mtype[0]); ++i) {
1199                 mtype = &smb_mtype[i];
1200                 if (strncasecmp(name, mtype->mt_name, mtype->mt_namelen) == 0)
1201                         flags |= mtype->mt_flags;
1202         }
1203 







1204         (void) strlcpy(tree->t_typename, name, SMB_TYPENAMELEN);
1205         (void) smb_strupr((char *)tree->t_typename);
1206 
1207         if (vfs_has_feature(vfsp, VFSFT_XVATTR))
1208                 flags |= SMB_TREE_XVATTR;
1209 
1210         if (vfs_has_feature(vfsp, VFSFT_CASEINSENSITIVE))
1211                 flags |= SMB_TREE_CASEINSENSITIVE;
1212 
1213         if (vfs_has_feature(vfsp, VFSFT_NOCASESENSITIVE))
1214                 flags |= SMB_TREE_NO_CASESENSITIVE;
1215 
1216         if (vfs_has_feature(vfsp, VFSFT_DIRENTFLAGS))
1217                 flags |= SMB_TREE_DIRENTFLAGS;
1218 
1219         if (vfs_has_feature(vfsp, VFSFT_ACLONCREATE))
1220                 flags |= SMB_TREE_ACLONCREATE;
1221 
1222         if (vfs_has_feature(vfsp, VFSFT_ACEMASKONACCESS))
1223                 flags |= SMB_TREE_ACEMASKONACCESS;


1303         if (!smb_odir_hold(od))
1304                 od = NULL;
1305 
1306 out:
1307         smb_llist_exit(od_list);
1308         return (od);
1309 }
1310 
1311 boolean_t
1312 smb_tree_is_connected(smb_tree_t *tree)
1313 {
1314         boolean_t       rb;
1315 
1316         mutex_enter(&tree->t_mutex);
1317         rb = smb_tree_is_connected_locked(tree);
1318         mutex_exit(&tree->t_mutex);
1319         return (rb);
1320 }
1321 
1322 /*
1323  * Get the next open ofile in the list.  A reference is taken on
1324  * the ofile, which can be released later with smb_ofile_release().
1325  *
1326  * If the specified ofile is NULL, search from the beginning of the
1327  * list.  Otherwise, the search starts just after that ofile.
1328  *
1329  * Returns NULL if there are no open files in the list.
1330  */
1331 static smb_ofile_t *
1332 smb_tree_get_ofile(smb_tree_t *tree, smb_ofile_t *of)
1333 {
1334         smb_llist_t *ofile_list;
1335 
1336         ASSERT(tree);
1337         ASSERT(tree->t_magic == SMB_TREE_MAGIC);
1338 
1339         ofile_list = &tree->t_ofile_list;
1340         smb_llist_enter(ofile_list, RW_READER);
1341 
1342         if (of) {
1343                 ASSERT(of->f_magic == SMB_OFILE_MAGIC);
1344                 of = smb_llist_next(ofile_list, of);
1345         } else {
1346                 of = smb_llist_head(ofile_list);
1347         }
1348 
1349         while (of) {
1350                 if (smb_ofile_hold(of))
1351                         break;
1352 
1353                 of = smb_llist_next(ofile_list, of);
1354         }
1355 
1356         smb_llist_exit(ofile_list);
1357         return (of);
1358 }
1359 
1360 /*
1361  * smb_tree_get_odir
1362  *
1363  * Find the next odir in the tree's list of odirs, and obtain a
1364  * hold on it.
1365  * If the specified odir is NULL the search starts at the beginning
1366  * of the tree's odir list, otherwise the search starts after the
1367  * specified odir.
1368  */
1369 static smb_odir_t *
1370 smb_tree_get_odir(smb_tree_t *tree, smb_odir_t *od)
1371 {
1372         smb_llist_t *od_list;

1373 
1374         ASSERT(tree);
1375         ASSERT(tree->t_magic == SMB_TREE_MAGIC);
1376 
1377         od_list = &tree->t_odir_list;
1378         smb_llist_enter(od_list, RW_READER);
1379 
1380         if (od) {
1381                 ASSERT(od->d_magic == SMB_ODIR_MAGIC);
1382                 od = smb_llist_next(od_list, od);
1383         } else {
1384                 od = smb_llist_head(od_list);
1385         }
1386 
1387         while (od) {
1388                 ASSERT(od->d_magic == SMB_ODIR_MAGIC);
1389 
1390                 if (smb_odir_hold(od))
1391                         break;
1392                 od = smb_llist_next(od_list, od);
1393         }
1394 
1395         smb_llist_exit(od_list);
1396         return (od);
1397 }
1398 
1399 /*
1400  * smb_tree_close_odirs
1401  *
1402  * Close all open odirs in the tree's list which were opened by
1403  * the process identified by pid.
1404  * If pid is zero, close all open odirs in the tree's list.
1405  */
1406 static void
1407 smb_tree_close_odirs(smb_tree_t *tree, uint16_t pid)
1408 {
1409         smb_odir_t *od, *next_od;
1410 
1411         ASSERT(tree);
1412         ASSERT(tree->t_magic == SMB_TREE_MAGIC);
1413 
1414         od = smb_tree_get_odir(tree, NULL);
1415         while (od) {
1416                 ASSERT(od->d_magic == SMB_ODIR_MAGIC);
1417                 ASSERT(od->d_tree == tree);
1418 
1419                 next_od = smb_tree_get_odir(tree, od);
1420                 if ((pid == 0) || (od->d_opened_by_pid == pid))


1421                         smb_odir_close(od);
1422                 smb_odir_release(od);
1423 
1424                 od = next_od;
1425         }



1426 }
1427 
1428 static void
1429 smb_tree_set_execinfo(smb_tree_t *tree, smb_shr_execinfo_t *exec,
1430     int exec_type)
1431 {
1432         exec->e_sharename = tree->t_sharename;
1433         exec->e_winname = tree->t_owner->u_name;
1434         exec->e_userdom = tree->t_owner->u_domain;
1435         exec->e_srv_ipaddr = tree->t_session->local_ipaddr;
1436         exec->e_cli_ipaddr = tree->t_session->ipaddr;
1437         exec->e_cli_netbiosname = tree->t_session->workstation;
1438         exec->e_uid = crgetuid(tree->t_owner->u_cred);
1439         exec->e_type = exec_type;
1440 }
1441 
1442 /*
1443  * Private function to support smb_tree_enum.
1444  */
1445 static int




   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  25  * Copyright (c) 2016 by Delphix. All rights reserved.
  26  */
  27 
  28 /*
  29  * General Structures Layout
  30  * -------------------------
  31  *
  32  * This is a simplified diagram showing the relationship between most of the
  33  * main structures.
  34  *
  35  * +-------------------+
  36  * |     SMB_INFO      |
  37  * +-------------------+
  38  *          |
  39  *          |
  40  *          v
  41  * +-------------------+       +-------------------+      +-------------------+
  42  * |     SESSION       |<----->|     SESSION       |......|      SESSION      |
  43  * +-------------------+       +-------------------+      +-------------------+
  44  *   |          |


 105  *
 106  * SMB_TREE_STATE_DISCONNECTED
 107  *
 108  *    While in this state:
 109  *      - The tree is queued in the list of trees of its user.
 110  *      - References will not be given out if the tree is looked up.
 111  *      - The tree has no more files and directories opened.
 112  *      - The resources associated with the tree remain.
 113  *
 114  * Transition T0
 115  *
 116  *    This transition occurs in smb_tree_connect(). A new tree is created and
 117  *    added to the list of trees of a user.
 118  *
 119  * Transition T1
 120  *
 121  *    This transition occurs in smb_tree_disconnect().
 122  *
 123  * Transition T2
 124  *
 125  *    This transition occurs in smb_tree_disconnect()
 126  *
 127  * Transition T3
 128  *
 129  *    This transition occurs in smb_tree_release(). The resources associated
 130  *    with the tree are freed as well as the tree structure. For the transition
 131  *    to occur, the tree must be in the SMB_TREE_STATE_DISCONNECTED and the
 132  *    reference count must be zero.
 133  *
 134  * Comments
 135  * --------
 136  *
 137  *    The state machine of the tree structures is controlled by 3 elements:
 138  *      - The list of trees of the user it belongs to.
 139  *      - The mutex embedded in the structure itself.
 140  *      - The reference count.
 141  *
 142  *    There's a mutex embedded in the tree structure used to protect its fields
 143  *    and there's a lock embedded in the list of trees of a user. To
 144  *    increment or to decrement the reference count the mutex must be entered.
 145  *    To insert the tree into the list of trees of the user and to remove
 146  *    the tree from it, the lock must be entered in RW_WRITER mode.
 147  *
 148  *    Rules of access to a tree structure:
 149  *
 150  *    1) In order to avoid deadlocks, when both (mutex and lock of the user
 151  *       list) have to be entered, the lock must be entered first. Additionally,
 152  *       when both the (mutex and lock of the ofile list) have to be entered,
 153  *       the mutex must be entered first. However, the ofile list lock must NOT
 154  *       be dropped while the mutex is held in such a way that the ofile deleteq
 155  *       is flushed.
 156  *
 157  *    2) All actions applied to a tree require a reference count.
 158  *
 159  *    3) There are 2 ways of getting a reference count: when a tree is
 160  *       connected and when a tree is looked up.
 161  *
 162  *    It should be noted that the reference count of a tree registers the
 163  *    number of references to the tree in other structures (such as an smb
 164  *    request). The reference count is not incremented in these 2 instances:
 165  *
 166  *    1) The tree is connected. An tree is anchored by its state. If there's
 167  *       no activity involving a tree currently connected, the reference
 168  *       count of that tree is zero.
 169  *
 170  *    2) The tree is queued in the list of trees of the user. The fact of
 171  *       being queued in that list is NOT registered by incrementing the
 172  *       reference count.
 173  */
 174 
 175 #include <sys/refstr_impl.h>
 176 #include <smbsrv/smb_kproto.h>
 177 #include <smbsrv/smb_ktypes.h>
 178 #include <smbsrv/smb_fsops.h>
 179 #include <smbsrv/smb_share.h>
 180 
 181 int smb_tcon_mute = 0;
 182 
 183 uint32_t        smb_tree_connect_core(smb_request_t *);
 184 uint32_t        smb_tree_connect_disk(smb_request_t *, smb_arg_tcon_t *);
 185 uint32_t        smb_tree_connect_printq(smb_request_t *, smb_arg_tcon_t *);
 186 uint32_t        smb_tree_connect_ipc(smb_request_t *, smb_arg_tcon_t *);
 187 static void smb_tree_dealloc(void *);

 188 static boolean_t smb_tree_is_connected_locked(smb_tree_t *);

 189 static char *smb_tree_get_sharename(char *);
 190 static int smb_tree_getattr(const smb_kshare_t *, smb_node_t *, smb_tree_t *);
 191 static void smb_tree_get_volname(vfs_t *, smb_tree_t *);
 192 static void smb_tree_get_flags(const smb_kshare_t *, vfs_t *, smb_tree_t *);
 193 static void smb_tree_log(smb_request_t *, const char *, const char *, ...);
 194 static void smb_tree_close_odirs(smb_tree_t *, uint32_t);


 195 static void smb_tree_set_execinfo(smb_tree_t *, smb_shr_execinfo_t *, int);
 196 static int smb_tree_enum_private(smb_tree_t *, smb_svcenum_t *);
 197 static int smb_tree_netinfo_encode(smb_tree_t *, uint8_t *, size_t, uint32_t *);
 198 static void smb_tree_netinfo_init(smb_tree_t *tree, smb_netconnectinfo_t *);
 199 static void smb_tree_netinfo_fini(smb_netconnectinfo_t *);
 200 
 201 uint32_t
 202 smb_tree_connect(smb_request_t *sr)
 203 {
 204         smb_server_t    *sv = sr->sr_server;
 205         uint32_t status;
 206 
 207         if (smb_threshold_enter(&sv->sv_tcon_ct) != 0) {
 208                 return (NT_STATUS_INSUFF_SERVER_RESOURCES);
 209         }
 210 
 211         status = smb_tree_connect_core(sr);
 212         smb_threshold_exit(&sv->sv_tcon_ct);
 213         return (status);
 214 }


 239                 smb_tree_log(sr, tcon->path, "invalid UNC path");
 240                 return (NT_STATUS_BAD_NETWORK_NAME);
 241         }
 242 
 243         si = smb_kshare_lookup(sr->sr_server, name);
 244         if (si == NULL) {
 245                 smb_tree_log(sr, name, "share not found");
 246                 return (NT_STATUS_BAD_NETWORK_NAME);
 247         }
 248 
 249         if (!strcasecmp(SMB_SHARE_PRINT, name)) {
 250                 smb_kshare_release(sr->sr_server, si);
 251                 smb_tree_log(sr, name, "access not permitted");
 252                 return (NT_STATUS_ACCESS_DENIED);
 253         }
 254 
 255         /* NB: name points into tcon->path - don't free it. */
 256         tcon->name = name;
 257         sr->sr_tcon.si = si;
 258 
 259         /*
 260          * [MS-SMB2] 3.3.5.7 Receiving an SMB2 TREE_CONNECT Request
 261          *
 262          * If we support 3.x, RejectUnencryptedAccess is TRUE,
 263          * if Tcon.EncryptData is TRUE or global EncryptData is TRUE,
 264          * and the connection doesn't support encryption,
 265          * return ACCESS_DENIED.
 266          *
 267          * If RejectUnencryptedAccess is TRUE, we force max_protocol
 268          * to at least 3.0. Additionally, if the tree requires encryption,
 269          * we don't care what we support, we still enforce encryption.
 270          */
 271         if ((sr->sr_server->sv_cfg.skc_encrypt == SMB_CONFIG_REQUIRED ||
 272             si->shr_encrypt == SMB_CONFIG_REQUIRED) &&
 273             (sr->session->srv_cap & SMB2_CAP_ENCRYPTION) == 0) {
 274                 status = NT_STATUS_ACCESS_DENIED;
 275                 goto out;
 276         }
 277 
 278         switch (si->shr_type & STYPE_MASK) {
 279         case STYPE_DISKTREE:
 280                 status = smb_tree_connect_disk(sr, &sr->sr_tcon);
 281                 break;
 282         case STYPE_IPC:
 283                 status = smb_tree_connect_ipc(sr, &sr->sr_tcon);
 284                 break;
 285         case STYPE_PRINTQ:
 286                 status = smb_tree_connect_printq(sr, &sr->sr_tcon);
 287                 break;
 288         default:
 289                 status = NT_STATUS_BAD_DEVICE_TYPE;
 290                 break;
 291         }
 292 
 293 out:
 294         /*
 295          * On return from smb_tree_connect_* sr->tid_tree is filled in
 296          * and valid for all share types.  We can't call smb_kshare_release
 297          * until we disconnect the tree or we will invalidate the reference
 298          * we have here.
 299          */
 300         if (sr->tid_tree != NULL) {
 301                 sr->tid_tree->t_kshare = si;
 302         } else {
 303                 smb_kshare_release(sr->sr_server, si);
 304         }
 305 
 306         sr->sr_tcon.si = NULL;
 307 
 308         return (status);
 309 }
 310 
 311 /*
 312  * Disconnect a tree.
 313  *
 314  * The "do_exec" arg is obsolete and ignored.
 315  */
 316 void
 317 smb_tree_disconnect(smb_tree_t *tree, boolean_t do_exec)
 318 {
 319         _NOTE(ARGUNUSED(do_exec))
 320         smb_shr_execinfo_t execinfo;
 321 
 322         ASSERT(tree->t_magic == SMB_TREE_MAGIC);
 323 
 324         mutex_enter(&tree->t_mutex);
 325         ASSERT(tree->t_refcnt);
 326 
 327         if (!smb_tree_is_connected_locked(tree)) {
 328                 mutex_exit(&tree->t_mutex);
 329                 return;
 330         }
 331 
 332         /*
 333          * Indicate that the disconnect process has started.
 334          */
 335         tree->t_state = SMB_TREE_STATE_DISCONNECTING;
 336         mutex_exit(&tree->t_mutex);
 337 

 338         /*
 339          * The files opened under this tree are closed.
 340          */
 341         smb_ofile_close_all(tree, 0);
 342         /*
 343          * The directories opened under this tree are closed.
 344          */
 345         smb_tree_close_odirs(tree, 0);

 346 
 347         if ((tree->t_execflags & SMB_EXEC_UNMAP) != 0) {









 348                 smb_tree_set_execinfo(tree, &execinfo, SMB_EXEC_UNMAP);
 349                 (void) smb_kshare_exec(tree->t_server, &execinfo);
 350         }
 351 }
 352 
 353 /*
 354  * Take a reference on a tree.
 355  */
 356 boolean_t
 357 smb_tree_hold(
 358     smb_tree_t          *tree)
 359 {
 360         SMB_TREE_VALID(tree);
 361 
 362         mutex_enter(&tree->t_mutex);
 363 
 364         if (smb_tree_is_connected_locked(tree)) {
 365                 tree->t_refcnt++;
 366                 mutex_exit(&tree->t_mutex);
 367                 return (B_TRUE);


 385 {
 386         SMB_TREE_VALID(tree);
 387 
 388         mutex_enter(&tree->t_mutex);
 389         tree->t_refcnt++;
 390         mutex_exit(&tree->t_mutex);
 391 }
 392 
 393 /*
 394  * Release a reference on a tree.  If the tree is disconnected and the
 395  * reference count falls to zero, post the object for deletion.
 396  * Object deletion is deferred to avoid modifying a list while an
 397  * iteration may be in progress.
 398  */
 399 void
 400 smb_tree_release(
 401     smb_tree_t          *tree)
 402 {
 403         SMB_TREE_VALID(tree);
 404 




 405         /* flush the ofile and odir lists' delete queues */
 406         smb_llist_flush(&tree->t_ofile_list);
 407         smb_llist_flush(&tree->t_odir_list);
 408 
 409         mutex_enter(&tree->t_mutex);
 410         ASSERT(tree->t_refcnt);
 411         tree->t_refcnt--;
 412 
 413         switch (tree->t_state) {
 414         case SMB_TREE_STATE_DISCONNECTING:
 415                 if (tree->t_refcnt == 0) {
 416                         smb_session_t *ssn = tree->t_session;
 417                         tree->t_state = SMB_TREE_STATE_DISCONNECTED;
 418                         smb_llist_post(&ssn->s_tree_list, tree,
 419                             smb_tree_dealloc);
 420                 }
 421                 break;
 422         case SMB_TREE_STATE_CONNECTED:
 423                 break;
 424         default:
 425                 ASSERT(0);
 426                 break;
 427         }
 428 
 429         mutex_exit(&tree->t_mutex);
 430 }
 431 
























 432 /*
 433  * Close ofiles and odirs that match pid.
 434  */
 435 void
 436 smb_tree_close_pid(
 437     smb_tree_t          *tree,
 438     uint32_t            pid)
 439 {
 440         ASSERT(tree);
 441         ASSERT(tree->t_magic == SMB_TREE_MAGIC);
 442 
 443         smb_ofile_close_all(tree, pid);
 444         smb_tree_close_odirs(tree, pid);
 445 }
 446 
 447 /*
 448  * Check whether or not a tree supports the features identified by flags.
 449  */
 450 boolean_t
 451 smb_tree_has_feature(smb_tree_t *tree, uint32_t flags)
 452 {
 453         ASSERT(tree);
 454         ASSERT(tree->t_magic == SMB_TREE_MAGIC);
 455 
 456         return ((tree->t_flags & flags) == flags);
 457 }
 458 
 459 /*
 460  * If the enumeration request is for tree data, handle the request
 461  * here.  Otherwise, pass it on to the ofiles.
 462  *
 463  * This function should be called with a hold on the tree.
 464  */
 465 int
 466 smb_tree_enum(smb_tree_t *tree, smb_svcenum_t *svcenum)
 467 {
 468         smb_llist_t     *of_list;
 469         smb_ofile_t     *of;

 470         int             rc = 0;
 471 



 472         if (svcenum->se_type == SMB_SVCENUM_TYPE_TREE)
 473                 return (smb_tree_enum_private(tree, svcenum));
 474 
 475         of_list = &tree->t_ofile_list;
 476         smb_llist_enter(of_list, RW_READER);

 477 
 478         of = smb_llist_head(of_list);
 479         while (of) {
 480                 if (smb_ofile_hold(of)) {
 481                         rc = smb_ofile_enum(of, svcenum);

 482                         smb_ofile_release(of);
 483                 }
 484                 if (rc != 0)
 485                         break;
 486                 of = smb_llist_next(of_list, of);
 487         }
 488 
 489         smb_llist_exit(of_list);



 490 
 491         return (rc);
 492 }
 493 
 494 /*
 495  * Close a file by its unique id.
 496  */
 497 int
 498 smb_tree_fclose(smb_tree_t *tree, uint32_t uniqid)
 499 {
 500         smb_ofile_t     *of;
 501 
 502         ASSERT(tree);
 503         ASSERT(tree->t_magic == SMB_TREE_MAGIC);
 504 
 505         /*
 506          * Note that ORPHANED ofiles aren't fclosable, as they have
 507          * no session, user, or tree by which they might be found.
 508          * They will eventually expire.
 509          */
 510         if ((of = smb_ofile_lookup_by_uniqid(tree, uniqid)) == NULL)
 511                 return (ENOENT);
 512 
 513         if (smb_ofile_disallow_fclose(of)) {
 514                 smb_ofile_release(of);
 515                 return (EACCES);
 516         }
 517 
 518         smb_ofile_close(of, 0);
 519         smb_ofile_release(of);
 520         return (0);
 521 }
 522 
 523 /* *************************** Static Functions ***************************** */
 524 
 525 #define SHARES_DIR      ".zfs/shares/"
 526 
 527 /*
 528  * Calculates permissions given by the share's ACL to the
 529  * user in the passed request.  The default is full access.


 645         if ((host_access & ACE_ALL_PERMS) == 0) {
 646                 smb_tree_log(sr, sharename, "access denied: host access");
 647                 return (0);
 648         }
 649 
 650         acl_access = smb_tree_acl_access(sr, shr, vp);
 651         if ((acl_access & ACE_ALL_PERMS) == 0) {
 652                 smb_tree_log(sr, sharename, "access denied: share ACL");
 653                 return (0);
 654         }
 655 
 656         access = host_access & acl_access;
 657         if ((access & ACE_ALL_PERMS) == 0) {
 658                 smb_tree_log(sr, sharename, "access denied");
 659                 return (0);
 660         }
 661 
 662         return (access);
 663 }
 664 
 665 /* How long should tree connect wait for DH import to complete? */
 666 int smb_tcon_import_wait = 20; /* sec. */
 667 
 668 /*
 669  * Connect a share for use with files and directories.
 670  */
 671 uint32_t
 672 smb_tree_connect_disk(smb_request_t *sr, smb_arg_tcon_t *tcon)
 673 {
 674         char                    *sharename = tcon->path;
 675         const char              *any = "?????";
 676         smb_user_t              *user = sr->uid_user;

 677         smb_node_t              *snode = NULL;
 678         smb_kshare_t            *si = tcon->si;
 679         char                    *service = tcon->service;

 680         smb_tree_t              *tree;
 681         int                     rc;
 682         uint32_t                access;
 683         smb_shr_execinfo_t      execinfo;
 684         clock_t time;
 685 
 686         ASSERT(user);
 687         ASSERT(user->u_cred);
 688 
 689         if (service != NULL &&
 690             strcmp(service, any) != 0 &&
 691             strcasecmp(service, "A:") != 0) {
 692                 smb_tree_log(sr, sharename, "invalid service (%s)", service);
 693                 return (NT_STATUS_BAD_DEVICE_TYPE);
 694         }
 695 
 696         /*
 697          * Check that the shared directory exists.
 698          */
 699         snode = si->shr_root_node;
 700         if (snode == NULL) {












 701                 smb_tree_log(sr, sharename, "bad path: %s", si->shr_path);
 702                 return (NT_STATUS_BAD_NETWORK_NAME);
 703         }
 704 
 705         if ((access = smb_tree_chkaccess(sr, si, snode->vp)) == 0) {

 706                 return (NT_STATUS_ACCESS_DENIED);
 707         }
 708 
 709         /*
 710          * Wait for DH import of persistent handles to finish.
 711          * If we timeout, it's not clear what status to return,
 712          * but as the share is not really availale yet, let's
 713          * return the status for "no such share".
 714          */
 715         time = SEC_TO_TICK(smb_tcon_import_wait) + ddi_get_lbolt();
 716         mutex_enter(&si->shr_mutex);
 717         while (si->shr_import_busy != NULL) {
 718                 if (cv_timedwait(&si->shr_cv, &si->shr_mutex, time) < 0) {
 719                         mutex_exit(&si->shr_mutex);
 720                         return (NT_STATUS_BAD_NETWORK_NAME);
 721                 }
 722         }
 723         mutex_exit(&si->shr_mutex);
 724 
 725         /*
 726          * Set up the OptionalSupport for this share.
 727          */
 728         tcon->optional_support = SMB_SUPPORT_SEARCH_BITS;
 729 
 730         switch (si->shr_flags & SMB_SHRF_CSC_MASK) {
 731         case SMB_SHRF_CSC_DISABLED:
 732                 tcon->optional_support |= SMB_CSC_CACHE_NONE;
 733                 break;
 734         case SMB_SHRF_CSC_AUTO:
 735                 tcon->optional_support |= SMB_CSC_CACHE_AUTO_REINT;
 736                 break;
 737         case SMB_SHRF_CSC_VDO:
 738                 tcon->optional_support |= SMB_CSC_CACHE_VDO;
 739                 break;
 740         case SMB_SHRF_CSC_MANUAL:
 741         default:
 742                 /*
 743                  * Default to SMB_CSC_CACHE_MANUAL_REINT.
 744                  */
 745                 break;
 746         }
 747 
 748         /* ABE support */
 749         if (si->shr_flags & SMB_SHRF_ABE)
 750                 tcon->optional_support |=
 751                     SHI1005_FLAGS_ACCESS_BASED_DIRECTORY_ENUM;
 752 
 753         if (si->shr_flags & SMB_SHRF_DFSROOT)
 754                 tcon->optional_support |= SMB_SHARE_IS_IN_DFS;
 755 
 756         /* if 'smb' zfs property: shortnames=disabled */
 757         if (!smb_shortnames)
 758                 sr->arg.tcon.optional_support |= SMB_UNIQUE_FILE_NAME;
 759 
 760         tree = smb_tree_alloc(sr, si, snode, access, sr->sr_cfg->skc_execflags);
 761 


 762         if (tree == NULL)
 763                 return (NT_STATUS_INSUFF_SERVER_RESOURCES);
 764 
 765         if (tree->t_execflags & SMB_EXEC_MAP) {
 766                 smb_tree_set_execinfo(tree, &execinfo, SMB_EXEC_MAP);
 767 
 768                 rc = smb_kshare_exec(tree->t_server, &execinfo);
 769 
 770                 if ((rc != 0) && (tree->t_execflags & SMB_EXEC_TERM)) {
 771                         /*
 772                          * Inline parts of: smb_tree_disconnect()
 773                          * Not using smb_tree_disconnect() for cleanup
 774                          * here because: we don't want an exec up-call,
 775                          * and there can't be any opens as we never
 776                          * returned this TID to the client.
 777                          */
 778                         mutex_enter(&tree->t_mutex);
 779                         tree->t_state = SMB_TREE_STATE_DISCONNECTING;
 780                         mutex_enter(&tree->t_mutex);
 781 
 782                         smb_tree_release(tree);
 783                         return (NT_STATUS_ACCESS_DENIED);
 784                 }
 785         }
 786 
 787         sr->tid_tree = tree;
 788         sr->smb_tid  = tree->t_tid;
 789 
 790         return (0);
 791 }
 792 
 793 /*
 794  * Shares have both a share and host based access control.  The access
 795  * granted will be minimum permissions based on both hostaccess
 796  * (permissions allowed by host based access) and aclaccess (from the
 797  * share ACL).
 798  */
 799 uint32_t
 800 smb_tree_connect_printq(smb_request_t *sr, smb_arg_tcon_t *tcon)
 801 {


 893             sr->sr_cfg->skc_restrict_anon) {
 894                 smb_tree_log(sr, name, "access denied: restrict anonymous");
 895                 return (NT_STATUS_ACCESS_DENIED);
 896         }
 897 
 898         tcon->optional_support = SMB_SUPPORT_SEARCH_BITS;
 899 
 900         tree = smb_tree_alloc(sr, si, NULL, ACE_ALL_PERMS, 0);
 901         if (tree == NULL)
 902                 return (NT_STATUS_INSUFF_SERVER_RESOURCES);
 903 
 904         sr->tid_tree = tree;
 905         sr->smb_tid  = tree->t_tid;
 906 
 907         return (0);
 908 }
 909 
 910 /*
 911  * Allocate a tree.
 912  */
 913 smb_tree_t *
 914 smb_tree_alloc(smb_request_t *sr, const smb_kshare_t *si,
 915     smb_node_t *snode, uint32_t access, uint32_t execflags)
 916 {
 917         smb_session_t   *session = sr->session;
 918         smb_tree_t      *tree;
 919         uint32_t        stype = si->shr_type;
 920         uint16_t        tid;
 921 
 922         if (smb_idpool_alloc(&session->s_tid_pool, &tid))
 923                 return (NULL);
 924 
 925         tree = kmem_cache_alloc(smb_cache_tree, KM_SLEEP);
 926         bzero(tree, sizeof (smb_tree_t));
 927 
 928         tree->t_session = session;
 929         tree->t_server = session->s_server;
 930 
 931         /* grab a ref for tree->t_owner */
 932         smb_user_hold_internal(sr->uid_user);
 933         tree->t_owner = sr->uid_user;


 937                         smb_idpool_free(&session->s_tid_pool, tid);
 938                         kmem_cache_free(smb_cache_tree, tree);
 939                         return (NULL);
 940                 }
 941         }
 942 
 943         if (smb_idpool_constructor(&tree->t_fid_pool)) {
 944                 smb_idpool_free(&session->s_tid_pool, tid);
 945                 kmem_cache_free(smb_cache_tree, tree);
 946                 return (NULL);
 947         }
 948 
 949         if (smb_idpool_constructor(&tree->t_odid_pool)) {
 950                 smb_idpool_destructor(&tree->t_fid_pool);
 951                 smb_idpool_free(&session->s_tid_pool, tid);
 952                 kmem_cache_free(smb_cache_tree, tree);
 953                 return (NULL);
 954         }
 955 
 956         smb_llist_constructor(&tree->t_ofile_list, sizeof (smb_ofile_t),
 957             offsetof(smb_ofile_t, f_tree_lnd));
 958 
 959         smb_llist_constructor(&tree->t_odir_list, sizeof (smb_odir_t),
 960             offsetof(smb_odir_t, d_lnd));
 961 
 962         (void) strlcpy(tree->t_sharename, si->shr_name,
 963             sizeof (tree->t_sharename));
 964         (void) strlcpy(tree->t_resource, si->shr_path,
 965             sizeof (tree->t_resource));
 966 
 967         mutex_init(&tree->t_mutex, NULL, MUTEX_DEFAULT, NULL);
 968 
 969         tree->t_refcnt = 1;
 970         tree->t_tid = tid;
 971         tree->t_res_type = stype;
 972         tree->t_state = SMB_TREE_STATE_CONNECTED;
 973         tree->t_magic = SMB_TREE_MAGIC;
 974         tree->t_access = access;
 975         tree->t_connect_time = gethrestime_sec();
 976         tree->t_execflags = execflags;
 977 


 983                 smb_node_ref(snode);
 984                 tree->t_snode = snode;
 985                 tree->t_acltype = smb_fsop_acltype(snode);
 986         }
 987 
 988         smb_llist_enter(&session->s_tree_list, RW_WRITER);
 989         smb_llist_insert_head(&session->s_tree_list, tree);
 990         smb_llist_exit(&session->s_tree_list);
 991         atomic_inc_32(&session->s_tree_cnt);
 992         smb_server_inc_trees(session->s_server);
 993         return (tree);
 994 }
 995 
 996 /*
 997  * Deallocate a tree.  The open file and open directory lists should be
 998  * empty.
 999  *
1000  * Remove the tree from the user's tree list before freeing resources
1001  * associated with the tree.
1002  */
1003 static void
1004 smb_tree_dealloc(void *arg)
1005 {
1006         smb_session_t   *session;
1007         smb_tree_t      *tree = (smb_tree_t *)arg;
1008 
1009         SMB_TREE_VALID(tree);
1010         ASSERT(tree->t_state == SMB_TREE_STATE_DISCONNECTED);
1011         ASSERT(tree->t_refcnt == 0);
1012 
1013         smb_server_dec_trees(tree->t_server);
1014 
1015         session = tree->t_session;
1016         smb_llist_enter(&session->s_tree_list, RW_WRITER);
1017         smb_llist_remove(&session->s_tree_list, tree);
1018         smb_idpool_free(&session->s_tid_pool, tree->t_tid);
1019         atomic_dec_32(&session->s_tree_cnt);
1020         smb_llist_exit(&session->s_tree_list);
1021 
1022         /*
1023          * This tree is no longer on s_tree_list, however...
1024          *
1025          * This is called via smb_llist_post, which means it may run
1026          * BEFORE smb_tree_release drops t_mutex (if another thread
1027          * flushes the delete queue before we do).  Synchronize.
1028          */
1029         mutex_enter(&tree->t_mutex);
1030         mutex_exit(&tree->t_mutex);
1031 
1032         tree->t_magic = (uint32_t)~SMB_TREE_MAGIC;
1033 
1034         if (tree->t_kshare != NULL) {
1035                 smb_kshare_release(tree->t_server, tree->t_kshare);
1036                 tree->t_kshare = NULL;
1037         }
1038 
1039         if (tree->t_snode)
1040                 smb_node_release(tree->t_snode);
1041 
1042         mutex_destroy(&tree->t_mutex);
1043         smb_llist_destructor(&tree->t_ofile_list);
1044         smb_llist_destructor(&tree->t_odir_list);
1045         smb_idpool_destructor(&tree->t_fid_pool);
1046         smb_idpool_destructor(&tree->t_odid_pool);
1047 
1048         SMB_USER_VALID(tree->t_owner);
1049         smb_user_release(tree->t_owner);
1050 
1051         kmem_cache_free(smb_cache_tree, tree);
1052 }
1053 
1054 /*
1055  * Determine whether or not a tree is connected.
1056  * This function must be called with the tree mutex held.
1057  */
1058 static boolean_t
1059 smb_tree_is_connected_locked(smb_tree_t *tree)
1060 {
1061         switch (tree->t_state) {
1062         case SMB_TREE_STATE_CONNECTED:
1063                 return (B_TRUE);
1064 
1065         case SMB_TREE_STATE_DISCONNECTING:
1066         case SMB_TREE_STATE_DISCONNECTED:
1067                 /*
1068                  * The tree exists but is being disconnected or destroyed.
1069                  */
1070                 return (B_FALSE);
1071 
1072         default:
1073                 ASSERT(0);
1074                 return (B_FALSE);
1075         }
1076 }
1077 
1078 /*





















1079  * Return a pointer to the share name within a share resource path.
1080  *
1081  * The share path may be a Uniform Naming Convention (UNC) string
1082  * (\\server\share) or simply the share name.  We validate the UNC
1083  * format but we don't look at the server name.
1084  */
1085 static char *
1086 smb_tree_get_sharename(char *unc_path)
1087 {
1088         char *sharename = unc_path;
1089 
1090         if (sharename[0] == '\\') {
1091                 /*
1092                  * Looks like a UNC path, validate the format.
1093                  */
1094                 if (sharename[1] != '\\')
1095                         return (NULL);
1096 
1097                 if ((sharename = strchr(sharename+2, '\\')) == NULL)
1098                         return (NULL);
1099 
1100                 ++sharename;
1101         } else if (strchr(sharename, '\\') != NULL) {
1102                 /*
1103                  * This should be a share name (no embedded \'s).
1104                  */
1105                 return (NULL);
1106         }
1107 
1108         return (sharename);
1109 }
1110 
1111 /*
1112  * Obtain the tree attributes: volume name, typename and flags.
1113  */
1114 static int
1115 smb_tree_getattr(const smb_kshare_t *si, smb_node_t *node, smb_tree_t *tree)
1116 {
1117         vfs_t *vfsp = SMB_NODE_VFS(node);
1118         smb_cfg_val_t srv_encrypt;
1119 
1120         ASSERT(vfsp);
1121 
1122         if (getvfs(&vfsp->vfs_fsid) != vfsp)
1123                 return (ESTALE);
1124 
1125         smb_tree_get_volname(vfsp, tree);
1126         smb_tree_get_flags(si, vfsp, tree);
1127 
1128         srv_encrypt = tree->t_session->s_server->sv_cfg.skc_encrypt;
1129         if (tree->t_session->dialect >= SMB_VERS_3_0) {
1130                 if (si->shr_encrypt == SMB_CONFIG_REQUIRED ||
1131                     srv_encrypt == SMB_CONFIG_REQUIRED)
1132                         tree->t_encrypt = SMB_CONFIG_REQUIRED;
1133                 else if (si->shr_encrypt == SMB_CONFIG_ENABLED ||
1134                     srv_encrypt == SMB_CONFIG_ENABLED)
1135                         tree->t_encrypt = SMB_CONFIG_ENABLED;
1136                 else
1137                         tree->t_encrypt = SMB_CONFIG_DISABLED;
1138         } else
1139                 tree->t_encrypt = SMB_CONFIG_DISABLED;
1140 
1141         VFS_RELE(vfsp);
1142         return (0);
1143 }
1144 
1145 /*
1146  * Extract the volume name.
1147  */
1148 static void
1149 smb_tree_get_volname(vfs_t *vfsp, smb_tree_t *tree)
1150 {
1151 #ifdef  _FAKE_KERNEL
1152         _NOTE(ARGUNUSED(vfsp))
1153         (void) strlcpy(tree->t_volume, "fake", SMB_VOLNAMELEN);
1154 #else   /* _FAKE_KERNEL */
1155         refstr_t *vfs_mntpoint;
1156         const char *s;
1157         char *name;
1158 
1159         vfs_mntpoint = vfs_getmntpoint(vfsp);
1160 


1173  * Always set "unicode on disk" because we always use utf8 names locally.
1174  * Always set ACL support because the VFS will fake ACLs for file systems
1175  * that don't support them.
1176  *
1177  * Some flags are dependent on the typename, which is also set up here.
1178  * File system types are hardcoded in uts/common/os/vfs_conf.c.
1179  */
1180 static void
1181 smb_tree_get_flags(const smb_kshare_t *si, vfs_t *vfsp, smb_tree_t *tree)
1182 {
1183         smb_session_t *ssn = tree->t_session;
1184         struct vfssw    *vswp;
1185 
1186         typedef struct smb_mtype {
1187                 char            *mt_name;
1188                 size_t          mt_namelen;
1189                 uint32_t        mt_flags;
1190         } smb_mtype_t;
1191 
1192         static smb_mtype_t smb_mtype[] = {
1193 #ifdef  _FAKE_KERNEL
1194                 /* See libfksmbsrv:fake_vfs.c */
1195                 { "fake",    3, SMB_TREE_SPARSE},
1196 #endif  /* _FAKE_KERNEL */
1197                 { "zfs",    3,  SMB_TREE_QUOTA | SMB_TREE_SPARSE},
1198                 { "ufs",    3,  0 },
1199                 { "nfs",    3,  SMB_TREE_NFS_MOUNTED },
1200                 { "tmpfs",  5,  SMB_TREE_NO_EXPORT }
1201         };
1202         smb_mtype_t     *mtype;
1203         char            *name;
1204         uint32_t        flags =
1205             SMB_TREE_SUPPORTS_ACLS |
1206             SMB_TREE_UNICODE_ON_DISK;
1207         int             i;
1208 
1209         if (si->shr_flags & SMB_SHRF_DFSROOT)
1210                 flags |= SMB_TREE_DFSROOT;
1211 
1212         if (si->shr_flags & SMB_SHRF_CATIA)
1213                 flags |= SMB_TREE_CATIA;
1214 
1215         if (si->shr_flags & SMB_SHRF_ABE)
1216                 flags |= SMB_TREE_ABE;
1217 
1218         if (si->shr_flags & SMB_SHRF_CA)
1219                 flags |= SMB_TREE_CA;
1220 
1221         if (si->shr_flags & SMB_SHRF_FSO)
1222                 flags |= SMB_TREE_FORCE_L2_OPLOCK;
1223 
1224         if (ssn->s_cfg.skc_oplock_enable) {
1225                 /* if 'smb' zfs property: oplocks=enabled */
1226                 flags |= SMB_TREE_OPLOCKS;
1227         }
1228 
1229         /* Global config option for now.  Later make per-share. */
1230         if (ssn->s_cfg.skc_traverse_mounts)
1231                 flags |= SMB_TREE_TRAVERSE_MOUNTS;
1232 
1233         /* if 'smb' zfs property: shortnames=enabled */
1234         if (smb_shortnames)
1235                 flags |= SMB_TREE_SHORTNAMES;
1236 
1237         if (vfsp->vfs_flag & VFS_RDONLY)
1238                 flags |= SMB_TREE_READONLY;
1239 
1240         if (vfsp->vfs_flag & VFS_XATTR)
1241                 flags |= SMB_TREE_STREAMS;
1242 
1243         vswp = vfs_getvfsswbyvfsops(vfs_getops(vfsp));
1244         if (vswp != NULL) {
1245                 name = vswp->vsw_name;
1246                 vfs_unrefvfssw(vswp);
1247         } else {
1248                 name = "?";
1249         }
1250 
1251         for (i = 0; i < sizeof (smb_mtype) / sizeof (smb_mtype[0]); ++i) {
1252                 mtype = &smb_mtype[i];
1253                 if (strncasecmp(name, mtype->mt_name, mtype->mt_namelen) == 0)
1254                         flags |= mtype->mt_flags;
1255         }
1256 
1257         /*
1258          * SMB_TREE_QUOTA will be on here if the FS is ZFS.  We want to
1259          * turn it OFF when the share property says false.
1260          */
1261         if ((si->shr_flags & SMB_SHRF_QUOTAS) == 0)
1262                 flags &= ~SMB_TREE_QUOTA;
1263 
1264         (void) strlcpy(tree->t_typename, name, SMB_TYPENAMELEN);
1265         (void) smb_strupr((char *)tree->t_typename);
1266 
1267         if (vfs_has_feature(vfsp, VFSFT_XVATTR))
1268                 flags |= SMB_TREE_XVATTR;
1269 
1270         if (vfs_has_feature(vfsp, VFSFT_CASEINSENSITIVE))
1271                 flags |= SMB_TREE_CASEINSENSITIVE;
1272 
1273         if (vfs_has_feature(vfsp, VFSFT_NOCASESENSITIVE))
1274                 flags |= SMB_TREE_NO_CASESENSITIVE;
1275 
1276         if (vfs_has_feature(vfsp, VFSFT_DIRENTFLAGS))
1277                 flags |= SMB_TREE_DIRENTFLAGS;
1278 
1279         if (vfs_has_feature(vfsp, VFSFT_ACLONCREATE))
1280                 flags |= SMB_TREE_ACLONCREATE;
1281 
1282         if (vfs_has_feature(vfsp, VFSFT_ACEMASKONACCESS))
1283                 flags |= SMB_TREE_ACEMASKONACCESS;


1363         if (!smb_odir_hold(od))
1364                 od = NULL;
1365 
1366 out:
1367         smb_llist_exit(od_list);
1368         return (od);
1369 }
1370 
1371 boolean_t
1372 smb_tree_is_connected(smb_tree_t *tree)
1373 {
1374         boolean_t       rb;
1375 
1376         mutex_enter(&tree->t_mutex);
1377         rb = smb_tree_is_connected_locked(tree);
1378         mutex_exit(&tree->t_mutex);
1379         return (rb);
1380 }
1381 
1382 /*
1383  * smb_tree_close_odirs

1384  *
1385  * Close all open odirs in the tree's list which were opened by
1386  * the process identified by pid.
1387  * If pid is zero, close all open odirs in the tree's list.

1388  */
1389 static void
1390 smb_tree_close_odirs(smb_tree_t *tree, uint32_t pid)
1391 {






































1392         smb_llist_t     *od_list;
1393         smb_odir_t      *od;
1394 
1395         ASSERT(tree);
1396         ASSERT(tree->t_magic == SMB_TREE_MAGIC);
1397 
1398         od_list = &tree->t_odir_list;
1399         smb_llist_enter(od_list, RW_READER);
1400 
1401         for (od = smb_llist_head(od_list);
1402             od != NULL;
1403             od = smb_llist_next(od_list, od)) {



1404 

1405                 ASSERT(od->d_magic == SMB_ODIR_MAGIC);




























1406                 ASSERT(od->d_tree == tree);
1407 
1408                 if (pid != 0 && od->d_opened_by_pid != pid)
1409                         continue;
1410 
1411                 if (smb_odir_hold(od)) {
1412                         smb_odir_close(od);
1413                         smb_odir_release(od);


1414                 }
1415         }
1416 
1417         smb_llist_exit(od_list);
1418 }
1419 
1420 static void
1421 smb_tree_set_execinfo(smb_tree_t *tree, smb_shr_execinfo_t *exec,
1422     int exec_type)
1423 {
1424         exec->e_sharename = tree->t_sharename;
1425         exec->e_winname = tree->t_owner->u_name;
1426         exec->e_userdom = tree->t_owner->u_domain;
1427         exec->e_srv_ipaddr = tree->t_session->local_ipaddr;
1428         exec->e_cli_ipaddr = tree->t_session->ipaddr;
1429         exec->e_cli_netbiosname = tree->t_session->workstation;
1430         exec->e_uid = crgetuid(tree->t_owner->u_cred);
1431         exec->e_type = exec_type;
1432 }
1433 
1434 /*
1435  * Private function to support smb_tree_enum.
1436  */
1437 static int