xref: /titanic_51/usr/src/uts/common/fs/smbsrv/smb_kshare.c (revision aab83bb83be7342f6cfccaed8d5fe0b2f404855d)
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