13ad684d6Sjb150015 /* 23ad684d6Sjb150015 * CDDL HEADER START 33ad684d6Sjb150015 * 43ad684d6Sjb150015 * The contents of this file are subject to the terms of the 53ad684d6Sjb150015 * Common Development and Distribution License (the "License"). 63ad684d6Sjb150015 * You may not use this file except in compliance with the License. 73ad684d6Sjb150015 * 83ad684d6Sjb150015 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 93ad684d6Sjb150015 * or http://www.opensolaris.org/os/licensing. 103ad684d6Sjb150015 * See the License for the specific language governing permissions 113ad684d6Sjb150015 * and limitations under the License. 123ad684d6Sjb150015 * 133ad684d6Sjb150015 * When distributing Covered Code, include this CDDL HEADER in each 143ad684d6Sjb150015 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 153ad684d6Sjb150015 * If applicable, add the following below this CDDL HEADER, with the 163ad684d6Sjb150015 * fields enclosed by brackets "[]" replaced with your own identifying 173ad684d6Sjb150015 * information: Portions Copyright [yyyy] [name of copyright owner] 183ad684d6Sjb150015 * 193ad684d6Sjb150015 * CDDL HEADER END 203ad684d6Sjb150015 */ 21148c5f43SAlan Wright 223ad684d6Sjb150015 /* 23c5866007SKeyur Desai * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 24b819cea2SGordon Ross * Copyright 2013 Nexenta Systems, Inc. All rights reserved. 251d443a93SDan McDonald * Copyright 2017 Joyent, Inc. 263ad684d6Sjb150015 */ 273ad684d6Sjb150015 289fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States #include <smbsrv/smb_door.h> 29148c5f43SAlan Wright #include <smbsrv/smb_kproto.h> 30148c5f43SAlan Wright #include <smbsrv/smb_ktypes.h> 31148c5f43SAlan Wright 32148c5f43SAlan Wright typedef struct smb_unshare { 33148c5f43SAlan Wright list_node_t us_lnd; 34148c5f43SAlan Wright char us_sharename[MAXNAMELEN]; 35148c5f43SAlan Wright } smb_unshare_t; 36148c5f43SAlan Wright 378622ec45SGordon Ross static kmem_cache_t *smb_kshare_cache_share; 388622ec45SGordon Ross static kmem_cache_t *smb_kshare_cache_unexport; 398622ec45SGordon Ross kmem_cache_t *smb_kshare_cache_vfs; 40148c5f43SAlan Wright 41148c5f43SAlan Wright static int smb_kshare_cmp(const void *, const void *); 42148c5f43SAlan Wright static void smb_kshare_hold(const void *); 43148c5f43SAlan Wright static boolean_t smb_kshare_rele(const void *); 44148c5f43SAlan Wright static void smb_kshare_destroy(void *); 45148c5f43SAlan Wright static char *smb_kshare_oemname(const char *); 46148c5f43SAlan Wright static int smb_kshare_is_special(const char *); 47148c5f43SAlan Wright static boolean_t smb_kshare_is_admin(const char *); 48148c5f43SAlan Wright static smb_kshare_t *smb_kshare_decode(nvlist_t *); 49148c5f43SAlan Wright static uint32_t smb_kshare_decode_bool(nvlist_t *, const char *, uint32_t); 50148c5f43SAlan Wright static void smb_kshare_unexport_thread(smb_thread_t *, void *); 518622ec45SGordon Ross static int smb_kshare_export(smb_server_t *, smb_kshare_t *); 528622ec45SGordon Ross static int smb_kshare_unexport(smb_server_t *, const char *); 538622ec45SGordon Ross static int smb_kshare_export_trans(smb_server_t *, char *, char *, char *); 54148c5f43SAlan Wright static void smb_kshare_csc_flags(smb_kshare_t *, const char *); 55148c5f43SAlan Wright 568622ec45SGordon Ross static boolean_t smb_export_isready(smb_server_t *); 573ad684d6Sjb150015 58b819cea2SGordon Ross #ifdef _KERNEL 593ad684d6Sjb150015 static int smb_kshare_chk_dsrv_status(int, smb_dr_ctx_t *); 60b819cea2SGordon Ross #endif /* _KERNEL */ 613ad684d6Sjb150015 628622ec45SGordon Ross static const smb_avl_nops_t smb_kshare_avlops = { 63148c5f43SAlan Wright smb_kshare_cmp, 64148c5f43SAlan Wright smb_kshare_hold, 65148c5f43SAlan Wright smb_kshare_rele, 66148c5f43SAlan Wright smb_kshare_destroy 67148c5f43SAlan Wright }; 68148c5f43SAlan Wright 69b819cea2SGordon Ross #ifdef _KERNEL 703ad684d6Sjb150015 /* 713ad684d6Sjb150015 * This function is not MultiThread safe. The caller has to make sure only one 723ad684d6Sjb150015 * thread calls this function. 733ad684d6Sjb150015 */ 743ad684d6Sjb150015 door_handle_t 75148c5f43SAlan Wright smb_kshare_door_init(int door_id) 763ad684d6Sjb150015 { 773ad684d6Sjb150015 return (door_ki_lookup(door_id)); 783ad684d6Sjb150015 } 793ad684d6Sjb150015 803ad684d6Sjb150015 /* 813ad684d6Sjb150015 * This function is not MultiThread safe. The caller has to make sure only one 823ad684d6Sjb150015 * thread calls this function. 833ad684d6Sjb150015 */ 843ad684d6Sjb150015 void 85148c5f43SAlan Wright smb_kshare_door_fini(door_handle_t dhdl) 863ad684d6Sjb150015 { 873ad684d6Sjb150015 if (dhdl) 883ad684d6Sjb150015 door_ki_rele(dhdl); 893ad684d6Sjb150015 } 903ad684d6Sjb150015 9129bd2886SAlan Wright /* 923ad684d6Sjb150015 * This is a special interface that will be utilized by ZFS to cause 933ad684d6Sjb150015 * a share to be added/removed 943ad684d6Sjb150015 * 953db3f65cSamw * arg is either a smb_share_t or share_name from userspace. 963db3f65cSamw * It will need to be copied into the kernel. It is smb_share_t 973ad684d6Sjb150015 * for add operations and share_name for delete operations. 983ad684d6Sjb150015 */ 993ad684d6Sjb150015 int 1003ad684d6Sjb150015 smb_kshare_upcall(door_handle_t dhdl, void *arg, boolean_t add_share) 1013ad684d6Sjb150015 { 1023ad684d6Sjb150015 door_arg_t doorarg = { 0 }; 1033ad684d6Sjb150015 char *buf = NULL; 1043ad684d6Sjb150015 char *str = NULL; 1053ad684d6Sjb150015 int error; 1063ad684d6Sjb150015 int rc; 1073ad684d6Sjb150015 unsigned int used; 1083ad684d6Sjb150015 smb_dr_ctx_t *dec_ctx; 1093ad684d6Sjb150015 smb_dr_ctx_t *enc_ctx; 1103db3f65cSamw smb_share_t *lmshare = NULL; 1113ad684d6Sjb150015 int opcode; 1123ad684d6Sjb150015 1133db3f65cSamw opcode = (add_share) ? SMB_SHROP_ADD : SMB_SHROP_DELETE; 1143ad684d6Sjb150015 1153db3f65cSamw buf = kmem_alloc(SMB_SHARE_DSIZE, KM_SLEEP); 1163db3f65cSamw enc_ctx = smb_dr_encode_start(buf, SMB_SHARE_DSIZE); 1173ad684d6Sjb150015 smb_dr_put_uint32(enc_ctx, opcode); 1183ad684d6Sjb150015 1193ad684d6Sjb150015 switch (opcode) { 1203db3f65cSamw case SMB_SHROP_ADD: 1213db3f65cSamw lmshare = kmem_alloc(sizeof (smb_share_t), KM_SLEEP); 122b819cea2SGordon Ross error = xcopyin(arg, lmshare, sizeof (smb_share_t)); 123b819cea2SGordon Ross if (error != 0) { 1243db3f65cSamw kmem_free(lmshare, sizeof (smb_share_t)); 1253db3f65cSamw kmem_free(buf, SMB_SHARE_DSIZE); 1263ad684d6Sjb150015 return (error); 1273ad684d6Sjb150015 } 1283db3f65cSamw smb_dr_put_share(enc_ctx, lmshare); 1293ad684d6Sjb150015 break; 1303ad684d6Sjb150015 1313db3f65cSamw case SMB_SHROP_DELETE: 1323ad684d6Sjb150015 str = kmem_alloc(MAXPATHLEN, KM_SLEEP); 133b819cea2SGordon Ross error = copyinstr(arg, str, MAXPATHLEN, NULL); 134b819cea2SGordon Ross if (error != 0) { 1353ad684d6Sjb150015 kmem_free(str, MAXPATHLEN); 1363db3f65cSamw kmem_free(buf, SMB_SHARE_DSIZE); 1373ad684d6Sjb150015 return (error); 1383ad684d6Sjb150015 } 1393ad684d6Sjb150015 smb_dr_put_string(enc_ctx, str); 1403ad684d6Sjb150015 kmem_free(str, MAXPATHLEN); 1413ad684d6Sjb150015 break; 1423ad684d6Sjb150015 } 1433ad684d6Sjb150015 1443ad684d6Sjb150015 if ((error = smb_dr_encode_finish(enc_ctx, &used)) != 0) { 1453db3f65cSamw kmem_free(buf, SMB_SHARE_DSIZE); 1463ad684d6Sjb150015 if (lmshare) 1473db3f65cSamw kmem_free(lmshare, sizeof (smb_share_t)); 1483ad684d6Sjb150015 return (NERR_InternalError); 1493ad684d6Sjb150015 } 1503ad684d6Sjb150015 1513ad684d6Sjb150015 doorarg.data_ptr = buf; 1523ad684d6Sjb150015 doorarg.data_size = used; 1533ad684d6Sjb150015 doorarg.rbuf = buf; 1543db3f65cSamw doorarg.rsize = SMB_SHARE_DSIZE; 1553ad684d6Sjb150015 156323a81d9Sjwadams error = door_ki_upcall_limited(dhdl, &doorarg, NULL, SIZE_MAX, 0); 1573ad684d6Sjb150015 1583ad684d6Sjb150015 if (error) { 1593db3f65cSamw kmem_free(buf, SMB_SHARE_DSIZE); 1603ad684d6Sjb150015 if (lmshare) 1613db3f65cSamw kmem_free(lmshare, sizeof (smb_share_t)); 1623ad684d6Sjb150015 return (error); 1633ad684d6Sjb150015 } 1643ad684d6Sjb150015 1653ad684d6Sjb150015 dec_ctx = smb_dr_decode_start(doorarg.data_ptr, doorarg.data_size); 1663ad684d6Sjb150015 if (smb_kshare_chk_dsrv_status(opcode, dec_ctx) != 0) { 1673db3f65cSamw kmem_free(buf, SMB_SHARE_DSIZE); 1683ad684d6Sjb150015 if (lmshare) 1693db3f65cSamw kmem_free(lmshare, sizeof (smb_share_t)); 1703ad684d6Sjb150015 return (NERR_InternalError); 1713ad684d6Sjb150015 } 1723ad684d6Sjb150015 1733ad684d6Sjb150015 rc = smb_dr_get_uint32(dec_ctx); 1743db3f65cSamw if (opcode == SMB_SHROP_ADD) 1753db3f65cSamw smb_dr_get_share(dec_ctx, lmshare); 1763ad684d6Sjb150015 1773ad684d6Sjb150015 if (smb_dr_decode_finish(dec_ctx)) 1783ad684d6Sjb150015 rc = NERR_InternalError; 1793ad684d6Sjb150015 1803db3f65cSamw kmem_free(buf, SMB_SHARE_DSIZE); 1813ad684d6Sjb150015 if (lmshare) 1823db3f65cSamw kmem_free(lmshare, sizeof (smb_share_t)); 1833ad684d6Sjb150015 1843ad684d6Sjb150015 return ((rc == NERR_DuplicateShare && add_share) ? 0 : rc); 1853ad684d6Sjb150015 } 186b819cea2SGordon Ross #endif /* _KERNEL */ 1873ad684d6Sjb150015 1883ad684d6Sjb150015 /* 189148c5f43SAlan Wright * Executes map and unmap command for shares. 190148c5f43SAlan Wright */ 191148c5f43SAlan Wright int 1928622ec45SGordon Ross smb_kshare_exec(smb_server_t *sv, smb_shr_execinfo_t *execinfo) 193148c5f43SAlan Wright { 194148c5f43SAlan Wright int exec_rc = 0; 195148c5f43SAlan Wright 1968622ec45SGordon Ross (void) smb_kdoor_upcall(sv, SMB_DR_SHR_EXEC, 197148c5f43SAlan Wright execinfo, smb_shr_execinfo_xdr, &exec_rc, xdr_int); 198148c5f43SAlan Wright 199148c5f43SAlan Wright return (exec_rc); 200148c5f43SAlan Wright } 201148c5f43SAlan Wright 202148c5f43SAlan Wright /* 203148c5f43SAlan Wright * Obtains any host access restriction on the specified 204148c5f43SAlan Wright * share for the given host (ipaddr) by calling smbd 205148c5f43SAlan Wright */ 206148c5f43SAlan Wright uint32_t 2078622ec45SGordon Ross smb_kshare_hostaccess(smb_kshare_t *shr, smb_session_t *session) 208148c5f43SAlan Wright { 209148c5f43SAlan Wright smb_shr_hostaccess_query_t req; 2108622ec45SGordon Ross smb_inaddr_t *ipaddr = &session->ipaddr; 211148c5f43SAlan Wright uint32_t host_access = SMB_SHRF_ACC_OPEN; 212148c5f43SAlan Wright uint32_t flag = SMB_SHRF_ACC_OPEN; 213148c5f43SAlan Wright uint32_t access; 214148c5f43SAlan Wright 215148c5f43SAlan Wright if (smb_inet_iszero(ipaddr)) 216148c5f43SAlan Wright return (ACE_ALL_PERMS); 217148c5f43SAlan Wright 218148c5f43SAlan Wright if ((shr->shr_access_none == NULL || *shr->shr_access_none == '\0') && 219148c5f43SAlan Wright (shr->shr_access_ro == NULL || *shr->shr_access_ro == '\0') && 220148c5f43SAlan Wright (shr->shr_access_rw == NULL || *shr->shr_access_rw == '\0')) 221148c5f43SAlan Wright return (ACE_ALL_PERMS); 222148c5f43SAlan Wright 223148c5f43SAlan Wright if (shr->shr_access_none != NULL) 224148c5f43SAlan Wright flag |= SMB_SHRF_ACC_NONE; 225148c5f43SAlan Wright if (shr->shr_access_ro != NULL) 226148c5f43SAlan Wright flag |= SMB_SHRF_ACC_RO; 227148c5f43SAlan Wright if (shr->shr_access_rw != NULL) 228148c5f43SAlan Wright flag |= SMB_SHRF_ACC_RW; 229148c5f43SAlan Wright 230148c5f43SAlan Wright req.shq_none = shr->shr_access_none; 231148c5f43SAlan Wright req.shq_ro = shr->shr_access_ro; 232148c5f43SAlan Wright req.shq_rw = shr->shr_access_rw; 233148c5f43SAlan Wright req.shq_flag = flag; 234148c5f43SAlan Wright req.shq_ipaddr = *ipaddr; 235148c5f43SAlan Wright 2368622ec45SGordon Ross (void) smb_kdoor_upcall(session->s_server, SMB_DR_SHR_HOSTACCESS, 237148c5f43SAlan Wright &req, smb_shr_hostaccess_query_xdr, &host_access, xdr_uint32_t); 238148c5f43SAlan Wright 239148c5f43SAlan Wright switch (host_access) { 240148c5f43SAlan Wright case SMB_SHRF_ACC_RO: 241148c5f43SAlan Wright access = ACE_ALL_PERMS & ~ACE_ALL_WRITE_PERMS; 242148c5f43SAlan Wright break; 243148c5f43SAlan Wright case SMB_SHRF_ACC_OPEN: 244148c5f43SAlan Wright case SMB_SHRF_ACC_RW: 245148c5f43SAlan Wright access = ACE_ALL_PERMS; 246148c5f43SAlan Wright break; 247148c5f43SAlan Wright case SMB_SHRF_ACC_NONE: 248148c5f43SAlan Wright default: 249148c5f43SAlan Wright access = 0; 250148c5f43SAlan Wright } 251148c5f43SAlan Wright 252148c5f43SAlan Wright return (access); 253148c5f43SAlan Wright } 254148c5f43SAlan Wright 255148c5f43SAlan Wright /* 256148c5f43SAlan Wright * This function is called when smb_server_t is 257148c5f43SAlan Wright * created which means smb/service is ready for 258148c5f43SAlan Wright * exporting SMB shares 259148c5f43SAlan Wright */ 260148c5f43SAlan Wright void 2618622ec45SGordon Ross smb_export_start(smb_server_t *sv) 262148c5f43SAlan Wright { 2638622ec45SGordon Ross mutex_enter(&sv->sv_export.e_mutex); 2648622ec45SGordon Ross if (sv->sv_export.e_ready) { 2658622ec45SGordon Ross mutex_exit(&sv->sv_export.e_mutex); 266148c5f43SAlan Wright return; 267148c5f43SAlan Wright } 268148c5f43SAlan Wright 2698622ec45SGordon Ross sv->sv_export.e_ready = B_TRUE; 2708622ec45SGordon Ross mutex_exit(&sv->sv_export.e_mutex); 271148c5f43SAlan Wright 2728622ec45SGordon Ross smb_avl_create(&sv->sv_export.e_share_avl, sizeof (smb_kshare_t), 273148c5f43SAlan Wright offsetof(smb_kshare_t, shr_link), &smb_kshare_avlops); 274148c5f43SAlan Wright 2758622ec45SGordon Ross (void) smb_kshare_export_trans(sv, "IPC$", "IPC$", "Remote IPC"); 2768622ec45SGordon Ross (void) smb_kshare_export_trans(sv, "c$", SMB_CVOL, "Default Share"); 2778622ec45SGordon Ross (void) smb_kshare_export_trans(sv, "vss$", SMB_VSS, "VSS"); 278148c5f43SAlan Wright } 279148c5f43SAlan Wright 280148c5f43SAlan Wright /* 281148c5f43SAlan Wright * This function is called when smb_server_t goes 282148c5f43SAlan Wright * away which means SMB shares should not be made 283148c5f43SAlan Wright * available to clients 284148c5f43SAlan Wright */ 285148c5f43SAlan Wright void 2868622ec45SGordon Ross smb_export_stop(smb_server_t *sv) 287148c5f43SAlan Wright { 2888622ec45SGordon Ross mutex_enter(&sv->sv_export.e_mutex); 2898622ec45SGordon Ross if (!sv->sv_export.e_ready) { 2908622ec45SGordon Ross mutex_exit(&sv->sv_export.e_mutex); 291148c5f43SAlan Wright return; 292148c5f43SAlan Wright } 2938622ec45SGordon Ross sv->sv_export.e_ready = B_FALSE; 2948622ec45SGordon Ross mutex_exit(&sv->sv_export.e_mutex); 295148c5f43SAlan Wright 2968622ec45SGordon Ross smb_avl_destroy(&sv->sv_export.e_share_avl); 2978622ec45SGordon Ross smb_vfs_rele_all(&sv->sv_export); 298148c5f43SAlan Wright } 299148c5f43SAlan Wright 300148c5f43SAlan Wright void 3018622ec45SGordon Ross smb_kshare_g_init(void) 3028622ec45SGordon Ross { 3038622ec45SGordon Ross smb_kshare_cache_share = kmem_cache_create("smb_share_cache", 3048622ec45SGordon Ross sizeof (smb_kshare_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 3058622ec45SGordon Ross 3068622ec45SGordon Ross smb_kshare_cache_unexport = kmem_cache_create("smb_unexport_cache", 3078622ec45SGordon Ross sizeof (smb_unshare_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 3088622ec45SGordon Ross 3098622ec45SGordon Ross smb_kshare_cache_vfs = kmem_cache_create("smb_vfs_cache", 3108622ec45SGordon Ross sizeof (smb_vfs_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 3118622ec45SGordon Ross } 3128622ec45SGordon Ross 3138622ec45SGordon Ross void 3148622ec45SGordon Ross smb_kshare_init(smb_server_t *sv) 3158622ec45SGordon Ross { 3168622ec45SGordon Ross 3178622ec45SGordon Ross smb_llist_constructor(&sv->sv_export.e_vfs_list, sizeof (smb_vfs_t), 3188622ec45SGordon Ross offsetof(smb_vfs_t, sv_lnd)); 3198622ec45SGordon Ross 3208622ec45SGordon Ross smb_slist_constructor(&sv->sv_export.e_unexport_list, 3218622ec45SGordon Ross sizeof (smb_unshare_t), offsetof(smb_unshare_t, us_lnd)); 3228622ec45SGordon Ross } 3238622ec45SGordon Ross 3248622ec45SGordon Ross int 3258622ec45SGordon Ross smb_kshare_start(smb_server_t *sv) 3268622ec45SGordon Ross { 327a90cf9f2SGordon Ross smb_thread_init(&sv->sv_export.e_unexport_thread, "smb_kshare_unexport", 3288622ec45SGordon Ross smb_kshare_unexport_thread, sv, smbsrv_base_pri); 3298622ec45SGordon Ross 3308622ec45SGordon Ross return (smb_thread_start(&sv->sv_export.e_unexport_thread)); 3318622ec45SGordon Ross } 3328622ec45SGordon Ross 3338622ec45SGordon Ross void 3348622ec45SGordon Ross smb_kshare_stop(smb_server_t *sv) 3358622ec45SGordon Ross { 3368622ec45SGordon Ross smb_thread_stop(&sv->sv_export.e_unexport_thread); 3378622ec45SGordon Ross smb_thread_destroy(&sv->sv_export.e_unexport_thread); 3388622ec45SGordon Ross } 3398622ec45SGordon Ross 3408622ec45SGordon Ross void 3418622ec45SGordon Ross smb_kshare_fini(smb_server_t *sv) 342148c5f43SAlan Wright { 343148c5f43SAlan Wright smb_unshare_t *ux; 344148c5f43SAlan Wright 3458622ec45SGordon Ross while ((ux = list_head(&sv->sv_export.e_unexport_list.sl_list)) 3468622ec45SGordon Ross != NULL) { 3478622ec45SGordon Ross smb_slist_remove(&sv->sv_export.e_unexport_list, ux); 3488622ec45SGordon Ross kmem_cache_free(smb_kshare_cache_unexport, ux); 349148c5f43SAlan Wright } 3508622ec45SGordon Ross smb_slist_destructor(&sv->sv_export.e_unexport_list); 351148c5f43SAlan Wright 3528622ec45SGordon Ross smb_vfs_rele_all(&sv->sv_export); 353148c5f43SAlan Wright 3548622ec45SGordon Ross smb_llist_destructor(&sv->sv_export.e_vfs_list); 3558622ec45SGordon Ross } 356148c5f43SAlan Wright 3578622ec45SGordon Ross void 3588622ec45SGordon Ross smb_kshare_g_fini(void) 3598622ec45SGordon Ross { 3608622ec45SGordon Ross kmem_cache_destroy(smb_kshare_cache_unexport); 3618622ec45SGordon Ross kmem_cache_destroy(smb_kshare_cache_share); 3628622ec45SGordon Ross kmem_cache_destroy(smb_kshare_cache_vfs); 363148c5f43SAlan Wright } 364148c5f43SAlan Wright 365148c5f43SAlan Wright /* 366148c5f43SAlan Wright * A list of shares in nvlist format can be sent down 367148c5f43SAlan Wright * from userspace thourgh the IOCTL interface. The nvlist 368148c5f43SAlan Wright * is unpacked here and all the shares in the list will 369148c5f43SAlan Wright * be exported. 370148c5f43SAlan Wright */ 371148c5f43SAlan Wright int 372148c5f43SAlan Wright smb_kshare_export_list(smb_ioc_share_t *ioc) 373148c5f43SAlan Wright { 3748622ec45SGordon Ross smb_server_t *sv = NULL; 3754846df9bSKevin Crowe nvlist_t *shrlist = NULL; 376148c5f43SAlan Wright nvlist_t *share; 377148c5f43SAlan Wright nvpair_t *nvp; 378148c5f43SAlan Wright smb_kshare_t *shr; 379148c5f43SAlan Wright char *shrname; 3808622ec45SGordon Ross int rc; 381148c5f43SAlan Wright 3824846df9bSKevin Crowe if ((rc = smb_server_lookup(&sv)) != 0) 3834846df9bSKevin Crowe return (rc); 3844846df9bSKevin Crowe 3858622ec45SGordon Ross if (!smb_export_isready(sv)) { 3868622ec45SGordon Ross rc = ENOTACTIVE; 3878622ec45SGordon Ross goto out; 3888622ec45SGordon Ross } 3898622ec45SGordon Ross 3901d443a93SDan McDonald /* 3911d443a93SDan McDonald * Reality check that the nvlist's reported length doesn't exceed the 3921d443a93SDan McDonald * ioctl's total length. We then assume the nvlist_unpack() will 3931d443a93SDan McDonald * sanity check the nvlist itself. 3941d443a93SDan McDonald */ 3951d443a93SDan McDonald if ((ioc->shrlen + offsetof(smb_ioc_share_t, shr)) > ioc->hdr.len) { 3961d443a93SDan McDonald rc = EINVAL; 3971d443a93SDan McDonald goto out; 3981d443a93SDan McDonald } 3998622ec45SGordon Ross rc = nvlist_unpack(ioc->shr, ioc->shrlen, &shrlist, KM_SLEEP); 4008622ec45SGordon Ross if (rc != 0) 4014846df9bSKevin Crowe goto out; 402148c5f43SAlan Wright 403148c5f43SAlan Wright for (nvp = nvlist_next_nvpair(shrlist, NULL); nvp != NULL; 404148c5f43SAlan Wright nvp = nvlist_next_nvpair(shrlist, nvp)) { 4054846df9bSKevin Crowe 4064846df9bSKevin Crowe /* 4074846df9bSKevin Crowe * Since this loop can run for a while we want to exit 4084846df9bSKevin Crowe * as soon as the server state is anything but RUNNING 4094846df9bSKevin Crowe * to allow shutdown to proceed. 4104846df9bSKevin Crowe */ 4114846df9bSKevin Crowe if (sv->sv_state != SMB_SERVER_STATE_RUNNING) 4124846df9bSKevin Crowe goto out; 4134846df9bSKevin Crowe 414148c5f43SAlan Wright if (nvpair_type(nvp) != DATA_TYPE_NVLIST) 415148c5f43SAlan Wright continue; 416148c5f43SAlan Wright 417148c5f43SAlan Wright shrname = nvpair_name(nvp); 418148c5f43SAlan Wright ASSERT(shrname); 419148c5f43SAlan Wright 420148c5f43SAlan Wright if ((rc = nvpair_value_nvlist(nvp, &share)) != 0) { 421148c5f43SAlan Wright cmn_err(CE_WARN, "export[%s]: failed accessing", 422148c5f43SAlan Wright shrname); 423148c5f43SAlan Wright continue; 424148c5f43SAlan Wright } 425148c5f43SAlan Wright 426148c5f43SAlan Wright if ((shr = smb_kshare_decode(share)) == NULL) { 427148c5f43SAlan Wright cmn_err(CE_WARN, "export[%s]: failed decoding", 428148c5f43SAlan Wright shrname); 429148c5f43SAlan Wright continue; 430148c5f43SAlan Wright } 431148c5f43SAlan Wright 4324846df9bSKevin Crowe /* smb_kshare_export consumes shr so it's not leaked */ 4338622ec45SGordon Ross if ((rc = smb_kshare_export(sv, shr)) != 0) { 434148c5f43SAlan Wright smb_kshare_destroy(shr); 435148c5f43SAlan Wright continue; 436148c5f43SAlan Wright } 437148c5f43SAlan Wright } 4384846df9bSKevin Crowe rc = 0; 439148c5f43SAlan Wright 4404846df9bSKevin Crowe out: 441148c5f43SAlan Wright nvlist_free(shrlist); 4424846df9bSKevin Crowe smb_server_release(sv); 4434846df9bSKevin Crowe return (rc); 444148c5f43SAlan Wright } 445148c5f43SAlan Wright 446148c5f43SAlan Wright /* 447148c5f43SAlan Wright * This function is invoked when a share is disabled to disconnect trees 448148c5f43SAlan Wright * and close files. Cleaning up may involve VOP and/or VFS calls, which 449148c5f43SAlan Wright * may conflict/deadlock with stuck threads if something is amiss with the 450148c5f43SAlan Wright * file system. Queueing the request for asynchronous processing allows the 451148c5f43SAlan Wright * call to return immediately so that, if the unshare is being done in the 452148c5f43SAlan Wright * context of a forced unmount, the forced unmount will always be able to 453148c5f43SAlan Wright * proceed (unblocking stuck I/O and eventually allowing all blocked unshare 454148c5f43SAlan Wright * processes to complete). 455148c5f43SAlan Wright * 456148c5f43SAlan Wright * The path lookup to find the root vnode of the VFS in question and the 457148c5f43SAlan Wright * release of this vnode are done synchronously prior to any associated 458148c5f43SAlan Wright * unmount. Doing these asynchronous to an associated unmount could run 459148c5f43SAlan Wright * the risk of a spurious EBUSY for a standard unmount or an EIO during 460148c5f43SAlan Wright * the path lookup due to a forced unmount finishing first. 461148c5f43SAlan Wright */ 462148c5f43SAlan Wright int 463148c5f43SAlan Wright smb_kshare_unexport_list(smb_ioc_share_t *ioc) 464148c5f43SAlan Wright { 4658622ec45SGordon Ross smb_server_t *sv = NULL; 466148c5f43SAlan Wright smb_unshare_t *ux; 4678622ec45SGordon Ross nvlist_t *shrlist = NULL; 468148c5f43SAlan Wright nvpair_t *nvp; 469148c5f43SAlan Wright boolean_t unexport = B_FALSE; 470148c5f43SAlan Wright char *shrname; 471148c5f43SAlan Wright int rc; 472148c5f43SAlan Wright 4738622ec45SGordon Ross if ((rc = smb_server_lookup(&sv)) != 0) 474148c5f43SAlan Wright return (rc); 475148c5f43SAlan Wright 4761d443a93SDan McDonald /* 4771d443a93SDan McDonald * Reality check that the nvlist's reported length doesn't exceed the 4781d443a93SDan McDonald * ioctl's total length. We then assume the nvlist_unpack() will 4791d443a93SDan McDonald * sanity check the nvlist itself. 4801d443a93SDan McDonald */ 4811d443a93SDan McDonald if ((ioc->shrlen + offsetof(smb_ioc_share_t, shr)) > ioc->hdr.len) { 4821d443a93SDan McDonald rc = EINVAL; 4831d443a93SDan McDonald goto out; 4841d443a93SDan McDonald } 4858622ec45SGordon Ross if ((rc = nvlist_unpack(ioc->shr, ioc->shrlen, &shrlist, 0)) != 0) 4868622ec45SGordon Ross goto out; 4878622ec45SGordon Ross 488148c5f43SAlan Wright for (nvp = nvlist_next_nvpair(shrlist, NULL); nvp != NULL; 489148c5f43SAlan Wright nvp = nvlist_next_nvpair(shrlist, nvp)) { 490148c5f43SAlan Wright if (nvpair_type(nvp) != DATA_TYPE_NVLIST) 491148c5f43SAlan Wright continue; 492148c5f43SAlan Wright 493148c5f43SAlan Wright shrname = nvpair_name(nvp); 494148c5f43SAlan Wright ASSERT(shrname); 495148c5f43SAlan Wright 4968622ec45SGordon Ross if ((rc = smb_kshare_unexport(sv, shrname)) != 0) 497148c5f43SAlan Wright continue; 498148c5f43SAlan Wright 4998622ec45SGordon Ross ux = kmem_cache_alloc(smb_kshare_cache_unexport, KM_SLEEP); 500148c5f43SAlan Wright (void) strlcpy(ux->us_sharename, shrname, MAXNAMELEN); 501148c5f43SAlan Wright 5028622ec45SGordon Ross smb_slist_insert_tail(&sv->sv_export.e_unexport_list, ux); 503148c5f43SAlan Wright unexport = B_TRUE; 504148c5f43SAlan Wright } 505148c5f43SAlan Wright 506148c5f43SAlan Wright if (unexport) 5078622ec45SGordon Ross smb_thread_signal(&sv->sv_export.e_unexport_thread); 5088622ec45SGordon Ross rc = 0; 509148c5f43SAlan Wright 5108622ec45SGordon Ross out: 5118622ec45SGordon Ross nvlist_free(shrlist); 5128622ec45SGordon Ross smb_server_release(sv); 5138622ec45SGordon Ross return (rc); 514148c5f43SAlan Wright } 515148c5f43SAlan Wright 516148c5f43SAlan Wright /* 517cb174861Sjoyce mcintosh * Get properties (currently only shortname enablement) 518cb174861Sjoyce mcintosh * of specified share. 519cb174861Sjoyce mcintosh */ 520cb174861Sjoyce mcintosh int 521cb174861Sjoyce mcintosh smb_kshare_info(smb_ioc_shareinfo_t *ioc) 522cb174861Sjoyce mcintosh { 523cb174861Sjoyce mcintosh ioc->shortnames = smb_shortnames; 524cb174861Sjoyce mcintosh return (0); 525cb174861Sjoyce mcintosh } 526cb174861Sjoyce mcintosh 527cb174861Sjoyce mcintosh /* 528148c5f43SAlan Wright * This function builds a response for a NetShareEnum RAP request. 529148c5f43SAlan Wright * List of shares is scanned twice. In the first round the total number 530148c5f43SAlan Wright * of shares which their OEM name is shorter than 13 chars (esi->es_ntotal) 531148c5f43SAlan Wright * and also the number of shares that fit in the given buffer are calculated. 532148c5f43SAlan Wright * In the second round the shares data are encoded in the buffer. 533148c5f43SAlan Wright * 534148c5f43SAlan Wright * The data associated with each share has two parts, a fixed size part and 535148c5f43SAlan Wright * a variable size part which is share's comment. The outline of the response 536148c5f43SAlan Wright * buffer is so that fixed part for all the shares will appear first and follows 537148c5f43SAlan Wright * with the comments for all those shares and that's why the data cannot be 538148c5f43SAlan Wright * encoded in one round without unnecessarily complicating the code. 539148c5f43SAlan Wright */ 540148c5f43SAlan Wright void 5418622ec45SGordon Ross smb_kshare_enum(smb_server_t *sv, smb_enumshare_info_t *esi) 542148c5f43SAlan Wright { 543148c5f43SAlan Wright smb_avl_t *share_avl; 544148c5f43SAlan Wright smb_avl_cursor_t cursor; 545148c5f43SAlan Wright smb_kshare_t *shr; 546148c5f43SAlan Wright int remained; 547148c5f43SAlan Wright uint16_t infolen = 0; 548148c5f43SAlan Wright uint16_t cmntlen = 0; 549148c5f43SAlan Wright uint16_t sharelen; 550148c5f43SAlan Wright uint16_t clen; 551148c5f43SAlan Wright uint32_t cmnt_offs; 552148c5f43SAlan Wright smb_msgbuf_t info_mb; 553148c5f43SAlan Wright smb_msgbuf_t cmnt_mb; 554148c5f43SAlan Wright boolean_t autohome_added = B_FALSE; 555148c5f43SAlan Wright 5568622ec45SGordon Ross if (!smb_export_isready(sv)) { 557148c5f43SAlan Wright esi->es_ntotal = esi->es_nsent = 0; 558148c5f43SAlan Wright esi->es_datasize = 0; 559148c5f43SAlan Wright return; 560148c5f43SAlan Wright } 561148c5f43SAlan Wright 562148c5f43SAlan Wright esi->es_ntotal = esi->es_nsent = 0; 563148c5f43SAlan Wright remained = esi->es_bufsize; 5648622ec45SGordon Ross share_avl = &sv->sv_export.e_share_avl; 565148c5f43SAlan Wright 566148c5f43SAlan Wright /* Do the necessary calculations in the first round */ 567148c5f43SAlan Wright smb_avl_iterinit(share_avl, &cursor); 568148c5f43SAlan Wright 569148c5f43SAlan Wright while ((shr = smb_avl_iterate(share_avl, &cursor)) != NULL) { 570148c5f43SAlan Wright if (shr->shr_oemname == NULL) { 571148c5f43SAlan Wright smb_avl_release(share_avl, shr); 572148c5f43SAlan Wright continue; 573148c5f43SAlan Wright } 574148c5f43SAlan Wright 575148c5f43SAlan Wright if ((shr->shr_flags & SMB_SHRF_AUTOHOME) && !autohome_added) { 576148c5f43SAlan Wright if (esi->es_posix_uid == shr->shr_uid) { 577148c5f43SAlan Wright autohome_added = B_TRUE; 578148c5f43SAlan Wright } else { 579148c5f43SAlan Wright smb_avl_release(share_avl, shr); 580148c5f43SAlan Wright continue; 581148c5f43SAlan Wright } 582148c5f43SAlan Wright } 583148c5f43SAlan Wright 584148c5f43SAlan Wright esi->es_ntotal++; 585148c5f43SAlan Wright 586148c5f43SAlan Wright if (remained <= 0) { 587148c5f43SAlan Wright smb_avl_release(share_avl, shr); 588148c5f43SAlan Wright continue; 589148c5f43SAlan Wright } 590148c5f43SAlan Wright 591148c5f43SAlan Wright clen = strlen(shr->shr_cmnt) + 1; 592148c5f43SAlan Wright sharelen = SHARE_INFO_1_SIZE + clen; 593148c5f43SAlan Wright 594148c5f43SAlan Wright if (sharelen <= remained) { 595148c5f43SAlan Wright infolen += SHARE_INFO_1_SIZE; 596148c5f43SAlan Wright cmntlen += clen; 597148c5f43SAlan Wright } 598148c5f43SAlan Wright 599148c5f43SAlan Wright remained -= sharelen; 600148c5f43SAlan Wright smb_avl_release(share_avl, shr); 601148c5f43SAlan Wright } 602148c5f43SAlan Wright 603148c5f43SAlan Wright esi->es_datasize = infolen + cmntlen; 604148c5f43SAlan Wright 605148c5f43SAlan Wright smb_msgbuf_init(&info_mb, (uint8_t *)esi->es_buf, infolen, 0); 606148c5f43SAlan Wright smb_msgbuf_init(&cmnt_mb, (uint8_t *)esi->es_buf + infolen, cmntlen, 0); 607148c5f43SAlan Wright cmnt_offs = infolen; 608148c5f43SAlan Wright 609148c5f43SAlan Wright /* Encode the data in the second round */ 610148c5f43SAlan Wright smb_avl_iterinit(share_avl, &cursor); 611148c5f43SAlan Wright autohome_added = B_FALSE; 612148c5f43SAlan Wright 613148c5f43SAlan Wright while ((shr = smb_avl_iterate(share_avl, &cursor)) != NULL) { 614148c5f43SAlan Wright if (shr->shr_oemname == NULL) { 615148c5f43SAlan Wright smb_avl_release(share_avl, shr); 616148c5f43SAlan Wright continue; 617148c5f43SAlan Wright } 618148c5f43SAlan Wright 619148c5f43SAlan Wright if ((shr->shr_flags & SMB_SHRF_AUTOHOME) && !autohome_added) { 620148c5f43SAlan Wright if (esi->es_posix_uid == shr->shr_uid) { 621148c5f43SAlan Wright autohome_added = B_TRUE; 622148c5f43SAlan Wright } else { 623148c5f43SAlan Wright smb_avl_release(share_avl, shr); 624148c5f43SAlan Wright continue; 625148c5f43SAlan Wright } 626148c5f43SAlan Wright } 627148c5f43SAlan Wright 628148c5f43SAlan Wright if (smb_msgbuf_encode(&info_mb, "13c.wl", 629148c5f43SAlan Wright shr->shr_oemname, shr->shr_type, cmnt_offs) < 0) { 630148c5f43SAlan Wright smb_avl_release(share_avl, shr); 631148c5f43SAlan Wright break; 632148c5f43SAlan Wright } 633148c5f43SAlan Wright 634148c5f43SAlan Wright if (smb_msgbuf_encode(&cmnt_mb, "s", shr->shr_cmnt) < 0) { 635148c5f43SAlan Wright smb_avl_release(share_avl, shr); 636148c5f43SAlan Wright break; 637148c5f43SAlan Wright } 638148c5f43SAlan Wright 639148c5f43SAlan Wright cmnt_offs += strlen(shr->shr_cmnt) + 1; 640148c5f43SAlan Wright esi->es_nsent++; 641148c5f43SAlan Wright 642148c5f43SAlan Wright smb_avl_release(share_avl, shr); 643148c5f43SAlan Wright } 644148c5f43SAlan Wright 645148c5f43SAlan Wright smb_msgbuf_term(&info_mb); 646148c5f43SAlan Wright smb_msgbuf_term(&cmnt_mb); 647148c5f43SAlan Wright } 648148c5f43SAlan Wright 649148c5f43SAlan Wright /* 650148c5f43SAlan Wright * Looks up the given share and returns a pointer 651148c5f43SAlan Wright * to its definition if it's found. A hold on the 652148c5f43SAlan Wright * object is taken before the pointer is returned 653148c5f43SAlan Wright * in which case the caller MUST always call 654148c5f43SAlan Wright * smb_kshare_release(). 655148c5f43SAlan Wright */ 656148c5f43SAlan Wright smb_kshare_t * 6578622ec45SGordon Ross smb_kshare_lookup(smb_server_t *sv, const char *shrname) 658148c5f43SAlan Wright { 659148c5f43SAlan Wright smb_kshare_t key; 660148c5f43SAlan Wright smb_kshare_t *shr; 661148c5f43SAlan Wright 662148c5f43SAlan Wright ASSERT(shrname); 663148c5f43SAlan Wright 6648622ec45SGordon Ross if (!smb_export_isready(sv)) 665148c5f43SAlan Wright return (NULL); 666148c5f43SAlan Wright 667148c5f43SAlan Wright key.shr_name = (char *)shrname; 6688622ec45SGordon Ross shr = smb_avl_lookup(&sv->sv_export.e_share_avl, &key); 669148c5f43SAlan Wright return (shr); 670148c5f43SAlan Wright } 671148c5f43SAlan Wright 672148c5f43SAlan Wright /* 673148c5f43SAlan Wright * Releases the hold taken on the specified share object 674148c5f43SAlan Wright */ 675148c5f43SAlan Wright void 6768622ec45SGordon Ross smb_kshare_release(smb_server_t *sv, smb_kshare_t *shr) 677148c5f43SAlan Wright { 678148c5f43SAlan Wright ASSERT(shr); 679148c5f43SAlan Wright ASSERT(shr->shr_magic == SMB_SHARE_MAGIC); 680148c5f43SAlan Wright 6818622ec45SGordon Ross smb_avl_release(&sv->sv_export.e_share_avl, shr); 682148c5f43SAlan Wright } 683148c5f43SAlan Wright 684148c5f43SAlan Wright /* 685148c5f43SAlan Wright * Add the given share in the specified server. 686148c5f43SAlan Wright * If the share is a disk share, smb_vfs_hold() is 687148c5f43SAlan Wright * invoked to ensure that there is a hold on the 688148c5f43SAlan Wright * corresponding file system before the share is 689148c5f43SAlan Wright * added to shares AVL. 690148c5f43SAlan Wright * 691148c5f43SAlan Wright * If the share is an Autohome share and it is 692148c5f43SAlan Wright * already in the AVL only a reference count for 693148c5f43SAlan Wright * that share is incremented. 694148c5f43SAlan Wright */ 695148c5f43SAlan Wright static int 6968622ec45SGordon Ross smb_kshare_export(smb_server_t *sv, smb_kshare_t *shr) 697148c5f43SAlan Wright { 698148c5f43SAlan Wright smb_avl_t *share_avl; 699148c5f43SAlan Wright smb_kshare_t *auto_shr; 700148c5f43SAlan Wright vnode_t *vp; 701148c5f43SAlan Wright int rc = 0; 702148c5f43SAlan Wright 7038622ec45SGordon Ross share_avl = &sv->sv_export.e_share_avl; 704148c5f43SAlan Wright 705148c5f43SAlan Wright if (!STYPE_ISDSK(shr->shr_type)) { 706148c5f43SAlan Wright if ((rc = smb_avl_add(share_avl, shr)) != 0) { 707148c5f43SAlan Wright cmn_err(CE_WARN, "export[%s]: failed caching (%d)", 708148c5f43SAlan Wright shr->shr_name, rc); 709148c5f43SAlan Wright } 710148c5f43SAlan Wright 711148c5f43SAlan Wright return (rc); 712148c5f43SAlan Wright } 713148c5f43SAlan Wright 714148c5f43SAlan Wright if ((auto_shr = smb_avl_lookup(share_avl, shr)) != NULL) { 715148c5f43SAlan Wright if ((auto_shr->shr_flags & SMB_SHRF_AUTOHOME) == 0) { 716148c5f43SAlan Wright smb_avl_release(share_avl, auto_shr); 717148c5f43SAlan Wright return (EEXIST); 718148c5f43SAlan Wright } 719148c5f43SAlan Wright 720148c5f43SAlan Wright mutex_enter(&auto_shr->shr_mutex); 721148c5f43SAlan Wright auto_shr->shr_autocnt++; 722148c5f43SAlan Wright mutex_exit(&auto_shr->shr_mutex); 723148c5f43SAlan Wright smb_avl_release(share_avl, auto_shr); 724148c5f43SAlan Wright return (0); 725148c5f43SAlan Wright } 726148c5f43SAlan Wright 7278622ec45SGordon Ross if ((rc = smb_server_sharevp(sv, shr->shr_path, &vp)) != 0) { 728148c5f43SAlan Wright cmn_err(CE_WARN, "export[%s(%s)]: failed obtaining vnode (%d)", 729148c5f43SAlan Wright shr->shr_name, shr->shr_path, rc); 730148c5f43SAlan Wright return (rc); 731148c5f43SAlan Wright } 732148c5f43SAlan Wright 7338622ec45SGordon Ross if ((rc = smb_vfs_hold(&sv->sv_export, vp->v_vfsp)) == 0) { 734148c5f43SAlan Wright if ((rc = smb_avl_add(share_avl, shr)) != 0) { 735148c5f43SAlan Wright cmn_err(CE_WARN, "export[%s]: failed caching (%d)", 736148c5f43SAlan Wright shr->shr_name, rc); 7378622ec45SGordon Ross smb_vfs_rele(&sv->sv_export, vp->v_vfsp); 738148c5f43SAlan Wright } 739148c5f43SAlan Wright } else { 740148c5f43SAlan Wright cmn_err(CE_WARN, "export[%s(%s)]: failed holding VFS (%d)", 741148c5f43SAlan Wright shr->shr_name, shr->shr_path, rc); 742148c5f43SAlan Wright } 743148c5f43SAlan Wright 744148c5f43SAlan Wright VN_RELE(vp); 745148c5f43SAlan Wright return (rc); 746148c5f43SAlan Wright } 747148c5f43SAlan Wright 748148c5f43SAlan Wright /* 749148c5f43SAlan Wright * Removes the share specified by 'shrname' from the AVL 750148c5f43SAlan Wright * tree of the given server if it's there. 751148c5f43SAlan Wright * 752148c5f43SAlan Wright * If the share is an Autohome share, the autohome count 753148c5f43SAlan Wright * is decremented and the share is only removed if the 754148c5f43SAlan Wright * count goes to zero. 755148c5f43SAlan Wright * 756148c5f43SAlan Wright * If the share is a disk share, the hold on the corresponding 757148c5f43SAlan Wright * file system is released before removing the share from 758148c5f43SAlan Wright * the AVL tree. 759148c5f43SAlan Wright */ 760148c5f43SAlan Wright static int 7618622ec45SGordon Ross smb_kshare_unexport(smb_server_t *sv, const char *shrname) 762148c5f43SAlan Wright { 763148c5f43SAlan Wright smb_avl_t *share_avl; 764148c5f43SAlan Wright smb_kshare_t key; 765148c5f43SAlan Wright smb_kshare_t *shr; 766148c5f43SAlan Wright vnode_t *vp; 767148c5f43SAlan Wright int rc; 768148c5f43SAlan Wright boolean_t auto_unexport; 769148c5f43SAlan Wright 7708622ec45SGordon Ross share_avl = &sv->sv_export.e_share_avl; 771148c5f43SAlan Wright 772148c5f43SAlan Wright key.shr_name = (char *)shrname; 773148c5f43SAlan Wright if ((shr = smb_avl_lookup(share_avl, &key)) == NULL) 774148c5f43SAlan Wright return (ENOENT); 775148c5f43SAlan Wright 776148c5f43SAlan Wright if ((shr->shr_flags & SMB_SHRF_AUTOHOME) != 0) { 777148c5f43SAlan Wright mutex_enter(&shr->shr_mutex); 778148c5f43SAlan Wright shr->shr_autocnt--; 779148c5f43SAlan Wright auto_unexport = (shr->shr_autocnt == 0); 780148c5f43SAlan Wright mutex_exit(&shr->shr_mutex); 781148c5f43SAlan Wright if (!auto_unexport) { 782148c5f43SAlan Wright smb_avl_release(share_avl, shr); 783148c5f43SAlan Wright return (0); 784148c5f43SAlan Wright } 785148c5f43SAlan Wright } 786148c5f43SAlan Wright 787148c5f43SAlan Wright if (STYPE_ISDSK(shr->shr_type)) { 7888622ec45SGordon Ross if ((rc = smb_server_sharevp(sv, shr->shr_path, &vp)) != 0) { 789148c5f43SAlan Wright smb_avl_release(share_avl, shr); 790148c5f43SAlan Wright cmn_err(CE_WARN, "unexport[%s]: failed obtaining vnode" 791148c5f43SAlan Wright " (%d)", shrname, rc); 792148c5f43SAlan Wright return (rc); 793148c5f43SAlan Wright } 794148c5f43SAlan Wright 7958622ec45SGordon Ross smb_vfs_rele(&sv->sv_export, vp->v_vfsp); 796148c5f43SAlan Wright VN_RELE(vp); 797148c5f43SAlan Wright } 798148c5f43SAlan Wright 799148c5f43SAlan Wright smb_avl_remove(share_avl, shr); 800148c5f43SAlan Wright smb_avl_release(share_avl, shr); 801148c5f43SAlan Wright 802148c5f43SAlan Wright return (0); 803148c5f43SAlan Wright } 804148c5f43SAlan Wright 805148c5f43SAlan Wright /* 806148c5f43SAlan Wright * Exports IPC$ or Admin shares 807148c5f43SAlan Wright */ 808148c5f43SAlan Wright static int 8098622ec45SGordon Ross smb_kshare_export_trans(smb_server_t *sv, char *name, char *path, char *cmnt) 810148c5f43SAlan Wright { 811148c5f43SAlan Wright smb_kshare_t *shr; 812148c5f43SAlan Wright 813148c5f43SAlan Wright ASSERT(name); 814148c5f43SAlan Wright ASSERT(path); 815148c5f43SAlan Wright 8168622ec45SGordon Ross shr = kmem_cache_alloc(smb_kshare_cache_share, KM_SLEEP); 817148c5f43SAlan Wright bzero(shr, sizeof (smb_kshare_t)); 818148c5f43SAlan Wright 819148c5f43SAlan Wright shr->shr_magic = SMB_SHARE_MAGIC; 820148c5f43SAlan Wright shr->shr_refcnt = 1; 821148c5f43SAlan Wright shr->shr_flags = SMB_SHRF_TRANS | smb_kshare_is_admin(shr->shr_name); 822148c5f43SAlan Wright if (strcasecmp(name, "IPC$") == 0) 823148c5f43SAlan Wright shr->shr_type = STYPE_IPC; 824148c5f43SAlan Wright else 825148c5f43SAlan Wright shr->shr_type = STYPE_DISKTREE; 826148c5f43SAlan Wright 827148c5f43SAlan Wright shr->shr_type |= smb_kshare_is_special(shr->shr_name); 828148c5f43SAlan Wright 829148c5f43SAlan Wright shr->shr_name = smb_mem_strdup(name); 830148c5f43SAlan Wright if (path) 831148c5f43SAlan Wright shr->shr_path = smb_mem_strdup(path); 832148c5f43SAlan Wright if (cmnt) 833148c5f43SAlan Wright shr->shr_cmnt = smb_mem_strdup(cmnt); 834148c5f43SAlan Wright shr->shr_oemname = smb_kshare_oemname(name); 835148c5f43SAlan Wright 8368622ec45SGordon Ross return (smb_kshare_export(sv, shr)); 837148c5f43SAlan Wright } 838148c5f43SAlan Wright 839148c5f43SAlan Wright /* 840148c5f43SAlan Wright * Decodes share information in an nvlist format into a smb_kshare_t 841148c5f43SAlan Wright * structure. 842148c5f43SAlan Wright * 843148c5f43SAlan Wright * This is a temporary function and will be replaced by functions 844148c5f43SAlan Wright * provided by libsharev2 code after it's available. 845148c5f43SAlan Wright */ 846148c5f43SAlan Wright static smb_kshare_t * 847148c5f43SAlan Wright smb_kshare_decode(nvlist_t *share) 848148c5f43SAlan Wright { 849148c5f43SAlan Wright smb_kshare_t tmp; 850148c5f43SAlan Wright smb_kshare_t *shr; 851148c5f43SAlan Wright nvlist_t *smb; 852148c5f43SAlan Wright char *csc_name = NULL; 853148c5f43SAlan Wright int rc; 854148c5f43SAlan Wright 855148c5f43SAlan Wright ASSERT(share); 856148c5f43SAlan Wright 857148c5f43SAlan Wright bzero(&tmp, sizeof (smb_kshare_t)); 858148c5f43SAlan Wright 859148c5f43SAlan Wright rc = nvlist_lookup_string(share, "name", &tmp.shr_name); 860148c5f43SAlan Wright rc |= nvlist_lookup_string(share, "path", &tmp.shr_path); 861148c5f43SAlan Wright (void) nvlist_lookup_string(share, "desc", &tmp.shr_cmnt); 862148c5f43SAlan Wright 863148c5f43SAlan Wright ASSERT(tmp.shr_name && tmp.shr_path); 864148c5f43SAlan Wright 865148c5f43SAlan Wright rc |= nvlist_lookup_nvlist(share, "smb", &smb); 866148c5f43SAlan Wright if (rc != 0) { 867148c5f43SAlan Wright cmn_err(CE_WARN, "kshare: failed looking up SMB properties" 868148c5f43SAlan Wright " (%d)", rc); 869148c5f43SAlan Wright return (NULL); 870148c5f43SAlan Wright } 871148c5f43SAlan Wright 872cb174861Sjoyce mcintosh rc = nvlist_lookup_uint32(smb, "type", &tmp.shr_type); 873cb174861Sjoyce mcintosh if (rc != 0) { 874cb174861Sjoyce mcintosh cmn_err(CE_WARN, "kshare[%s]: failed getting the share type" 875cb174861Sjoyce mcintosh " (%d)", tmp.shr_name, rc); 876cb174861Sjoyce mcintosh return (NULL); 877cb174861Sjoyce mcintosh } 878cb174861Sjoyce mcintosh 879148c5f43SAlan Wright (void) nvlist_lookup_string(smb, SHOPT_AD_CONTAINER, 880148c5f43SAlan Wright &tmp.shr_container); 881148c5f43SAlan Wright (void) nvlist_lookup_string(smb, SHOPT_NONE, &tmp.shr_access_none); 882148c5f43SAlan Wright (void) nvlist_lookup_string(smb, SHOPT_RO, &tmp.shr_access_ro); 883148c5f43SAlan Wright (void) nvlist_lookup_string(smb, SHOPT_RW, &tmp.shr_access_rw); 884148c5f43SAlan Wright 885148c5f43SAlan Wright tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_ABE, SMB_SHRF_ABE); 886148c5f43SAlan Wright tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_CATIA, 887148c5f43SAlan Wright SMB_SHRF_CATIA); 888148c5f43SAlan Wright tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_GUEST, 889148c5f43SAlan Wright SMB_SHRF_GUEST_OK); 890148c5f43SAlan Wright tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_DFSROOT, 891148c5f43SAlan Wright SMB_SHRF_DFSROOT); 892ca5fb90aSGordon Ross tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_QUOTAS, 893ca5fb90aSGordon Ross SMB_SHRF_QUOTAS); 894*94047d49SGordon Ross tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_FSO, SMB_SHRF_FSO); 895ca5fb90aSGordon Ross tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_AUTOHOME, 896148c5f43SAlan Wright SMB_SHRF_AUTOHOME); 897148c5f43SAlan Wright 898148c5f43SAlan Wright if ((tmp.shr_flags & SMB_SHRF_AUTOHOME) == SMB_SHRF_AUTOHOME) { 899148c5f43SAlan Wright rc = nvlist_lookup_uint32(smb, "uid", &tmp.shr_uid); 900148c5f43SAlan Wright rc |= nvlist_lookup_uint32(smb, "gid", &tmp.shr_gid); 901148c5f43SAlan Wright if (rc != 0) { 902cb174861Sjoyce mcintosh cmn_err(CE_WARN, "kshare: failed looking up uid/gid" 903148c5f43SAlan Wright " (%d)", rc); 904148c5f43SAlan Wright return (NULL); 905148c5f43SAlan Wright } 906148c5f43SAlan Wright } 907148c5f43SAlan Wright 908148c5f43SAlan Wright (void) nvlist_lookup_string(smb, SHOPT_CSC, &csc_name); 909148c5f43SAlan Wright smb_kshare_csc_flags(&tmp, csc_name); 910148c5f43SAlan Wright 9118622ec45SGordon Ross shr = kmem_cache_alloc(smb_kshare_cache_share, KM_SLEEP); 912148c5f43SAlan Wright bzero(shr, sizeof (smb_kshare_t)); 913148c5f43SAlan Wright 914148c5f43SAlan Wright shr->shr_magic = SMB_SHARE_MAGIC; 915148c5f43SAlan Wright shr->shr_refcnt = 1; 916148c5f43SAlan Wright 917148c5f43SAlan Wright shr->shr_name = smb_mem_strdup(tmp.shr_name); 918148c5f43SAlan Wright shr->shr_path = smb_mem_strdup(tmp.shr_path); 919148c5f43SAlan Wright if (tmp.shr_cmnt) 920148c5f43SAlan Wright shr->shr_cmnt = smb_mem_strdup(tmp.shr_cmnt); 921148c5f43SAlan Wright if (tmp.shr_container) 922148c5f43SAlan Wright shr->shr_container = smb_mem_strdup(tmp.shr_container); 923148c5f43SAlan Wright if (tmp.shr_access_none) 924148c5f43SAlan Wright shr->shr_access_none = smb_mem_strdup(tmp.shr_access_none); 925148c5f43SAlan Wright if (tmp.shr_access_ro) 926148c5f43SAlan Wright shr->shr_access_ro = smb_mem_strdup(tmp.shr_access_ro); 927148c5f43SAlan Wright if (tmp.shr_access_rw) 928148c5f43SAlan Wright shr->shr_access_rw = smb_mem_strdup(tmp.shr_access_rw); 929148c5f43SAlan Wright 930148c5f43SAlan Wright shr->shr_oemname = smb_kshare_oemname(shr->shr_name); 931148c5f43SAlan Wright shr->shr_flags = tmp.shr_flags | smb_kshare_is_admin(shr->shr_name); 932cb174861Sjoyce mcintosh shr->shr_type = tmp.shr_type | smb_kshare_is_special(shr->shr_name); 933148c5f43SAlan Wright 934148c5f43SAlan Wright shr->shr_uid = tmp.shr_uid; 935148c5f43SAlan Wright shr->shr_gid = tmp.shr_gid; 936148c5f43SAlan Wright 937148c5f43SAlan Wright if ((shr->shr_flags & SMB_SHRF_AUTOHOME) == SMB_SHRF_AUTOHOME) 938148c5f43SAlan Wright shr->shr_autocnt = 1; 939148c5f43SAlan Wright 940148c5f43SAlan Wright return (shr); 941148c5f43SAlan Wright } 942148c5f43SAlan Wright 943148c5f43SAlan Wright #if 0 944148c5f43SAlan Wright static void 945148c5f43SAlan Wright smb_kshare_log(smb_kshare_t *shr) 946148c5f43SAlan Wright { 947148c5f43SAlan Wright cmn_err(CE_NOTE, "Share info:"); 948148c5f43SAlan Wright cmn_err(CE_NOTE, "\tname: %s", (shr->shr_name) ? shr->shr_name : ""); 949148c5f43SAlan Wright cmn_err(CE_NOTE, "\tpath: %s", (shr->shr_path) ? shr->shr_path : ""); 950148c5f43SAlan Wright cmn_err(CE_NOTE, "\tcmnt: (%s)", 951148c5f43SAlan Wright (shr->shr_cmnt) ? shr->shr_cmnt : "NULL"); 952148c5f43SAlan Wright cmn_err(CE_NOTE, "\toemname: (%s)", 953148c5f43SAlan Wright (shr->shr_oemname) ? shr->shr_oemname : "NULL"); 954148c5f43SAlan Wright cmn_err(CE_NOTE, "\tflags: %X", shr->shr_flags); 955148c5f43SAlan Wright cmn_err(CE_NOTE, "\ttype: %d", shr->shr_type); 956148c5f43SAlan Wright } 957148c5f43SAlan Wright #endif 958148c5f43SAlan Wright 959148c5f43SAlan Wright /* 960148c5f43SAlan Wright * Compare function used by shares AVL 961148c5f43SAlan Wright */ 962148c5f43SAlan Wright static int 963148c5f43SAlan Wright smb_kshare_cmp(const void *p1, const void *p2) 964148c5f43SAlan Wright { 965148c5f43SAlan Wright smb_kshare_t *shr1 = (smb_kshare_t *)p1; 966148c5f43SAlan Wright smb_kshare_t *shr2 = (smb_kshare_t *)p2; 967148c5f43SAlan Wright int rc; 968148c5f43SAlan Wright 969148c5f43SAlan Wright ASSERT(shr1); 970148c5f43SAlan Wright ASSERT(shr1->shr_name); 971148c5f43SAlan Wright 972148c5f43SAlan Wright ASSERT(shr2); 973148c5f43SAlan Wright ASSERT(shr2->shr_name); 974148c5f43SAlan Wright 975148c5f43SAlan Wright rc = smb_strcasecmp(shr1->shr_name, shr2->shr_name, 0); 976148c5f43SAlan Wright 977148c5f43SAlan Wright if (rc < 0) 978148c5f43SAlan Wright return (-1); 979148c5f43SAlan Wright 980148c5f43SAlan Wright if (rc > 0) 981148c5f43SAlan Wright return (1); 982148c5f43SAlan Wright 983148c5f43SAlan Wright return (0); 984148c5f43SAlan Wright } 985148c5f43SAlan Wright 986148c5f43SAlan Wright /* 987148c5f43SAlan Wright * This function is called by smb_avl routines whenever 988148c5f43SAlan Wright * there is a need to take a hold on a share structure 989148c5f43SAlan Wright * inside AVL 990148c5f43SAlan Wright */ 991148c5f43SAlan Wright static void 992148c5f43SAlan Wright smb_kshare_hold(const void *p) 993148c5f43SAlan Wright { 994148c5f43SAlan Wright smb_kshare_t *shr = (smb_kshare_t *)p; 995148c5f43SAlan Wright 996148c5f43SAlan Wright ASSERT(shr); 997148c5f43SAlan Wright ASSERT(shr->shr_magic == SMB_SHARE_MAGIC); 998148c5f43SAlan Wright 999148c5f43SAlan Wright mutex_enter(&shr->shr_mutex); 1000148c5f43SAlan Wright shr->shr_refcnt++; 1001148c5f43SAlan Wright mutex_exit(&shr->shr_mutex); 1002148c5f43SAlan Wright } 1003148c5f43SAlan Wright 1004148c5f43SAlan Wright /* 1005148c5f43SAlan Wright * This function must be called by smb_avl routines whenever 1006148c5f43SAlan Wright * smb_kshare_hold is called and the hold needs to be released. 1007148c5f43SAlan Wright */ 1008148c5f43SAlan Wright static boolean_t 1009148c5f43SAlan Wright smb_kshare_rele(const void *p) 1010148c5f43SAlan Wright { 1011148c5f43SAlan Wright smb_kshare_t *shr = (smb_kshare_t *)p; 1012148c5f43SAlan Wright boolean_t destroy; 1013148c5f43SAlan Wright 1014148c5f43SAlan Wright ASSERT(shr); 1015148c5f43SAlan Wright ASSERT(shr->shr_magic == SMB_SHARE_MAGIC); 1016148c5f43SAlan Wright 1017148c5f43SAlan Wright mutex_enter(&shr->shr_mutex); 1018148c5f43SAlan Wright ASSERT(shr->shr_refcnt > 0); 1019148c5f43SAlan Wright shr->shr_refcnt--; 1020148c5f43SAlan Wright destroy = (shr->shr_refcnt == 0); 1021148c5f43SAlan Wright mutex_exit(&shr->shr_mutex); 1022148c5f43SAlan Wright 1023148c5f43SAlan Wright return (destroy); 1024148c5f43SAlan Wright } 1025148c5f43SAlan Wright 1026148c5f43SAlan Wright /* 1027148c5f43SAlan Wright * Frees all the memory allocated for the given 1028148c5f43SAlan Wright * share structure. It also removes the structure 1029148c5f43SAlan Wright * from the share cache. 1030148c5f43SAlan Wright */ 1031148c5f43SAlan Wright static void 1032148c5f43SAlan Wright smb_kshare_destroy(void *p) 1033148c5f43SAlan Wright { 1034148c5f43SAlan Wright smb_kshare_t *shr = (smb_kshare_t *)p; 1035148c5f43SAlan Wright 1036148c5f43SAlan Wright ASSERT(shr); 1037148c5f43SAlan Wright ASSERT(shr->shr_magic == SMB_SHARE_MAGIC); 1038148c5f43SAlan Wright 1039148c5f43SAlan Wright smb_mem_free(shr->shr_name); 1040148c5f43SAlan Wright smb_mem_free(shr->shr_path); 1041148c5f43SAlan Wright smb_mem_free(shr->shr_cmnt); 1042148c5f43SAlan Wright smb_mem_free(shr->shr_container); 1043148c5f43SAlan Wright smb_mem_free(shr->shr_oemname); 1044148c5f43SAlan Wright smb_mem_free(shr->shr_access_none); 1045148c5f43SAlan Wright smb_mem_free(shr->shr_access_ro); 1046148c5f43SAlan Wright smb_mem_free(shr->shr_access_rw); 1047148c5f43SAlan Wright 10488622ec45SGordon Ross kmem_cache_free(smb_kshare_cache_share, shr); 1049148c5f43SAlan Wright } 1050148c5f43SAlan Wright 1051148c5f43SAlan Wright 1052148c5f43SAlan Wright /* 1053148c5f43SAlan Wright * Generate an OEM name for the given share name. If the name is 1054148c5f43SAlan Wright * shorter than 13 bytes the oemname will be returned; otherwise NULL 1055148c5f43SAlan Wright * is returned. 1056148c5f43SAlan Wright */ 1057148c5f43SAlan Wright static char * 1058148c5f43SAlan Wright smb_kshare_oemname(const char *shrname) 1059148c5f43SAlan Wright { 1060148c5f43SAlan Wright smb_wchar_t *unibuf; 1061148c5f43SAlan Wright char *oem_name; 1062148c5f43SAlan Wright int length; 1063148c5f43SAlan Wright 1064148c5f43SAlan Wright length = strlen(shrname) + 1; 1065148c5f43SAlan Wright 1066148c5f43SAlan Wright oem_name = smb_mem_alloc(length); 1067148c5f43SAlan Wright unibuf = smb_mem_alloc(length * sizeof (smb_wchar_t)); 1068148c5f43SAlan Wright 1069148c5f43SAlan Wright (void) smb_mbstowcs(unibuf, shrname, length); 1070148c5f43SAlan Wright 1071148c5f43SAlan Wright if (ucstooem(oem_name, unibuf, length, OEM_CPG_850) == 0) 1072148c5f43SAlan Wright (void) strcpy(oem_name, shrname); 1073148c5f43SAlan Wright 1074148c5f43SAlan Wright smb_mem_free(unibuf); 1075148c5f43SAlan Wright 1076148c5f43SAlan Wright if (strlen(oem_name) + 1 > SMB_SHARE_OEMNAME_MAX) { 1077148c5f43SAlan Wright smb_mem_free(oem_name); 1078148c5f43SAlan Wright return (NULL); 1079148c5f43SAlan Wright } 1080148c5f43SAlan Wright 1081148c5f43SAlan Wright return (oem_name); 1082148c5f43SAlan Wright } 1083148c5f43SAlan Wright 1084148c5f43SAlan Wright /* 1085148c5f43SAlan Wright * Special share reserved for interprocess communication (IPC$) or 1086148c5f43SAlan Wright * remote administration of the server (ADMIN$). Can also refer to 1087148c5f43SAlan Wright * administrative shares such as C$, D$, E$, and so forth. 1088148c5f43SAlan Wright */ 1089148c5f43SAlan Wright static int 1090148c5f43SAlan Wright smb_kshare_is_special(const char *sharename) 1091148c5f43SAlan Wright { 1092148c5f43SAlan Wright int len; 1093148c5f43SAlan Wright 1094148c5f43SAlan Wright if (sharename == NULL) 1095148c5f43SAlan Wright return (0); 1096148c5f43SAlan Wright 1097148c5f43SAlan Wright if ((len = strlen(sharename)) == 0) 1098148c5f43SAlan Wright return (0); 1099148c5f43SAlan Wright 1100148c5f43SAlan Wright if (sharename[len - 1] == '$') 1101148c5f43SAlan Wright return (STYPE_SPECIAL); 1102148c5f43SAlan Wright 1103148c5f43SAlan Wright return (0); 1104148c5f43SAlan Wright } 1105148c5f43SAlan Wright 1106148c5f43SAlan Wright /* 1107148c5f43SAlan Wright * Check whether or not this is a default admin share: C$, D$ etc. 1108148c5f43SAlan Wright */ 1109148c5f43SAlan Wright static boolean_t 1110148c5f43SAlan Wright smb_kshare_is_admin(const char *sharename) 1111148c5f43SAlan Wright { 1112148c5f43SAlan Wright if (sharename == NULL) 1113148c5f43SAlan Wright return (B_FALSE); 1114148c5f43SAlan Wright 1115148c5f43SAlan Wright if (strlen(sharename) == 2 && 1116148c5f43SAlan Wright smb_isalpha(sharename[0]) && sharename[1] == '$') { 1117148c5f43SAlan Wright return (B_TRUE); 1118148c5f43SAlan Wright } 1119148c5f43SAlan Wright 1120148c5f43SAlan Wright return (B_FALSE); 1121148c5f43SAlan Wright } 1122148c5f43SAlan Wright 1123148c5f43SAlan Wright /* 1124148c5f43SAlan Wright * Decodes the given boolean share option. 1125148c5f43SAlan Wright * If the option is present in the nvlist and it's value is true 1126148c5f43SAlan Wright * returns the corresponding flag value, otherwise returns 0. 1127148c5f43SAlan Wright */ 1128148c5f43SAlan Wright static uint32_t 1129148c5f43SAlan Wright smb_kshare_decode_bool(nvlist_t *nvl, const char *propname, uint32_t flag) 1130148c5f43SAlan Wright { 1131148c5f43SAlan Wright char *boolp; 1132148c5f43SAlan Wright 1133148c5f43SAlan Wright if (nvlist_lookup_string(nvl, propname, &boolp) == 0) 1134148c5f43SAlan Wright if (strcasecmp(boolp, "true") == 0) 1135148c5f43SAlan Wright return (flag); 1136148c5f43SAlan Wright 1137148c5f43SAlan Wright return (0); 1138148c5f43SAlan Wright } 1139148c5f43SAlan Wright 1140148c5f43SAlan Wright /* 1141148c5f43SAlan Wright * Map a client-side caching (CSC) option to the appropriate share 1142148c5f43SAlan Wright * flag. Only one option is allowed; an error will be logged if 1143148c5f43SAlan Wright * multiple options have been specified. We don't need to do anything 1144148c5f43SAlan Wright * about multiple values here because the SRVSVC will not recognize 1145148c5f43SAlan Wright * a value containing multiple flags and will return the default value. 1146148c5f43SAlan Wright * 1147148c5f43SAlan Wright * If the option value is not recognized, it will be ignored: invalid 1148148c5f43SAlan Wright * values will typically be caught and rejected by sharemgr. 1149148c5f43SAlan Wright */ 1150148c5f43SAlan Wright static void 1151148c5f43SAlan Wright smb_kshare_csc_flags(smb_kshare_t *shr, const char *value) 1152148c5f43SAlan Wright { 1153148c5f43SAlan Wright int i; 1154148c5f43SAlan Wright static struct { 1155148c5f43SAlan Wright char *value; 1156148c5f43SAlan Wright uint32_t flag; 1157148c5f43SAlan Wright } cscopt[] = { 1158148c5f43SAlan Wright { "disabled", SMB_SHRF_CSC_DISABLED }, 1159148c5f43SAlan Wright { "manual", SMB_SHRF_CSC_MANUAL }, 1160148c5f43SAlan Wright { "auto", SMB_SHRF_CSC_AUTO }, 1161148c5f43SAlan Wright { "vdo", SMB_SHRF_CSC_VDO } 1162148c5f43SAlan Wright }; 1163148c5f43SAlan Wright 1164148c5f43SAlan Wright if (value == NULL) 1165148c5f43SAlan Wright return; 1166148c5f43SAlan Wright 1167148c5f43SAlan Wright for (i = 0; i < (sizeof (cscopt) / sizeof (cscopt[0])); ++i) { 1168148c5f43SAlan Wright if (strcasecmp(value, cscopt[i].value) == 0) { 1169148c5f43SAlan Wright shr->shr_flags |= cscopt[i].flag; 1170148c5f43SAlan Wright break; 1171148c5f43SAlan Wright } 1172148c5f43SAlan Wright } 1173148c5f43SAlan Wright 1174148c5f43SAlan Wright switch (shr->shr_flags & SMB_SHRF_CSC_MASK) { 1175148c5f43SAlan Wright case 0: 1176148c5f43SAlan Wright case SMB_SHRF_CSC_DISABLED: 1177148c5f43SAlan Wright case SMB_SHRF_CSC_MANUAL: 1178148c5f43SAlan Wright case SMB_SHRF_CSC_AUTO: 1179148c5f43SAlan Wright case SMB_SHRF_CSC_VDO: 1180148c5f43SAlan Wright break; 1181148c5f43SAlan Wright 1182148c5f43SAlan Wright default: 1183148c5f43SAlan Wright cmn_err(CE_NOTE, "csc option conflict: 0x%08x", 1184148c5f43SAlan Wright shr->shr_flags & SMB_SHRF_CSC_MASK); 1185148c5f43SAlan Wright break; 1186148c5f43SAlan Wright } 1187148c5f43SAlan Wright } 1188148c5f43SAlan Wright 1189148c5f43SAlan Wright /* 1190148c5f43SAlan Wright * This function processes the unexport event list and disconnects shares 1191148c5f43SAlan Wright * asynchronously. The function executes as a zone-specific thread. 1192148c5f43SAlan Wright * 1193148c5f43SAlan Wright * The server arg passed in is safe to use without a reference count, because 1194148c5f43SAlan Wright * the server cannot be deleted until smb_thread_stop()/destroy() return, 1195148c5f43SAlan Wright * which is also when the thread exits. 1196148c5f43SAlan Wright */ 1197148c5f43SAlan Wright /*ARGSUSED*/ 1198148c5f43SAlan Wright static void 1199148c5f43SAlan Wright smb_kshare_unexport_thread(smb_thread_t *thread, void *arg) 1200148c5f43SAlan Wright { 12018622ec45SGordon Ross smb_server_t *sv = arg; 1202148c5f43SAlan Wright smb_unshare_t *ux; 1203148c5f43SAlan Wright 1204148c5f43SAlan Wright while (smb_thread_continue(thread)) { 12058622ec45SGordon Ross while ((ux = list_head(&sv->sv_export.e_unexport_list.sl_list)) 1206148c5f43SAlan Wright != NULL) { 12078622ec45SGordon Ross smb_slist_remove(&sv->sv_export.e_unexport_list, ux); 1208148c5f43SAlan Wright (void) smb_server_unshare(ux->us_sharename); 12098622ec45SGordon Ross kmem_cache_free(smb_kshare_cache_unexport, ux); 1210148c5f43SAlan Wright } 1211148c5f43SAlan Wright } 1212148c5f43SAlan Wright } 1213148c5f43SAlan Wright 1214148c5f43SAlan Wright static boolean_t 12158622ec45SGordon Ross smb_export_isready(smb_server_t *sv) 1216148c5f43SAlan Wright { 1217148c5f43SAlan Wright boolean_t ready; 1218148c5f43SAlan Wright 12198622ec45SGordon Ross mutex_enter(&sv->sv_export.e_mutex); 12208622ec45SGordon Ross ready = sv->sv_export.e_ready; 12218622ec45SGordon Ross mutex_exit(&sv->sv_export.e_mutex); 1222148c5f43SAlan Wright 1223148c5f43SAlan Wright return (ready); 1224148c5f43SAlan Wright } 1225148c5f43SAlan Wright 1226b819cea2SGordon Ross #ifdef _KERNEL 1227148c5f43SAlan Wright /* 12283ad684d6Sjb150015 * Return 0 upon success. Otherwise > 0 12293ad684d6Sjb150015 */ 12303ad684d6Sjb150015 static int 12313ad684d6Sjb150015 smb_kshare_chk_dsrv_status(int opcode, smb_dr_ctx_t *dec_ctx) 12323ad684d6Sjb150015 { 12333ad684d6Sjb150015 int status = smb_dr_get_int32(dec_ctx); 12343ad684d6Sjb150015 int err; 12353ad684d6Sjb150015 12363ad684d6Sjb150015 switch (status) { 12373db3f65cSamw case SMB_SHARE_DSUCCESS: 12383ad684d6Sjb150015 return (0); 12393ad684d6Sjb150015 12403db3f65cSamw case SMB_SHARE_DERROR: 12413ad684d6Sjb150015 err = smb_dr_get_uint32(dec_ctx); 12423ad684d6Sjb150015 cmn_err(CE_WARN, "%d: Encountered door server error %d", 12433ad684d6Sjb150015 opcode, err); 12443ad684d6Sjb150015 (void) smb_dr_decode_finish(dec_ctx); 12453ad684d6Sjb150015 return (err); 12463ad684d6Sjb150015 } 12473ad684d6Sjb150015 12483ad684d6Sjb150015 ASSERT(0); 12493ad684d6Sjb150015 return (EINVAL); 12503ad684d6Sjb150015 } 1251b819cea2SGordon Ross #endif /* _KERNEL */ 1252