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. 253ad684d6Sjb150015 */ 263ad684d6Sjb150015 279fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States #include <smbsrv/smb_door.h> 28148c5f43SAlan Wright #include <smbsrv/smb_kproto.h> 29148c5f43SAlan Wright #include <smbsrv/smb_ktypes.h> 30148c5f43SAlan Wright 31148c5f43SAlan Wright typedef struct smb_unshare { 32148c5f43SAlan Wright list_node_t us_lnd; 33148c5f43SAlan Wright char us_sharename[MAXNAMELEN]; 34148c5f43SAlan Wright } smb_unshare_t; 35148c5f43SAlan Wright 368622ec45SGordon Ross static kmem_cache_t *smb_kshare_cache_share; 378622ec45SGordon Ross static kmem_cache_t *smb_kshare_cache_unexport; 388622ec45SGordon Ross kmem_cache_t *smb_kshare_cache_vfs; 39148c5f43SAlan Wright 40148c5f43SAlan Wright static int smb_kshare_cmp(const void *, const void *); 41148c5f43SAlan Wright static void smb_kshare_hold(const void *); 42148c5f43SAlan Wright static boolean_t smb_kshare_rele(const void *); 43148c5f43SAlan Wright static void smb_kshare_destroy(void *); 44148c5f43SAlan Wright static char *smb_kshare_oemname(const char *); 45148c5f43SAlan Wright static int smb_kshare_is_special(const char *); 46148c5f43SAlan Wright static boolean_t smb_kshare_is_admin(const char *); 47148c5f43SAlan Wright static smb_kshare_t *smb_kshare_decode(nvlist_t *); 48148c5f43SAlan Wright static uint32_t smb_kshare_decode_bool(nvlist_t *, const char *, uint32_t); 49148c5f43SAlan Wright static void smb_kshare_unexport_thread(smb_thread_t *, void *); 508622ec45SGordon Ross static int smb_kshare_export(smb_server_t *, smb_kshare_t *); 518622ec45SGordon Ross static int smb_kshare_unexport(smb_server_t *, const char *); 528622ec45SGordon Ross static int smb_kshare_export_trans(smb_server_t *, char *, char *, char *); 53148c5f43SAlan Wright static void smb_kshare_csc_flags(smb_kshare_t *, const char *); 54148c5f43SAlan Wright 558622ec45SGordon Ross static boolean_t smb_export_isready(smb_server_t *); 563ad684d6Sjb150015 57b819cea2SGordon Ross #ifdef _KERNEL 583ad684d6Sjb150015 static int smb_kshare_chk_dsrv_status(int, smb_dr_ctx_t *); 59b819cea2SGordon Ross #endif /* _KERNEL */ 603ad684d6Sjb150015 618622ec45SGordon Ross static const smb_avl_nops_t smb_kshare_avlops = { 62148c5f43SAlan Wright smb_kshare_cmp, 63148c5f43SAlan Wright smb_kshare_hold, 64148c5f43SAlan Wright smb_kshare_rele, 65148c5f43SAlan Wright smb_kshare_destroy 66148c5f43SAlan Wright }; 67148c5f43SAlan Wright 68b819cea2SGordon Ross #ifdef _KERNEL 693ad684d6Sjb150015 /* 703ad684d6Sjb150015 * This function is not MultiThread safe. The caller has to make sure only one 713ad684d6Sjb150015 * thread calls this function. 723ad684d6Sjb150015 */ 733ad684d6Sjb150015 door_handle_t 74148c5f43SAlan Wright smb_kshare_door_init(int door_id) 753ad684d6Sjb150015 { 763ad684d6Sjb150015 return (door_ki_lookup(door_id)); 773ad684d6Sjb150015 } 783ad684d6Sjb150015 793ad684d6Sjb150015 /* 803ad684d6Sjb150015 * This function is not MultiThread safe. The caller has to make sure only one 813ad684d6Sjb150015 * thread calls this function. 823ad684d6Sjb150015 */ 833ad684d6Sjb150015 void 84148c5f43SAlan Wright smb_kshare_door_fini(door_handle_t dhdl) 853ad684d6Sjb150015 { 863ad684d6Sjb150015 if (dhdl) 873ad684d6Sjb150015 door_ki_rele(dhdl); 883ad684d6Sjb150015 } 893ad684d6Sjb150015 9029bd2886SAlan Wright /* 913ad684d6Sjb150015 * This is a special interface that will be utilized by ZFS to cause 923ad684d6Sjb150015 * a share to be added/removed 933ad684d6Sjb150015 * 943db3f65cSamw * arg is either a smb_share_t or share_name from userspace. 953db3f65cSamw * It will need to be copied into the kernel. It is smb_share_t 963ad684d6Sjb150015 * for add operations and share_name for delete operations. 973ad684d6Sjb150015 */ 983ad684d6Sjb150015 int 993ad684d6Sjb150015 smb_kshare_upcall(door_handle_t dhdl, void *arg, boolean_t add_share) 1003ad684d6Sjb150015 { 1013ad684d6Sjb150015 door_arg_t doorarg = { 0 }; 1023ad684d6Sjb150015 char *buf = NULL; 1033ad684d6Sjb150015 char *str = NULL; 1043ad684d6Sjb150015 int error; 1053ad684d6Sjb150015 int rc; 1063ad684d6Sjb150015 unsigned int used; 1073ad684d6Sjb150015 smb_dr_ctx_t *dec_ctx; 1083ad684d6Sjb150015 smb_dr_ctx_t *enc_ctx; 1093db3f65cSamw smb_share_t *lmshare = NULL; 1103ad684d6Sjb150015 int opcode; 1113ad684d6Sjb150015 1123db3f65cSamw opcode = (add_share) ? SMB_SHROP_ADD : SMB_SHROP_DELETE; 1133ad684d6Sjb150015 1143db3f65cSamw buf = kmem_alloc(SMB_SHARE_DSIZE, KM_SLEEP); 1153db3f65cSamw enc_ctx = smb_dr_encode_start(buf, SMB_SHARE_DSIZE); 1163ad684d6Sjb150015 smb_dr_put_uint32(enc_ctx, opcode); 1173ad684d6Sjb150015 1183ad684d6Sjb150015 switch (opcode) { 1193db3f65cSamw case SMB_SHROP_ADD: 1203db3f65cSamw lmshare = kmem_alloc(sizeof (smb_share_t), KM_SLEEP); 121b819cea2SGordon Ross error = xcopyin(arg, lmshare, sizeof (smb_share_t)); 122b819cea2SGordon Ross if (error != 0) { 1233db3f65cSamw kmem_free(lmshare, sizeof (smb_share_t)); 1243db3f65cSamw kmem_free(buf, SMB_SHARE_DSIZE); 1253ad684d6Sjb150015 return (error); 1263ad684d6Sjb150015 } 1273db3f65cSamw smb_dr_put_share(enc_ctx, lmshare); 1283ad684d6Sjb150015 break; 1293ad684d6Sjb150015 1303db3f65cSamw case SMB_SHROP_DELETE: 1313ad684d6Sjb150015 str = kmem_alloc(MAXPATHLEN, KM_SLEEP); 132b819cea2SGordon Ross error = copyinstr(arg, str, MAXPATHLEN, NULL); 133b819cea2SGordon Ross if (error != 0) { 1343ad684d6Sjb150015 kmem_free(str, MAXPATHLEN); 1353db3f65cSamw kmem_free(buf, SMB_SHARE_DSIZE); 1363ad684d6Sjb150015 return (error); 1373ad684d6Sjb150015 } 1383ad684d6Sjb150015 smb_dr_put_string(enc_ctx, str); 1393ad684d6Sjb150015 kmem_free(str, MAXPATHLEN); 1403ad684d6Sjb150015 break; 1413ad684d6Sjb150015 } 1423ad684d6Sjb150015 1433ad684d6Sjb150015 if ((error = smb_dr_encode_finish(enc_ctx, &used)) != 0) { 1443db3f65cSamw kmem_free(buf, SMB_SHARE_DSIZE); 1453ad684d6Sjb150015 if (lmshare) 1463db3f65cSamw kmem_free(lmshare, sizeof (smb_share_t)); 1473ad684d6Sjb150015 return (NERR_InternalError); 1483ad684d6Sjb150015 } 1493ad684d6Sjb150015 1503ad684d6Sjb150015 doorarg.data_ptr = buf; 1513ad684d6Sjb150015 doorarg.data_size = used; 1523ad684d6Sjb150015 doorarg.rbuf = buf; 1533db3f65cSamw doorarg.rsize = SMB_SHARE_DSIZE; 1543ad684d6Sjb150015 155323a81d9Sjwadams error = door_ki_upcall_limited(dhdl, &doorarg, NULL, SIZE_MAX, 0); 1563ad684d6Sjb150015 1573ad684d6Sjb150015 if (error) { 1583db3f65cSamw kmem_free(buf, SMB_SHARE_DSIZE); 1593ad684d6Sjb150015 if (lmshare) 1603db3f65cSamw kmem_free(lmshare, sizeof (smb_share_t)); 1613ad684d6Sjb150015 return (error); 1623ad684d6Sjb150015 } 1633ad684d6Sjb150015 1643ad684d6Sjb150015 dec_ctx = smb_dr_decode_start(doorarg.data_ptr, doorarg.data_size); 1653ad684d6Sjb150015 if (smb_kshare_chk_dsrv_status(opcode, dec_ctx) != 0) { 1663db3f65cSamw kmem_free(buf, SMB_SHARE_DSIZE); 1673ad684d6Sjb150015 if (lmshare) 1683db3f65cSamw kmem_free(lmshare, sizeof (smb_share_t)); 1693ad684d6Sjb150015 return (NERR_InternalError); 1703ad684d6Sjb150015 } 1713ad684d6Sjb150015 1723ad684d6Sjb150015 rc = smb_dr_get_uint32(dec_ctx); 1733db3f65cSamw if (opcode == SMB_SHROP_ADD) 1743db3f65cSamw smb_dr_get_share(dec_ctx, lmshare); 1753ad684d6Sjb150015 1763ad684d6Sjb150015 if (smb_dr_decode_finish(dec_ctx)) 1773ad684d6Sjb150015 rc = NERR_InternalError; 1783ad684d6Sjb150015 1793db3f65cSamw kmem_free(buf, SMB_SHARE_DSIZE); 1803ad684d6Sjb150015 if (lmshare) 1813db3f65cSamw kmem_free(lmshare, sizeof (smb_share_t)); 1823ad684d6Sjb150015 1833ad684d6Sjb150015 return ((rc == NERR_DuplicateShare && add_share) ? 0 : rc); 1843ad684d6Sjb150015 } 185b819cea2SGordon Ross #endif /* _KERNEL */ 1863ad684d6Sjb150015 1873ad684d6Sjb150015 /* 188148c5f43SAlan Wright * Executes map and unmap command for shares. 189148c5f43SAlan Wright */ 190148c5f43SAlan Wright int 1918622ec45SGordon Ross smb_kshare_exec(smb_server_t *sv, smb_shr_execinfo_t *execinfo) 192148c5f43SAlan Wright { 193148c5f43SAlan Wright int exec_rc = 0; 194148c5f43SAlan Wright 1958622ec45SGordon Ross (void) smb_kdoor_upcall(sv, SMB_DR_SHR_EXEC, 196148c5f43SAlan Wright execinfo, smb_shr_execinfo_xdr, &exec_rc, xdr_int); 197148c5f43SAlan Wright 198148c5f43SAlan Wright return (exec_rc); 199148c5f43SAlan Wright } 200148c5f43SAlan Wright 201148c5f43SAlan Wright /* 202148c5f43SAlan Wright * Obtains any host access restriction on the specified 203148c5f43SAlan Wright * share for the given host (ipaddr) by calling smbd 204148c5f43SAlan Wright */ 205148c5f43SAlan Wright uint32_t 2068622ec45SGordon Ross smb_kshare_hostaccess(smb_kshare_t *shr, smb_session_t *session) 207148c5f43SAlan Wright { 208148c5f43SAlan Wright smb_shr_hostaccess_query_t req; 2098622ec45SGordon Ross smb_inaddr_t *ipaddr = &session->ipaddr; 210148c5f43SAlan Wright uint32_t host_access = SMB_SHRF_ACC_OPEN; 211148c5f43SAlan Wright uint32_t flag = SMB_SHRF_ACC_OPEN; 212148c5f43SAlan Wright uint32_t access; 213148c5f43SAlan Wright 214148c5f43SAlan Wright if (smb_inet_iszero(ipaddr)) 215148c5f43SAlan Wright return (ACE_ALL_PERMS); 216148c5f43SAlan Wright 217148c5f43SAlan Wright if ((shr->shr_access_none == NULL || *shr->shr_access_none == '\0') && 218148c5f43SAlan Wright (shr->shr_access_ro == NULL || *shr->shr_access_ro == '\0') && 219148c5f43SAlan Wright (shr->shr_access_rw == NULL || *shr->shr_access_rw == '\0')) 220148c5f43SAlan Wright return (ACE_ALL_PERMS); 221148c5f43SAlan Wright 222148c5f43SAlan Wright if (shr->shr_access_none != NULL) 223148c5f43SAlan Wright flag |= SMB_SHRF_ACC_NONE; 224148c5f43SAlan Wright if (shr->shr_access_ro != NULL) 225148c5f43SAlan Wright flag |= SMB_SHRF_ACC_RO; 226148c5f43SAlan Wright if (shr->shr_access_rw != NULL) 227148c5f43SAlan Wright flag |= SMB_SHRF_ACC_RW; 228148c5f43SAlan Wright 229148c5f43SAlan Wright req.shq_none = shr->shr_access_none; 230148c5f43SAlan Wright req.shq_ro = shr->shr_access_ro; 231148c5f43SAlan Wright req.shq_rw = shr->shr_access_rw; 232148c5f43SAlan Wright req.shq_flag = flag; 233148c5f43SAlan Wright req.shq_ipaddr = *ipaddr; 234148c5f43SAlan Wright 2358622ec45SGordon Ross (void) smb_kdoor_upcall(session->s_server, SMB_DR_SHR_HOSTACCESS, 236148c5f43SAlan Wright &req, smb_shr_hostaccess_query_xdr, &host_access, xdr_uint32_t); 237148c5f43SAlan Wright 238148c5f43SAlan Wright switch (host_access) { 239148c5f43SAlan Wright case SMB_SHRF_ACC_RO: 240148c5f43SAlan Wright access = ACE_ALL_PERMS & ~ACE_ALL_WRITE_PERMS; 241148c5f43SAlan Wright break; 242148c5f43SAlan Wright case SMB_SHRF_ACC_OPEN: 243148c5f43SAlan Wright case SMB_SHRF_ACC_RW: 244148c5f43SAlan Wright access = ACE_ALL_PERMS; 245148c5f43SAlan Wright break; 246148c5f43SAlan Wright case SMB_SHRF_ACC_NONE: 247148c5f43SAlan Wright default: 248148c5f43SAlan Wright access = 0; 249148c5f43SAlan Wright } 250148c5f43SAlan Wright 251148c5f43SAlan Wright return (access); 252148c5f43SAlan Wright } 253148c5f43SAlan Wright 254148c5f43SAlan Wright /* 255148c5f43SAlan Wright * This function is called when smb_server_t is 256148c5f43SAlan Wright * created which means smb/service is ready for 257148c5f43SAlan Wright * exporting SMB shares 258148c5f43SAlan Wright */ 259148c5f43SAlan Wright void 2608622ec45SGordon Ross smb_export_start(smb_server_t *sv) 261148c5f43SAlan Wright { 2628622ec45SGordon Ross mutex_enter(&sv->sv_export.e_mutex); 2638622ec45SGordon Ross if (sv->sv_export.e_ready) { 2648622ec45SGordon Ross mutex_exit(&sv->sv_export.e_mutex); 265148c5f43SAlan Wright return; 266148c5f43SAlan Wright } 267148c5f43SAlan Wright 2688622ec45SGordon Ross sv->sv_export.e_ready = B_TRUE; 2698622ec45SGordon Ross mutex_exit(&sv->sv_export.e_mutex); 270148c5f43SAlan Wright 2718622ec45SGordon Ross smb_avl_create(&sv->sv_export.e_share_avl, sizeof (smb_kshare_t), 272148c5f43SAlan Wright offsetof(smb_kshare_t, shr_link), &smb_kshare_avlops); 273148c5f43SAlan Wright 2748622ec45SGordon Ross (void) smb_kshare_export_trans(sv, "IPC$", "IPC$", "Remote IPC"); 2758622ec45SGordon Ross (void) smb_kshare_export_trans(sv, "c$", SMB_CVOL, "Default Share"); 2768622ec45SGordon Ross (void) smb_kshare_export_trans(sv, "vss$", SMB_VSS, "VSS"); 277148c5f43SAlan Wright } 278148c5f43SAlan Wright 279148c5f43SAlan Wright /* 280148c5f43SAlan Wright * This function is called when smb_server_t goes 281148c5f43SAlan Wright * away which means SMB shares should not be made 282148c5f43SAlan Wright * available to clients 283148c5f43SAlan Wright */ 284148c5f43SAlan Wright void 2858622ec45SGordon Ross smb_export_stop(smb_server_t *sv) 286148c5f43SAlan Wright { 2878622ec45SGordon Ross mutex_enter(&sv->sv_export.e_mutex); 2888622ec45SGordon Ross if (!sv->sv_export.e_ready) { 2898622ec45SGordon Ross mutex_exit(&sv->sv_export.e_mutex); 290148c5f43SAlan Wright return; 291148c5f43SAlan Wright } 2928622ec45SGordon Ross sv->sv_export.e_ready = B_FALSE; 2938622ec45SGordon Ross mutex_exit(&sv->sv_export.e_mutex); 294148c5f43SAlan Wright 2958622ec45SGordon Ross smb_avl_destroy(&sv->sv_export.e_share_avl); 2968622ec45SGordon Ross smb_vfs_rele_all(&sv->sv_export); 297148c5f43SAlan Wright } 298148c5f43SAlan Wright 299148c5f43SAlan Wright void 3008622ec45SGordon Ross smb_kshare_g_init(void) 3018622ec45SGordon Ross { 3028622ec45SGordon Ross smb_kshare_cache_share = kmem_cache_create("smb_share_cache", 3038622ec45SGordon Ross sizeof (smb_kshare_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 3048622ec45SGordon Ross 3058622ec45SGordon Ross smb_kshare_cache_unexport = kmem_cache_create("smb_unexport_cache", 3068622ec45SGordon Ross sizeof (smb_unshare_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 3078622ec45SGordon Ross 3088622ec45SGordon Ross smb_kshare_cache_vfs = kmem_cache_create("smb_vfs_cache", 3098622ec45SGordon Ross sizeof (smb_vfs_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 3108622ec45SGordon Ross } 3118622ec45SGordon Ross 3128622ec45SGordon Ross void 3138622ec45SGordon Ross smb_kshare_init(smb_server_t *sv) 3148622ec45SGordon Ross { 3158622ec45SGordon Ross 3168622ec45SGordon Ross smb_llist_constructor(&sv->sv_export.e_vfs_list, sizeof (smb_vfs_t), 3178622ec45SGordon Ross offsetof(smb_vfs_t, sv_lnd)); 3188622ec45SGordon Ross 3198622ec45SGordon Ross smb_slist_constructor(&sv->sv_export.e_unexport_list, 3208622ec45SGordon Ross sizeof (smb_unshare_t), offsetof(smb_unshare_t, us_lnd)); 3218622ec45SGordon Ross } 3228622ec45SGordon Ross 3238622ec45SGordon Ross int 3248622ec45SGordon Ross smb_kshare_start(smb_server_t *sv) 3258622ec45SGordon Ross { 326*a90cf9f2SGordon Ross smb_thread_init(&sv->sv_export.e_unexport_thread, "smb_kshare_unexport", 3278622ec45SGordon Ross smb_kshare_unexport_thread, sv, smbsrv_base_pri); 3288622ec45SGordon Ross 3298622ec45SGordon Ross return (smb_thread_start(&sv->sv_export.e_unexport_thread)); 3308622ec45SGordon Ross } 3318622ec45SGordon Ross 3328622ec45SGordon Ross void 3338622ec45SGordon Ross smb_kshare_stop(smb_server_t *sv) 3348622ec45SGordon Ross { 3358622ec45SGordon Ross smb_thread_stop(&sv->sv_export.e_unexport_thread); 3368622ec45SGordon Ross smb_thread_destroy(&sv->sv_export.e_unexport_thread); 3378622ec45SGordon Ross } 3388622ec45SGordon Ross 3398622ec45SGordon Ross void 3408622ec45SGordon Ross smb_kshare_fini(smb_server_t *sv) 341148c5f43SAlan Wright { 342148c5f43SAlan Wright smb_unshare_t *ux; 343148c5f43SAlan Wright 3448622ec45SGordon Ross while ((ux = list_head(&sv->sv_export.e_unexport_list.sl_list)) 3458622ec45SGordon Ross != NULL) { 3468622ec45SGordon Ross smb_slist_remove(&sv->sv_export.e_unexport_list, ux); 3478622ec45SGordon Ross kmem_cache_free(smb_kshare_cache_unexport, ux); 348148c5f43SAlan Wright } 3498622ec45SGordon Ross smb_slist_destructor(&sv->sv_export.e_unexport_list); 350148c5f43SAlan Wright 3518622ec45SGordon Ross smb_vfs_rele_all(&sv->sv_export); 352148c5f43SAlan Wright 3538622ec45SGordon Ross smb_llist_destructor(&sv->sv_export.e_vfs_list); 3548622ec45SGordon Ross } 355148c5f43SAlan Wright 3568622ec45SGordon Ross void 3578622ec45SGordon Ross smb_kshare_g_fini(void) 3588622ec45SGordon Ross { 3598622ec45SGordon Ross kmem_cache_destroy(smb_kshare_cache_unexport); 3608622ec45SGordon Ross kmem_cache_destroy(smb_kshare_cache_share); 3618622ec45SGordon Ross kmem_cache_destroy(smb_kshare_cache_vfs); 362148c5f43SAlan Wright } 363148c5f43SAlan Wright 364148c5f43SAlan Wright /* 365148c5f43SAlan Wright * A list of shares in nvlist format can be sent down 366148c5f43SAlan Wright * from userspace thourgh the IOCTL interface. The nvlist 367148c5f43SAlan Wright * is unpacked here and all the shares in the list will 368148c5f43SAlan Wright * be exported. 369148c5f43SAlan Wright */ 370148c5f43SAlan Wright int 371148c5f43SAlan Wright smb_kshare_export_list(smb_ioc_share_t *ioc) 372148c5f43SAlan Wright { 3738622ec45SGordon Ross smb_server_t *sv = NULL; 3744846df9bSKevin Crowe nvlist_t *shrlist = NULL; 375148c5f43SAlan Wright nvlist_t *share; 376148c5f43SAlan Wright nvpair_t *nvp; 377148c5f43SAlan Wright smb_kshare_t *shr; 378148c5f43SAlan Wright char *shrname; 3798622ec45SGordon Ross int rc; 380148c5f43SAlan Wright 3814846df9bSKevin Crowe if ((rc = smb_server_lookup(&sv)) != 0) 3824846df9bSKevin Crowe return (rc); 3834846df9bSKevin Crowe 3848622ec45SGordon Ross if (!smb_export_isready(sv)) { 3858622ec45SGordon Ross rc = ENOTACTIVE; 3868622ec45SGordon Ross goto out; 3878622ec45SGordon Ross } 3888622ec45SGordon Ross 3898622ec45SGordon Ross rc = nvlist_unpack(ioc->shr, ioc->shrlen, &shrlist, KM_SLEEP); 3908622ec45SGordon Ross if (rc != 0) 3914846df9bSKevin Crowe goto out; 392148c5f43SAlan Wright 393148c5f43SAlan Wright for (nvp = nvlist_next_nvpair(shrlist, NULL); nvp != NULL; 394148c5f43SAlan Wright nvp = nvlist_next_nvpair(shrlist, nvp)) { 3954846df9bSKevin Crowe 3964846df9bSKevin Crowe /* 3974846df9bSKevin Crowe * Since this loop can run for a while we want to exit 3984846df9bSKevin Crowe * as soon as the server state is anything but RUNNING 3994846df9bSKevin Crowe * to allow shutdown to proceed. 4004846df9bSKevin Crowe */ 4014846df9bSKevin Crowe if (sv->sv_state != SMB_SERVER_STATE_RUNNING) 4024846df9bSKevin Crowe goto out; 4034846df9bSKevin Crowe 404148c5f43SAlan Wright if (nvpair_type(nvp) != DATA_TYPE_NVLIST) 405148c5f43SAlan Wright continue; 406148c5f43SAlan Wright 407148c5f43SAlan Wright shrname = nvpair_name(nvp); 408148c5f43SAlan Wright ASSERT(shrname); 409148c5f43SAlan Wright 410148c5f43SAlan Wright if ((rc = nvpair_value_nvlist(nvp, &share)) != 0) { 411148c5f43SAlan Wright cmn_err(CE_WARN, "export[%s]: failed accessing", 412148c5f43SAlan Wright shrname); 413148c5f43SAlan Wright continue; 414148c5f43SAlan Wright } 415148c5f43SAlan Wright 416148c5f43SAlan Wright if ((shr = smb_kshare_decode(share)) == NULL) { 417148c5f43SAlan Wright cmn_err(CE_WARN, "export[%s]: failed decoding", 418148c5f43SAlan Wright shrname); 419148c5f43SAlan Wright continue; 420148c5f43SAlan Wright } 421148c5f43SAlan Wright 4224846df9bSKevin Crowe /* smb_kshare_export consumes shr so it's not leaked */ 4238622ec45SGordon Ross if ((rc = smb_kshare_export(sv, shr)) != 0) { 424148c5f43SAlan Wright smb_kshare_destroy(shr); 425148c5f43SAlan Wright continue; 426148c5f43SAlan Wright } 427148c5f43SAlan Wright } 4284846df9bSKevin Crowe rc = 0; 429148c5f43SAlan Wright 4304846df9bSKevin Crowe out: 431148c5f43SAlan Wright nvlist_free(shrlist); 4324846df9bSKevin Crowe smb_server_release(sv); 4334846df9bSKevin Crowe return (rc); 434148c5f43SAlan Wright } 435148c5f43SAlan Wright 436148c5f43SAlan Wright /* 437148c5f43SAlan Wright * This function is invoked when a share is disabled to disconnect trees 438148c5f43SAlan Wright * and close files. Cleaning up may involve VOP and/or VFS calls, which 439148c5f43SAlan Wright * may conflict/deadlock with stuck threads if something is amiss with the 440148c5f43SAlan Wright * file system. Queueing the request for asynchronous processing allows the 441148c5f43SAlan Wright * call to return immediately so that, if the unshare is being done in the 442148c5f43SAlan Wright * context of a forced unmount, the forced unmount will always be able to 443148c5f43SAlan Wright * proceed (unblocking stuck I/O and eventually allowing all blocked unshare 444148c5f43SAlan Wright * processes to complete). 445148c5f43SAlan Wright * 446148c5f43SAlan Wright * The path lookup to find the root vnode of the VFS in question and the 447148c5f43SAlan Wright * release of this vnode are done synchronously prior to any associated 448148c5f43SAlan Wright * unmount. Doing these asynchronous to an associated unmount could run 449148c5f43SAlan Wright * the risk of a spurious EBUSY for a standard unmount or an EIO during 450148c5f43SAlan Wright * the path lookup due to a forced unmount finishing first. 451148c5f43SAlan Wright */ 452148c5f43SAlan Wright int 453148c5f43SAlan Wright smb_kshare_unexport_list(smb_ioc_share_t *ioc) 454148c5f43SAlan Wright { 4558622ec45SGordon Ross smb_server_t *sv = NULL; 456148c5f43SAlan Wright smb_unshare_t *ux; 4578622ec45SGordon Ross nvlist_t *shrlist = NULL; 458148c5f43SAlan Wright nvpair_t *nvp; 459148c5f43SAlan Wright boolean_t unexport = B_FALSE; 460148c5f43SAlan Wright char *shrname; 461148c5f43SAlan Wright int rc; 462148c5f43SAlan Wright 4638622ec45SGordon Ross if ((rc = smb_server_lookup(&sv)) != 0) 464148c5f43SAlan Wright return (rc); 465148c5f43SAlan Wright 4668622ec45SGordon Ross if ((rc = nvlist_unpack(ioc->shr, ioc->shrlen, &shrlist, 0)) != 0) 4678622ec45SGordon Ross goto out; 4688622ec45SGordon Ross 469148c5f43SAlan Wright for (nvp = nvlist_next_nvpair(shrlist, NULL); nvp != NULL; 470148c5f43SAlan Wright nvp = nvlist_next_nvpair(shrlist, nvp)) { 471148c5f43SAlan Wright if (nvpair_type(nvp) != DATA_TYPE_NVLIST) 472148c5f43SAlan Wright continue; 473148c5f43SAlan Wright 474148c5f43SAlan Wright shrname = nvpair_name(nvp); 475148c5f43SAlan Wright ASSERT(shrname); 476148c5f43SAlan Wright 4778622ec45SGordon Ross if ((rc = smb_kshare_unexport(sv, shrname)) != 0) 478148c5f43SAlan Wright continue; 479148c5f43SAlan Wright 4808622ec45SGordon Ross ux = kmem_cache_alloc(smb_kshare_cache_unexport, KM_SLEEP); 481148c5f43SAlan Wright (void) strlcpy(ux->us_sharename, shrname, MAXNAMELEN); 482148c5f43SAlan Wright 4838622ec45SGordon Ross smb_slist_insert_tail(&sv->sv_export.e_unexport_list, ux); 484148c5f43SAlan Wright unexport = B_TRUE; 485148c5f43SAlan Wright } 486148c5f43SAlan Wright 487148c5f43SAlan Wright if (unexport) 4888622ec45SGordon Ross smb_thread_signal(&sv->sv_export.e_unexport_thread); 4898622ec45SGordon Ross rc = 0; 490148c5f43SAlan Wright 4918622ec45SGordon Ross out: 4928622ec45SGordon Ross nvlist_free(shrlist); 4938622ec45SGordon Ross smb_server_release(sv); 4948622ec45SGordon Ross return (rc); 495148c5f43SAlan Wright } 496148c5f43SAlan Wright 497148c5f43SAlan Wright /* 498cb174861Sjoyce mcintosh * Get properties (currently only shortname enablement) 499cb174861Sjoyce mcintosh * of specified share. 500cb174861Sjoyce mcintosh */ 501cb174861Sjoyce mcintosh int 502cb174861Sjoyce mcintosh smb_kshare_info(smb_ioc_shareinfo_t *ioc) 503cb174861Sjoyce mcintosh { 504cb174861Sjoyce mcintosh ioc->shortnames = smb_shortnames; 505cb174861Sjoyce mcintosh return (0); 506cb174861Sjoyce mcintosh } 507cb174861Sjoyce mcintosh 508cb174861Sjoyce mcintosh /* 509148c5f43SAlan Wright * This function builds a response for a NetShareEnum RAP request. 510148c5f43SAlan Wright * List of shares is scanned twice. In the first round the total number 511148c5f43SAlan Wright * of shares which their OEM name is shorter than 13 chars (esi->es_ntotal) 512148c5f43SAlan Wright * and also the number of shares that fit in the given buffer are calculated. 513148c5f43SAlan Wright * In the second round the shares data are encoded in the buffer. 514148c5f43SAlan Wright * 515148c5f43SAlan Wright * The data associated with each share has two parts, a fixed size part and 516148c5f43SAlan Wright * a variable size part which is share's comment. The outline of the response 517148c5f43SAlan Wright * buffer is so that fixed part for all the shares will appear first and follows 518148c5f43SAlan Wright * with the comments for all those shares and that's why the data cannot be 519148c5f43SAlan Wright * encoded in one round without unnecessarily complicating the code. 520148c5f43SAlan Wright */ 521148c5f43SAlan Wright void 5228622ec45SGordon Ross smb_kshare_enum(smb_server_t *sv, smb_enumshare_info_t *esi) 523148c5f43SAlan Wright { 524148c5f43SAlan Wright smb_avl_t *share_avl; 525148c5f43SAlan Wright smb_avl_cursor_t cursor; 526148c5f43SAlan Wright smb_kshare_t *shr; 527148c5f43SAlan Wright int remained; 528148c5f43SAlan Wright uint16_t infolen = 0; 529148c5f43SAlan Wright uint16_t cmntlen = 0; 530148c5f43SAlan Wright uint16_t sharelen; 531148c5f43SAlan Wright uint16_t clen; 532148c5f43SAlan Wright uint32_t cmnt_offs; 533148c5f43SAlan Wright smb_msgbuf_t info_mb; 534148c5f43SAlan Wright smb_msgbuf_t cmnt_mb; 535148c5f43SAlan Wright boolean_t autohome_added = B_FALSE; 536148c5f43SAlan Wright 5378622ec45SGordon Ross if (!smb_export_isready(sv)) { 538148c5f43SAlan Wright esi->es_ntotal = esi->es_nsent = 0; 539148c5f43SAlan Wright esi->es_datasize = 0; 540148c5f43SAlan Wright return; 541148c5f43SAlan Wright } 542148c5f43SAlan Wright 543148c5f43SAlan Wright esi->es_ntotal = esi->es_nsent = 0; 544148c5f43SAlan Wright remained = esi->es_bufsize; 5458622ec45SGordon Ross share_avl = &sv->sv_export.e_share_avl; 546148c5f43SAlan Wright 547148c5f43SAlan Wright /* Do the necessary calculations in the first round */ 548148c5f43SAlan Wright smb_avl_iterinit(share_avl, &cursor); 549148c5f43SAlan Wright 550148c5f43SAlan Wright while ((shr = smb_avl_iterate(share_avl, &cursor)) != NULL) { 551148c5f43SAlan Wright if (shr->shr_oemname == NULL) { 552148c5f43SAlan Wright smb_avl_release(share_avl, shr); 553148c5f43SAlan Wright continue; 554148c5f43SAlan Wright } 555148c5f43SAlan Wright 556148c5f43SAlan Wright if ((shr->shr_flags & SMB_SHRF_AUTOHOME) && !autohome_added) { 557148c5f43SAlan Wright if (esi->es_posix_uid == shr->shr_uid) { 558148c5f43SAlan Wright autohome_added = B_TRUE; 559148c5f43SAlan Wright } else { 560148c5f43SAlan Wright smb_avl_release(share_avl, shr); 561148c5f43SAlan Wright continue; 562148c5f43SAlan Wright } 563148c5f43SAlan Wright } 564148c5f43SAlan Wright 565148c5f43SAlan Wright esi->es_ntotal++; 566148c5f43SAlan Wright 567148c5f43SAlan Wright if (remained <= 0) { 568148c5f43SAlan Wright smb_avl_release(share_avl, shr); 569148c5f43SAlan Wright continue; 570148c5f43SAlan Wright } 571148c5f43SAlan Wright 572148c5f43SAlan Wright clen = strlen(shr->shr_cmnt) + 1; 573148c5f43SAlan Wright sharelen = SHARE_INFO_1_SIZE + clen; 574148c5f43SAlan Wright 575148c5f43SAlan Wright if (sharelen <= remained) { 576148c5f43SAlan Wright infolen += SHARE_INFO_1_SIZE; 577148c5f43SAlan Wright cmntlen += clen; 578148c5f43SAlan Wright } 579148c5f43SAlan Wright 580148c5f43SAlan Wright remained -= sharelen; 581148c5f43SAlan Wright smb_avl_release(share_avl, shr); 582148c5f43SAlan Wright } 583148c5f43SAlan Wright 584148c5f43SAlan Wright esi->es_datasize = infolen + cmntlen; 585148c5f43SAlan Wright 586148c5f43SAlan Wright smb_msgbuf_init(&info_mb, (uint8_t *)esi->es_buf, infolen, 0); 587148c5f43SAlan Wright smb_msgbuf_init(&cmnt_mb, (uint8_t *)esi->es_buf + infolen, cmntlen, 0); 588148c5f43SAlan Wright cmnt_offs = infolen; 589148c5f43SAlan Wright 590148c5f43SAlan Wright /* Encode the data in the second round */ 591148c5f43SAlan Wright smb_avl_iterinit(share_avl, &cursor); 592148c5f43SAlan Wright autohome_added = B_FALSE; 593148c5f43SAlan Wright 594148c5f43SAlan Wright while ((shr = smb_avl_iterate(share_avl, &cursor)) != NULL) { 595148c5f43SAlan Wright if (shr->shr_oemname == NULL) { 596148c5f43SAlan Wright smb_avl_release(share_avl, shr); 597148c5f43SAlan Wright continue; 598148c5f43SAlan Wright } 599148c5f43SAlan Wright 600148c5f43SAlan Wright if ((shr->shr_flags & SMB_SHRF_AUTOHOME) && !autohome_added) { 601148c5f43SAlan Wright if (esi->es_posix_uid == shr->shr_uid) { 602148c5f43SAlan Wright autohome_added = B_TRUE; 603148c5f43SAlan Wright } else { 604148c5f43SAlan Wright smb_avl_release(share_avl, shr); 605148c5f43SAlan Wright continue; 606148c5f43SAlan Wright } 607148c5f43SAlan Wright } 608148c5f43SAlan Wright 609148c5f43SAlan Wright if (smb_msgbuf_encode(&info_mb, "13c.wl", 610148c5f43SAlan Wright shr->shr_oemname, shr->shr_type, cmnt_offs) < 0) { 611148c5f43SAlan Wright smb_avl_release(share_avl, shr); 612148c5f43SAlan Wright break; 613148c5f43SAlan Wright } 614148c5f43SAlan Wright 615148c5f43SAlan Wright if (smb_msgbuf_encode(&cmnt_mb, "s", shr->shr_cmnt) < 0) { 616148c5f43SAlan Wright smb_avl_release(share_avl, shr); 617148c5f43SAlan Wright break; 618148c5f43SAlan Wright } 619148c5f43SAlan Wright 620148c5f43SAlan Wright cmnt_offs += strlen(shr->shr_cmnt) + 1; 621148c5f43SAlan Wright esi->es_nsent++; 622148c5f43SAlan Wright 623148c5f43SAlan Wright smb_avl_release(share_avl, shr); 624148c5f43SAlan Wright } 625148c5f43SAlan Wright 626148c5f43SAlan Wright smb_msgbuf_term(&info_mb); 627148c5f43SAlan Wright smb_msgbuf_term(&cmnt_mb); 628148c5f43SAlan Wright } 629148c5f43SAlan Wright 630148c5f43SAlan Wright /* 631148c5f43SAlan Wright * Looks up the given share and returns a pointer 632148c5f43SAlan Wright * to its definition if it's found. A hold on the 633148c5f43SAlan Wright * object is taken before the pointer is returned 634148c5f43SAlan Wright * in which case the caller MUST always call 635148c5f43SAlan Wright * smb_kshare_release(). 636148c5f43SAlan Wright */ 637148c5f43SAlan Wright smb_kshare_t * 6388622ec45SGordon Ross smb_kshare_lookup(smb_server_t *sv, const char *shrname) 639148c5f43SAlan Wright { 640148c5f43SAlan Wright smb_kshare_t key; 641148c5f43SAlan Wright smb_kshare_t *shr; 642148c5f43SAlan Wright 643148c5f43SAlan Wright ASSERT(shrname); 644148c5f43SAlan Wright 6458622ec45SGordon Ross if (!smb_export_isready(sv)) 646148c5f43SAlan Wright return (NULL); 647148c5f43SAlan Wright 648148c5f43SAlan Wright key.shr_name = (char *)shrname; 6498622ec45SGordon Ross shr = smb_avl_lookup(&sv->sv_export.e_share_avl, &key); 650148c5f43SAlan Wright return (shr); 651148c5f43SAlan Wright } 652148c5f43SAlan Wright 653148c5f43SAlan Wright /* 654148c5f43SAlan Wright * Releases the hold taken on the specified share object 655148c5f43SAlan Wright */ 656148c5f43SAlan Wright void 6578622ec45SGordon Ross smb_kshare_release(smb_server_t *sv, smb_kshare_t *shr) 658148c5f43SAlan Wright { 659148c5f43SAlan Wright ASSERT(shr); 660148c5f43SAlan Wright ASSERT(shr->shr_magic == SMB_SHARE_MAGIC); 661148c5f43SAlan Wright 6628622ec45SGordon Ross smb_avl_release(&sv->sv_export.e_share_avl, shr); 663148c5f43SAlan Wright } 664148c5f43SAlan Wright 665148c5f43SAlan Wright /* 666148c5f43SAlan Wright * Add the given share in the specified server. 667148c5f43SAlan Wright * If the share is a disk share, smb_vfs_hold() is 668148c5f43SAlan Wright * invoked to ensure that there is a hold on the 669148c5f43SAlan Wright * corresponding file system before the share is 670148c5f43SAlan Wright * added to shares AVL. 671148c5f43SAlan Wright * 672148c5f43SAlan Wright * If the share is an Autohome share and it is 673148c5f43SAlan Wright * already in the AVL only a reference count for 674148c5f43SAlan Wright * that share is incremented. 675148c5f43SAlan Wright */ 676148c5f43SAlan Wright static int 6778622ec45SGordon Ross smb_kshare_export(smb_server_t *sv, smb_kshare_t *shr) 678148c5f43SAlan Wright { 679148c5f43SAlan Wright smb_avl_t *share_avl; 680148c5f43SAlan Wright smb_kshare_t *auto_shr; 681148c5f43SAlan Wright vnode_t *vp; 682148c5f43SAlan Wright int rc = 0; 683148c5f43SAlan Wright 6848622ec45SGordon Ross share_avl = &sv->sv_export.e_share_avl; 685148c5f43SAlan Wright 686148c5f43SAlan Wright if (!STYPE_ISDSK(shr->shr_type)) { 687148c5f43SAlan Wright if ((rc = smb_avl_add(share_avl, shr)) != 0) { 688148c5f43SAlan Wright cmn_err(CE_WARN, "export[%s]: failed caching (%d)", 689148c5f43SAlan Wright shr->shr_name, rc); 690148c5f43SAlan Wright } 691148c5f43SAlan Wright 692148c5f43SAlan Wright return (rc); 693148c5f43SAlan Wright } 694148c5f43SAlan Wright 695148c5f43SAlan Wright if ((auto_shr = smb_avl_lookup(share_avl, shr)) != NULL) { 696148c5f43SAlan Wright if ((auto_shr->shr_flags & SMB_SHRF_AUTOHOME) == 0) { 697148c5f43SAlan Wright smb_avl_release(share_avl, auto_shr); 698148c5f43SAlan Wright return (EEXIST); 699148c5f43SAlan Wright } 700148c5f43SAlan Wright 701148c5f43SAlan Wright mutex_enter(&auto_shr->shr_mutex); 702148c5f43SAlan Wright auto_shr->shr_autocnt++; 703148c5f43SAlan Wright mutex_exit(&auto_shr->shr_mutex); 704148c5f43SAlan Wright smb_avl_release(share_avl, auto_shr); 705148c5f43SAlan Wright return (0); 706148c5f43SAlan Wright } 707148c5f43SAlan Wright 7088622ec45SGordon Ross if ((rc = smb_server_sharevp(sv, shr->shr_path, &vp)) != 0) { 709148c5f43SAlan Wright cmn_err(CE_WARN, "export[%s(%s)]: failed obtaining vnode (%d)", 710148c5f43SAlan Wright shr->shr_name, shr->shr_path, rc); 711148c5f43SAlan Wright return (rc); 712148c5f43SAlan Wright } 713148c5f43SAlan Wright 7148622ec45SGordon Ross if ((rc = smb_vfs_hold(&sv->sv_export, vp->v_vfsp)) == 0) { 715148c5f43SAlan Wright if ((rc = smb_avl_add(share_avl, shr)) != 0) { 716148c5f43SAlan Wright cmn_err(CE_WARN, "export[%s]: failed caching (%d)", 717148c5f43SAlan Wright shr->shr_name, rc); 7188622ec45SGordon Ross smb_vfs_rele(&sv->sv_export, vp->v_vfsp); 719148c5f43SAlan Wright } 720148c5f43SAlan Wright } else { 721148c5f43SAlan Wright cmn_err(CE_WARN, "export[%s(%s)]: failed holding VFS (%d)", 722148c5f43SAlan Wright shr->shr_name, shr->shr_path, rc); 723148c5f43SAlan Wright } 724148c5f43SAlan Wright 725148c5f43SAlan Wright VN_RELE(vp); 726148c5f43SAlan Wright return (rc); 727148c5f43SAlan Wright } 728148c5f43SAlan Wright 729148c5f43SAlan Wright /* 730148c5f43SAlan Wright * Removes the share specified by 'shrname' from the AVL 731148c5f43SAlan Wright * tree of the given server if it's there. 732148c5f43SAlan Wright * 733148c5f43SAlan Wright * If the share is an Autohome share, the autohome count 734148c5f43SAlan Wright * is decremented and the share is only removed if the 735148c5f43SAlan Wright * count goes to zero. 736148c5f43SAlan Wright * 737148c5f43SAlan Wright * If the share is a disk share, the hold on the corresponding 738148c5f43SAlan Wright * file system is released before removing the share from 739148c5f43SAlan Wright * the AVL tree. 740148c5f43SAlan Wright */ 741148c5f43SAlan Wright static int 7428622ec45SGordon Ross smb_kshare_unexport(smb_server_t *sv, const char *shrname) 743148c5f43SAlan Wright { 744148c5f43SAlan Wright smb_avl_t *share_avl; 745148c5f43SAlan Wright smb_kshare_t key; 746148c5f43SAlan Wright smb_kshare_t *shr; 747148c5f43SAlan Wright vnode_t *vp; 748148c5f43SAlan Wright int rc; 749148c5f43SAlan Wright boolean_t auto_unexport; 750148c5f43SAlan Wright 7518622ec45SGordon Ross share_avl = &sv->sv_export.e_share_avl; 752148c5f43SAlan Wright 753148c5f43SAlan Wright key.shr_name = (char *)shrname; 754148c5f43SAlan Wright if ((shr = smb_avl_lookup(share_avl, &key)) == NULL) 755148c5f43SAlan Wright return (ENOENT); 756148c5f43SAlan Wright 757148c5f43SAlan Wright if ((shr->shr_flags & SMB_SHRF_AUTOHOME) != 0) { 758148c5f43SAlan Wright mutex_enter(&shr->shr_mutex); 759148c5f43SAlan Wright shr->shr_autocnt--; 760148c5f43SAlan Wright auto_unexport = (shr->shr_autocnt == 0); 761148c5f43SAlan Wright mutex_exit(&shr->shr_mutex); 762148c5f43SAlan Wright if (!auto_unexport) { 763148c5f43SAlan Wright smb_avl_release(share_avl, shr); 764148c5f43SAlan Wright return (0); 765148c5f43SAlan Wright } 766148c5f43SAlan Wright } 767148c5f43SAlan Wright 768148c5f43SAlan Wright if (STYPE_ISDSK(shr->shr_type)) { 7698622ec45SGordon Ross if ((rc = smb_server_sharevp(sv, shr->shr_path, &vp)) != 0) { 770148c5f43SAlan Wright smb_avl_release(share_avl, shr); 771148c5f43SAlan Wright cmn_err(CE_WARN, "unexport[%s]: failed obtaining vnode" 772148c5f43SAlan Wright " (%d)", shrname, rc); 773148c5f43SAlan Wright return (rc); 774148c5f43SAlan Wright } 775148c5f43SAlan Wright 7768622ec45SGordon Ross smb_vfs_rele(&sv->sv_export, vp->v_vfsp); 777148c5f43SAlan Wright VN_RELE(vp); 778148c5f43SAlan Wright } 779148c5f43SAlan Wright 780148c5f43SAlan Wright smb_avl_remove(share_avl, shr); 781148c5f43SAlan Wright smb_avl_release(share_avl, shr); 782148c5f43SAlan Wright 783148c5f43SAlan Wright return (0); 784148c5f43SAlan Wright } 785148c5f43SAlan Wright 786148c5f43SAlan Wright /* 787148c5f43SAlan Wright * Exports IPC$ or Admin shares 788148c5f43SAlan Wright */ 789148c5f43SAlan Wright static int 7908622ec45SGordon Ross smb_kshare_export_trans(smb_server_t *sv, char *name, char *path, char *cmnt) 791148c5f43SAlan Wright { 792148c5f43SAlan Wright smb_kshare_t *shr; 793148c5f43SAlan Wright 794148c5f43SAlan Wright ASSERT(name); 795148c5f43SAlan Wright ASSERT(path); 796148c5f43SAlan Wright 7978622ec45SGordon Ross shr = kmem_cache_alloc(smb_kshare_cache_share, KM_SLEEP); 798148c5f43SAlan Wright bzero(shr, sizeof (smb_kshare_t)); 799148c5f43SAlan Wright 800148c5f43SAlan Wright shr->shr_magic = SMB_SHARE_MAGIC; 801148c5f43SAlan Wright shr->shr_refcnt = 1; 802148c5f43SAlan Wright shr->shr_flags = SMB_SHRF_TRANS | smb_kshare_is_admin(shr->shr_name); 803148c5f43SAlan Wright if (strcasecmp(name, "IPC$") == 0) 804148c5f43SAlan Wright shr->shr_type = STYPE_IPC; 805148c5f43SAlan Wright else 806148c5f43SAlan Wright shr->shr_type = STYPE_DISKTREE; 807148c5f43SAlan Wright 808148c5f43SAlan Wright shr->shr_type |= smb_kshare_is_special(shr->shr_name); 809148c5f43SAlan Wright 810148c5f43SAlan Wright shr->shr_name = smb_mem_strdup(name); 811148c5f43SAlan Wright if (path) 812148c5f43SAlan Wright shr->shr_path = smb_mem_strdup(path); 813148c5f43SAlan Wright if (cmnt) 814148c5f43SAlan Wright shr->shr_cmnt = smb_mem_strdup(cmnt); 815148c5f43SAlan Wright shr->shr_oemname = smb_kshare_oemname(name); 816148c5f43SAlan Wright 8178622ec45SGordon Ross return (smb_kshare_export(sv, shr)); 818148c5f43SAlan Wright } 819148c5f43SAlan Wright 820148c5f43SAlan Wright /* 821148c5f43SAlan Wright * Decodes share information in an nvlist format into a smb_kshare_t 822148c5f43SAlan Wright * structure. 823148c5f43SAlan Wright * 824148c5f43SAlan Wright * This is a temporary function and will be replaced by functions 825148c5f43SAlan Wright * provided by libsharev2 code after it's available. 826148c5f43SAlan Wright */ 827148c5f43SAlan Wright static smb_kshare_t * 828148c5f43SAlan Wright smb_kshare_decode(nvlist_t *share) 829148c5f43SAlan Wright { 830148c5f43SAlan Wright smb_kshare_t tmp; 831148c5f43SAlan Wright smb_kshare_t *shr; 832148c5f43SAlan Wright nvlist_t *smb; 833148c5f43SAlan Wright char *csc_name = NULL; 834148c5f43SAlan Wright int rc; 835148c5f43SAlan Wright 836148c5f43SAlan Wright ASSERT(share); 837148c5f43SAlan Wright 838148c5f43SAlan Wright bzero(&tmp, sizeof (smb_kshare_t)); 839148c5f43SAlan Wright 840148c5f43SAlan Wright rc = nvlist_lookup_string(share, "name", &tmp.shr_name); 841148c5f43SAlan Wright rc |= nvlist_lookup_string(share, "path", &tmp.shr_path); 842148c5f43SAlan Wright (void) nvlist_lookup_string(share, "desc", &tmp.shr_cmnt); 843148c5f43SAlan Wright 844148c5f43SAlan Wright ASSERT(tmp.shr_name && tmp.shr_path); 845148c5f43SAlan Wright 846148c5f43SAlan Wright rc |= nvlist_lookup_nvlist(share, "smb", &smb); 847148c5f43SAlan Wright if (rc != 0) { 848148c5f43SAlan Wright cmn_err(CE_WARN, "kshare: failed looking up SMB properties" 849148c5f43SAlan Wright " (%d)", rc); 850148c5f43SAlan Wright return (NULL); 851148c5f43SAlan Wright } 852148c5f43SAlan Wright 853cb174861Sjoyce mcintosh rc = nvlist_lookup_uint32(smb, "type", &tmp.shr_type); 854cb174861Sjoyce mcintosh if (rc != 0) { 855cb174861Sjoyce mcintosh cmn_err(CE_WARN, "kshare[%s]: failed getting the share type" 856cb174861Sjoyce mcintosh " (%d)", tmp.shr_name, rc); 857cb174861Sjoyce mcintosh return (NULL); 858cb174861Sjoyce mcintosh } 859cb174861Sjoyce mcintosh 860148c5f43SAlan Wright (void) nvlist_lookup_string(smb, SHOPT_AD_CONTAINER, 861148c5f43SAlan Wright &tmp.shr_container); 862148c5f43SAlan Wright (void) nvlist_lookup_string(smb, SHOPT_NONE, &tmp.shr_access_none); 863148c5f43SAlan Wright (void) nvlist_lookup_string(smb, SHOPT_RO, &tmp.shr_access_ro); 864148c5f43SAlan Wright (void) nvlist_lookup_string(smb, SHOPT_RW, &tmp.shr_access_rw); 865148c5f43SAlan Wright 866148c5f43SAlan Wright tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_ABE, SMB_SHRF_ABE); 867148c5f43SAlan Wright tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_CATIA, 868148c5f43SAlan Wright SMB_SHRF_CATIA); 869148c5f43SAlan Wright tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_GUEST, 870148c5f43SAlan Wright SMB_SHRF_GUEST_OK); 871148c5f43SAlan Wright tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_DFSROOT, 872148c5f43SAlan Wright SMB_SHRF_DFSROOT); 873148c5f43SAlan Wright tmp.shr_flags |= smb_kshare_decode_bool(smb, "Autohome", 874148c5f43SAlan Wright SMB_SHRF_AUTOHOME); 875148c5f43SAlan Wright 876148c5f43SAlan Wright if ((tmp.shr_flags & SMB_SHRF_AUTOHOME) == SMB_SHRF_AUTOHOME) { 877148c5f43SAlan Wright rc = nvlist_lookup_uint32(smb, "uid", &tmp.shr_uid); 878148c5f43SAlan Wright rc |= nvlist_lookup_uint32(smb, "gid", &tmp.shr_gid); 879148c5f43SAlan Wright if (rc != 0) { 880cb174861Sjoyce mcintosh cmn_err(CE_WARN, "kshare: failed looking up uid/gid" 881148c5f43SAlan Wright " (%d)", rc); 882148c5f43SAlan Wright return (NULL); 883148c5f43SAlan Wright } 884148c5f43SAlan Wright } 885148c5f43SAlan Wright 886148c5f43SAlan Wright (void) nvlist_lookup_string(smb, SHOPT_CSC, &csc_name); 887148c5f43SAlan Wright smb_kshare_csc_flags(&tmp, csc_name); 888148c5f43SAlan Wright 8898622ec45SGordon Ross shr = kmem_cache_alloc(smb_kshare_cache_share, KM_SLEEP); 890148c5f43SAlan Wright bzero(shr, sizeof (smb_kshare_t)); 891148c5f43SAlan Wright 892148c5f43SAlan Wright shr->shr_magic = SMB_SHARE_MAGIC; 893148c5f43SAlan Wright shr->shr_refcnt = 1; 894148c5f43SAlan Wright 895148c5f43SAlan Wright shr->shr_name = smb_mem_strdup(tmp.shr_name); 896148c5f43SAlan Wright shr->shr_path = smb_mem_strdup(tmp.shr_path); 897148c5f43SAlan Wright if (tmp.shr_cmnt) 898148c5f43SAlan Wright shr->shr_cmnt = smb_mem_strdup(tmp.shr_cmnt); 899148c5f43SAlan Wright if (tmp.shr_container) 900148c5f43SAlan Wright shr->shr_container = smb_mem_strdup(tmp.shr_container); 901148c5f43SAlan Wright if (tmp.shr_access_none) 902148c5f43SAlan Wright shr->shr_access_none = smb_mem_strdup(tmp.shr_access_none); 903148c5f43SAlan Wright if (tmp.shr_access_ro) 904148c5f43SAlan Wright shr->shr_access_ro = smb_mem_strdup(tmp.shr_access_ro); 905148c5f43SAlan Wright if (tmp.shr_access_rw) 906148c5f43SAlan Wright shr->shr_access_rw = smb_mem_strdup(tmp.shr_access_rw); 907148c5f43SAlan Wright 908148c5f43SAlan Wright shr->shr_oemname = smb_kshare_oemname(shr->shr_name); 909148c5f43SAlan Wright shr->shr_flags = tmp.shr_flags | smb_kshare_is_admin(shr->shr_name); 910cb174861Sjoyce mcintosh shr->shr_type = tmp.shr_type | smb_kshare_is_special(shr->shr_name); 911148c5f43SAlan Wright 912148c5f43SAlan Wright shr->shr_uid = tmp.shr_uid; 913148c5f43SAlan Wright shr->shr_gid = tmp.shr_gid; 914148c5f43SAlan Wright 915148c5f43SAlan Wright if ((shr->shr_flags & SMB_SHRF_AUTOHOME) == SMB_SHRF_AUTOHOME) 916148c5f43SAlan Wright shr->shr_autocnt = 1; 917148c5f43SAlan Wright 918148c5f43SAlan Wright return (shr); 919148c5f43SAlan Wright } 920148c5f43SAlan Wright 921148c5f43SAlan Wright #if 0 922148c5f43SAlan Wright static void 923148c5f43SAlan Wright smb_kshare_log(smb_kshare_t *shr) 924148c5f43SAlan Wright { 925148c5f43SAlan Wright cmn_err(CE_NOTE, "Share info:"); 926148c5f43SAlan Wright cmn_err(CE_NOTE, "\tname: %s", (shr->shr_name) ? shr->shr_name : ""); 927148c5f43SAlan Wright cmn_err(CE_NOTE, "\tpath: %s", (shr->shr_path) ? shr->shr_path : ""); 928148c5f43SAlan Wright cmn_err(CE_NOTE, "\tcmnt: (%s)", 929148c5f43SAlan Wright (shr->shr_cmnt) ? shr->shr_cmnt : "NULL"); 930148c5f43SAlan Wright cmn_err(CE_NOTE, "\toemname: (%s)", 931148c5f43SAlan Wright (shr->shr_oemname) ? shr->shr_oemname : "NULL"); 932148c5f43SAlan Wright cmn_err(CE_NOTE, "\tflags: %X", shr->shr_flags); 933148c5f43SAlan Wright cmn_err(CE_NOTE, "\ttype: %d", shr->shr_type); 934148c5f43SAlan Wright } 935148c5f43SAlan Wright #endif 936148c5f43SAlan Wright 937148c5f43SAlan Wright /* 938148c5f43SAlan Wright * Compare function used by shares AVL 939148c5f43SAlan Wright */ 940148c5f43SAlan Wright static int 941148c5f43SAlan Wright smb_kshare_cmp(const void *p1, const void *p2) 942148c5f43SAlan Wright { 943148c5f43SAlan Wright smb_kshare_t *shr1 = (smb_kshare_t *)p1; 944148c5f43SAlan Wright smb_kshare_t *shr2 = (smb_kshare_t *)p2; 945148c5f43SAlan Wright int rc; 946148c5f43SAlan Wright 947148c5f43SAlan Wright ASSERT(shr1); 948148c5f43SAlan Wright ASSERT(shr1->shr_name); 949148c5f43SAlan Wright 950148c5f43SAlan Wright ASSERT(shr2); 951148c5f43SAlan Wright ASSERT(shr2->shr_name); 952148c5f43SAlan Wright 953148c5f43SAlan Wright rc = smb_strcasecmp(shr1->shr_name, shr2->shr_name, 0); 954148c5f43SAlan Wright 955148c5f43SAlan Wright if (rc < 0) 956148c5f43SAlan Wright return (-1); 957148c5f43SAlan Wright 958148c5f43SAlan Wright if (rc > 0) 959148c5f43SAlan Wright return (1); 960148c5f43SAlan Wright 961148c5f43SAlan Wright return (0); 962148c5f43SAlan Wright } 963148c5f43SAlan Wright 964148c5f43SAlan Wright /* 965148c5f43SAlan Wright * This function is called by smb_avl routines whenever 966148c5f43SAlan Wright * there is a need to take a hold on a share structure 967148c5f43SAlan Wright * inside AVL 968148c5f43SAlan Wright */ 969148c5f43SAlan Wright static void 970148c5f43SAlan Wright smb_kshare_hold(const void *p) 971148c5f43SAlan Wright { 972148c5f43SAlan Wright smb_kshare_t *shr = (smb_kshare_t *)p; 973148c5f43SAlan Wright 974148c5f43SAlan Wright ASSERT(shr); 975148c5f43SAlan Wright ASSERT(shr->shr_magic == SMB_SHARE_MAGIC); 976148c5f43SAlan Wright 977148c5f43SAlan Wright mutex_enter(&shr->shr_mutex); 978148c5f43SAlan Wright shr->shr_refcnt++; 979148c5f43SAlan Wright mutex_exit(&shr->shr_mutex); 980148c5f43SAlan Wright } 981148c5f43SAlan Wright 982148c5f43SAlan Wright /* 983148c5f43SAlan Wright * This function must be called by smb_avl routines whenever 984148c5f43SAlan Wright * smb_kshare_hold is called and the hold needs to be released. 985148c5f43SAlan Wright */ 986148c5f43SAlan Wright static boolean_t 987148c5f43SAlan Wright smb_kshare_rele(const void *p) 988148c5f43SAlan Wright { 989148c5f43SAlan Wright smb_kshare_t *shr = (smb_kshare_t *)p; 990148c5f43SAlan Wright boolean_t destroy; 991148c5f43SAlan Wright 992148c5f43SAlan Wright ASSERT(shr); 993148c5f43SAlan Wright ASSERT(shr->shr_magic == SMB_SHARE_MAGIC); 994148c5f43SAlan Wright 995148c5f43SAlan Wright mutex_enter(&shr->shr_mutex); 996148c5f43SAlan Wright ASSERT(shr->shr_refcnt > 0); 997148c5f43SAlan Wright shr->shr_refcnt--; 998148c5f43SAlan Wright destroy = (shr->shr_refcnt == 0); 999148c5f43SAlan Wright mutex_exit(&shr->shr_mutex); 1000148c5f43SAlan Wright 1001148c5f43SAlan Wright return (destroy); 1002148c5f43SAlan Wright } 1003148c5f43SAlan Wright 1004148c5f43SAlan Wright /* 1005148c5f43SAlan Wright * Frees all the memory allocated for the given 1006148c5f43SAlan Wright * share structure. It also removes the structure 1007148c5f43SAlan Wright * from the share cache. 1008148c5f43SAlan Wright */ 1009148c5f43SAlan Wright static void 1010148c5f43SAlan Wright smb_kshare_destroy(void *p) 1011148c5f43SAlan Wright { 1012148c5f43SAlan Wright smb_kshare_t *shr = (smb_kshare_t *)p; 1013148c5f43SAlan Wright 1014148c5f43SAlan Wright ASSERT(shr); 1015148c5f43SAlan Wright ASSERT(shr->shr_magic == SMB_SHARE_MAGIC); 1016148c5f43SAlan Wright 1017148c5f43SAlan Wright smb_mem_free(shr->shr_name); 1018148c5f43SAlan Wright smb_mem_free(shr->shr_path); 1019148c5f43SAlan Wright smb_mem_free(shr->shr_cmnt); 1020148c5f43SAlan Wright smb_mem_free(shr->shr_container); 1021148c5f43SAlan Wright smb_mem_free(shr->shr_oemname); 1022148c5f43SAlan Wright smb_mem_free(shr->shr_access_none); 1023148c5f43SAlan Wright smb_mem_free(shr->shr_access_ro); 1024148c5f43SAlan Wright smb_mem_free(shr->shr_access_rw); 1025148c5f43SAlan Wright 10268622ec45SGordon Ross kmem_cache_free(smb_kshare_cache_share, shr); 1027148c5f43SAlan Wright } 1028148c5f43SAlan Wright 1029148c5f43SAlan Wright 1030148c5f43SAlan Wright /* 1031148c5f43SAlan Wright * Generate an OEM name for the given share name. If the name is 1032148c5f43SAlan Wright * shorter than 13 bytes the oemname will be returned; otherwise NULL 1033148c5f43SAlan Wright * is returned. 1034148c5f43SAlan Wright */ 1035148c5f43SAlan Wright static char * 1036148c5f43SAlan Wright smb_kshare_oemname(const char *shrname) 1037148c5f43SAlan Wright { 1038148c5f43SAlan Wright smb_wchar_t *unibuf; 1039148c5f43SAlan Wright char *oem_name; 1040148c5f43SAlan Wright int length; 1041148c5f43SAlan Wright 1042148c5f43SAlan Wright length = strlen(shrname) + 1; 1043148c5f43SAlan Wright 1044148c5f43SAlan Wright oem_name = smb_mem_alloc(length); 1045148c5f43SAlan Wright unibuf = smb_mem_alloc(length * sizeof (smb_wchar_t)); 1046148c5f43SAlan Wright 1047148c5f43SAlan Wright (void) smb_mbstowcs(unibuf, shrname, length); 1048148c5f43SAlan Wright 1049148c5f43SAlan Wright if (ucstooem(oem_name, unibuf, length, OEM_CPG_850) == 0) 1050148c5f43SAlan Wright (void) strcpy(oem_name, shrname); 1051148c5f43SAlan Wright 1052148c5f43SAlan Wright smb_mem_free(unibuf); 1053148c5f43SAlan Wright 1054148c5f43SAlan Wright if (strlen(oem_name) + 1 > SMB_SHARE_OEMNAME_MAX) { 1055148c5f43SAlan Wright smb_mem_free(oem_name); 1056148c5f43SAlan Wright return (NULL); 1057148c5f43SAlan Wright } 1058148c5f43SAlan Wright 1059148c5f43SAlan Wright return (oem_name); 1060148c5f43SAlan Wright } 1061148c5f43SAlan Wright 1062148c5f43SAlan Wright /* 1063148c5f43SAlan Wright * Special share reserved for interprocess communication (IPC$) or 1064148c5f43SAlan Wright * remote administration of the server (ADMIN$). Can also refer to 1065148c5f43SAlan Wright * administrative shares such as C$, D$, E$, and so forth. 1066148c5f43SAlan Wright */ 1067148c5f43SAlan Wright static int 1068148c5f43SAlan Wright smb_kshare_is_special(const char *sharename) 1069148c5f43SAlan Wright { 1070148c5f43SAlan Wright int len; 1071148c5f43SAlan Wright 1072148c5f43SAlan Wright if (sharename == NULL) 1073148c5f43SAlan Wright return (0); 1074148c5f43SAlan Wright 1075148c5f43SAlan Wright if ((len = strlen(sharename)) == 0) 1076148c5f43SAlan Wright return (0); 1077148c5f43SAlan Wright 1078148c5f43SAlan Wright if (sharename[len - 1] == '$') 1079148c5f43SAlan Wright return (STYPE_SPECIAL); 1080148c5f43SAlan Wright 1081148c5f43SAlan Wright return (0); 1082148c5f43SAlan Wright } 1083148c5f43SAlan Wright 1084148c5f43SAlan Wright /* 1085148c5f43SAlan Wright * Check whether or not this is a default admin share: C$, D$ etc. 1086148c5f43SAlan Wright */ 1087148c5f43SAlan Wright static boolean_t 1088148c5f43SAlan Wright smb_kshare_is_admin(const char *sharename) 1089148c5f43SAlan Wright { 1090148c5f43SAlan Wright if (sharename == NULL) 1091148c5f43SAlan Wright return (B_FALSE); 1092148c5f43SAlan Wright 1093148c5f43SAlan Wright if (strlen(sharename) == 2 && 1094148c5f43SAlan Wright smb_isalpha(sharename[0]) && sharename[1] == '$') { 1095148c5f43SAlan Wright return (B_TRUE); 1096148c5f43SAlan Wright } 1097148c5f43SAlan Wright 1098148c5f43SAlan Wright return (B_FALSE); 1099148c5f43SAlan Wright } 1100148c5f43SAlan Wright 1101148c5f43SAlan Wright /* 1102148c5f43SAlan Wright * Decodes the given boolean share option. 1103148c5f43SAlan Wright * If the option is present in the nvlist and it's value is true 1104148c5f43SAlan Wright * returns the corresponding flag value, otherwise returns 0. 1105148c5f43SAlan Wright */ 1106148c5f43SAlan Wright static uint32_t 1107148c5f43SAlan Wright smb_kshare_decode_bool(nvlist_t *nvl, const char *propname, uint32_t flag) 1108148c5f43SAlan Wright { 1109148c5f43SAlan Wright char *boolp; 1110148c5f43SAlan Wright 1111148c5f43SAlan Wright if (nvlist_lookup_string(nvl, propname, &boolp) == 0) 1112148c5f43SAlan Wright if (strcasecmp(boolp, "true") == 0) 1113148c5f43SAlan Wright return (flag); 1114148c5f43SAlan Wright 1115148c5f43SAlan Wright return (0); 1116148c5f43SAlan Wright } 1117148c5f43SAlan Wright 1118148c5f43SAlan Wright /* 1119148c5f43SAlan Wright * Map a client-side caching (CSC) option to the appropriate share 1120148c5f43SAlan Wright * flag. Only one option is allowed; an error will be logged if 1121148c5f43SAlan Wright * multiple options have been specified. We don't need to do anything 1122148c5f43SAlan Wright * about multiple values here because the SRVSVC will not recognize 1123148c5f43SAlan Wright * a value containing multiple flags and will return the default value. 1124148c5f43SAlan Wright * 1125148c5f43SAlan Wright * If the option value is not recognized, it will be ignored: invalid 1126148c5f43SAlan Wright * values will typically be caught and rejected by sharemgr. 1127148c5f43SAlan Wright */ 1128148c5f43SAlan Wright static void 1129148c5f43SAlan Wright smb_kshare_csc_flags(smb_kshare_t *shr, const char *value) 1130148c5f43SAlan Wright { 1131148c5f43SAlan Wright int i; 1132148c5f43SAlan Wright static struct { 1133148c5f43SAlan Wright char *value; 1134148c5f43SAlan Wright uint32_t flag; 1135148c5f43SAlan Wright } cscopt[] = { 1136148c5f43SAlan Wright { "disabled", SMB_SHRF_CSC_DISABLED }, 1137148c5f43SAlan Wright { "manual", SMB_SHRF_CSC_MANUAL }, 1138148c5f43SAlan Wright { "auto", SMB_SHRF_CSC_AUTO }, 1139148c5f43SAlan Wright { "vdo", SMB_SHRF_CSC_VDO } 1140148c5f43SAlan Wright }; 1141148c5f43SAlan Wright 1142148c5f43SAlan Wright if (value == NULL) 1143148c5f43SAlan Wright return; 1144148c5f43SAlan Wright 1145148c5f43SAlan Wright for (i = 0; i < (sizeof (cscopt) / sizeof (cscopt[0])); ++i) { 1146148c5f43SAlan Wright if (strcasecmp(value, cscopt[i].value) == 0) { 1147148c5f43SAlan Wright shr->shr_flags |= cscopt[i].flag; 1148148c5f43SAlan Wright break; 1149148c5f43SAlan Wright } 1150148c5f43SAlan Wright } 1151148c5f43SAlan Wright 1152148c5f43SAlan Wright switch (shr->shr_flags & SMB_SHRF_CSC_MASK) { 1153148c5f43SAlan Wright case 0: 1154148c5f43SAlan Wright case SMB_SHRF_CSC_DISABLED: 1155148c5f43SAlan Wright case SMB_SHRF_CSC_MANUAL: 1156148c5f43SAlan Wright case SMB_SHRF_CSC_AUTO: 1157148c5f43SAlan Wright case SMB_SHRF_CSC_VDO: 1158148c5f43SAlan Wright break; 1159148c5f43SAlan Wright 1160148c5f43SAlan Wright default: 1161148c5f43SAlan Wright cmn_err(CE_NOTE, "csc option conflict: 0x%08x", 1162148c5f43SAlan Wright shr->shr_flags & SMB_SHRF_CSC_MASK); 1163148c5f43SAlan Wright break; 1164148c5f43SAlan Wright } 1165148c5f43SAlan Wright } 1166148c5f43SAlan Wright 1167148c5f43SAlan Wright /* 1168148c5f43SAlan Wright * This function processes the unexport event list and disconnects shares 1169148c5f43SAlan Wright * asynchronously. The function executes as a zone-specific thread. 1170148c5f43SAlan Wright * 1171148c5f43SAlan Wright * The server arg passed in is safe to use without a reference count, because 1172148c5f43SAlan Wright * the server cannot be deleted until smb_thread_stop()/destroy() return, 1173148c5f43SAlan Wright * which is also when the thread exits. 1174148c5f43SAlan Wright */ 1175148c5f43SAlan Wright /*ARGSUSED*/ 1176148c5f43SAlan Wright static void 1177148c5f43SAlan Wright smb_kshare_unexport_thread(smb_thread_t *thread, void *arg) 1178148c5f43SAlan Wright { 11798622ec45SGordon Ross smb_server_t *sv = arg; 1180148c5f43SAlan Wright smb_unshare_t *ux; 1181148c5f43SAlan Wright 1182148c5f43SAlan Wright while (smb_thread_continue(thread)) { 11838622ec45SGordon Ross while ((ux = list_head(&sv->sv_export.e_unexport_list.sl_list)) 1184148c5f43SAlan Wright != NULL) { 11858622ec45SGordon Ross smb_slist_remove(&sv->sv_export.e_unexport_list, ux); 1186148c5f43SAlan Wright (void) smb_server_unshare(ux->us_sharename); 11878622ec45SGordon Ross kmem_cache_free(smb_kshare_cache_unexport, ux); 1188148c5f43SAlan Wright } 1189148c5f43SAlan Wright } 1190148c5f43SAlan Wright } 1191148c5f43SAlan Wright 1192148c5f43SAlan Wright static boolean_t 11938622ec45SGordon Ross smb_export_isready(smb_server_t *sv) 1194148c5f43SAlan Wright { 1195148c5f43SAlan Wright boolean_t ready; 1196148c5f43SAlan Wright 11978622ec45SGordon Ross mutex_enter(&sv->sv_export.e_mutex); 11988622ec45SGordon Ross ready = sv->sv_export.e_ready; 11998622ec45SGordon Ross mutex_exit(&sv->sv_export.e_mutex); 1200148c5f43SAlan Wright 1201148c5f43SAlan Wright return (ready); 1202148c5f43SAlan Wright } 1203148c5f43SAlan Wright 1204b819cea2SGordon Ross #ifdef _KERNEL 1205148c5f43SAlan Wright /* 12063ad684d6Sjb150015 * Return 0 upon success. Otherwise > 0 12073ad684d6Sjb150015 */ 12083ad684d6Sjb150015 static int 12093ad684d6Sjb150015 smb_kshare_chk_dsrv_status(int opcode, smb_dr_ctx_t *dec_ctx) 12103ad684d6Sjb150015 { 12113ad684d6Sjb150015 int status = smb_dr_get_int32(dec_ctx); 12123ad684d6Sjb150015 int err; 12133ad684d6Sjb150015 12143ad684d6Sjb150015 switch (status) { 12153db3f65cSamw case SMB_SHARE_DSUCCESS: 12163ad684d6Sjb150015 return (0); 12173ad684d6Sjb150015 12183db3f65cSamw case SMB_SHARE_DERROR: 12193ad684d6Sjb150015 err = smb_dr_get_uint32(dec_ctx); 12203ad684d6Sjb150015 cmn_err(CE_WARN, "%d: Encountered door server error %d", 12213ad684d6Sjb150015 opcode, err); 12223ad684d6Sjb150015 (void) smb_dr_decode_finish(dec_ctx); 12233ad684d6Sjb150015 return (err); 12243ad684d6Sjb150015 } 12253ad684d6Sjb150015 12263ad684d6Sjb150015 ASSERT(0); 12273ad684d6Sjb150015 return (EINVAL); 12283ad684d6Sjb150015 } 1229b819cea2SGordon Ross #endif /* _KERNEL */ 1230