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.
24*b819cea2SGordon 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
57*b819cea2SGordon Ross #ifdef _KERNEL
583ad684d6Sjb150015 static int smb_kshare_chk_dsrv_status(int, smb_dr_ctx_t *);
59*b819cea2SGordon 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
68*b819cea2SGordon 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
smb_kshare_door_init(int door_id)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
smb_kshare_door_fini(door_handle_t dhdl)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
smb_kshare_upcall(door_handle_t dhdl,void * arg,boolean_t add_share)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);
121*b819cea2SGordon Ross error = xcopyin(arg, lmshare, sizeof (smb_share_t));
122*b819cea2SGordon 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);
132*b819cea2SGordon Ross error = copyinstr(arg, str, MAXPATHLEN, NULL);
133*b819cea2SGordon 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 }
185*b819cea2SGordon Ross #endif /* _KERNEL */
1863ad684d6Sjb150015
1873ad684d6Sjb150015 /*
188148c5f43SAlan Wright * Executes map and unmap command for shares.
189148c5f43SAlan Wright */
190148c5f43SAlan Wright int
smb_kshare_exec(smb_server_t * sv,smb_shr_execinfo_t * execinfo)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
smb_kshare_hostaccess(smb_kshare_t * shr,smb_session_t * session)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
smb_export_start(smb_server_t * sv)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
smb_export_stop(smb_server_t * sv)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
smb_kshare_g_init(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
smb_kshare_init(smb_server_t * sv)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
smb_kshare_start(smb_server_t * sv)3248622ec45SGordon Ross smb_kshare_start(smb_server_t *sv)
3258622ec45SGordon Ross {
3268622ec45SGordon Ross smb_thread_init(&sv->sv_export.e_unexport_thread, "smb_thread_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
smb_kshare_stop(smb_server_t * sv)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
smb_kshare_fini(smb_server_t * sv)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
smb_kshare_g_fini(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
smb_kshare_export_list(smb_ioc_share_t * ioc)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
smb_kshare_unexport_list(smb_ioc_share_t * ioc)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
smb_kshare_info(smb_ioc_shareinfo_t * ioc)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
smb_kshare_enum(smb_server_t * sv,smb_enumshare_info_t * esi)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 *
smb_kshare_lookup(smb_server_t * sv,const char * shrname)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
smb_kshare_release(smb_server_t * sv,smb_kshare_t * shr)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
smb_kshare_export(smb_server_t * sv,smb_kshare_t * shr)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
smb_kshare_unexport(smb_server_t * sv,const char * shrname)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
smb_kshare_export_trans(smb_server_t * sv,char * name,char * path,char * cmnt)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 *
smb_kshare_decode(nvlist_t * share)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
smb_kshare_cmp(const void * p1,const void * p2)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
smb_kshare_hold(const void * p)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
smb_kshare_rele(const void * p)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
smb_kshare_destroy(void * p)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 *
smb_kshare_oemname(const char * shrname)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
smb_kshare_is_special(const char * sharename)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
smb_kshare_is_admin(const char * sharename)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
smb_kshare_decode_bool(nvlist_t * nvl,const char * propname,uint32_t flag)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
smb_kshare_csc_flags(smb_kshare_t * shr,const char * value)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
smb_kshare_unexport_thread(smb_thread_t * thread,void * arg)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
smb_export_isready(smb_server_t * sv)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
1204*b819cea2SGordon Ross #ifdef _KERNEL
1205148c5f43SAlan Wright /*
12063ad684d6Sjb150015 * Return 0 upon success. Otherwise > 0
12073ad684d6Sjb150015 */
12083ad684d6Sjb150015 static int
smb_kshare_chk_dsrv_status(int opcode,smb_dr_ctx_t * dec_ctx)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 }
1229*b819cea2SGordon Ross #endif /* _KERNEL */
1230