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 --- |