smb_tree.c (fc724630b14603e4c1147df68b7bf45f7de7431f) smb_tree.c (8b2cc8ac894f2d58f38cf2fb7c3ac778f4c57c09)
1/*
2 * CDDL HEADER START
3 *
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

--- 166 unchanged lines hidden (view full) ---

175#include <smbsrv/smb_door_svc.h>
176#include <smbsrv/smb_share.h>
177#include <sys/pathname.h>
178
179int smb_tcon_mute = 0;
180
181static smb_tree_t *smb_tree_connect_disk(smb_request_t *, const char *);
182static smb_tree_t *smb_tree_connect_ipc(smb_request_t *, const char *);
1/*
2 * CDDL HEADER START
3 *
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

--- 166 unchanged lines hidden (view full) ---

175#include <smbsrv/smb_door_svc.h>
176#include <smbsrv/smb_share.h>
177#include <sys/pathname.h>
178
179int smb_tcon_mute = 0;
180
181static smb_tree_t *smb_tree_connect_disk(smb_request_t *, const char *);
182static smb_tree_t *smb_tree_connect_ipc(smb_request_t *, const char *);
183static smb_tree_t *smb_tree_alloc(smb_user_t *, const char *, const char *,
183static smb_tree_t *smb_tree_alloc(smb_user_t *, const smb_share_t *,
184 int32_t, smb_node_t *, uint32_t);
185static void smb_tree_dealloc(smb_tree_t *);
184 int32_t, smb_node_t *, uint32_t);
185static void smb_tree_dealloc(smb_tree_t *);
186static boolean_t smb_tree_is_connected(smb_tree_t *);
186static boolean_t smb_tree_is_connected_locked(smb_tree_t *);
187static boolean_t smb_tree_is_disconnected(smb_tree_t *);
188static const char *smb_tree_get_sharename(const char *);
189static int smb_tree_get_stype(const char *, const char *, int32_t *);
187static boolean_t smb_tree_is_disconnected(smb_tree_t *);
188static const char *smb_tree_get_sharename(const char *);
189static int smb_tree_get_stype(const char *, const char *, int32_t *);
190static int smb_tree_getattr(smb_node_t *, smb_tree_t *);
190static int smb_tree_getattr(const smb_share_t *, smb_node_t *, smb_tree_t *);
191static void smb_tree_get_volname(vfs_t *, smb_tree_t *);
191static void smb_tree_get_volname(vfs_t *, smb_tree_t *);
192static void smb_tree_get_flags(vfs_t *, smb_tree_t *);
192static void smb_tree_get_flags(const smb_share_t *, vfs_t *, smb_tree_t *);
193static void smb_tree_log(smb_request_t *, const char *, const char *, ...);
194static void smb_tree_close_odirs(smb_tree_t *, uint16_t);
195static smb_odir_t *smb_tree_get_odir(smb_tree_t *, smb_odir_t *);
196
197/*
198 * Extract the share name and share type and connect as appropriate.
199 * Share names are case insensitive so we map the share name to
200 * lower-case as a convenience for internal processing.

--- 45 unchanged lines hidden (view full) ---

246smb_tree_disconnect(
247 smb_tree_t *tree)
248{
249 ASSERT(tree->t_magic == SMB_TREE_MAGIC);
250
251 mutex_enter(&tree->t_mutex);
252 ASSERT(tree->t_refcnt);
253
193static void smb_tree_log(smb_request_t *, const char *, const char *, ...);
194static void smb_tree_close_odirs(smb_tree_t *, uint16_t);
195static smb_odir_t *smb_tree_get_odir(smb_tree_t *, smb_odir_t *);
196
197/*
198 * Extract the share name and share type and connect as appropriate.
199 * Share names are case insensitive so we map the share name to
200 * lower-case as a convenience for internal processing.

--- 45 unchanged lines hidden (view full) ---

246smb_tree_disconnect(
247 smb_tree_t *tree)
248{
249 ASSERT(tree->t_magic == SMB_TREE_MAGIC);
250
251 mutex_enter(&tree->t_mutex);
252 ASSERT(tree->t_refcnt);
253
254 if (smb_tree_is_connected(tree)) {
254 if (smb_tree_is_connected_locked(tree)) {
255 /*
256 * Indicate that the disconnect process has started.
257 */
258 tree->t_state = SMB_TREE_STATE_DISCONNECTING;
259 mutex_exit(&tree->t_mutex);
260 atomic_dec_32(&tree->t_server->sv_open_trees);
261
262 /*

--- 18 unchanged lines hidden (view full) ---

281smb_tree_hold(
282 smb_tree_t *tree)
283{
284 ASSERT(tree);
285 ASSERT(tree->t_magic == SMB_TREE_MAGIC);
286
287 mutex_enter(&tree->t_mutex);
288
255 /*
256 * Indicate that the disconnect process has started.
257 */
258 tree->t_state = SMB_TREE_STATE_DISCONNECTING;
259 mutex_exit(&tree->t_mutex);
260 atomic_dec_32(&tree->t_server->sv_open_trees);
261
262 /*

--- 18 unchanged lines hidden (view full) ---

281smb_tree_hold(
282 smb_tree_t *tree)
283{
284 ASSERT(tree);
285 ASSERT(tree->t_magic == SMB_TREE_MAGIC);
286
287 mutex_enter(&tree->t_mutex);
288
289 if (smb_tree_is_connected(tree)) {
289 if (smb_tree_is_connected_locked(tree)) {
290 tree->t_refcnt++;
291 mutex_exit(&tree->t_mutex);
292 return (B_TRUE);
293 }
294
295 mutex_exit(&tree->t_mutex);
296 return (B_FALSE);
297}

--- 203 unchanged lines hidden (view full) ---

501
502 /*
503 * Check that the shared directory exists.
504 */
505 rc = smb_pathname_reduce(sr, u_cred, si->shr_path, 0, 0, &dir_snode,
506 last_component);
507
508 if (rc == 0) {
290 tree->t_refcnt++;
291 mutex_exit(&tree->t_mutex);
292 return (B_TRUE);
293 }
294
295 mutex_exit(&tree->t_mutex);
296 return (B_FALSE);
297}

--- 203 unchanged lines hidden (view full) ---

501
502 /*
503 * Check that the shared directory exists.
504 */
505 rc = smb_pathname_reduce(sr, u_cred, si->shr_path, 0, 0, &dir_snode,
506 last_component);
507
508 if (rc == 0) {
509 rc = smb_fsop_lookup(sr, u_cred, SMB_FOLLOW_LINKS, 0,
510 dir_snode, last_component, &snode, &attr, 0, 0);
509 rc = smb_fsop_lookup(sr, u_cred, SMB_FOLLOW_LINKS,
510 sr->sr_server->si_root_smb_node, dir_snode, last_component,
511 &snode, &attr);
511
512 smb_node_release(dir_snode);
513 }
514
515 if (rc) {
516 if (snode)
517 smb_node_release(snode);
518

--- 26 unchanged lines hidden (view full) ---

545
546 /*
547 * Set tree ACL access to the minimum ACL permissions based on
548 * hostaccess (those allowed by host based access) and
549 * aclaccess (those from the ACL object for the share). This
550 * is done during the alloc.
551 */
552
512
513 smb_node_release(dir_snode);
514 }
515
516 if (rc) {
517 if (snode)
518 smb_node_release(snode);
519

--- 26 unchanged lines hidden (view full) ---

546
547 /*
548 * Set tree ACL access to the minimum ACL permissions based on
549 * hostaccess (those allowed by host based access) and
550 * aclaccess (those from the ACL object for the share). This
551 * is done during the alloc.
552 */
553
553 tree = smb_tree_alloc(user, sharename, si->shr_path, STYPE_DISKTREE,
554 snode, hostaccess & aclaccess);
554 (void) strlcpy(si->shr_name, sharename, MAXNAMELEN);
555 tree = smb_tree_alloc(user, si, STYPE_DISKTREE, snode,
556 hostaccess & aclaccess);
555
556 if (tree == NULL)
557 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRSRV, ERRaccess);
558
559 smb_node_release(snode);
560 kmem_free(si, sizeof (smb_share_t));
561 return (tree);
562}
563
564/*
565 * Connect an IPC share for use with named pipes.
566 */
567static smb_tree_t *
568smb_tree_connect_ipc(smb_request_t *sr, const char *name)
569{
557
558 if (tree == NULL)
559 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRSRV, ERRaccess);
560
561 smb_node_release(snode);
562 kmem_free(si, sizeof (smb_share_t));
563 return (tree);
564}
565
566/*
567 * Connect an IPC share for use with named pipes.
568 */
569static smb_tree_t *
570smb_tree_connect_ipc(smb_request_t *sr, const char *name)
571{
570 smb_user_t *user = sr->uid_user;
571 smb_tree_t *tree;
572 smb_user_t *user = sr->uid_user;
573 smb_tree_t *tree;
574 smb_share_t *si;
572
573 ASSERT(user);
574
575 if ((user->u_flags & SMB_USER_FLAG_IPC) &&
576 sr->sr_cfg->skc_restrict_anon) {
577 smb_tree_log(sr, name, "access denied: restrict anonymous");
578 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRSRV, ERRaccess);
579 return (NULL);
580 }
581
582 sr->arg.tcon.optional_support = SMB_SUPPORT_SEARCH_BITS;
583
575
576 ASSERT(user);
577
578 if ((user->u_flags & SMB_USER_FLAG_IPC) &&
579 sr->sr_cfg->skc_restrict_anon) {
580 smb_tree_log(sr, name, "access denied: restrict anonymous");
581 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRSRV, ERRaccess);
582 return (NULL);
583 }
584
585 sr->arg.tcon.optional_support = SMB_SUPPORT_SEARCH_BITS;
586
584 tree = smb_tree_alloc(user, name, name, STYPE_IPC, NULL, ACE_ALL_PERMS);
587 si = kmem_zalloc(sizeof (smb_share_t), KM_SLEEP);
588 (void) strlcpy(si->shr_name, name, MAXNAMELEN);
589 (void) strlcpy(si->shr_path, name, MAXPATHLEN);
590 si->shr_type = STYPE_IPC | STYPE_SPECIAL;
591
592 tree = smb_tree_alloc(user, si, STYPE_IPC, NULL, ACE_ALL_PERMS);
585 if (tree == NULL) {
586 smb_tree_log(sr, name, "access denied");
587 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRSRV, ERRaccess);
588 }
589
593 if (tree == NULL) {
594 smb_tree_log(sr, name, "access denied");
595 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRSRV, ERRaccess);
596 }
597
598 kmem_free(si, sizeof (smb_share_t));
590 return (tree);
591}
592
593/*
594 * Allocate a tree.
595 */
596static smb_tree_t *
597smb_tree_alloc(
598 smb_user_t *user,
599 return (tree);
600}
601
602/*
603 * Allocate a tree.
604 */
605static smb_tree_t *
606smb_tree_alloc(
607 smb_user_t *user,
599 const char *sharename,
600 const char *resource,
608 const smb_share_t *si,
601 int32_t stype,
602 smb_node_t *snode,
603 uint32_t access)
604{
605 smb_tree_t *tree;
606 uint16_t tid;
607
608 if (smb_idpool_alloc(&user->u_tid_pool, &tid))
609 return (NULL);
610
611 tree = kmem_cache_alloc(user->u_server->si_cache_tree, KM_SLEEP);
612 bzero(tree, sizeof (smb_tree_t));
613
614 if (STYPE_ISDSK(stype)) {
609 int32_t stype,
610 smb_node_t *snode,
611 uint32_t access)
612{
613 smb_tree_t *tree;
614 uint16_t tid;
615
616 if (smb_idpool_alloc(&user->u_tid_pool, &tid))
617 return (NULL);
618
619 tree = kmem_cache_alloc(user->u_server->si_cache_tree, KM_SLEEP);
620 bzero(tree, sizeof (smb_tree_t));
621
622 if (STYPE_ISDSK(stype)) {
615 if (smb_tree_getattr(snode, tree) != 0) {
623 if (smb_tree_getattr(si, snode, tree) != 0) {
616 smb_idpool_free(&user->u_tid_pool, tid);
617 kmem_cache_free(user->u_server->si_cache_tree, tree);
618 return (NULL);
619 }
620 }
621
622 if (smb_idpool_constructor(&tree->t_fid_pool)) {
623 smb_idpool_free(&user->u_tid_pool, tid);

--- 9 unchanged lines hidden (view full) ---

633 }
634
635 smb_llist_constructor(&tree->t_ofile_list, sizeof (smb_ofile_t),
636 offsetof(smb_ofile_t, f_lnd));
637
638 smb_llist_constructor(&tree->t_odir_list, sizeof (smb_odir_t),
639 offsetof(smb_odir_t, d_lnd));
640
624 smb_idpool_free(&user->u_tid_pool, tid);
625 kmem_cache_free(user->u_server->si_cache_tree, tree);
626 return (NULL);
627 }
628 }
629
630 if (smb_idpool_constructor(&tree->t_fid_pool)) {
631 smb_idpool_free(&user->u_tid_pool, tid);

--- 9 unchanged lines hidden (view full) ---

641 }
642
643 smb_llist_constructor(&tree->t_ofile_list, sizeof (smb_ofile_t),
644 offsetof(smb_ofile_t, f_lnd));
645
646 smb_llist_constructor(&tree->t_odir_list, sizeof (smb_odir_t),
647 offsetof(smb_odir_t, d_lnd));
648
641 (void) strlcpy(tree->t_sharename, sharename,
649 (void) strlcpy(tree->t_sharename, si->shr_name,
642 sizeof (tree->t_sharename));
650 sizeof (tree->t_sharename));
643 (void) strlcpy(tree->t_resource, resource, sizeof (tree->t_resource));
651 (void) strlcpy(tree->t_resource, si->shr_path,
652 sizeof (tree->t_resource));
644
645 mutex_init(&tree->t_mutex, NULL, MUTEX_DEFAULT, NULL);
646
647 tree->t_user = user;
648 tree->t_session = user->u_session;
649 tree->t_server = user->u_server;
650 tree->t_refcnt = 1;
651 tree->t_tid = tid;

--- 66 unchanged lines hidden (view full) ---

718 kmem_cache_free(tree->t_server->si_cache_tree, tree);
719}
720
721/*
722 * Determine whether or not a tree is connected.
723 * This function must be called with the tree mutex held.
724 */
725static boolean_t
653
654 mutex_init(&tree->t_mutex, NULL, MUTEX_DEFAULT, NULL);
655
656 tree->t_user = user;
657 tree->t_session = user->u_session;
658 tree->t_server = user->u_server;
659 tree->t_refcnt = 1;
660 tree->t_tid = tid;

--- 66 unchanged lines hidden (view full) ---

727 kmem_cache_free(tree->t_server->si_cache_tree, tree);
728}
729
730/*
731 * Determine whether or not a tree is connected.
732 * This function must be called with the tree mutex held.
733 */
734static boolean_t
726smb_tree_is_connected(smb_tree_t *tree)
735smb_tree_is_connected_locked(smb_tree_t *tree)
727{
728 switch (tree->t_state) {
729 case SMB_TREE_STATE_CONNECTED:
730 return (B_TRUE);
731
732 case SMB_TREE_STATE_DISCONNECTING:
733 case SMB_TREE_STATE_DISCONNECTED:
734 /*

--- 96 unchanged lines hidden (view full) ---

831
832 return (-1);
833}
834
835/*
836 * Obtain the tree attributes: volume name, typename and flags.
837 */
838static int
736{
737 switch (tree->t_state) {
738 case SMB_TREE_STATE_CONNECTED:
739 return (B_TRUE);
740
741 case SMB_TREE_STATE_DISCONNECTING:
742 case SMB_TREE_STATE_DISCONNECTED:
743 /*

--- 96 unchanged lines hidden (view full) ---

840
841 return (-1);
842}
843
844/*
845 * Obtain the tree attributes: volume name, typename and flags.
846 */
847static int
839smb_tree_getattr(smb_node_t *node, smb_tree_t *tree)
848smb_tree_getattr(const smb_share_t *si, smb_node_t *node, smb_tree_t *tree)
840{
841 vfs_t *vfsp = SMB_NODE_VFS(node);
842
843 ASSERT(vfsp);
844
845 if (getvfs(&vfsp->vfs_fsid) != vfsp)
846 return (ESTALE);
847
848 smb_tree_get_volname(vfsp, tree);
849{
850 vfs_t *vfsp = SMB_NODE_VFS(node);
851
852 ASSERT(vfsp);
853
854 if (getvfs(&vfsp->vfs_fsid) != vfsp)
855 return (ESTALE);
856
857 smb_tree_get_volname(vfsp, tree);
849 smb_tree_get_flags(vfsp, tree);
858 smb_tree_get_flags(si, vfsp, tree);
850
851 VFS_RELE(vfsp);
852 return (0);
853}
854
855/*
856 * Extract the volume name.
857 */

--- 19 unchanged lines hidden (view full) ---

877/*
878 * Always set ACL support because the VFS will fake ACLs for file systems
879 * that don't support them.
880 *
881 * Some flags are dependent on the typename, which is also set up here.
882 * File system types are hardcoded in uts/common/os/vfs_conf.c.
883 */
884static void
859
860 VFS_RELE(vfsp);
861 return (0);
862}
863
864/*
865 * Extract the volume name.
866 */

--- 19 unchanged lines hidden (view full) ---

886/*
887 * Always set ACL support because the VFS will fake ACLs for file systems
888 * that don't support them.
889 *
890 * Some flags are dependent on the typename, which is also set up here.
891 * File system types are hardcoded in uts/common/os/vfs_conf.c.
892 */
893static void
885smb_tree_get_flags(vfs_t *vfsp, smb_tree_t *tree)
894smb_tree_get_flags(const smb_share_t *si, vfs_t *vfsp, smb_tree_t *tree)
886{
887 typedef struct smb_mtype {
888 char *mt_name;
889 size_t mt_namelen;
890 uint32_t mt_flags;
891 } smb_mtype_t;
892
893 static smb_mtype_t smb_mtype[] = {
894 { "zfs", 3, SMB_TREE_UNICODE_ON_DISK },
895 { "ufs", 3, SMB_TREE_UNICODE_ON_DISK },
896 { "nfs", 3, SMB_TREE_NFS_MOUNTED },
897 { "tmpfs", 5, SMB_TREE_NO_EXPORT }
898 };
899 smb_mtype_t *mtype;
900 char *name;
901 uint32_t flags = SMB_TREE_SUPPORTS_ACLS;
902 int i;
903
895{
896 typedef struct smb_mtype {
897 char *mt_name;
898 size_t mt_namelen;
899 uint32_t mt_flags;
900 } smb_mtype_t;
901
902 static smb_mtype_t smb_mtype[] = {
903 { "zfs", 3, SMB_TREE_UNICODE_ON_DISK },
904 { "ufs", 3, SMB_TREE_UNICODE_ON_DISK },
905 { "nfs", 3, SMB_TREE_NFS_MOUNTED },
906 { "tmpfs", 5, SMB_TREE_NO_EXPORT }
907 };
908 smb_mtype_t *mtype;
909 char *name;
910 uint32_t flags = SMB_TREE_SUPPORTS_ACLS;
911 int i;
912
913 if (si->shr_flags & SMB_SHRF_CATIA)
914 flags |= SMB_TREE_CATIA;
915
904 if (vfsp->vfs_flag & VFS_RDONLY)
905 flags |= SMB_TREE_READONLY;
906
907 if (vfsp->vfs_flag & VFS_XATTR)
908 flags |= SMB_TREE_STREAMS;
909
910 if (vfs_optionisset(vfsp, MNTOPT_NOATIME, NULL))
911 flags |= SMB_TREE_NO_ATIME;

--- 97 unchanged lines hidden (view full) ---

1009 }
1010 od = smb_llist_next(od_list, od);
1011 }
1012
1013 smb_llist_exit(od_list);
1014 return (od);
1015}
1016
916 if (vfsp->vfs_flag & VFS_RDONLY)
917 flags |= SMB_TREE_READONLY;
918
919 if (vfsp->vfs_flag & VFS_XATTR)
920 flags |= SMB_TREE_STREAMS;
921
922 if (vfs_optionisset(vfsp, MNTOPT_NOATIME, NULL))
923 flags |= SMB_TREE_NO_ATIME;

--- 97 unchanged lines hidden (view full) ---

1021 }
1022 od = smb_llist_next(od_list, od);
1023 }
1024
1025 smb_llist_exit(od_list);
1026 return (od);
1027}
1028
1029boolean_t
1030smb_tree_is_connected(smb_tree_t *tree)
1031{
1032 boolean_t rb;
1033
1034 mutex_enter(&tree->t_mutex);
1035 rb = smb_tree_is_connected_locked(tree);
1036 mutex_exit(&tree->t_mutex);
1037 return (rb);
1038}
1039
1017/*
1018 * smb_tree_get_odir
1019 *
1020 * Find the next open odir in the tree's list of odirs, and obtain
1021 * a hold on it. (A hold can only be obtained on an open odir.)
1022 * If the specified odir is NULL the search starts at the beginning
1023 * of the tree's odir list, otherwise the search starts after the
1024 * specified odir.

--- 59 unchanged lines hidden ---
1040/*
1041 * smb_tree_get_odir
1042 *
1043 * Find the next open odir in the tree's list of odirs, and obtain
1044 * a hold on it. (A hold can only be obtained on an open odir.)
1045 * If the specified odir is NULL the search starts at the beginning
1046 * of the tree's odir list, otherwise the search starts after the
1047 * specified odir.

--- 59 unchanged lines hidden ---