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 2017 Joyent, Inc.
26 */
27
28 #include <smbsrv/smb_door.h>
29 #include <smbsrv/smb_kproto.h>
30 #include <smbsrv/smb_ktypes.h>
31
32 typedef struct smb_unshare {
33 list_node_t us_lnd;
34 char us_sharename[MAXNAMELEN];
35 } smb_unshare_t;
36
37 static kmem_cache_t *smb_kshare_cache_share;
38 static kmem_cache_t *smb_kshare_cache_unexport;
39 kmem_cache_t *smb_kshare_cache_vfs;
40
41 static int smb_kshare_cmp(const void *, const void *);
42 static void smb_kshare_hold(const void *);
43 static boolean_t smb_kshare_rele(const void *);
44 static void smb_kshare_destroy(void *);
45 static char *smb_kshare_oemname(const char *);
46 static int smb_kshare_is_special(const char *);
47 static boolean_t smb_kshare_is_admin(const char *);
48 static smb_kshare_t *smb_kshare_decode(nvlist_t *);
49 static uint32_t smb_kshare_decode_bool(nvlist_t *, const char *, uint32_t);
50 static void smb_kshare_unexport_thread(smb_thread_t *, void *);
51 static int smb_kshare_export(smb_server_t *, smb_kshare_t *);
52 static int smb_kshare_unexport(smb_server_t *, const char *);
53 static int smb_kshare_export_trans(smb_server_t *, char *, char *, char *);
54 static void smb_kshare_csc_flags(smb_kshare_t *, const char *);
55
56 static boolean_t smb_export_isready(smb_server_t *);
57
58 #ifdef _KERNEL
59 static int smb_kshare_chk_dsrv_status(int, smb_dr_ctx_t *);
60 #endif /* _KERNEL */
61
62 static const smb_avl_nops_t smb_kshare_avlops = {
63 smb_kshare_cmp,
64 smb_kshare_hold,
65 smb_kshare_rele,
66 smb_kshare_destroy
67 };
68
69 #ifdef _KERNEL
70 /*
71 * This function is not MultiThread safe. The caller has to make sure only one
72 * thread calls this function.
73 */
74 door_handle_t
277 (void) smb_kshare_export_trans(sv, "vss$", SMB_VSS, "VSS");
278 }
279
280 /*
281 * This function is called when smb_server_t goes
282 * away which means SMB shares should not be made
283 * available to clients
284 */
285 void
286 smb_export_stop(smb_server_t *sv)
287 {
288 mutex_enter(&sv->sv_export.e_mutex);
289 if (!sv->sv_export.e_ready) {
290 mutex_exit(&sv->sv_export.e_mutex);
291 return;
292 }
293 sv->sv_export.e_ready = B_FALSE;
294 mutex_exit(&sv->sv_export.e_mutex);
295
296 smb_avl_destroy(&sv->sv_export.e_share_avl);
297 smb_vfs_rele_all(&sv->sv_export);
298 }
299
300 void
301 smb_kshare_g_init(void)
302 {
303 smb_kshare_cache_share = kmem_cache_create("smb_share_cache",
304 sizeof (smb_kshare_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
305
306 smb_kshare_cache_unexport = kmem_cache_create("smb_unexport_cache",
307 sizeof (smb_unshare_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
308
309 smb_kshare_cache_vfs = kmem_cache_create("smb_vfs_cache",
310 sizeof (smb_vfs_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
311 }
312
313 void
314 smb_kshare_init(smb_server_t *sv)
315 {
316
317 smb_llist_constructor(&sv->sv_export.e_vfs_list, sizeof (smb_vfs_t),
318 offsetof(smb_vfs_t, sv_lnd));
319
320 smb_slist_constructor(&sv->sv_export.e_unexport_list,
321 sizeof (smb_unshare_t), offsetof(smb_unshare_t, us_lnd));
322 }
323
324 int
325 smb_kshare_start(smb_server_t *sv)
326 {
327 smb_thread_init(&sv->sv_export.e_unexport_thread, "smb_kshare_unexport",
328 smb_kshare_unexport_thread, sv, smbsrv_base_pri);
329
330 return (smb_thread_start(&sv->sv_export.e_unexport_thread));
331 }
332
333 void
334 smb_kshare_stop(smb_server_t *sv)
335 {
336 smb_thread_stop(&sv->sv_export.e_unexport_thread);
337 smb_thread_destroy(&sv->sv_export.e_unexport_thread);
338 }
339
340 void
341 smb_kshare_fini(smb_server_t *sv)
342 {
343 smb_unshare_t *ux;
344
345 while ((ux = list_head(&sv->sv_export.e_unexport_list.sl_list))
346 != NULL) {
347 smb_slist_remove(&sv->sv_export.e_unexport_list, ux);
348 kmem_cache_free(smb_kshare_cache_unexport, ux);
349 }
350 smb_slist_destructor(&sv->sv_export.e_unexport_list);
351
352 smb_vfs_rele_all(&sv->sv_export);
353
354 smb_llist_destructor(&sv->sv_export.e_vfs_list);
355 }
356
357 void
358 smb_kshare_g_fini(void)
359 {
360 kmem_cache_destroy(smb_kshare_cache_unexport);
361 kmem_cache_destroy(smb_kshare_cache_share);
362 kmem_cache_destroy(smb_kshare_cache_vfs);
363 }
364
365 /*
366 * A list of shares in nvlist format can be sent down
367 * from userspace thourgh the IOCTL interface. The nvlist
368 * is unpacked here and all the shares in the list will
369 * be exported.
370 */
371 int
372 smb_kshare_export_list(smb_ioc_share_t *ioc)
373 {
374 smb_server_t *sv = NULL;
375 nvlist_t *shrlist = NULL;
376 nvlist_t *share;
377 nvpair_t *nvp;
378 smb_kshare_t *shr;
379 char *shrname;
380 int rc;
381
382 if ((rc = smb_server_lookup(&sv)) != 0)
666
667 key.shr_name = (char *)shrname;
668 shr = smb_avl_lookup(&sv->sv_export.e_share_avl, &key);
669 return (shr);
670 }
671
672 /*
673 * Releases the hold taken on the specified share object
674 */
675 void
676 smb_kshare_release(smb_server_t *sv, smb_kshare_t *shr)
677 {
678 ASSERT(shr);
679 ASSERT(shr->shr_magic == SMB_SHARE_MAGIC);
680
681 smb_avl_release(&sv->sv_export.e_share_avl, shr);
682 }
683
684 /*
685 * Add the given share in the specified server.
686 * If the share is a disk share, smb_vfs_hold() is
687 * invoked to ensure that there is a hold on the
688 * corresponding file system before the share is
689 * added to shares AVL.
690 *
691 * If the share is an Autohome share and it is
692 * already in the AVL only a reference count for
693 * that share is incremented.
694 */
695 static int
696 smb_kshare_export(smb_server_t *sv, smb_kshare_t *shr)
697 {
698 smb_avl_t *share_avl;
699 smb_kshare_t *auto_shr;
700 vnode_t *vp;
701 int rc = 0;
702
703 share_avl = &sv->sv_export.e_share_avl;
704
705 if (!STYPE_ISDSK(shr->shr_type)) {
706 if ((rc = smb_avl_add(share_avl, shr)) != 0) {
707 cmn_err(CE_WARN, "export[%s]: failed caching (%d)",
708 shr->shr_name, rc);
709 }
710
711 return (rc);
712 }
713
714 if ((auto_shr = smb_avl_lookup(share_avl, shr)) != NULL) {
715 if ((auto_shr->shr_flags & SMB_SHRF_AUTOHOME) == 0) {
716 smb_avl_release(share_avl, auto_shr);
717 return (EEXIST);
718 }
719
720 mutex_enter(&auto_shr->shr_mutex);
721 auto_shr->shr_autocnt++;
722 mutex_exit(&auto_shr->shr_mutex);
723 smb_avl_release(share_avl, auto_shr);
724 return (0);
725 }
726
727 if ((rc = smb_server_sharevp(sv, shr->shr_path, &vp)) != 0) {
728 cmn_err(CE_WARN, "export[%s(%s)]: failed obtaining vnode (%d)",
729 shr->shr_name, shr->shr_path, rc);
730 return (rc);
731 }
732
733 if ((rc = smb_vfs_hold(&sv->sv_export, vp->v_vfsp)) == 0) {
734 if ((rc = smb_avl_add(share_avl, shr)) != 0) {
735 cmn_err(CE_WARN, "export[%s]: failed caching (%d)",
736 shr->shr_name, rc);
737 smb_vfs_rele(&sv->sv_export, vp->v_vfsp);
738 }
739 } else {
740 cmn_err(CE_WARN, "export[%s(%s)]: failed holding VFS (%d)",
741 shr->shr_name, shr->shr_path, rc);
742 }
743
744 VN_RELE(vp);
745 return (rc);
746 }
747
748 /*
749 * Removes the share specified by 'shrname' from the AVL
750 * tree of the given server if it's there.
751 *
752 * If the share is an Autohome share, the autohome count
753 * is decremented and the share is only removed if the
754 * count goes to zero.
755 *
756 * If the share is a disk share, the hold on the corresponding
757 * file system is released before removing the share from
758 * the AVL tree.
759 */
760 static int
761 smb_kshare_unexport(smb_server_t *sv, const char *shrname)
762 {
763 smb_avl_t *share_avl;
764 smb_kshare_t key;
765 smb_kshare_t *shr;
766 vnode_t *vp;
767 int rc;
768 boolean_t auto_unexport;
769
770 share_avl = &sv->sv_export.e_share_avl;
771
772 key.shr_name = (char *)shrname;
773 if ((shr = smb_avl_lookup(share_avl, &key)) == NULL)
774 return (ENOENT);
775
776 if ((shr->shr_flags & SMB_SHRF_AUTOHOME) != 0) {
777 mutex_enter(&shr->shr_mutex);
778 shr->shr_autocnt--;
779 auto_unexport = (shr->shr_autocnt == 0);
780 mutex_exit(&shr->shr_mutex);
781 if (!auto_unexport) {
782 smb_avl_release(share_avl, shr);
783 return (0);
784 }
785 }
786
787 if (STYPE_ISDSK(shr->shr_type)) {
788 if ((rc = smb_server_sharevp(sv, shr->shr_path, &vp)) != 0) {
789 smb_avl_release(share_avl, shr);
790 cmn_err(CE_WARN, "unexport[%s]: failed obtaining vnode"
791 " (%d)", shrname, rc);
792 return (rc);
793 }
794
795 smb_vfs_rele(&sv->sv_export, vp->v_vfsp);
796 VN_RELE(vp);
797 }
798
799 smb_avl_remove(share_avl, shr);
800 smb_avl_release(share_avl, shr);
801
802 return (0);
803 }
804
805 /*
806 * Exports IPC$ or Admin shares
807 */
808 static int
809 smb_kshare_export_trans(smb_server_t *sv, char *name, char *path, char *cmnt)
810 {
811 smb_kshare_t *shr;
812
813 ASSERT(name);
814 ASSERT(path);
815
816 shr = kmem_cache_alloc(smb_kshare_cache_share, KM_SLEEP);
817 bzero(shr, sizeof (smb_kshare_t));
818
819 shr->shr_magic = SMB_SHARE_MAGIC;
832 if (cmnt)
833 shr->shr_cmnt = smb_mem_strdup(cmnt);
834 shr->shr_oemname = smb_kshare_oemname(name);
835
836 return (smb_kshare_export(sv, shr));
837 }
838
839 /*
840 * Decodes share information in an nvlist format into a smb_kshare_t
841 * structure.
842 *
843 * This is a temporary function and will be replaced by functions
844 * provided by libsharev2 code after it's available.
845 */
846 static smb_kshare_t *
847 smb_kshare_decode(nvlist_t *share)
848 {
849 smb_kshare_t tmp;
850 smb_kshare_t *shr;
851 nvlist_t *smb;
852 char *csc_name = NULL;
853 int rc;
854
855 ASSERT(share);
856
857 bzero(&tmp, sizeof (smb_kshare_t));
858
859 rc = nvlist_lookup_string(share, "name", &tmp.shr_name);
860 rc |= nvlist_lookup_string(share, "path", &tmp.shr_path);
861 (void) nvlist_lookup_string(share, "desc", &tmp.shr_cmnt);
862
863 ASSERT(tmp.shr_name && tmp.shr_path);
864
865 rc |= nvlist_lookup_nvlist(share, "smb", &smb);
866 if (rc != 0) {
867 cmn_err(CE_WARN, "kshare: failed looking up SMB properties"
868 " (%d)", rc);
869 return (NULL);
870 }
871
872 rc = nvlist_lookup_uint32(smb, "type", &tmp.shr_type);
873 if (rc != 0) {
874 cmn_err(CE_WARN, "kshare[%s]: failed getting the share type"
875 " (%d)", tmp.shr_name, rc);
876 return (NULL);
877 }
878
879 (void) nvlist_lookup_string(smb, SHOPT_AD_CONTAINER,
880 &tmp.shr_container);
881 (void) nvlist_lookup_string(smb, SHOPT_NONE, &tmp.shr_access_none);
882 (void) nvlist_lookup_string(smb, SHOPT_RO, &tmp.shr_access_ro);
883 (void) nvlist_lookup_string(smb, SHOPT_RW, &tmp.shr_access_rw);
884
885 tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_ABE, SMB_SHRF_ABE);
886 tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_CATIA,
887 SMB_SHRF_CATIA);
888 tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_GUEST,
889 SMB_SHRF_GUEST_OK);
890 tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_DFSROOT,
891 SMB_SHRF_DFSROOT);
892 tmp.shr_flags |= smb_kshare_decode_bool(smb, "Autohome",
893 SMB_SHRF_AUTOHOME);
894
895 if ((tmp.shr_flags & SMB_SHRF_AUTOHOME) == SMB_SHRF_AUTOHOME) {
896 rc = nvlist_lookup_uint32(smb, "uid", &tmp.shr_uid);
897 rc |= nvlist_lookup_uint32(smb, "gid", &tmp.shr_gid);
898 if (rc != 0) {
899 cmn_err(CE_WARN, "kshare: failed looking up uid/gid"
900 " (%d)", rc);
901 return (NULL);
902 }
903 }
904
905 (void) nvlist_lookup_string(smb, SHOPT_CSC, &csc_name);
906 smb_kshare_csc_flags(&tmp, csc_name);
907
908 shr = kmem_cache_alloc(smb_kshare_cache_share, KM_SLEEP);
909 bzero(shr, sizeof (smb_kshare_t));
910
911 shr->shr_magic = SMB_SHARE_MAGIC;
912 shr->shr_refcnt = 1;
913
914 shr->shr_name = smb_mem_strdup(tmp.shr_name);
915 shr->shr_path = smb_mem_strdup(tmp.shr_path);
916 if (tmp.shr_cmnt)
917 shr->shr_cmnt = smb_mem_strdup(tmp.shr_cmnt);
918 if (tmp.shr_container)
919 shr->shr_container = smb_mem_strdup(tmp.shr_container);
920 if (tmp.shr_access_none)
921 shr->shr_access_none = smb_mem_strdup(tmp.shr_access_none);
922 if (tmp.shr_access_ro)
923 shr->shr_access_ro = smb_mem_strdup(tmp.shr_access_ro);
924 if (tmp.shr_access_rw)
925 shr->shr_access_rw = smb_mem_strdup(tmp.shr_access_rw);
926
927 shr->shr_oemname = smb_kshare_oemname(shr->shr_name);
928 shr->shr_flags = tmp.shr_flags | smb_kshare_is_admin(shr->shr_name);
929 shr->shr_type = tmp.shr_type | smb_kshare_is_special(shr->shr_name);
930
931 shr->shr_uid = tmp.shr_uid;
932 shr->shr_gid = tmp.shr_gid;
933
934 if ((shr->shr_flags & SMB_SHRF_AUTOHOME) == SMB_SHRF_AUTOHOME)
935 shr->shr_autocnt = 1;
936
937 return (shr);
938 }
939
940 #if 0
941 static void
942 smb_kshare_log(smb_kshare_t *shr)
943 {
944 cmn_err(CE_NOTE, "Share info:");
945 cmn_err(CE_NOTE, "\tname: %s", (shr->shr_name) ? shr->shr_name : "");
946 cmn_err(CE_NOTE, "\tpath: %s", (shr->shr_path) ? shr->shr_path : "");
947 cmn_err(CE_NOTE, "\tcmnt: (%s)",
948 (shr->shr_cmnt) ? shr->shr_cmnt : "NULL");
949 cmn_err(CE_NOTE, "\toemname: (%s)",
950 (shr->shr_oemname) ? shr->shr_oemname : "NULL");
951 cmn_err(CE_NOTE, "\tflags: %X", shr->shr_flags);
952 cmn_err(CE_NOTE, "\ttype: %d", shr->shr_type);
953 }
954 #endif
955
956 /*
1016 shr->shr_refcnt--;
1017 destroy = (shr->shr_refcnt == 0);
1018 mutex_exit(&shr->shr_mutex);
1019
1020 return (destroy);
1021 }
1022
1023 /*
1024 * Frees all the memory allocated for the given
1025 * share structure. It also removes the structure
1026 * from the share cache.
1027 */
1028 static void
1029 smb_kshare_destroy(void *p)
1030 {
1031 smb_kshare_t *shr = (smb_kshare_t *)p;
1032
1033 ASSERT(shr);
1034 ASSERT(shr->shr_magic == SMB_SHARE_MAGIC);
1035
1036 smb_mem_free(shr->shr_name);
1037 smb_mem_free(shr->shr_path);
1038 smb_mem_free(shr->shr_cmnt);
1039 smb_mem_free(shr->shr_container);
1040 smb_mem_free(shr->shr_oemname);
1041 smb_mem_free(shr->shr_access_none);
1042 smb_mem_free(shr->shr_access_ro);
1043 smb_mem_free(shr->shr_access_rw);
1044
1045 kmem_cache_free(smb_kshare_cache_share, shr);
1046 }
1047
1048
1049 /*
1050 * Generate an OEM name for the given share name. If the name is
1051 * shorter than 13 bytes the oemname will be returned; otherwise NULL
1052 * is returned.
1053 */
1054 static char *
1055 smb_kshare_oemname(const char *shrname)
|
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 2017 Nexenta Systems, Inc. All rights reserved.
25 * Copyright 2017 Joyent, Inc.
26 */
27
28 #include <smbsrv/smb_door.h>
29 #include <smbsrv/smb_ktypes.h>
30 #include <smbsrv/smb2_kproto.h>
31 #include <smbsrv/smb_kstat.h>
32
33 typedef struct smb_unshare {
34 list_node_t us_lnd;
35 char us_sharename[MAXNAMELEN];
36 } smb_unshare_t;
37
38 static kmem_cache_t *smb_kshare_cache_share;
39 static kmem_cache_t *smb_kshare_cache_unexport;
40
41 static int smb_kshare_cmp(const void *, const void *);
42 static void smb_kshare_hold(const void *);
43 static boolean_t smb_kshare_rele(const void *);
44 static void smb_kshare_destroy(void *);
45 static char *smb_kshare_oemname(const char *);
46 static int smb_kshare_is_special(const char *);
47 static boolean_t smb_kshare_is_admin(const char *);
48 static smb_kshare_t *smb_kshare_decode(nvlist_t *);
49 static uint32_t smb_kshare_decode_bool(nvlist_t *, const char *, uint32_t);
50 static void smb_kshare_unexport_thread(smb_thread_t *, void *);
51 static int smb_kshare_export(smb_server_t *, smb_kshare_t *);
52 static int smb_kshare_unexport(smb_server_t *, const char *);
53 static int smb_kshare_export_trans(smb_server_t *, char *, char *, char *);
54 static void smb_kshare_csc_flags(smb_kshare_t *, const char *);
55 static int smb_named_kstat_update(kstat_t *ks, int rw);
56 static int smb_kshare_kstat_update(kstat_t *, int);
57 void kshare_stats_init(smb_server_t *, smb_kshare_t *);
58 void kshare_stats_fini(smb_kshare_t *);
59
60 static boolean_t smb_export_isready(smb_server_t *);
61
62 #ifdef _KERNEL
63 static int smb_kshare_chk_dsrv_status(int, smb_dr_ctx_t *);
64 #endif /* _KERNEL */
65
66 static const smb_avl_nops_t smb_kshare_avlops = {
67 smb_kshare_cmp,
68 smb_kshare_hold,
69 smb_kshare_rele,
70 smb_kshare_destroy
71 };
72
73 #ifdef _KERNEL
74 /*
75 * This function is not MultiThread safe. The caller has to make sure only one
76 * thread calls this function.
77 */
78 door_handle_t
281 (void) smb_kshare_export_trans(sv, "vss$", SMB_VSS, "VSS");
282 }
283
284 /*
285 * This function is called when smb_server_t goes
286 * away which means SMB shares should not be made
287 * available to clients
288 */
289 void
290 smb_export_stop(smb_server_t *sv)
291 {
292 mutex_enter(&sv->sv_export.e_mutex);
293 if (!sv->sv_export.e_ready) {
294 mutex_exit(&sv->sv_export.e_mutex);
295 return;
296 }
297 sv->sv_export.e_ready = B_FALSE;
298 mutex_exit(&sv->sv_export.e_mutex);
299
300 smb_avl_destroy(&sv->sv_export.e_share_avl);
301 }
302
303 void
304 smb_kshare_g_init(void)
305 {
306 smb_kshare_cache_share = kmem_cache_create("smb_share_cache",
307 sizeof (smb_kshare_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
308
309 smb_kshare_cache_unexport = kmem_cache_create("smb_unexport_cache",
310 sizeof (smb_unshare_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
311 }
312
313 void
314 smb_kshare_init(smb_server_t *sv)
315 {
316
317 smb_slist_constructor(&sv->sv_export.e_unexport_list,
318 sizeof (smb_unshare_t), offsetof(smb_unshare_t, us_lnd));
319 }
320
321 int
322 smb_kshare_start(smb_server_t *sv)
323 {
324 smb_thread_init(&sv->sv_export.e_unexport_thread, "smb_kshare_unexport",
325 smb_kshare_unexport_thread, sv, smbsrv_base_pri);
326
327 return (smb_thread_start(&sv->sv_export.e_unexport_thread));
328 }
329
330 void
331 smb_kshare_stop(smb_server_t *sv)
332 {
333 smb_thread_stop(&sv->sv_export.e_unexport_thread);
334 smb_thread_destroy(&sv->sv_export.e_unexport_thread);
335 }
336
337 void
338 smb_kshare_fini(smb_server_t *sv)
339 {
340 smb_unshare_t *ux;
341
342 while ((ux = list_head(&sv->sv_export.e_unexport_list.sl_list))
343 != NULL) {
344 smb_slist_remove(&sv->sv_export.e_unexport_list, ux);
345 kmem_cache_free(smb_kshare_cache_unexport, ux);
346 }
347 smb_slist_destructor(&sv->sv_export.e_unexport_list);
348 }
349
350 void
351 smb_kshare_g_fini(void)
352 {
353 kmem_cache_destroy(smb_kshare_cache_unexport);
354 kmem_cache_destroy(smb_kshare_cache_share);
355 }
356
357 /*
358 * A list of shares in nvlist format can be sent down
359 * from userspace thourgh the IOCTL interface. The nvlist
360 * is unpacked here and all the shares in the list will
361 * be exported.
362 */
363 int
364 smb_kshare_export_list(smb_ioc_share_t *ioc)
365 {
366 smb_server_t *sv = NULL;
367 nvlist_t *shrlist = NULL;
368 nvlist_t *share;
369 nvpair_t *nvp;
370 smb_kshare_t *shr;
371 char *shrname;
372 int rc;
373
374 if ((rc = smb_server_lookup(&sv)) != 0)
658
659 key.shr_name = (char *)shrname;
660 shr = smb_avl_lookup(&sv->sv_export.e_share_avl, &key);
661 return (shr);
662 }
663
664 /*
665 * Releases the hold taken on the specified share object
666 */
667 void
668 smb_kshare_release(smb_server_t *sv, smb_kshare_t *shr)
669 {
670 ASSERT(shr);
671 ASSERT(shr->shr_magic == SMB_SHARE_MAGIC);
672
673 smb_avl_release(&sv->sv_export.e_share_avl, shr);
674 }
675
676 /*
677 * Add the given share in the specified server.
678 * If the share is a disk share, lookup the share path
679 * and hold the smb_node_t for the share root.
680 *
681 * If the share is an Autohome share and it is
682 * already in the AVL only a reference count for
683 * that share is incremented.
684 */
685 static int
686 smb_kshare_export(smb_server_t *sv, smb_kshare_t *shr)
687 {
688 smb_avl_t *share_avl;
689 smb_kshare_t *auto_shr;
690 smb_node_t *snode = NULL;
691 int rc = 0;
692
693 share_avl = &sv->sv_export.e_share_avl;
694
695 if (!STYPE_ISDSK(shr->shr_type)) {
696 if ((rc = smb_avl_add(share_avl, shr)) != 0) {
697 cmn_err(CE_WARN, "export[%s]: failed caching (%d)",
698 shr->shr_name, rc);
699 }
700
701 return (rc);
702 }
703
704 if ((auto_shr = smb_avl_lookup(share_avl, shr)) != NULL) {
705 rc = EEXIST;
706 if ((auto_shr->shr_flags & SMB_SHRF_AUTOHOME) != 0) {
707 mutex_enter(&auto_shr->shr_mutex);
708 auto_shr->shr_autocnt++;
709 mutex_exit(&auto_shr->shr_mutex);
710 rc = 0;
711 }
712 smb_avl_release(share_avl, auto_shr);
713 return (rc);
714 }
715
716 /*
717 * Get the root smb_node_t for this share, held.
718 * This hold is normally released during AVL destroy,
719 * via the element destructor: smb_kshare_destroy
720 */
721 rc = smb_server_share_lookup(sv, shr->shr_path, &snode);
722 if (rc != 0) {
723 cmn_err(CE_WARN, "export[%s(%s)]: lookup failed (%d)",
724 shr->shr_name, shr->shr_path, rc);
725 return (rc);
726 }
727
728 shr->shr_root_node = snode;
729 if ((rc = smb_avl_add(share_avl, shr)) != 0) {
730 cmn_err(CE_WARN, "export[%s]: failed caching (%d)",
731 shr->shr_name, rc);
732 shr->shr_root_node = NULL;
733 smb_node_release(snode);
734 return (rc);
735 }
736
737 kshare_stats_init(sv, shr);
738
739 /*
740 * For CA shares, find or create the CA handle dir,
741 * and (if restarted) import persistent handles.
742 */
743 if ((shr->shr_flags & SMB_SHRF_CA) != 0) {
744 rc = smb2_dh_new_ca_share(sv, shr);
745 if (rc != 0) {
746 /* Just make it a non-CA share. */
747 mutex_enter(&shr->shr_mutex);
748 shr->shr_flags &= ~SMB_SHRF_CA;
749 mutex_exit(&shr->shr_mutex);
750 rc = 0;
751 }
752 }
753
754 return (rc);
755 }
756
757
758 /*
759 * Following a pattern somewhat similar to smb_server_kstat_init,
760 * but organized a little differently.
761 */
762 void
763 kshare_stats_init(smb_server_t *sv, smb_kshare_t *ks)
764 {
765 static const char *kr_names[] = SMBSRV_CLSH__NAMES;
766 char ks_name[KSTAT_STRLEN];
767 smbsrv_clsh_kstats_t *ksr;
768 int idx;
769 smb_named_stats_t *smbnsp;
770 kstat_t *kstat = NULL;
771 int namelen;
772
773 /*
774 * Most share names are short, and we'd like to allow consumers like
775 * the smbstat command to compose the kstat names for short share names
776 * directly. In the (rare) case where we have longer share names, we
777 * need an indirection scheme to get around the limited (31 chars) size
778 * of kstat names. So for share names 24 chars or shorter, we compose
779 * the kstat name directly as "smbsrv:0:sh/sharename" and when the share
780 * name is longer, compose the kstat name using an arbitrary
781 * (but unique) identifier like: "smbsrv:0:sh/:ffffff0009560a98". To
782 * find the unique identifier given a (long) share name, the consumer
783 * has to enumerate the (fake) "smbsrvshr" kstat module, looking for the
784 * kstat with the sharename element matching the one they want. Both
785 * direct and indirect names are instantiated under the "smbsrvshr"
786 * module, so a consumer that wants all the share kstats could always
787 * lookup the kstat names using the indirection scheme if that's easier.
788 * (Nothing forces the consumer to directly compose kstat names when the
789 * share name happens to be short -- they can always enumerate to find
790 * it.)
791 *
792 * SMB share names are not allowed to contain a colon. The naming
793 * scheme here uses a colon at the beginning of what would otherwise be
794 * the share name part of the kstat name to indicate that this name uses
795 * the "indirection" scheme. With indirection, the part after the colon
796 * is an arbitrary (but unique per share) identifier of some other
797 * kstat, and a consumer needs to fetch that kstat to get the real share
798 * name.
799 */
800 namelen = strlen(ks->shr_name);
801 if (namelen <= 24) {
802 (void) snprintf(ks_name, sizeof (ks_name), "sh/%s",
803 ks->shr_name);
804
805 kstat = kstat_hold_byname("smbsrvshr", 0, ks_name, sv->sv_zid);
806 }
807
808 if (namelen > 24 || kstat != NULL) {
809 (void) snprintf(ks_name, sizeof (ks_name), "sh/:%p",
810 (void *)ks);
811
812 if (kstat != NULL)
813 kstat_rele(kstat);
814 }
815
816 ks->shr_ksp = kstat_create_zone(SMBSRV_KSTAT_MODULE, 0,
817 ks_name, SMBSRV_KSTAT_CLASS, KSTAT_TYPE_RAW,
818 sizeof (smbsrv_clsh_kstats_t), 0, sv->sv_zid);
819
820 if (ks->shr_ksp == NULL)
821 return;
822
823 ks->stats.ksns = kstat_create_zone("smbsrvshr", 0,
824 ks_name, SMBSRV_KSTAT_CLASS, KSTAT_TYPE_NAMED,
825 0, KSTAT_FLAG_VIRTUAL, sv->sv_zid);
826
827 if (ks->stats.ksns == NULL) {
828 kstat_delete(ks->shr_ksp);
829 ks->shr_ksp = NULL;
830 return;
831 }
832
833 ks->shr_ksp->ks_update = smb_kshare_kstat_update;
834 ks->shr_ksp->ks_private = ks;
835
836 /*
837 * In-line equivalent of smb_dispatch_stats_init
838 */
839 ksr = (smbsrv_clsh_kstats_t *)ks->shr_ksp->ks_data;
840 for (idx = 0; idx < SMBSRV_CLSH__NREQ; idx++) {
841 smb_latency_init(&ks->shr_stats[idx].sdt_lat);
842 (void) strlcpy(ksr->ks_clsh[idx].kr_name, kr_names[idx],
843 KSTAT_STRLEN);
844 }
845
846 /*
847 * SMB named kstats setup for > KSTAT_STRLEN name to short name mapping.
848 */
849 smbnsp = &ks->stats.ks_data;
850 ks->stats.ksns->ks_data = &ks->stats.ks_data;
851 ks->stats.ksns->ks_data_size = sizeof (ks->stats.ks_data);
852 ks->stats.ksns->ks_ndata = 1;
853 kstat_named_init(smbnsp->kn, "share name",
854 KSTAT_DATA_STRING);
855 ks->stats.ksns->ks_update = smb_named_kstat_update;
856 ks->stats.ksns->ks_private = (void *)ks;
857
858 kstat_install(ks->shr_ksp);
859 kstat_install(ks->stats.ksns);
860 }
861
862 void
863 kshare_stats_fini(smb_kshare_t *ks)
864 {
865 int idx;
866
867 for (idx = 0; idx < SMBSRV_CLSH__NREQ; idx++)
868 smb_latency_destroy(&ks->shr_stats[idx].sdt_lat);
869 }
870
871 static int
872 smb_named_kstat_update(kstat_t *ks, int rw)
873 {
874 smb_kshare_t *smbksp = (smb_kshare_t *)ks->ks_private;
875 smb_named_stats_t *smbnsp = &smbksp->stats.ks_data;
876
877 if (rw == KSTAT_READ) {
878 (void) strlcpy(smbnsp->name, smbksp->shr_name,
879 sizeof (smbnsp->name));
880
881 kstat_named_setstr(&smbnsp->kn[0],
882 (const char *)smbksp->shr_name);
883 }
884 return (0);
885 }
886
887 /*
888 * Update the kstat data from our private stats.
889 */
890 static int
891 smb_kshare_kstat_update(kstat_t *ksp, int rw)
892 {
893 smb_kshare_t *kshare;
894 smb_disp_stats_t *sds;
895 smbsrv_clsh_kstats_t *clsh;
896 smb_kstat_req_t *ksr;
897 int i;
898
899 if (rw == KSTAT_WRITE)
900 return (EACCES);
901
902 kshare = ksp->ks_private;
903 ASSERT(kshare->shr_magic == SMB_SHARE_MAGIC);
904 sds = kshare->shr_stats;
905
906 clsh = (smbsrv_clsh_kstats_t *)ksp->ks_data;
907 ksr = clsh->ks_clsh;
908
909 for (i = 0; i < SMBSRV_CLSH__NREQ; i++, ksr++, sds++) {
910 ksr->kr_rxb = sds->sdt_rxb;
911 ksr->kr_txb = sds->sdt_txb;
912 mutex_enter(&sds->sdt_lat.ly_mutex);
913 ksr->kr_nreq = sds->sdt_lat.ly_a_nreq;
914 ksr->kr_sum = sds->sdt_lat.ly_a_sum;
915 ksr->kr_a_mean = sds->sdt_lat.ly_a_mean;
916 ksr->kr_a_stddev = sds->sdt_lat.ly_a_stddev;
917 ksr->kr_d_mean = sds->sdt_lat.ly_d_mean;
918 ksr->kr_d_stddev = sds->sdt_lat.ly_d_stddev;
919 sds->sdt_lat.ly_d_mean = 0;
920 sds->sdt_lat.ly_d_nreq = 0;
921 sds->sdt_lat.ly_d_stddev = 0;
922 sds->sdt_lat.ly_d_sum = 0;
923 mutex_exit(&sds->sdt_lat.ly_mutex);
924 }
925
926 return (0);
927 }
928
929 /*
930 * Removes the share specified by 'shrname' from the AVL
931 * tree of the given server if it's there.
932 *
933 * If the share is an Autohome share, the autohome count
934 * is decremented and the share is only removed if the
935 * count goes to zero.
936 *
937 * If the share is a disk share, the hold on the corresponding
938 * file system is released before removing the share from
939 * the AVL tree.
940 */
941 static int
942 smb_kshare_unexport(smb_server_t *sv, const char *shrname)
943 {
944 smb_avl_t *share_avl;
945 smb_kshare_t key;
946 smb_kshare_t *shr;
947 boolean_t auto_unexport;
948
949 share_avl = &sv->sv_export.e_share_avl;
950
951 key.shr_name = (char *)shrname;
952 if ((shr = smb_avl_lookup(share_avl, &key)) == NULL)
953 return (ENOENT);
954
955 if ((shr->shr_flags & SMB_SHRF_AUTOHOME) != 0) {
956 mutex_enter(&shr->shr_mutex);
957 shr->shr_autocnt--;
958 auto_unexport = (shr->shr_autocnt == 0);
959 mutex_exit(&shr->shr_mutex);
960 if (!auto_unexport) {
961 smb_avl_release(share_avl, shr);
962 return (0);
963 }
964 }
965
966 smb_avl_remove(share_avl, shr);
967
968 mutex_enter(&shr->shr_mutex);
969 shr->shr_flags |= SMB_SHRF_REMOVED;
970 mutex_exit(&shr->shr_mutex);
971
972 smb_avl_release(share_avl, shr);
973
974 return (0);
975 }
976
977 /*
978 * Exports IPC$ or Admin shares
979 */
980 static int
981 smb_kshare_export_trans(smb_server_t *sv, char *name, char *path, char *cmnt)
982 {
983 smb_kshare_t *shr;
984
985 ASSERT(name);
986 ASSERT(path);
987
988 shr = kmem_cache_alloc(smb_kshare_cache_share, KM_SLEEP);
989 bzero(shr, sizeof (smb_kshare_t));
990
991 shr->shr_magic = SMB_SHARE_MAGIC;
1004 if (cmnt)
1005 shr->shr_cmnt = smb_mem_strdup(cmnt);
1006 shr->shr_oemname = smb_kshare_oemname(name);
1007
1008 return (smb_kshare_export(sv, shr));
1009 }
1010
1011 /*
1012 * Decodes share information in an nvlist format into a smb_kshare_t
1013 * structure.
1014 *
1015 * This is a temporary function and will be replaced by functions
1016 * provided by libsharev2 code after it's available.
1017 */
1018 static smb_kshare_t *
1019 smb_kshare_decode(nvlist_t *share)
1020 {
1021 smb_kshare_t tmp;
1022 smb_kshare_t *shr;
1023 nvlist_t *smb;
1024 char *csc_name = NULL, *strbuf = NULL;
1025 int rc;
1026
1027 ASSERT(share);
1028
1029 bzero(&tmp, sizeof (smb_kshare_t));
1030
1031 rc = nvlist_lookup_string(share, "name", &tmp.shr_name);
1032 rc |= nvlist_lookup_string(share, "path", &tmp.shr_path);
1033 (void) nvlist_lookup_string(share, "desc", &tmp.shr_cmnt);
1034
1035 ASSERT(tmp.shr_name && tmp.shr_path);
1036
1037 rc |= nvlist_lookup_nvlist(share, "smb", &smb);
1038 if (rc != 0) {
1039 cmn_err(CE_WARN, "kshare: failed looking up SMB properties"
1040 " (%d)", rc);
1041 return (NULL);
1042 }
1043
1044 rc = nvlist_lookup_uint32(smb, "type", &tmp.shr_type);
1045 if (rc != 0) {
1046 cmn_err(CE_WARN, "kshare[%s]: failed getting the share type"
1047 " (%d)", tmp.shr_name, rc);
1048 return (NULL);
1049 }
1050
1051 (void) nvlist_lookup_string(smb, SHOPT_AD_CONTAINER,
1052 &tmp.shr_container);
1053 (void) nvlist_lookup_string(smb, SHOPT_NONE, &tmp.shr_access_none);
1054 (void) nvlist_lookup_string(smb, SHOPT_RO, &tmp.shr_access_ro);
1055 (void) nvlist_lookup_string(smb, SHOPT_RW, &tmp.shr_access_rw);
1056
1057 tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_ABE, SMB_SHRF_ABE);
1058 tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_CATIA,
1059 SMB_SHRF_CATIA);
1060 tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_GUEST,
1061 SMB_SHRF_GUEST_OK);
1062 tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_DFSROOT,
1063 SMB_SHRF_DFSROOT);
1064 tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_QUOTAS,
1065 SMB_SHRF_QUOTAS);
1066 tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_CA, SMB_SHRF_CA);
1067 tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_FSO, SMB_SHRF_FSO);
1068 tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_AUTOHOME,
1069 SMB_SHRF_AUTOHOME);
1070
1071 if ((tmp.shr_flags & SMB_SHRF_AUTOHOME) == SMB_SHRF_AUTOHOME) {
1072 rc = nvlist_lookup_uint32(smb, "uid", &tmp.shr_uid);
1073 rc |= nvlist_lookup_uint32(smb, "gid", &tmp.shr_gid);
1074 if (rc != 0) {
1075 cmn_err(CE_WARN, "kshare: failed looking up uid/gid"
1076 " (%d)", rc);
1077 return (NULL);
1078 }
1079 }
1080
1081 (void) nvlist_lookup_string(smb, SHOPT_ENCRYPT, &strbuf);
1082 smb_cfg_set_require(strbuf, &tmp.shr_encrypt);
1083
1084 (void) nvlist_lookup_string(smb, SHOPT_CSC, &csc_name);
1085 smb_kshare_csc_flags(&tmp, csc_name);
1086
1087 shr = kmem_cache_alloc(smb_kshare_cache_share, KM_SLEEP);
1088 bzero(shr, sizeof (smb_kshare_t));
1089
1090 shr->shr_magic = SMB_SHARE_MAGIC;
1091 shr->shr_refcnt = 1;
1092
1093 shr->shr_name = smb_mem_strdup(tmp.shr_name);
1094 shr->shr_path = smb_mem_strdup(tmp.shr_path);
1095 if (tmp.shr_cmnt)
1096 shr->shr_cmnt = smb_mem_strdup(tmp.shr_cmnt);
1097 if (tmp.shr_container)
1098 shr->shr_container = smb_mem_strdup(tmp.shr_container);
1099 if (tmp.shr_access_none)
1100 shr->shr_access_none = smb_mem_strdup(tmp.shr_access_none);
1101 if (tmp.shr_access_ro)
1102 shr->shr_access_ro = smb_mem_strdup(tmp.shr_access_ro);
1103 if (tmp.shr_access_rw)
1104 shr->shr_access_rw = smb_mem_strdup(tmp.shr_access_rw);
1105
1106 shr->shr_oemname = smb_kshare_oemname(shr->shr_name);
1107 shr->shr_flags = tmp.shr_flags | smb_kshare_is_admin(shr->shr_name);
1108 shr->shr_type = tmp.shr_type | smb_kshare_is_special(shr->shr_name);
1109 shr->shr_encrypt = tmp.shr_encrypt;
1110
1111 shr->shr_uid = tmp.shr_uid;
1112 shr->shr_gid = tmp.shr_gid;
1113
1114 if ((shr->shr_flags & SMB_SHRF_AUTOHOME) == SMB_SHRF_AUTOHOME)
1115 shr->shr_autocnt = 1;
1116 return (shr);
1117 }
1118
1119 #if 0
1120 static void
1121 smb_kshare_log(smb_kshare_t *shr)
1122 {
1123 cmn_err(CE_NOTE, "Share info:");
1124 cmn_err(CE_NOTE, "\tname: %s", (shr->shr_name) ? shr->shr_name : "");
1125 cmn_err(CE_NOTE, "\tpath: %s", (shr->shr_path) ? shr->shr_path : "");
1126 cmn_err(CE_NOTE, "\tcmnt: (%s)",
1127 (shr->shr_cmnt) ? shr->shr_cmnt : "NULL");
1128 cmn_err(CE_NOTE, "\toemname: (%s)",
1129 (shr->shr_oemname) ? shr->shr_oemname : "NULL");
1130 cmn_err(CE_NOTE, "\tflags: %X", shr->shr_flags);
1131 cmn_err(CE_NOTE, "\ttype: %d", shr->shr_type);
1132 }
1133 #endif
1134
1135 /*
1195 shr->shr_refcnt--;
1196 destroy = (shr->shr_refcnt == 0);
1197 mutex_exit(&shr->shr_mutex);
1198
1199 return (destroy);
1200 }
1201
1202 /*
1203 * Frees all the memory allocated for the given
1204 * share structure. It also removes the structure
1205 * from the share cache.
1206 */
1207 static void
1208 smb_kshare_destroy(void *p)
1209 {
1210 smb_kshare_t *shr = (smb_kshare_t *)p;
1211
1212 ASSERT(shr);
1213 ASSERT(shr->shr_magic == SMB_SHARE_MAGIC);
1214
1215 if (shr->shr_ksp != NULL) {
1216 kstat_delete(shr->shr_ksp);
1217 shr->shr_ksp = NULL;
1218 kshare_stats_fini(shr);
1219 }
1220
1221 if (shr->stats.ksns != NULL) {
1222 kstat_delete(shr->stats.ksns);
1223 }
1224
1225 if (shr->shr_ca_dir != NULL)
1226 smb_node_release(shr->shr_ca_dir);
1227 if (shr->shr_root_node)
1228 smb_node_release(shr->shr_root_node);
1229
1230 smb_mem_free(shr->shr_name);
1231 smb_mem_free(shr->shr_path);
1232 smb_mem_free(shr->shr_cmnt);
1233 smb_mem_free(shr->shr_container);
1234 smb_mem_free(shr->shr_oemname);
1235 smb_mem_free(shr->shr_access_none);
1236 smb_mem_free(shr->shr_access_ro);
1237 smb_mem_free(shr->shr_access_rw);
1238
1239 kmem_cache_free(smb_kshare_cache_share, shr);
1240 }
1241
1242
1243 /*
1244 * Generate an OEM name for the given share name. If the name is
1245 * shorter than 13 bytes the oemname will be returned; otherwise NULL
1246 * is returned.
1247 */
1248 static char *
1249 smb_kshare_oemname(const char *shrname)
|