xref: /onnv-gate/usr/src/lib/smbsrv/libmlsvc/common/smb_share.c (revision 13082:81ec56bf6147)
17052Samw /*
27052Samw  * CDDL HEADER START
37052Samw  *
47052Samw  * The contents of this file are subject to the terms of the
57052Samw  * Common Development and Distribution License (the "License").
67052Samw  * You may not use this file except in compliance with the License.
77052Samw  *
87052Samw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97052Samw  * or http://www.opensolaris.org/os/licensing.
107052Samw  * See the License for the specific language governing permissions
117052Samw  * and limitations under the License.
127052Samw  *
137052Samw  * When distributing Covered Code, include this CDDL HEADER in each
147052Samw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157052Samw  * If applicable, add the following below this CDDL HEADER, with the
167052Samw  * fields enclosed by brackets "[]" replaced with your own identifying
177052Samw  * information: Portions Copyright [yyyy] [name of copyright owner]
187052Samw  *
197052Samw  * CDDL HEADER END
207052Samw  */
217052Samw /*
2212065SKeyur.Desai@Sun.COM  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
237052Samw  */
247052Samw 
257052Samw /*
267961SNatalie.Li@Sun.COM  * SMB/CIFS share cache implementation.
277052Samw  */
287052Samw 
297052Samw #include <errno.h>
307052Samw #include <synch.h>
317052Samw #include <stdlib.h>
327052Samw #include <strings.h>
337052Samw #include <syslog.h>
347052Samw #include <thread.h>
357052Samw #include <pthread.h>
367348SJose.Borrego@Sun.COM #include <assert.h>
377961SNatalie.Li@Sun.COM #include <libshare.h>
388845Samw@Sun.COM #include <libzfs.h>
399832Samw@Sun.COM #include <priv_utils.h>
409832Samw@Sun.COM #include <sys/types.h>
419832Samw@Sun.COM #include <sys/wait.h>
429832Samw@Sun.COM #include <unistd.h>
439832Samw@Sun.COM #include <pwd.h>
449832Samw@Sun.COM #include <signal.h>
4512065SKeyur.Desai@Sun.COM #include <dirent.h>
4612890SJoyce.McIntosh@Sun.COM #include <dlfcn.h>
477052Samw 
487052Samw #include <smbsrv/libsmb.h>
497052Samw #include <smbsrv/libsmbns.h>
507588Samw@Sun.COM #include <smbsrv/libmlsvc.h>
517052Samw #include <smbsrv/smb_share.h>
5210966SJordan.Brown@Sun.COM #include <smbsrv/smb.h>
5310504SKeyur.Desai@Sun.COM #include <mlsvc.h>
5411963SAfshin.Ardakani@Sun.COM #include <dfs.h>
557052Samw 
567961SNatalie.Li@Sun.COM #define	SMB_SHR_ERROR_THRESHOLD		3
578334SJose.Borrego@Sun.COM #define	SMB_SHR_CSC_BUFSZ		64
588334SJose.Borrego@Sun.COM 
5912065SKeyur.Desai@Sun.COM typedef struct smb_transient {
6012065SKeyur.Desai@Sun.COM 	char		*name;
6112065SKeyur.Desai@Sun.COM 	char		*cmnt;
6212065SKeyur.Desai@Sun.COM 	char		*path;
6312065SKeyur.Desai@Sun.COM 	char		drive;
6412065SKeyur.Desai@Sun.COM 	boolean_t	check;
6512065SKeyur.Desai@Sun.COM } smb_transient_t;
6612065SKeyur.Desai@Sun.COM 
6712065SKeyur.Desai@Sun.COM static smb_transient_t tshare[] = {
6812065SKeyur.Desai@Sun.COM 	{ "IPC$", "Remote IPC",		NULL,		'\0', B_FALSE },
6912065SKeyur.Desai@Sun.COM 	{ "c$",   "Default Share",	SMB_CVOL,	'C',  B_FALSE },
7012065SKeyur.Desai@Sun.COM 	{ "vss$", "VSS",		SMB_VSS,	'V',  B_TRUE }
7112065SKeyur.Desai@Sun.COM };
7212065SKeyur.Desai@Sun.COM 
739832Samw@Sun.COM static struct {
749832Samw@Sun.COM 	char *value;
759832Samw@Sun.COM 	uint32_t flag;
769832Samw@Sun.COM } cscopt[] = {
779832Samw@Sun.COM 	{ "disabled",	SMB_SHRF_CSC_DISABLED },
789832Samw@Sun.COM 	{ "manual",	SMB_SHRF_CSC_MANUAL },
799832Samw@Sun.COM 	{ "auto",	SMB_SHRF_CSC_AUTO },
809832Samw@Sun.COM 	{ "vdo",	SMB_SHRF_CSC_VDO }
819832Samw@Sun.COM };
829832Samw@Sun.COM 
837348SJose.Borrego@Sun.COM /*
847348SJose.Borrego@Sun.COM  * Cache functions and vars
857348SJose.Borrego@Sun.COM  */
867961SNatalie.Li@Sun.COM #define	SMB_SHR_HTAB_SZ			1024
877052Samw 
887961SNatalie.Li@Sun.COM /*
897961SNatalie.Li@Sun.COM  * Cache handle
907961SNatalie.Li@Sun.COM  *
917961SNatalie.Li@Sun.COM  * Shares cache is a hash table.
927961SNatalie.Li@Sun.COM  *
937961SNatalie.Li@Sun.COM  * sc_cache		pointer to hash table handle
947961SNatalie.Li@Sun.COM  * sc_cache_lck		synchronize cache read/write accesses
957961SNatalie.Li@Sun.COM  * sc_state		cache state machine values
967961SNatalie.Li@Sun.COM  * sc_nops		number of inflight/pending cache operations
977961SNatalie.Li@Sun.COM  * sc_mtx		protects handle fields
987961SNatalie.Li@Sun.COM  */
997961SNatalie.Li@Sun.COM typedef struct smb_shr_cache {
1007961SNatalie.Li@Sun.COM 	HT_HANDLE	*sc_cache;
1017961SNatalie.Li@Sun.COM 	rwlock_t	sc_cache_lck;
1027961SNatalie.Li@Sun.COM 	mutex_t		sc_mtx;
1037961SNatalie.Li@Sun.COM 	cond_t		sc_cv;
1047961SNatalie.Li@Sun.COM 	uint32_t	sc_state;
1057961SNatalie.Li@Sun.COM 	uint32_t	sc_nops;
1067961SNatalie.Li@Sun.COM } smb_shr_cache_t;
1077961SNatalie.Li@Sun.COM 
1087961SNatalie.Li@Sun.COM /*
1097961SNatalie.Li@Sun.COM  * Cache states
1107961SNatalie.Li@Sun.COM  */
1117961SNatalie.Li@Sun.COM #define	SMB_SHR_CACHE_STATE_NONE	0
1127961SNatalie.Li@Sun.COM #define	SMB_SHR_CACHE_STATE_CREATED	1
1137961SNatalie.Li@Sun.COM #define	SMB_SHR_CACHE_STATE_DESTROYING	2
1147961SNatalie.Li@Sun.COM 
1157961SNatalie.Li@Sun.COM /*
1167961SNatalie.Li@Sun.COM  * Cache lock modes
1177961SNatalie.Li@Sun.COM  */
1187961SNatalie.Li@Sun.COM #define	SMB_SHR_CACHE_RDLOCK	0
1197961SNatalie.Li@Sun.COM #define	SMB_SHR_CACHE_WRLOCK	1
1207961SNatalie.Li@Sun.COM 
1217961SNatalie.Li@Sun.COM static smb_shr_cache_t smb_shr_cache;
1227052Samw 
1237052Samw static uint32_t smb_shr_cache_create(void);
1247348SJose.Borrego@Sun.COM static void smb_shr_cache_destroy(void);
1257961SNatalie.Li@Sun.COM static uint32_t smb_shr_cache_lock(int);
1267961SNatalie.Li@Sun.COM static void smb_shr_cache_unlock(void);
1277961SNatalie.Li@Sun.COM static int smb_shr_cache_count(void);
1287961SNatalie.Li@Sun.COM static smb_share_t *smb_shr_cache_iterate(smb_shriter_t *);
1297961SNatalie.Li@Sun.COM 
1307961SNatalie.Li@Sun.COM static smb_share_t *smb_shr_cache_findent(char *);
1317348SJose.Borrego@Sun.COM static uint32_t smb_shr_cache_addent(smb_share_t *);
1327348SJose.Borrego@Sun.COM static void smb_shr_cache_delent(char *);
1337348SJose.Borrego@Sun.COM static void smb_shr_cache_freent(HT_ITEM *);
1347052Samw 
13512065SKeyur.Desai@Sun.COM static boolean_t smb_shr_is_empty(const char *);
13612065SKeyur.Desai@Sun.COM static boolean_t smb_shr_is_dot_or_dotdot(const char *);
13712065SKeyur.Desai@Sun.COM 
1387348SJose.Borrego@Sun.COM /*
1397348SJose.Borrego@Sun.COM  * sharemgr functions
1407348SJose.Borrego@Sun.COM  */
1417961SNatalie.Li@Sun.COM static void smb_shr_sa_loadgrp(sa_group_t);
1427961SNatalie.Li@Sun.COM static uint32_t smb_shr_sa_load(sa_share_t, sa_resource_t);
1438334SJose.Borrego@Sun.COM static uint32_t smb_shr_sa_loadbyname(char *);
1447961SNatalie.Li@Sun.COM static uint32_t smb_shr_sa_get(sa_share_t, sa_resource_t, smb_share_t *);
1457052Samw 
1467052Samw /*
1478845Samw@Sun.COM  * .ZFS management functions
1488845Samw@Sun.COM  */
1498845Samw@Sun.COM static void smb_shr_zfs_add(smb_share_t *);
1508845Samw@Sun.COM static void smb_shr_zfs_remove(smb_share_t *);
1518845Samw@Sun.COM static void smb_shr_zfs_rename(smb_share_t *, smb_share_t *);
1528845Samw@Sun.COM 
1538845Samw@Sun.COM /*
1547348SJose.Borrego@Sun.COM  * share publishing
1557348SJose.Borrego@Sun.COM  */
1567348SJose.Borrego@Sun.COM #define	SMB_SHR_PUBLISH		0
1577348SJose.Borrego@Sun.COM #define	SMB_SHR_UNPUBLISH	1
1587348SJose.Borrego@Sun.COM 
1597348SJose.Borrego@Sun.COM typedef struct smb_shr_pitem {
1607348SJose.Borrego@Sun.COM 	list_node_t	spi_lnd;
1617348SJose.Borrego@Sun.COM 	char		spi_name[MAXNAMELEN];
1627348SJose.Borrego@Sun.COM 	char		spi_container[MAXPATHLEN];
1637348SJose.Borrego@Sun.COM 	char		spi_op;
1647348SJose.Borrego@Sun.COM } smb_shr_pitem_t;
1657348SJose.Borrego@Sun.COM 
1667348SJose.Borrego@Sun.COM /*
1677348SJose.Borrego@Sun.COM  * publish queue states
1687348SJose.Borrego@Sun.COM  */
1697348SJose.Borrego@Sun.COM #define	SMB_SHR_PQS_NOQUEUE	0
1707348SJose.Borrego@Sun.COM #define	SMB_SHR_PQS_READY	1	/* the queue is ready */
1717348SJose.Borrego@Sun.COM #define	SMB_SHR_PQS_PUBLISHING	2	/* publisher thread is running */
1727348SJose.Borrego@Sun.COM #define	SMB_SHR_PQS_STOPPING	3
1737348SJose.Borrego@Sun.COM 
1747348SJose.Borrego@Sun.COM /*
1757348SJose.Borrego@Sun.COM  * share publishing queue
1767348SJose.Borrego@Sun.COM  */
1777348SJose.Borrego@Sun.COM typedef struct smb_shr_pqueue {
1787348SJose.Borrego@Sun.COM 	list_t		spq_list;
1797348SJose.Borrego@Sun.COM 	mutex_t		spq_mtx;
1807348SJose.Borrego@Sun.COM 	cond_t		spq_cv;
1817348SJose.Borrego@Sun.COM 	uint32_t	spq_state;
1827348SJose.Borrego@Sun.COM } smb_shr_pqueue_t;
1837348SJose.Borrego@Sun.COM 
1847348SJose.Borrego@Sun.COM static smb_shr_pqueue_t ad_queue;
1857348SJose.Borrego@Sun.COM 
1867348SJose.Borrego@Sun.COM static int smb_shr_publisher_start(void);
1877348SJose.Borrego@Sun.COM static void smb_shr_publisher_stop(void);
1887348SJose.Borrego@Sun.COM static void smb_shr_publisher_send(smb_ads_handle_t *, list_t *, const char *);
1897961SNatalie.Li@Sun.COM static void smb_shr_publisher_queue(const char *, const char *, char);
1907348SJose.Borrego@Sun.COM static void *smb_shr_publisher(void *);
1917961SNatalie.Li@Sun.COM static void smb_shr_publisher_flush(list_t *);
1927961SNatalie.Li@Sun.COM static void smb_shr_publish(const char *, const char *);
1937961SNatalie.Li@Sun.COM static void smb_shr_unpublish(const char *, const char *);
1947348SJose.Borrego@Sun.COM 
1957348SJose.Borrego@Sun.COM /*
1967961SNatalie.Li@Sun.COM  * Utility/helper functions
1977961SNatalie.Li@Sun.COM  */
1988334SJose.Borrego@Sun.COM static uint32_t smb_shr_lookup(char *, smb_share_t *);
19911963SAfshin.Ardakani@Sun.COM static uint32_t smb_shr_add_transient(char *, char *, char *);
2009832Samw@Sun.COM static int smb_shr_enable_all_privs(void);
20112508Samw@Sun.COM static int smb_shr_expand_subs(char **, smb_share_t *, smb_shr_execinfo_t *);
2029832Samw@Sun.COM static char **smb_shr_tokenize_cmd(char *);
2039832Samw@Sun.COM static void smb_shr_sig_abnormal_term(int);
2049832Samw@Sun.COM static void smb_shr_sig_child(int);
20512508Samw@Sun.COM static int smb_shr_encode(smb_share_t *, nvlist_t **);
2068474SJose.Borrego@Sun.COM 
2078474SJose.Borrego@Sun.COM /*
2088474SJose.Borrego@Sun.COM  * libshare handle and synchronization
2098474SJose.Borrego@Sun.COM  */
2108474SJose.Borrego@Sun.COM typedef struct smb_sa_handle {
2118474SJose.Borrego@Sun.COM 	sa_handle_t	sa_handle;
2128474SJose.Borrego@Sun.COM 	mutex_t		sa_mtx;
2138474SJose.Borrego@Sun.COM 	boolean_t	sa_in_service;
2148474SJose.Borrego@Sun.COM } smb_sa_handle_t;
2158474SJose.Borrego@Sun.COM 
2168474SJose.Borrego@Sun.COM static smb_sa_handle_t smb_sa_handle;
2178474SJose.Borrego@Sun.COM 
2189832Samw@Sun.COM static char smb_shr_exec_map[MAXPATHLEN];
2199832Samw@Sun.COM static char smb_shr_exec_unmap[MAXPATHLEN];
2209832Samw@Sun.COM static mutex_t smb_shr_exec_mtx;
2219832Samw@Sun.COM 
2227961SNatalie.Li@Sun.COM /*
22310504SKeyur.Desai@Sun.COM  * Semaphore held during temporary, process-wide changes
22410504SKeyur.Desai@Sun.COM  * such as process privileges.  It is a seamaphore and
22510504SKeyur.Desai@Sun.COM  * not a mutex so a child of fork can reset it.
22610504SKeyur.Desai@Sun.COM  */
22710504SKeyur.Desai@Sun.COM static sema_t smb_proc_sem = DEFAULTSEMA;
22810504SKeyur.Desai@Sun.COM 
22910504SKeyur.Desai@Sun.COM /*
2308334SJose.Borrego@Sun.COM  * Creates and initializes the cache and starts the publisher
2318334SJose.Borrego@Sun.COM  * thread.
2327052Samw  */
2337052Samw int
smb_shr_start(void)2347052Samw smb_shr_start(void)
2357052Samw {
23612065SKeyur.Desai@Sun.COM 	smb_transient_t	*ts;
23712065SKeyur.Desai@Sun.COM 	uint32_t	nerr;
23812065SKeyur.Desai@Sun.COM 	int		i;
23911963SAfshin.Ardakani@Sun.COM 
2408474SJose.Borrego@Sun.COM 	(void) mutex_lock(&smb_sa_handle.sa_mtx);
2418474SJose.Borrego@Sun.COM 	smb_sa_handle.sa_in_service = B_TRUE;
2428474SJose.Borrego@Sun.COM 	(void) mutex_unlock(&smb_sa_handle.sa_mtx);
2438474SJose.Borrego@Sun.COM 
2447961SNatalie.Li@Sun.COM 	if (smb_shr_cache_create() != NERR_Success)
2457961SNatalie.Li@Sun.COM 		return (ENOMEM);
2467961SNatalie.Li@Sun.COM 
24711963SAfshin.Ardakani@Sun.COM 	for (i = 0; i < sizeof (tshare)/sizeof (tshare[0]); ++i) {
24812065SKeyur.Desai@Sun.COM 		ts = &tshare[i];
24912065SKeyur.Desai@Sun.COM 
25012065SKeyur.Desai@Sun.COM 		if (ts->check && smb_shr_is_empty(ts->path))
25112065SKeyur.Desai@Sun.COM 			continue;
25212065SKeyur.Desai@Sun.COM 
25312065SKeyur.Desai@Sun.COM 		nerr = smb_shr_add_transient(ts->name, ts->cmnt, ts->path);
25412065SKeyur.Desai@Sun.COM 		if (nerr != NERR_Success)
25511963SAfshin.Ardakani@Sun.COM 			return (ENOMEM);
25611963SAfshin.Ardakani@Sun.COM 	}
2577961SNatalie.Li@Sun.COM 
2588334SJose.Borrego@Sun.COM 	return (smb_shr_publisher_start());
2598334SJose.Borrego@Sun.COM }
2608334SJose.Borrego@Sun.COM 
2618334SJose.Borrego@Sun.COM void
smb_shr_stop(void)2628334SJose.Borrego@Sun.COM smb_shr_stop(void)
2638334SJose.Borrego@Sun.COM {
2648334SJose.Borrego@Sun.COM 	smb_shr_cache_destroy();
2658334SJose.Borrego@Sun.COM 	smb_shr_publisher_stop();
2668474SJose.Borrego@Sun.COM 
2678474SJose.Borrego@Sun.COM 	(void) mutex_lock(&smb_sa_handle.sa_mtx);
2688474SJose.Borrego@Sun.COM 	smb_sa_handle.sa_in_service = B_FALSE;
2698474SJose.Borrego@Sun.COM 
2708474SJose.Borrego@Sun.COM 	if (smb_sa_handle.sa_handle != NULL) {
2718474SJose.Borrego@Sun.COM 		sa_fini(smb_sa_handle.sa_handle);
2728474SJose.Borrego@Sun.COM 		smb_sa_handle.sa_handle = NULL;
2738474SJose.Borrego@Sun.COM 	}
2748474SJose.Borrego@Sun.COM 
2758474SJose.Borrego@Sun.COM 	(void) mutex_unlock(&smb_sa_handle.sa_mtx);
2768474SJose.Borrego@Sun.COM }
2778474SJose.Borrego@Sun.COM 
2788474SJose.Borrego@Sun.COM /*
2798474SJose.Borrego@Sun.COM  * Get a handle and exclusive access to the libshare API.
2808474SJose.Borrego@Sun.COM  */
2818474SJose.Borrego@Sun.COM sa_handle_t
smb_shr_sa_enter(void)2828474SJose.Borrego@Sun.COM smb_shr_sa_enter(void)
2838474SJose.Borrego@Sun.COM {
2848474SJose.Borrego@Sun.COM 	(void) mutex_lock(&smb_sa_handle.sa_mtx);
2858474SJose.Borrego@Sun.COM 	if (!smb_sa_handle.sa_in_service) {
2868474SJose.Borrego@Sun.COM 		(void) mutex_unlock(&smb_sa_handle.sa_mtx);
2878474SJose.Borrego@Sun.COM 		return (NULL);
2888474SJose.Borrego@Sun.COM 	}
2898474SJose.Borrego@Sun.COM 
2908474SJose.Borrego@Sun.COM 	if (smb_sa_handle.sa_handle == NULL) {
2918474SJose.Borrego@Sun.COM 		smb_sa_handle.sa_handle = sa_init(SA_INIT_SHARE_API);
2928474SJose.Borrego@Sun.COM 		if (smb_sa_handle.sa_handle == NULL) {
2938474SJose.Borrego@Sun.COM 			syslog(LOG_ERR, "share: failed to get libshare handle");
2948474SJose.Borrego@Sun.COM 			(void) mutex_unlock(&smb_sa_handle.sa_mtx);
2958474SJose.Borrego@Sun.COM 			return (NULL);
2968474SJose.Borrego@Sun.COM 		}
2978474SJose.Borrego@Sun.COM 	}
2988474SJose.Borrego@Sun.COM 
2998474SJose.Borrego@Sun.COM 	return (smb_sa_handle.sa_handle);
3008474SJose.Borrego@Sun.COM }
3018474SJose.Borrego@Sun.COM 
3028474SJose.Borrego@Sun.COM /*
3038474SJose.Borrego@Sun.COM  * Release exclusive access to the libshare API.
3048474SJose.Borrego@Sun.COM  */
3058474SJose.Borrego@Sun.COM void
smb_shr_sa_exit(void)3068474SJose.Borrego@Sun.COM smb_shr_sa_exit(void)
3078474SJose.Borrego@Sun.COM {
3088474SJose.Borrego@Sun.COM 	(void) mutex_unlock(&smb_sa_handle.sa_mtx);
3098334SJose.Borrego@Sun.COM }
3108334SJose.Borrego@Sun.COM 
3118334SJose.Borrego@Sun.COM /*
3127348SJose.Borrego@Sun.COM  * Return the total number of shares
3137052Samw  */
3147052Samw int
smb_shr_count(void)3157052Samw smb_shr_count(void)
3167052Samw {
3177961SNatalie.Li@Sun.COM 	int n_shares = 0;
3187052Samw 
3197961SNatalie.Li@Sun.COM 	if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) {
3207961SNatalie.Li@Sun.COM 		n_shares = smb_shr_cache_count();
3217961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
3227961SNatalie.Li@Sun.COM 	}
3237052Samw 
3247052Samw 	return (n_shares);
3257052Samw }
3267052Samw 
3277052Samw /*
3287052Samw  * smb_shr_iterinit
3297052Samw  *
3307348SJose.Borrego@Sun.COM  * Initialize given iterator for traversing hash table.
3317052Samw  */
3327052Samw void
smb_shr_iterinit(smb_shriter_t * shi)3337348SJose.Borrego@Sun.COM smb_shr_iterinit(smb_shriter_t *shi)
3347052Samw {
3357052Samw 	bzero(shi, sizeof (smb_shriter_t));
3367348SJose.Borrego@Sun.COM 	shi->si_first = B_TRUE;
3377052Samw }
3387052Samw 
3397052Samw /*
3407052Samw  * smb_shr_iterate
3417052Samw  *
3427052Samw  * Iterate on the shares in the hash table. The iterator must be initialized
3437052Samw  * before the first iteration. On subsequent calls, the iterator must be
3447052Samw  * passed unchanged.
3457052Samw  *
3467052Samw  * Returns NULL on failure or when all shares are visited, otherwise
3477052Samw  * returns information of visited share.
3487052Samw  */
3497052Samw smb_share_t *
smb_shr_iterate(smb_shriter_t * shi)3507052Samw smb_shr_iterate(smb_shriter_t *shi)
3517052Samw {
3527348SJose.Borrego@Sun.COM 	smb_share_t *share = NULL;
3537961SNatalie.Li@Sun.COM 	smb_share_t *cached_si;
3547052Samw 
3557961SNatalie.Li@Sun.COM 	if (shi == NULL)
3567052Samw 		return (NULL);
3577052Samw 
3587961SNatalie.Li@Sun.COM 	if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) {
3597961SNatalie.Li@Sun.COM 		if ((cached_si = smb_shr_cache_iterate(shi)) != NULL) {
3607961SNatalie.Li@Sun.COM 			share = &shi->si_share;
3617961SNatalie.Li@Sun.COM 			bcopy(cached_si, share, sizeof (smb_share_t));
3627961SNatalie.Li@Sun.COM 		}
3637961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
3647052Samw 	}
3657052Samw 
3667348SJose.Borrego@Sun.COM 	return (share);
3677052Samw }
3687052Samw 
3697052Samw /*
3707961SNatalie.Li@Sun.COM  * Adds the given share to cache, publishes the share in ADS
3717961SNatalie.Li@Sun.COM  * if it has an AD container, calls kernel to take a hold on
3727961SNatalie.Li@Sun.COM  * the shared file system. If it can't take a hold on the
3737961SNatalie.Li@Sun.COM  * shared file system, it's either because shared directory
3747961SNatalie.Li@Sun.COM  * does not exist or some other error has occurred, in any
3757961SNatalie.Li@Sun.COM  * case the share is removed from the cache.
3767052Samw  *
3777961SNatalie.Li@Sun.COM  * If the specified share is an autohome share which already
3787961SNatalie.Li@Sun.COM  * exists in the cache, just increments the reference count.
3797052Samw  */
3807052Samw uint32_t
smb_shr_add(smb_share_t * si)3817961SNatalie.Li@Sun.COM smb_shr_add(smb_share_t *si)
3827052Samw {
3837961SNatalie.Li@Sun.COM 	smb_share_t *cached_si;
38412508Samw@Sun.COM 	nvlist_t *shrlist;
3857961SNatalie.Li@Sun.COM 	uint32_t status;
3867348SJose.Borrego@Sun.COM 	int rc;
3877052Samw 
3887348SJose.Borrego@Sun.COM 	assert(si != NULL);
3897052Samw 
39011337SWilliam.Krier@Sun.COM 	if (smb_name_validate_share(si->shr_name) != ERROR_SUCCESS)
3917348SJose.Borrego@Sun.COM 		return (ERROR_INVALID_NAME);
3927052Samw 
3937961SNatalie.Li@Sun.COM 	if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success)
3947961SNatalie.Li@Sun.COM 		return (NERR_InternalError);
3957052Samw 
3967961SNatalie.Li@Sun.COM 	cached_si = smb_shr_cache_findent(si->shr_name);
3977961SNatalie.Li@Sun.COM 	if (cached_si) {
3987961SNatalie.Li@Sun.COM 		if (si->shr_flags & SMB_SHRF_AUTOHOME) {
3997961SNatalie.Li@Sun.COM 			cached_si->shr_refcnt++;
4007961SNatalie.Li@Sun.COM 			status = NERR_Success;
4017961SNatalie.Li@Sun.COM 		} else {
4027961SNatalie.Li@Sun.COM 			status = NERR_DuplicateShare;
4037961SNatalie.Li@Sun.COM 		}
4047961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
4057052Samw 		return (status);
4067052Samw 	}
4077052Samw 
4087961SNatalie.Li@Sun.COM 	if ((status = smb_shr_cache_addent(si)) != NERR_Success) {
4097961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
4107961SNatalie.Li@Sun.COM 		return (status);
4117961SNatalie.Li@Sun.COM 	}
4127961SNatalie.Li@Sun.COM 
4137961SNatalie.Li@Sun.COM 	/* don't hold the lock across door call */
4147961SNatalie.Li@Sun.COM 	smb_shr_cache_unlock();
4157961SNatalie.Li@Sun.COM 
41612508Samw@Sun.COM 	if ((rc = smb_shr_encode(si, &shrlist)) == 0) {
41712508Samw@Sun.COM 		/* send the share to kernel */
41812508Samw@Sun.COM 		rc = smb_kmod_share(shrlist);
41912508Samw@Sun.COM 		nvlist_free(shrlist);
4207348SJose.Borrego@Sun.COM 
42112508Samw@Sun.COM 		if (rc == 0) {
42212508Samw@Sun.COM 			smb_shr_publish(si->shr_name, si->shr_container);
4238845Samw@Sun.COM 
42412508Samw@Sun.COM 			/* If path is ZFS, add the .zfs/shares/<share> entry. */
42512508Samw@Sun.COM 			smb_shr_zfs_add(si);
4268845Samw@Sun.COM 
42712890SJoyce.McIntosh@Sun.COM 			if ((si->shr_flags & SMB_SHRF_DFSROOT) != 0)
42812890SJoyce.McIntosh@Sun.COM 				dfs_namespace_load(si->shr_name);
42912890SJoyce.McIntosh@Sun.COM 
43012508Samw@Sun.COM 			return (NERR_Success);
43112508Samw@Sun.COM 		}
4327052Samw 	}
4337052Samw 
4347961SNatalie.Li@Sun.COM 	if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) == NERR_Success) {
4357961SNatalie.Li@Sun.COM 		smb_shr_cache_delent(si->shr_name);
4367961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
4377961SNatalie.Li@Sun.COM 	}
4387052Samw 
4397052Samw 	/*
4407348SJose.Borrego@Sun.COM 	 * rc == ENOENT means the shared directory doesn't exist
4417052Samw 	 */
4427348SJose.Borrego@Sun.COM 	return ((rc == ENOENT) ? NERR_UnknownDevDir : NERR_InternalError);
4437052Samw }
4447052Samw 
4457052Samw /*
4467961SNatalie.Li@Sun.COM  * Removes the specified share from cache, removes it from AD
4477961SNatalie.Li@Sun.COM  * if it has an AD container, and calls the kernel to release
4487961SNatalie.Li@Sun.COM  * the hold on the shared file system.
4497052Samw  *
4507961SNatalie.Li@Sun.COM  * If this is an autohome share then decrement the reference
4517961SNatalie.Li@Sun.COM  * count. If it reaches 0 then it proceeds with removing steps.
4527052Samw  */
4537348SJose.Borrego@Sun.COM uint32_t
smb_shr_remove(char * sharename)4547961SNatalie.Li@Sun.COM smb_shr_remove(char *sharename)
4557052Samw {
4567961SNatalie.Li@Sun.COM 	smb_share_t *si;
4577961SNatalie.Li@Sun.COM 	char container[MAXPATHLEN];
45811963SAfshin.Ardakani@Sun.COM 	boolean_t dfsroot;
45912508Samw@Sun.COM 	nvlist_t *shrlist;
4607348SJose.Borrego@Sun.COM 
4617348SJose.Borrego@Sun.COM 	assert(sharename != NULL);
4627348SJose.Borrego@Sun.COM 
46311337SWilliam.Krier@Sun.COM 	if (smb_name_validate_share(sharename) != ERROR_SUCCESS)
4647961SNatalie.Li@Sun.COM 		return (ERROR_INVALID_NAME);
4657052Samw 
4667961SNatalie.Li@Sun.COM 	if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success)
4677961SNatalie.Li@Sun.COM 		return (NERR_InternalError);
4687961SNatalie.Li@Sun.COM 
4697961SNatalie.Li@Sun.COM 	if ((si = smb_shr_cache_findent(sharename)) == NULL) {
4707961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
4717961SNatalie.Li@Sun.COM 		return (NERR_NetNameNotFound);
4727961SNatalie.Li@Sun.COM 	}
4737348SJose.Borrego@Sun.COM 
4747961SNatalie.Li@Sun.COM 	if (si->shr_type & STYPE_IPC) {
4757961SNatalie.Li@Sun.COM 		/* IPC$ share cannot be removed */
4767961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
4777961SNatalie.Li@Sun.COM 		return (ERROR_ACCESS_DENIED);
4787961SNatalie.Li@Sun.COM 	}
4797961SNatalie.Li@Sun.COM 
4807961SNatalie.Li@Sun.COM 	if (si->shr_flags & SMB_SHRF_AUTOHOME) {
4817961SNatalie.Li@Sun.COM 		if ((--si->shr_refcnt) > 0) {
4827961SNatalie.Li@Sun.COM 			smb_shr_cache_unlock();
4837961SNatalie.Li@Sun.COM 			return (NERR_Success);
4847348SJose.Borrego@Sun.COM 		}
4857052Samw 	}
4867052Samw 
4878845Samw@Sun.COM 	/*
4888845Samw@Sun.COM 	 * If path is ZFS, remove the .zfs/shares/<share> entry.  Need
4898845Samw@Sun.COM 	 * to remove before cleanup of cache occurs.
4908845Samw@Sun.COM 	 */
4918845Samw@Sun.COM 	smb_shr_zfs_remove(si);
49212508Samw@Sun.COM 	(void) smb_shr_encode(si, &shrlist);
4938845Samw@Sun.COM 
4947961SNatalie.Li@Sun.COM 	(void) strlcpy(container, si->shr_container, sizeof (container));
49511963SAfshin.Ardakani@Sun.COM 	dfsroot = ((si->shr_flags & SMB_SHRF_DFSROOT) != 0);
4967961SNatalie.Li@Sun.COM 	smb_shr_cache_delent(sharename);
4977961SNatalie.Li@Sun.COM 	smb_shr_cache_unlock();
4987348SJose.Borrego@Sun.COM 
4997961SNatalie.Li@Sun.COM 	smb_shr_unpublish(sharename, container);
5007961SNatalie.Li@Sun.COM 
5017961SNatalie.Li@Sun.COM 	/* call kernel to release the hold on the shared file system */
50212508Samw@Sun.COM 	if (shrlist != NULL) {
50312508Samw@Sun.COM 		(void) smb_kmod_unshare(shrlist);
50412508Samw@Sun.COM 		nvlist_free(shrlist);
50512508Samw@Sun.COM 	}
5067348SJose.Borrego@Sun.COM 
50711963SAfshin.Ardakani@Sun.COM 	if (dfsroot)
50811963SAfshin.Ardakani@Sun.COM 		dfs_namespace_unload(sharename);
50911963SAfshin.Ardakani@Sun.COM 
5107052Samw 	return (NERR_Success);
5117052Samw }
5127052Samw 
5137052Samw /*
5147052Samw  * Rename a share. Check that the current name exists and the new name
5157052Samw  * doesn't exist. The rename is performed by deleting the current share
5167052Samw  * definition and creating a new share with the new name.
5177052Samw  */
5187052Samw uint32_t
smb_shr_rename(char * from_name,char * to_name)5197348SJose.Borrego@Sun.COM smb_shr_rename(char *from_name, char *to_name)
5207052Samw {
5217961SNatalie.Li@Sun.COM 	smb_share_t *from_si;
5227961SNatalie.Li@Sun.COM 	smb_share_t to_si;
5237348SJose.Borrego@Sun.COM 	uint32_t status;
52412508Samw@Sun.COM 	nvlist_t *shrlist;
5257348SJose.Borrego@Sun.COM 
5267348SJose.Borrego@Sun.COM 	assert((from_name != NULL) && (to_name != NULL));
5277052Samw 
52811337SWilliam.Krier@Sun.COM 	if (smb_name_validate_share(from_name) != ERROR_SUCCESS ||
52911337SWilliam.Krier@Sun.COM 	    smb_name_validate_share(to_name) != ERROR_SUCCESS)
5307348SJose.Borrego@Sun.COM 		return (ERROR_INVALID_NAME);
5317052Samw 
5327961SNatalie.Li@Sun.COM 	if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success)
5337961SNatalie.Li@Sun.COM 		return (NERR_InternalError);
5347961SNatalie.Li@Sun.COM 
5357961SNatalie.Li@Sun.COM 	if ((from_si = smb_shr_cache_findent(from_name)) == NULL) {
5367961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
5377052Samw 		return (NERR_NetNameNotFound);
5387961SNatalie.Li@Sun.COM 	}
5397052Samw 
5407961SNatalie.Li@Sun.COM 	if (from_si->shr_type & STYPE_IPC) {
5417961SNatalie.Li@Sun.COM 		/* IPC$ share cannot be renamed */
5427961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
5437961SNatalie.Li@Sun.COM 		return (ERROR_ACCESS_DENIED);
5447961SNatalie.Li@Sun.COM 	}
5457961SNatalie.Li@Sun.COM 
5467961SNatalie.Li@Sun.COM 	if (smb_shr_cache_findent(to_name) != NULL) {
5477961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
5487052Samw 		return (NERR_DuplicateShare);
5497961SNatalie.Li@Sun.COM 	}
5507052Samw 
5517961SNatalie.Li@Sun.COM 	bcopy(from_si, &to_si, sizeof (smb_share_t));
5527961SNatalie.Li@Sun.COM 	(void) strlcpy(to_si.shr_name, to_name, sizeof (to_si.shr_name));
5537961SNatalie.Li@Sun.COM 
55412890SJoyce.McIntosh@Sun.COM 
5558845Samw@Sun.COM 	/* If path is ZFS, rename the .zfs/shares/<share> entry. */
5568845Samw@Sun.COM 	smb_shr_zfs_rename(from_si, &to_si);
5578845Samw@Sun.COM 
5587961SNatalie.Li@Sun.COM 	if ((status = smb_shr_cache_addent(&to_si)) != NERR_Success) {
5597961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
5607348SJose.Borrego@Sun.COM 		return (status);
5617961SNatalie.Li@Sun.COM 	}
5627348SJose.Borrego@Sun.COM 
5637348SJose.Borrego@Sun.COM 	smb_shr_cache_delent(from_name);
5647961SNatalie.Li@Sun.COM 	smb_shr_cache_unlock();
5657961SNatalie.Li@Sun.COM 
56612508Samw@Sun.COM 	if (smb_shr_encode(from_si, &shrlist) == 0) {
56712508Samw@Sun.COM 		(void) smb_kmod_unshare(shrlist);
56812508Samw@Sun.COM 		nvlist_free(shrlist);
56912508Samw@Sun.COM 
57012508Samw@Sun.COM 		if (smb_shr_encode(&to_si, &shrlist) == 0) {
57112508Samw@Sun.COM 			(void) smb_kmod_share(shrlist);
57212508Samw@Sun.COM 			nvlist_free(shrlist);
57312508Samw@Sun.COM 		}
57412508Samw@Sun.COM 	}
57512508Samw@Sun.COM 
5767961SNatalie.Li@Sun.COM 	smb_shr_unpublish(from_name, to_si.shr_container);
5777961SNatalie.Li@Sun.COM 	smb_shr_publish(to_name, to_si.shr_container);
5787348SJose.Borrego@Sun.COM 
5797348SJose.Borrego@Sun.COM 	return (NERR_Success);
5807348SJose.Borrego@Sun.COM }
5817348SJose.Borrego@Sun.COM 
5827348SJose.Borrego@Sun.COM /*
5837348SJose.Borrego@Sun.COM  * Load the information for the specified share into the supplied share
5847348SJose.Borrego@Sun.COM  * info structure.
5858334SJose.Borrego@Sun.COM  *
5868334SJose.Borrego@Sun.COM  * First looks up the cache to see if the specified share exists, if there
5878334SJose.Borrego@Sun.COM  * is a miss then it looks up sharemgr.
5887348SJose.Borrego@Sun.COM  */
5897348SJose.Borrego@Sun.COM uint32_t
smb_shr_get(char * sharename,smb_share_t * si)5907348SJose.Borrego@Sun.COM smb_shr_get(char *sharename, smb_share_t *si)
5917348SJose.Borrego@Sun.COM {
5928334SJose.Borrego@Sun.COM 	uint32_t status;
5937348SJose.Borrego@Sun.COM 
5947961SNatalie.Li@Sun.COM 	if (sharename == NULL || *sharename == '\0')
5957961SNatalie.Li@Sun.COM 		return (NERR_NetNameNotFound);
5967348SJose.Borrego@Sun.COM 
5978334SJose.Borrego@Sun.COM 	if ((status = smb_shr_lookup(sharename, si)) == NERR_Success)
5988334SJose.Borrego@Sun.COM 		return (status);
5997961SNatalie.Li@Sun.COM 
6008334SJose.Borrego@Sun.COM 	if ((status = smb_shr_sa_loadbyname(sharename)) == NERR_Success)
6018334SJose.Borrego@Sun.COM 		status = smb_shr_lookup(sharename, si);
6027348SJose.Borrego@Sun.COM 
6037961SNatalie.Li@Sun.COM 	return (status);
6047348SJose.Borrego@Sun.COM }
6057348SJose.Borrego@Sun.COM 
6067348SJose.Borrego@Sun.COM /*
6077348SJose.Borrego@Sun.COM  * Modifies an existing share. Properties that can be modified are:
6087348SJose.Borrego@Sun.COM  *
6097348SJose.Borrego@Sun.COM  *   o comment
6107348SJose.Borrego@Sun.COM  *   o AD container
6117961SNatalie.Li@Sun.COM  *   o host access
61210504SKeyur.Desai@Sun.COM  *   o abe
6137348SJose.Borrego@Sun.COM  */
6147348SJose.Borrego@Sun.COM uint32_t
smb_shr_modify(smb_share_t * new_si)6157961SNatalie.Li@Sun.COM smb_shr_modify(smb_share_t *new_si)
6167348SJose.Borrego@Sun.COM {
6177961SNatalie.Li@Sun.COM 	smb_share_t *si;
6187348SJose.Borrego@Sun.COM 	boolean_t adc_changed = B_FALSE;
6197961SNatalie.Li@Sun.COM 	char old_container[MAXPATHLEN];
62011963SAfshin.Ardakani@Sun.COM 	uint32_t access, flag;
62112508Samw@Sun.COM 	nvlist_t *shrlist;
6227348SJose.Borrego@Sun.COM 
6237961SNatalie.Li@Sun.COM 	assert(new_si != NULL);
6247348SJose.Borrego@Sun.COM 
6257961SNatalie.Li@Sun.COM 	if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success)
6267961SNatalie.Li@Sun.COM 		return (NERR_InternalError);
6277348SJose.Borrego@Sun.COM 
6287961SNatalie.Li@Sun.COM 	if ((si = smb_shr_cache_findent(new_si->shr_name)) == NULL) {
6297961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
6307961SNatalie.Li@Sun.COM 		return (NERR_NetNameNotFound);
6317961SNatalie.Li@Sun.COM 	}
6327348SJose.Borrego@Sun.COM 
6337961SNatalie.Li@Sun.COM 	if (si->shr_type & STYPE_IPC) {
6347961SNatalie.Li@Sun.COM 		/* IPC$ share cannot be modified */
6357961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
6367961SNatalie.Li@Sun.COM 		return (ERROR_ACCESS_DENIED);
6377348SJose.Borrego@Sun.COM 	}
6387348SJose.Borrego@Sun.COM 
6398474SJose.Borrego@Sun.COM 	(void) strlcpy(si->shr_cmnt, new_si->shr_cmnt, sizeof (si->shr_cmnt));
6407961SNatalie.Li@Sun.COM 
6417961SNatalie.Li@Sun.COM 	adc_changed = (strcmp(new_si->shr_container, si->shr_container) != 0);
6427961SNatalie.Li@Sun.COM 	if (adc_changed) {
6437961SNatalie.Li@Sun.COM 		/* save current container - needed for unpublishing */
6447961SNatalie.Li@Sun.COM 		(void) strlcpy(old_container, si->shr_container,
6457961SNatalie.Li@Sun.COM 		    sizeof (old_container));
6467961SNatalie.Li@Sun.COM 		(void) strlcpy(si->shr_container, new_si->shr_container,
6477961SNatalie.Li@Sun.COM 		    sizeof (si->shr_container));
6487348SJose.Borrego@Sun.COM 	}
6497348SJose.Borrego@Sun.COM 
65011963SAfshin.Ardakani@Sun.COM 	flag = (new_si->shr_flags & SMB_SHRF_ABE);
65110504SKeyur.Desai@Sun.COM 	si->shr_flags &= ~SMB_SHRF_ABE;
65211963SAfshin.Ardakani@Sun.COM 	si->shr_flags |= flag;
65310504SKeyur.Desai@Sun.COM 
65411963SAfshin.Ardakani@Sun.COM 	flag = (new_si->shr_flags & SMB_SHRF_CATIA);
6559231SAfshin.Ardakani@Sun.COM 	si->shr_flags &= ~SMB_SHRF_CATIA;
65611963SAfshin.Ardakani@Sun.COM 	si->shr_flags |= flag;
6579231SAfshin.Ardakani@Sun.COM 
65811963SAfshin.Ardakani@Sun.COM 	flag = (new_si->shr_flags & SMB_SHRF_GUEST_OK);
65911963SAfshin.Ardakani@Sun.COM 	si->shr_flags &= ~SMB_SHRF_GUEST_OK;
66011963SAfshin.Ardakani@Sun.COM 	si->shr_flags |= flag;
6619832Samw@Sun.COM 
66211963SAfshin.Ardakani@Sun.COM 	flag = (new_si->shr_flags & SMB_SHRF_DFSROOT);
66311963SAfshin.Ardakani@Sun.COM 	si->shr_flags &= ~SMB_SHRF_DFSROOT;
66411963SAfshin.Ardakani@Sun.COM 	si->shr_flags |= flag;
66511963SAfshin.Ardakani@Sun.COM 
66611963SAfshin.Ardakani@Sun.COM 	flag = (new_si->shr_flags & SMB_SHRF_CSC_MASK);
66711963SAfshin.Ardakani@Sun.COM 	si->shr_flags &= ~SMB_SHRF_CSC_MASK;
66811963SAfshin.Ardakani@Sun.COM 	si->shr_flags |= flag;
6698334SJose.Borrego@Sun.COM 
6707961SNatalie.Li@Sun.COM 	access = (new_si->shr_flags & SMB_SHRF_ACC_ALL);
6718474SJose.Borrego@Sun.COM 	si->shr_flags &= ~SMB_SHRF_ACC_ALL;
6727961SNatalie.Li@Sun.COM 	si->shr_flags |= access;
6737961SNatalie.Li@Sun.COM 
6747961SNatalie.Li@Sun.COM 	if (access & SMB_SHRF_ACC_NONE)
6757961SNatalie.Li@Sun.COM 		(void) strlcpy(si->shr_access_none, new_si->shr_access_none,
6767961SNatalie.Li@Sun.COM 		    sizeof (si->shr_access_none));
6777348SJose.Borrego@Sun.COM 
6787961SNatalie.Li@Sun.COM 	if (access & SMB_SHRF_ACC_RO)
6797961SNatalie.Li@Sun.COM 		(void) strlcpy(si->shr_access_ro, new_si->shr_access_ro,
6807961SNatalie.Li@Sun.COM 		    sizeof (si->shr_access_ro));
6817348SJose.Borrego@Sun.COM 
6827961SNatalie.Li@Sun.COM 	if (access & SMB_SHRF_ACC_RW)
6837961SNatalie.Li@Sun.COM 		(void) strlcpy(si->shr_access_rw, new_si->shr_access_rw,
6847961SNatalie.Li@Sun.COM 		    sizeof (si->shr_access_rw));
6857961SNatalie.Li@Sun.COM 
6867961SNatalie.Li@Sun.COM 	smb_shr_cache_unlock();
6877052Samw 
68812508Samw@Sun.COM 	if (smb_shr_encode(si, &shrlist) == 0) {
68912508Samw@Sun.COM 		(void) smb_kmod_unshare(shrlist);
69012508Samw@Sun.COM 		nvlist_free(shrlist);
69112508Samw@Sun.COM 
69212508Samw@Sun.COM 		if (smb_shr_encode(new_si, &shrlist) == 0) {
69312508Samw@Sun.COM 			(void) smb_kmod_share(shrlist);
69412508Samw@Sun.COM 			nvlist_free(shrlist);
69512508Samw@Sun.COM 		}
69612508Samw@Sun.COM 	}
69712508Samw@Sun.COM 
6987348SJose.Borrego@Sun.COM 	if (adc_changed) {
6997961SNatalie.Li@Sun.COM 		smb_shr_unpublish(new_si->shr_name, old_container);
7007961SNatalie.Li@Sun.COM 		smb_shr_publish(new_si->shr_name, new_si->shr_container);
7017348SJose.Borrego@Sun.COM 	}
7027348SJose.Borrego@Sun.COM 
7037348SJose.Borrego@Sun.COM 	return (NERR_Success);
7047052Samw }
7057052Samw 
7067052Samw /*
7077052Samw  * smb_shr_exists
7087052Samw  *
7097348SJose.Borrego@Sun.COM  * Returns B_TRUE if the share exists. Otherwise returns B_FALSE
7107052Samw  */
7117348SJose.Borrego@Sun.COM boolean_t
smb_shr_exists(char * sharename)7127348SJose.Borrego@Sun.COM smb_shr_exists(char *sharename)
7137052Samw {
7147961SNatalie.Li@Sun.COM 	boolean_t exists = B_FALSE;
7157348SJose.Borrego@Sun.COM 
7167348SJose.Borrego@Sun.COM 	if (sharename == NULL || *sharename == '\0')
7177348SJose.Borrego@Sun.COM 		return (B_FALSE);
7187052Samw 
7197961SNatalie.Li@Sun.COM 	if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) {
7207961SNatalie.Li@Sun.COM 		exists = (smb_shr_cache_findent(sharename) != NULL);
7217961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
7227961SNatalie.Li@Sun.COM 	}
7237348SJose.Borrego@Sun.COM 
7247348SJose.Borrego@Sun.COM 	return (exists);
7257052Samw }
7267052Samw 
7277052Samw /*
7287961SNatalie.Li@Sun.COM  * If the shared directory does not begin with a /, one will be
7297961SNatalie.Li@Sun.COM  * inserted as a prefix. If ipaddr is not zero, then also return
7307961SNatalie.Li@Sun.COM  * information about access based on the host level access lists, if
7317961SNatalie.Li@Sun.COM  * present. Also return access check if there is an IP address and
7327961SNatalie.Li@Sun.COM  * shr_accflags.
7337961SNatalie.Li@Sun.COM  *
7347961SNatalie.Li@Sun.COM  * The value of smb_chk_hostaccess is checked for an access match.
7357961SNatalie.Li@Sun.COM  * -1 is wildcard match
7367961SNatalie.Li@Sun.COM  * 0 is no match
7377961SNatalie.Li@Sun.COM  * 1 is match
7387961SNatalie.Li@Sun.COM  *
7397961SNatalie.Li@Sun.COM  * Precedence is none is checked first followed by ro then rw if
7407961SNatalie.Li@Sun.COM  * needed.  If x is wildcard (< 0) then check to see if the other
7417961SNatalie.Li@Sun.COM  * values are a match. If a match, that wins.
7428670SJose.Borrego@Sun.COM  *
74312508Samw@Sun.COM  * ipv6 is wide open (returns SMB_SHRF_ACC_OPEN) for now until the underlying
74412508Samw@Sun.COM  * functions support ipv6.
7457961SNatalie.Li@Sun.COM  */
74612508Samw@Sun.COM uint32_t
smb_shr_hostaccess(smb_inaddr_t * ipaddr,char * none_list,char * ro_list,char * rw_list,uint32_t flag)74712508Samw@Sun.COM smb_shr_hostaccess(smb_inaddr_t *ipaddr, char *none_list, char *ro_list,
74812508Samw@Sun.COM     char *rw_list, uint32_t flag)
7497961SNatalie.Li@Sun.COM {
75012508Samw@Sun.COM 	uint32_t acc = SMB_SHRF_ACC_NONE;
75112508Samw@Sun.COM 	int none = 0;
75212508Samw@Sun.COM 	int ro = 0;
75312508Samw@Sun.COM 	int rw = 0;
7547961SNatalie.Li@Sun.COM 
75512508Samw@Sun.COM 	if (!smb_inet_iszero(ipaddr)) {
75612508Samw@Sun.COM 
75712508Samw@Sun.COM 		if (ipaddr->a_family == AF_INET6)
75812508Samw@Sun.COM 			return (SMB_SHRF_ACC_OPEN);
7597961SNatalie.Li@Sun.COM 
76012508Samw@Sun.COM 		if ((flag & SMB_SHRF_ACC_NONE) != 0)
76112508Samw@Sun.COM 			none = smb_chk_hostaccess(ipaddr, none_list);
76212508Samw@Sun.COM 		if ((flag & SMB_SHRF_ACC_RO) != 0)
76312508Samw@Sun.COM 			ro = smb_chk_hostaccess(ipaddr, ro_list);
76412508Samw@Sun.COM 		if ((flag & SMB_SHRF_ACC_RW) != 0)
76512508Samw@Sun.COM 			rw = smb_chk_hostaccess(ipaddr, rw_list);
76612508Samw@Sun.COM 
7677961SNatalie.Li@Sun.COM 		/* make first pass to get basic value */
7687961SNatalie.Li@Sun.COM 		if (none != 0)
7697961SNatalie.Li@Sun.COM 			acc = SMB_SHRF_ACC_NONE;
7707961SNatalie.Li@Sun.COM 		else if (ro != 0)
7717961SNatalie.Li@Sun.COM 			acc = SMB_SHRF_ACC_RO;
7727961SNatalie.Li@Sun.COM 		else if (rw != 0)
7737961SNatalie.Li@Sun.COM 			acc = SMB_SHRF_ACC_RW;
7747961SNatalie.Li@Sun.COM 
7757961SNatalie.Li@Sun.COM 		/* make second pass to handle '*' case */
7767961SNatalie.Li@Sun.COM 		if (none < 0) {
7777961SNatalie.Li@Sun.COM 			acc = SMB_SHRF_ACC_NONE;
7787961SNatalie.Li@Sun.COM 			if (ro > 0)
7797961SNatalie.Li@Sun.COM 				acc = SMB_SHRF_ACC_RO;
7807961SNatalie.Li@Sun.COM 			else if (rw > 0)
7817961SNatalie.Li@Sun.COM 				acc = SMB_SHRF_ACC_RW;
7827961SNatalie.Li@Sun.COM 		} else if (ro < 0) {
7837961SNatalie.Li@Sun.COM 			acc = SMB_SHRF_ACC_RO;
7847961SNatalie.Li@Sun.COM 			if (none > 0)
7857961SNatalie.Li@Sun.COM 				acc = SMB_SHRF_ACC_NONE;
7867961SNatalie.Li@Sun.COM 			else if (rw > 0)
7877961SNatalie.Li@Sun.COM 				acc = SMB_SHRF_ACC_RW;
7887961SNatalie.Li@Sun.COM 		} else if (rw < 0) {
7897961SNatalie.Li@Sun.COM 			acc = SMB_SHRF_ACC_RW;
7907961SNatalie.Li@Sun.COM 			if (none > 0)
7917961SNatalie.Li@Sun.COM 				acc = SMB_SHRF_ACC_NONE;
7927961SNatalie.Li@Sun.COM 			else if (ro > 0)
7937961SNatalie.Li@Sun.COM 				acc = SMB_SHRF_ACC_RO;
7947961SNatalie.Li@Sun.COM 		}
7957961SNatalie.Li@Sun.COM 	}
79612508Samw@Sun.COM 
79712508Samw@Sun.COM 	return (acc);
7987961SNatalie.Li@Sun.COM }
7997961SNatalie.Li@Sun.COM 
8007961SNatalie.Li@Sun.COM /*
8017052Samw  * smb_shr_is_special
8027052Samw  *
8037348SJose.Borrego@Sun.COM  * Special share reserved for interprocess communication (IPC$) or
8047348SJose.Borrego@Sun.COM  * remote administration of the server (ADMIN$). Can also refer to
8057348SJose.Borrego@Sun.COM  * administrative shares such as C$, D$, E$, and so forth.
8067052Samw  */
8077052Samw int
smb_shr_is_special(char * sharename)8087348SJose.Borrego@Sun.COM smb_shr_is_special(char *sharename)
8097052Samw {
8107052Samw 	int len;
8117052Samw 
8127348SJose.Borrego@Sun.COM 	if (sharename == NULL)
8137052Samw 		return (0);
8147052Samw 
8157348SJose.Borrego@Sun.COM 	if ((len = strlen(sharename)) == 0)
8167052Samw 		return (0);
8177052Samw 
8187348SJose.Borrego@Sun.COM 	if (sharename[len - 1] == '$')
8197052Samw 		return (STYPE_SPECIAL);
8207348SJose.Borrego@Sun.COM 
8217348SJose.Borrego@Sun.COM 	return (0);
8227052Samw }
8237052Samw 
8247052Samw /*
8257052Samw  * smb_shr_is_restricted
8267052Samw  *
8277052Samw  * Check whether or not there is a restriction on a share. Restricted
8287052Samw  * shares are generally STYPE_SPECIAL, for example, IPC$. All the
8297348SJose.Borrego@Sun.COM  * administration share names are restricted: C$, D$ etc. Returns B_TRUE
8307348SJose.Borrego@Sun.COM  * if the share is restricted. Otherwise B_FALSE is returned to indicate
8317052Samw  * that there are no restrictions.
8327052Samw  */
8337348SJose.Borrego@Sun.COM boolean_t
smb_shr_is_restricted(char * sharename)8347348SJose.Borrego@Sun.COM smb_shr_is_restricted(char *sharename)
8357052Samw {
8367052Samw 	static char *restricted[] = {
8377052Samw 		"IPC$"
8387052Samw 	};
8397052Samw 
8407052Samw 	int i;
8417052Samw 
8427348SJose.Borrego@Sun.COM 	if (sharename == NULL)
8437348SJose.Borrego@Sun.COM 		return (B_FALSE);
8447348SJose.Borrego@Sun.COM 
8457052Samw 	for (i = 0; i < sizeof (restricted)/sizeof (restricted[0]); i++) {
84610966SJordan.Brown@Sun.COM 		if (smb_strcasecmp(restricted[i], sharename, 0) == 0)
8477348SJose.Borrego@Sun.COM 			return (B_TRUE);
8487052Samw 	}
8497052Samw 
8507348SJose.Borrego@Sun.COM 	return (smb_shr_is_admin(sharename));
8517052Samw }
8527052Samw 
8537052Samw /*
8547052Samw  * smb_shr_is_admin
8557052Samw  *
8567052Samw  * Check whether or not access to the share should be restricted to
8577052Samw  * administrators. This is a bit of a hack because what we're doing
8587052Samw  * is checking for the default admin shares: C$, D$ etc.. There are
8597052Samw  * other shares that have restrictions: see smb_shr_is_restricted().
8607052Samw  *
8617348SJose.Borrego@Sun.COM  * Returns B_TRUE if the shares is an admin share. Otherwise B_FALSE
8627348SJose.Borrego@Sun.COM  * is returned to indicate that there are no restrictions.
8637052Samw  */
8647348SJose.Borrego@Sun.COM boolean_t
smb_shr_is_admin(char * sharename)8657348SJose.Borrego@Sun.COM smb_shr_is_admin(char *sharename)
8667052Samw {
8677348SJose.Borrego@Sun.COM 	if (sharename == NULL)
8687348SJose.Borrego@Sun.COM 		return (B_FALSE);
8697052Samw 
8707348SJose.Borrego@Sun.COM 	if (strlen(sharename) == 2 &&
87110966SJordan.Brown@Sun.COM 	    smb_isalpha(sharename[0]) && sharename[1] == '$') {
8727348SJose.Borrego@Sun.COM 		return (B_TRUE);
8737052Samw 	}
8747052Samw 
8757348SJose.Borrego@Sun.COM 	return (B_FALSE);
8767052Samw }
8777052Samw 
87812065SKeyur.Desai@Sun.COM char
smb_shr_drive_letter(const char * path)87912065SKeyur.Desai@Sun.COM smb_shr_drive_letter(const char *path)
88012065SKeyur.Desai@Sun.COM {
88112065SKeyur.Desai@Sun.COM 	smb_transient_t	*ts;
88212065SKeyur.Desai@Sun.COM 	int i;
88312065SKeyur.Desai@Sun.COM 
88412065SKeyur.Desai@Sun.COM 	if (path == NULL)
88512065SKeyur.Desai@Sun.COM 		return ('\0');
88612065SKeyur.Desai@Sun.COM 
88712065SKeyur.Desai@Sun.COM 	for (i = 0; i < sizeof (tshare)/sizeof (tshare[0]); ++i) {
88812065SKeyur.Desai@Sun.COM 		ts = &tshare[i];
88912065SKeyur.Desai@Sun.COM 
89012065SKeyur.Desai@Sun.COM 		if (ts->path == NULL)
89112065SKeyur.Desai@Sun.COM 			continue;
89212065SKeyur.Desai@Sun.COM 
89312065SKeyur.Desai@Sun.COM 		if (strcasecmp(ts->path, path) == 0)
89412065SKeyur.Desai@Sun.COM 			return (ts->drive);
89512065SKeyur.Desai@Sun.COM 	}
89612065SKeyur.Desai@Sun.COM 
89712065SKeyur.Desai@Sun.COM 	return ('\0');
89812065SKeyur.Desai@Sun.COM }
89912065SKeyur.Desai@Sun.COM 
90012065SKeyur.Desai@Sun.COM /*
90112065SKeyur.Desai@Sun.COM  * Returns true if the specified directory is empty,
90212065SKeyur.Desai@Sun.COM  * otherwise returns false.
90312065SKeyur.Desai@Sun.COM  */
90412065SKeyur.Desai@Sun.COM static boolean_t
smb_shr_is_empty(const char * path)90512065SKeyur.Desai@Sun.COM smb_shr_is_empty(const char *path)
90612065SKeyur.Desai@Sun.COM {
90712065SKeyur.Desai@Sun.COM 	DIR *dirp;
90812065SKeyur.Desai@Sun.COM 	struct dirent *dp;
90912065SKeyur.Desai@Sun.COM 
91012065SKeyur.Desai@Sun.COM 	if (path == NULL)
91112065SKeyur.Desai@Sun.COM 		return (B_TRUE);
91212065SKeyur.Desai@Sun.COM 
91312065SKeyur.Desai@Sun.COM 	if ((dirp = opendir(path)) == NULL)
91412065SKeyur.Desai@Sun.COM 		return (B_TRUE);
91512065SKeyur.Desai@Sun.COM 
91612065SKeyur.Desai@Sun.COM 	while ((dp = readdir(dirp)) != NULL) {
91712065SKeyur.Desai@Sun.COM 		if (!smb_shr_is_dot_or_dotdot(dp->d_name))
91812065SKeyur.Desai@Sun.COM 			return (B_FALSE);
91912065SKeyur.Desai@Sun.COM 	}
92012065SKeyur.Desai@Sun.COM 
92112065SKeyur.Desai@Sun.COM 	(void) closedir(dirp);
92212065SKeyur.Desai@Sun.COM 	return (B_TRUE);
92312065SKeyur.Desai@Sun.COM }
92412065SKeyur.Desai@Sun.COM 
92512065SKeyur.Desai@Sun.COM /*
92612065SKeyur.Desai@Sun.COM  * Returns true if name is "." or "..", otherwise returns false.
92712065SKeyur.Desai@Sun.COM  */
92812065SKeyur.Desai@Sun.COM static boolean_t
smb_shr_is_dot_or_dotdot(const char * name)92912065SKeyur.Desai@Sun.COM smb_shr_is_dot_or_dotdot(const char *name)
93012065SKeyur.Desai@Sun.COM {
93112065SKeyur.Desai@Sun.COM 	if (*name != '.')
93212065SKeyur.Desai@Sun.COM 		return (B_FALSE);
93312065SKeyur.Desai@Sun.COM 
93412065SKeyur.Desai@Sun.COM 	if ((name[1] == '\0') || (name[1] == '.' && name[2] == '\0'))
93512065SKeyur.Desai@Sun.COM 		return (B_TRUE);
93612065SKeyur.Desai@Sun.COM 
93712065SKeyur.Desai@Sun.COM 	return (B_FALSE);
93812065SKeyur.Desai@Sun.COM }
93912065SKeyur.Desai@Sun.COM 
9407052Samw /*
9417052Samw  * smb_shr_get_realpath
9427052Samw  *
9437961SNatalie.Li@Sun.COM  * Derive the real path for a share from the path provided by a client.
9447961SNatalie.Li@Sun.COM  * For instance, the real path of C:\ may be /cvol or the real path of
9457961SNatalie.Li@Sun.COM  * F:\home may be /vol1/home.
9467052Samw  *
9477961SNatalie.Li@Sun.COM  * clntpath - path provided by the Windows client is in the
9487052Samw  *            format of <drive letter>:\<dir>
9497052Samw  * realpath - path that will be stored as the directory field of
9507052Samw  *            the smb_share_t structure of the share.
9517961SNatalie.Li@Sun.COM  * maxlen   - maximum length of the realpath buffer
9527052Samw  *
9537052Samw  * Return LAN Manager network error code.
9547052Samw  */
9557052Samw uint32_t
smb_shr_get_realpath(const char * clntpath,char * realpath,int maxlen)9567961SNatalie.Li@Sun.COM smb_shr_get_realpath(const char *clntpath, char *realpath, int maxlen)
9577052Samw {
9587961SNatalie.Li@Sun.COM 	const char *p;
9597961SNatalie.Li@Sun.COM 	int len;
9607348SJose.Borrego@Sun.COM 
9617961SNatalie.Li@Sun.COM 	if ((p = strchr(clntpath, ':')) != NULL)
9627961SNatalie.Li@Sun.COM 		++p;
9637961SNatalie.Li@Sun.COM 	else
9647961SNatalie.Li@Sun.COM 		p = clntpath;
9657348SJose.Borrego@Sun.COM 
9667961SNatalie.Li@Sun.COM 	(void) strlcpy(realpath, p, maxlen);
9677961SNatalie.Li@Sun.COM 	(void) strcanon(realpath, "/\\");
9687961SNatalie.Li@Sun.COM 	(void) strsubst(realpath, '\\', '/');
9697348SJose.Borrego@Sun.COM 
9707961SNatalie.Li@Sun.COM 	len = strlen(realpath);
9717961SNatalie.Li@Sun.COM 	if ((len > 1) && (realpath[len - 1] == '/'))
9727961SNatalie.Li@Sun.COM 		realpath[len - 1] = '\0';
9737348SJose.Borrego@Sun.COM 
9747348SJose.Borrego@Sun.COM 	return (NERR_Success);
9757348SJose.Borrego@Sun.COM }
9767348SJose.Borrego@Sun.COM 
9777961SNatalie.Li@Sun.COM void
smb_shr_list(int offset,smb_shrlist_t * list)9787961SNatalie.Li@Sun.COM smb_shr_list(int offset, smb_shrlist_t *list)
9797348SJose.Borrego@Sun.COM {
9807961SNatalie.Li@Sun.COM 	smb_shriter_t iterator;
9817961SNatalie.Li@Sun.COM 	smb_share_t *si;
9827961SNatalie.Li@Sun.COM 	int n = 0;
9837961SNatalie.Li@Sun.COM 
9847961SNatalie.Li@Sun.COM 	bzero(list, sizeof (smb_shrlist_t));
9857961SNatalie.Li@Sun.COM 	smb_shr_iterinit(&iterator);
9867961SNatalie.Li@Sun.COM 
9877961SNatalie.Li@Sun.COM 	while ((si = smb_shr_iterate(&iterator)) != NULL) {
9887961SNatalie.Li@Sun.COM 		if (--offset > 0)
9897961SNatalie.Li@Sun.COM 			continue;
9907961SNatalie.Li@Sun.COM 
9917961SNatalie.Li@Sun.COM 		if ((si->shr_flags & SMB_SHRF_TRANS) &&
9927961SNatalie.Li@Sun.COM 		    ((si->shr_type & STYPE_IPC) == 0)) {
9937961SNatalie.Li@Sun.COM 			bcopy(si, &list->sl_shares[n], sizeof (smb_share_t));
9947961SNatalie.Li@Sun.COM 			if (++n == LMSHARES_PER_REQUEST)
9957961SNatalie.Li@Sun.COM 				break;
9967961SNatalie.Li@Sun.COM 		}
9977348SJose.Borrego@Sun.COM 	}
9987961SNatalie.Li@Sun.COM 
9997961SNatalie.Li@Sun.COM 	list->sl_cnt = n;
10007348SJose.Borrego@Sun.COM }
10017348SJose.Borrego@Sun.COM 
10027348SJose.Borrego@Sun.COM /*
10039832Samw@Sun.COM  * Executes the map/unmap command associated with a share.
10049832Samw@Sun.COM  *
10059832Samw@Sun.COM  * Returns 0 on success.  Otherwise non-zero for errors.
10069832Samw@Sun.COM  */
10079832Samw@Sun.COM int
smb_shr_exec(smb_shr_execinfo_t * subs)100812508Samw@Sun.COM smb_shr_exec(smb_shr_execinfo_t *subs)
10099832Samw@Sun.COM {
10109832Samw@Sun.COM 	char cmd[MAXPATHLEN], **cmd_tokens, *path, *ptr;
10119832Samw@Sun.COM 	pid_t child_pid;
10129832Samw@Sun.COM 	int child_status;
10139832Samw@Sun.COM 	struct sigaction pact, cact;
10149832Samw@Sun.COM 	smb_share_t si;
10159832Samw@Sun.COM 
101612508Samw@Sun.COM 	if (smb_shr_get(subs->e_sharename, &si) != 0)
10179832Samw@Sun.COM 		return (-1);
10189832Samw@Sun.COM 
10199832Samw@Sun.COM 	*cmd = '\0';
10209832Samw@Sun.COM 
10219832Samw@Sun.COM 	(void) mutex_lock(&smb_shr_exec_mtx);
10229832Samw@Sun.COM 
102312508Samw@Sun.COM 	switch (subs->e_type) {
102412508Samw@Sun.COM 	case SMB_EXEC_MAP:
10259832Samw@Sun.COM 		(void) strlcpy(cmd, smb_shr_exec_map, sizeof (cmd));
10269832Samw@Sun.COM 		break;
102712508Samw@Sun.COM 	case SMB_EXEC_UNMAP:
10289832Samw@Sun.COM 		(void) strlcpy(cmd, smb_shr_exec_unmap, sizeof (cmd));
10299832Samw@Sun.COM 		break;
10309832Samw@Sun.COM 	default:
10319832Samw@Sun.COM 		(void) mutex_unlock(&smb_shr_exec_mtx);
10329832Samw@Sun.COM 		return (-1);
10339832Samw@Sun.COM 	}
10349832Samw@Sun.COM 
10359832Samw@Sun.COM 	(void) mutex_unlock(&smb_shr_exec_mtx);
10369832Samw@Sun.COM 
10379832Samw@Sun.COM 	if (*cmd == '\0')
10389832Samw@Sun.COM 		return (0);
10399832Samw@Sun.COM 
104010504SKeyur.Desai@Sun.COM 	if (smb_proc_takesem() != 0)
104110504SKeyur.Desai@Sun.COM 		return (-1);
104210504SKeyur.Desai@Sun.COM 
10439832Samw@Sun.COM 	pact.sa_handler = smb_shr_sig_child;
10449832Samw@Sun.COM 	pact.sa_flags = 0;
10459832Samw@Sun.COM 	(void) sigemptyset(&pact.sa_mask);
10469832Samw@Sun.COM 	sigaction(SIGCHLD, &pact, NULL);
10479832Samw@Sun.COM 
10489832Samw@Sun.COM 	(void) priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_FORK, NULL);
10499832Samw@Sun.COM 
10509832Samw@Sun.COM 	if ((child_pid = fork()) == -1) {
10519832Samw@Sun.COM 		(void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_FORK, NULL);
105210504SKeyur.Desai@Sun.COM 		smb_proc_givesem();
10539832Samw@Sun.COM 		return (-1);
10549832Samw@Sun.COM 	}
10559832Samw@Sun.COM 
10569832Samw@Sun.COM 	if (child_pid == 0) {
10579832Samw@Sun.COM 
10589832Samw@Sun.COM 		/* child process */
10599832Samw@Sun.COM 
10609832Samw@Sun.COM 		cact.sa_handler = smb_shr_sig_abnormal_term;
10619832Samw@Sun.COM 		cact.sa_flags = 0;
10629832Samw@Sun.COM 		(void) sigemptyset(&cact.sa_mask);
10639832Samw@Sun.COM 		sigaction(SIGTERM, &cact, NULL);
10649832Samw@Sun.COM 		sigaction(SIGABRT, &cact, NULL);
10659832Samw@Sun.COM 		sigaction(SIGSEGV, &cact, NULL);
10669832Samw@Sun.COM 
10679832Samw@Sun.COM 		if (priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_EXEC,
10689832Samw@Sun.COM 		    PRIV_FILE_DAC_EXECUTE, NULL))
10699832Samw@Sun.COM 			_exit(-1);
10709832Samw@Sun.COM 
10719832Samw@Sun.COM 		if (smb_shr_enable_all_privs())
10729832Samw@Sun.COM 			_exit(-1);
10739832Samw@Sun.COM 
107410504SKeyur.Desai@Sun.COM 		smb_proc_initsem();
107510504SKeyur.Desai@Sun.COM 
10769832Samw@Sun.COM 		(void) trim_whitespace(cmd);
10779832Samw@Sun.COM 		(void) strcanon(cmd, " ");
10789832Samw@Sun.COM 
10799832Samw@Sun.COM 		if ((cmd_tokens = smb_shr_tokenize_cmd(cmd)) != NULL) {
10809832Samw@Sun.COM 
10819832Samw@Sun.COM 			if (smb_shr_expand_subs(cmd_tokens, &si, subs) != 0) {
10829832Samw@Sun.COM 				free(cmd_tokens[0]);
10839832Samw@Sun.COM 				free(cmd_tokens);
10849832Samw@Sun.COM 				_exit(-1);
10859832Samw@Sun.COM 			}
10869832Samw@Sun.COM 
10879832Samw@Sun.COM 			ptr = cmd;
10889832Samw@Sun.COM 			path = strsep(&ptr, " ");
10899832Samw@Sun.COM 
10909832Samw@Sun.COM 			(void) execv(path, cmd_tokens);
10919832Samw@Sun.COM 		}
10929832Samw@Sun.COM 
10939832Samw@Sun.COM 		_exit(-1);
10949832Samw@Sun.COM 	}
10959832Samw@Sun.COM 
109610504SKeyur.Desai@Sun.COM 	(void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_FORK, NULL);
109710504SKeyur.Desai@Sun.COM 	smb_proc_givesem();
109810504SKeyur.Desai@Sun.COM 
10999832Samw@Sun.COM 	/* parent process */
11009832Samw@Sun.COM 
11019832Samw@Sun.COM 	while (waitpid(child_pid, &child_status, 0) < 0) {
11029832Samw@Sun.COM 		if (errno != EINTR)
11039832Samw@Sun.COM 			break;
11049832Samw@Sun.COM 
11059832Samw@Sun.COM 		/* continue if waitpid got interrupted by a signal */
11069832Samw@Sun.COM 		errno = 0;
11079832Samw@Sun.COM 		continue;
11089832Samw@Sun.COM 	}
11099832Samw@Sun.COM 
11109832Samw@Sun.COM 	if (WIFEXITED(child_status))
11119832Samw@Sun.COM 		return (WEXITSTATUS(child_status));
11129832Samw@Sun.COM 
11139832Samw@Sun.COM 	return (child_status);
11149832Samw@Sun.COM }
11159832Samw@Sun.COM 
11169832Samw@Sun.COM /*
111710504SKeyur.Desai@Sun.COM  * Locking for process-wide settings (i.e. privileges)
111810504SKeyur.Desai@Sun.COM  */
111910504SKeyur.Desai@Sun.COM void
smb_proc_initsem(void)112010504SKeyur.Desai@Sun.COM smb_proc_initsem(void)
112110504SKeyur.Desai@Sun.COM {
112210504SKeyur.Desai@Sun.COM 	(void) sema_init(&smb_proc_sem, 1, USYNC_THREAD, NULL);
112310504SKeyur.Desai@Sun.COM }
112410504SKeyur.Desai@Sun.COM 
112510504SKeyur.Desai@Sun.COM int
smb_proc_takesem(void)112610504SKeyur.Desai@Sun.COM smb_proc_takesem(void)
112710504SKeyur.Desai@Sun.COM {
112810504SKeyur.Desai@Sun.COM 	return (sema_wait(&smb_proc_sem));
112910504SKeyur.Desai@Sun.COM }
113010504SKeyur.Desai@Sun.COM 
113110504SKeyur.Desai@Sun.COM void
smb_proc_givesem(void)113210504SKeyur.Desai@Sun.COM smb_proc_givesem(void)
113310504SKeyur.Desai@Sun.COM {
113410504SKeyur.Desai@Sun.COM 	(void) sema_post(&smb_proc_sem);
113510504SKeyur.Desai@Sun.COM }
113610504SKeyur.Desai@Sun.COM 
113710504SKeyur.Desai@Sun.COM /*
11387961SNatalie.Li@Sun.COM  * ============================================
11397961SNatalie.Li@Sun.COM  * Private helper/utility functions
11407961SNatalie.Li@Sun.COM  * ============================================
11417348SJose.Borrego@Sun.COM  */
11427348SJose.Borrego@Sun.COM 
11437961SNatalie.Li@Sun.COM /*
11448334SJose.Borrego@Sun.COM  * Looks up the given share in the cache and return
11458334SJose.Borrego@Sun.COM  * the info in 'si'
11468334SJose.Borrego@Sun.COM  */
11478334SJose.Borrego@Sun.COM static uint32_t
smb_shr_lookup(char * sharename,smb_share_t * si)11488334SJose.Borrego@Sun.COM smb_shr_lookup(char *sharename, smb_share_t *si)
11498334SJose.Borrego@Sun.COM {
11508334SJose.Borrego@Sun.COM 	smb_share_t *cached_si;
11518334SJose.Borrego@Sun.COM 	uint32_t status = NERR_NetNameNotFound;
11528334SJose.Borrego@Sun.COM 
11538334SJose.Borrego@Sun.COM 	if (sharename == NULL || *sharename == '\0')
11548334SJose.Borrego@Sun.COM 		return (NERR_NetNameNotFound);
11558334SJose.Borrego@Sun.COM 	if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) {
11568334SJose.Borrego@Sun.COM 		cached_si = smb_shr_cache_findent(sharename);
11578334SJose.Borrego@Sun.COM 		if (cached_si != NULL) {
11588334SJose.Borrego@Sun.COM 			bcopy(cached_si, si, sizeof (smb_share_t));
11598334SJose.Borrego@Sun.COM 			status = NERR_Success;
11608334SJose.Borrego@Sun.COM 		}
11618334SJose.Borrego@Sun.COM 
11628334SJose.Borrego@Sun.COM 		smb_shr_cache_unlock();
11638334SJose.Borrego@Sun.COM 	}
11648334SJose.Borrego@Sun.COM 	return (status);
11658334SJose.Borrego@Sun.COM }
11668334SJose.Borrego@Sun.COM 
11678334SJose.Borrego@Sun.COM /*
116811963SAfshin.Ardakani@Sun.COM  * Add IPC$ or Admin shares to the cache upon startup.
11697961SNatalie.Li@Sun.COM  */
11707348SJose.Borrego@Sun.COM static uint32_t
smb_shr_add_transient(char * name,char * cmnt,char * path)117111963SAfshin.Ardakani@Sun.COM smb_shr_add_transient(char *name, char *cmnt, char *path)
11727348SJose.Borrego@Sun.COM {
117311963SAfshin.Ardakani@Sun.COM 	smb_share_t trans;
11747961SNatalie.Li@Sun.COM 	uint32_t status = NERR_InternalError;
11757348SJose.Borrego@Sun.COM 
117611963SAfshin.Ardakani@Sun.COM 	if (name == NULL)
117711963SAfshin.Ardakani@Sun.COM 		return (status);
117811963SAfshin.Ardakani@Sun.COM 
117911963SAfshin.Ardakani@Sun.COM 	bzero(&trans, sizeof (smb_share_t));
118011963SAfshin.Ardakani@Sun.COM 	(void) strlcpy(trans.shr_name, name, MAXNAMELEN);
118111963SAfshin.Ardakani@Sun.COM 	if (cmnt)
118211963SAfshin.Ardakani@Sun.COM 		(void) strlcpy(trans.shr_cmnt, cmnt, SMB_SHARE_CMNT_MAX);
118311963SAfshin.Ardakani@Sun.COM 
118411963SAfshin.Ardakani@Sun.COM 	if (path)
118511963SAfshin.Ardakani@Sun.COM 		(void) strlcpy(trans.shr_path, path, MAXPATHLEN);
118611963SAfshin.Ardakani@Sun.COM 
118711963SAfshin.Ardakani@Sun.COM 	if (strcasecmp(name, "IPC$") == 0)
118811963SAfshin.Ardakani@Sun.COM 		trans.shr_type = STYPE_IPC;
118911963SAfshin.Ardakani@Sun.COM 
119011963SAfshin.Ardakani@Sun.COM 	trans.shr_flags = SMB_SHRF_TRANS;
11917348SJose.Borrego@Sun.COM 
11927961SNatalie.Li@Sun.COM 	if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) == NERR_Success) {
119311963SAfshin.Ardakani@Sun.COM 		status = smb_shr_cache_addent(&trans);
11947961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
11957348SJose.Borrego@Sun.COM 	}
11967348SJose.Borrego@Sun.COM 
11977348SJose.Borrego@Sun.COM 	return (status);
11987348SJose.Borrego@Sun.COM }
11997348SJose.Borrego@Sun.COM 
12007348SJose.Borrego@Sun.COM /*
12017348SJose.Borrego@Sun.COM  * ============================================
12027961SNatalie.Li@Sun.COM  * Cache management functions
12037961SNatalie.Li@Sun.COM  *
12047961SNatalie.Li@Sun.COM  * All cache functions are private
12057348SJose.Borrego@Sun.COM  * ============================================
12067348SJose.Borrego@Sun.COM  */
12077348SJose.Borrego@Sun.COM 
12087348SJose.Borrego@Sun.COM /*
12097961SNatalie.Li@Sun.COM  * Create the share cache (hash table).
12107348SJose.Borrego@Sun.COM  */
12117348SJose.Borrego@Sun.COM static uint32_t
smb_shr_cache_create(void)12127961SNatalie.Li@Sun.COM smb_shr_cache_create(void)
12137348SJose.Borrego@Sun.COM {
12147961SNatalie.Li@Sun.COM 	uint32_t status = NERR_Success;
12157348SJose.Borrego@Sun.COM 
12167961SNatalie.Li@Sun.COM 	(void) mutex_lock(&smb_shr_cache.sc_mtx);
12177961SNatalie.Li@Sun.COM 	switch (smb_shr_cache.sc_state) {
12187961SNatalie.Li@Sun.COM 	case SMB_SHR_CACHE_STATE_NONE:
12197961SNatalie.Li@Sun.COM 		smb_shr_cache.sc_cache = ht_create_table(SMB_SHR_HTAB_SZ,
12207961SNatalie.Li@Sun.COM 		    MAXNAMELEN, 0);
12217961SNatalie.Li@Sun.COM 		if (smb_shr_cache.sc_cache == NULL) {
12227961SNatalie.Li@Sun.COM 			status = NERR_InternalError;
12237961SNatalie.Li@Sun.COM 			break;
12247348SJose.Borrego@Sun.COM 		}
12257348SJose.Borrego@Sun.COM 
12267961SNatalie.Li@Sun.COM 		(void) ht_register_callback(smb_shr_cache.sc_cache,
12277961SNatalie.Li@Sun.COM 		    smb_shr_cache_freent);
12287961SNatalie.Li@Sun.COM 		smb_shr_cache.sc_nops = 0;
12297961SNatalie.Li@Sun.COM 		smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_CREATED;
12307961SNatalie.Li@Sun.COM 		break;
12317961SNatalie.Li@Sun.COM 
12327961SNatalie.Li@Sun.COM 	default:
12337961SNatalie.Li@Sun.COM 		assert(0);
12347961SNatalie.Li@Sun.COM 		status = NERR_InternalError;
12357961SNatalie.Li@Sun.COM 		break;
12367961SNatalie.Li@Sun.COM 	}
12377961SNatalie.Li@Sun.COM 	(void) mutex_unlock(&smb_shr_cache.sc_mtx);
12387961SNatalie.Li@Sun.COM 
12397961SNatalie.Li@Sun.COM 	return (status);
12407961SNatalie.Li@Sun.COM }
12417961SNatalie.Li@Sun.COM 
12427961SNatalie.Li@Sun.COM /*
12437961SNatalie.Li@Sun.COM  * Destroy the share cache (hash table).
12447961SNatalie.Li@Sun.COM  * Wait for inflight/pending operations to finish or abort before
12457961SNatalie.Li@Sun.COM  * destroying the cache.
12467961SNatalie.Li@Sun.COM  */
12477961SNatalie.Li@Sun.COM static void
smb_shr_cache_destroy(void)12487961SNatalie.Li@Sun.COM smb_shr_cache_destroy(void)
12497961SNatalie.Li@Sun.COM {
12507961SNatalie.Li@Sun.COM 	(void) mutex_lock(&smb_shr_cache.sc_mtx);
12517961SNatalie.Li@Sun.COM 	if (smb_shr_cache.sc_state == SMB_SHR_CACHE_STATE_CREATED) {
12527961SNatalie.Li@Sun.COM 		smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_DESTROYING;
12537961SNatalie.Li@Sun.COM 		while (smb_shr_cache.sc_nops > 0)
12547961SNatalie.Li@Sun.COM 			(void) cond_wait(&smb_shr_cache.sc_cv,
12557961SNatalie.Li@Sun.COM 			    &smb_shr_cache.sc_mtx);
12567961SNatalie.Li@Sun.COM 
12577961SNatalie.Li@Sun.COM 		smb_shr_cache.sc_cache = NULL;
12587961SNatalie.Li@Sun.COM 		smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_NONE;
12597961SNatalie.Li@Sun.COM 	}
12607961SNatalie.Li@Sun.COM 	(void) mutex_unlock(&smb_shr_cache.sc_mtx);
12617961SNatalie.Li@Sun.COM }
12627961SNatalie.Li@Sun.COM 
12637961SNatalie.Li@Sun.COM /*
12647961SNatalie.Li@Sun.COM  * If the cache is in "created" state, lock the cache for read
12657961SNatalie.Li@Sun.COM  * or read/write based on the specified mode.
12667961SNatalie.Li@Sun.COM  *
12677961SNatalie.Li@Sun.COM  * Whenever a lock is granted, the number of inflight cache
12687961SNatalie.Li@Sun.COM  * operations is incremented.
12697961SNatalie.Li@Sun.COM  */
12707961SNatalie.Li@Sun.COM static uint32_t
smb_shr_cache_lock(int mode)12717961SNatalie.Li@Sun.COM smb_shr_cache_lock(int mode)
12727961SNatalie.Li@Sun.COM {
12737961SNatalie.Li@Sun.COM 	(void) mutex_lock(&smb_shr_cache.sc_mtx);
12748334SJose.Borrego@Sun.COM 	if (smb_shr_cache.sc_state != SMB_SHR_CACHE_STATE_CREATED) {
12757961SNatalie.Li@Sun.COM 		(void) mutex_unlock(&smb_shr_cache.sc_mtx);
12767961SNatalie.Li@Sun.COM 		return (NERR_InternalError);
12777961SNatalie.Li@Sun.COM 	}
12788334SJose.Borrego@Sun.COM 	smb_shr_cache.sc_nops++;
12797961SNatalie.Li@Sun.COM 	(void) mutex_unlock(&smb_shr_cache.sc_mtx);
12807961SNatalie.Li@Sun.COM 
12817961SNatalie.Li@Sun.COM 	/*
12827961SNatalie.Li@Sun.COM 	 * Lock has to be taken outside the mutex otherwise
12837961SNatalie.Li@Sun.COM 	 * there could be a deadlock
12847961SNatalie.Li@Sun.COM 	 */
12857961SNatalie.Li@Sun.COM 	if (mode == SMB_SHR_CACHE_RDLOCK)
12867961SNatalie.Li@Sun.COM 		(void) rw_rdlock(&smb_shr_cache.sc_cache_lck);
12877961SNatalie.Li@Sun.COM 	else
12887961SNatalie.Li@Sun.COM 		(void) rw_wrlock(&smb_shr_cache.sc_cache_lck);
12897961SNatalie.Li@Sun.COM 
12907961SNatalie.Li@Sun.COM 	return (NERR_Success);
12917961SNatalie.Li@Sun.COM }
12927961SNatalie.Li@Sun.COM 
12937961SNatalie.Li@Sun.COM /*
12947961SNatalie.Li@Sun.COM  * Decrement the number of inflight operations and then unlock.
12957961SNatalie.Li@Sun.COM  */
12967961SNatalie.Li@Sun.COM static void
smb_shr_cache_unlock(void)12977961SNatalie.Li@Sun.COM smb_shr_cache_unlock(void)
12987961SNatalie.Li@Sun.COM {
12997961SNatalie.Li@Sun.COM 	(void) mutex_lock(&smb_shr_cache.sc_mtx);
13007961SNatalie.Li@Sun.COM 	assert(smb_shr_cache.sc_nops > 0);
13017961SNatalie.Li@Sun.COM 	smb_shr_cache.sc_nops--;
13027961SNatalie.Li@Sun.COM 	(void) cond_broadcast(&smb_shr_cache.sc_cv);
13037961SNatalie.Li@Sun.COM 	(void) mutex_unlock(&smb_shr_cache.sc_mtx);
13047961SNatalie.Li@Sun.COM 
13057961SNatalie.Li@Sun.COM 	(void) rw_unlock(&smb_shr_cache.sc_cache_lck);
13067961SNatalie.Li@Sun.COM }
13077961SNatalie.Li@Sun.COM 
13087961SNatalie.Li@Sun.COM /*
13097961SNatalie.Li@Sun.COM  * Return the total number of shares
13107961SNatalie.Li@Sun.COM  */
13117961SNatalie.Li@Sun.COM static int
smb_shr_cache_count(void)13127961SNatalie.Li@Sun.COM smb_shr_cache_count(void)
13137961SNatalie.Li@Sun.COM {
13147961SNatalie.Li@Sun.COM 	return (ht_get_total_items(smb_shr_cache.sc_cache));
13157961SNatalie.Li@Sun.COM }
13167961SNatalie.Li@Sun.COM 
13177961SNatalie.Li@Sun.COM /*
13187961SNatalie.Li@Sun.COM  * looks up the given share name in the cache and if it
13197961SNatalie.Li@Sun.COM  * finds a match returns a pointer to the cached entry.
13207961SNatalie.Li@Sun.COM  * Note that since a pointer is returned this function
13217961SNatalie.Li@Sun.COM  * MUST be protected by smb_shr_cache_lock/unlock pair
13227961SNatalie.Li@Sun.COM  */
13237961SNatalie.Li@Sun.COM static smb_share_t *
smb_shr_cache_findent(char * sharename)13247961SNatalie.Li@Sun.COM smb_shr_cache_findent(char *sharename)
13257961SNatalie.Li@Sun.COM {
13267961SNatalie.Li@Sun.COM 	HT_ITEM *item;
13277961SNatalie.Li@Sun.COM 
132810966SJordan.Brown@Sun.COM 	(void) smb_strlwr(sharename);
13297961SNatalie.Li@Sun.COM 	item = ht_find_item(smb_shr_cache.sc_cache, sharename);
13307961SNatalie.Li@Sun.COM 	if (item && item->hi_data)
13317961SNatalie.Li@Sun.COM 		return ((smb_share_t *)item->hi_data);
13327961SNatalie.Li@Sun.COM 
13337961SNatalie.Li@Sun.COM 	return (NULL);
13347961SNatalie.Li@Sun.COM }
13357961SNatalie.Li@Sun.COM 
13367961SNatalie.Li@Sun.COM /*
13377961SNatalie.Li@Sun.COM  * Return a pointer to the first/next entry in
13387961SNatalie.Li@Sun.COM  * the cache based on the given iterator.
13397961SNatalie.Li@Sun.COM  *
13407961SNatalie.Li@Sun.COM  * Calls to this function MUST be protected by
13417961SNatalie.Li@Sun.COM  * smb_shr_cache_lock/unlock.
13427961SNatalie.Li@Sun.COM  */
13437961SNatalie.Li@Sun.COM static smb_share_t *
smb_shr_cache_iterate(smb_shriter_t * shi)13447961SNatalie.Li@Sun.COM smb_shr_cache_iterate(smb_shriter_t *shi)
13457961SNatalie.Li@Sun.COM {
13467961SNatalie.Li@Sun.COM 	HT_ITEM *item;
13477961SNatalie.Li@Sun.COM 
13487961SNatalie.Li@Sun.COM 	if (shi->si_first) {
13497961SNatalie.Li@Sun.COM 		item = ht_findfirst(smb_shr_cache.sc_cache, &shi->si_hashiter);
13507961SNatalie.Li@Sun.COM 		shi->si_first = B_FALSE;
13517961SNatalie.Li@Sun.COM 	} else {
13527961SNatalie.Li@Sun.COM 		item = ht_findnext(&shi->si_hashiter);
13537348SJose.Borrego@Sun.COM 	}
13547348SJose.Borrego@Sun.COM 
13557961SNatalie.Li@Sun.COM 	if (item && item->hi_data)
13567961SNatalie.Li@Sun.COM 		return ((smb_share_t *)item->hi_data);
13577961SNatalie.Li@Sun.COM 
13587961SNatalie.Li@Sun.COM 	return (NULL);
13597961SNatalie.Li@Sun.COM }
13607961SNatalie.Li@Sun.COM 
13617961SNatalie.Li@Sun.COM /*
13627961SNatalie.Li@Sun.COM  * Add the specified share to the cache.  Memory needs to be allocated
13637961SNatalie.Li@Sun.COM  * for the cache entry and the passed information is copied to the
13647961SNatalie.Li@Sun.COM  * allocated space.
13657961SNatalie.Li@Sun.COM  */
13667961SNatalie.Li@Sun.COM static uint32_t
smb_shr_cache_addent(smb_share_t * si)13677961SNatalie.Li@Sun.COM smb_shr_cache_addent(smb_share_t *si)
13687961SNatalie.Li@Sun.COM {
13697961SNatalie.Li@Sun.COM 	smb_share_t *cache_ent;
13707961SNatalie.Li@Sun.COM 	uint32_t status = NERR_Success;
13717961SNatalie.Li@Sun.COM 
13727961SNatalie.Li@Sun.COM 	if ((cache_ent = malloc(sizeof (smb_share_t))) == NULL)
13737961SNatalie.Li@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
13747961SNatalie.Li@Sun.COM 
137512508Samw@Sun.COM 	(void) smb_strlwr(si->shr_name);
13767961SNatalie.Li@Sun.COM 
137712890SJoyce.McIntosh@Sun.COM 	if (((si->shr_type & STYPE_PRINTQ) == 0) &&
137812890SJoyce.McIntosh@Sun.COM 	    (si->shr_type & STYPE_IPC) == 0)
137912508Samw@Sun.COM 		si->shr_type = STYPE_DISKTREE;
138012890SJoyce.McIntosh@Sun.COM 
138112508Samw@Sun.COM 	si->shr_type |= smb_shr_is_special(cache_ent->shr_name);
13827961SNatalie.Li@Sun.COM 
13837961SNatalie.Li@Sun.COM 	if (smb_shr_is_admin(cache_ent->shr_name))
138412508Samw@Sun.COM 		si->shr_flags |= SMB_SHRF_ADMIN;
138512508Samw@Sun.COM 
138612508Samw@Sun.COM 	bcopy(si, cache_ent, sizeof (smb_share_t));
13877961SNatalie.Li@Sun.COM 
13887961SNatalie.Li@Sun.COM 	if (si->shr_flags & SMB_SHRF_AUTOHOME)
13897961SNatalie.Li@Sun.COM 		cache_ent->shr_refcnt = 1;
13907961SNatalie.Li@Sun.COM 
13917961SNatalie.Li@Sun.COM 	if (ht_add_item(smb_shr_cache.sc_cache, cache_ent->shr_name, cache_ent)
13927961SNatalie.Li@Sun.COM 	    == NULL) {
13937961SNatalie.Li@Sun.COM 		syslog(LOG_DEBUG, "share: %s: cache update failed",
13947961SNatalie.Li@Sun.COM 		    cache_ent->shr_name);
13957961SNatalie.Li@Sun.COM 		free(cache_ent);
13967961SNatalie.Li@Sun.COM 		status = NERR_InternalError;
13977348SJose.Borrego@Sun.COM 	}
13987348SJose.Borrego@Sun.COM 
13997961SNatalie.Li@Sun.COM 	return (status);
14007961SNatalie.Li@Sun.COM }
14017961SNatalie.Li@Sun.COM 
14027961SNatalie.Li@Sun.COM /*
14037961SNatalie.Li@Sun.COM  * Delete the specified share from the cache.
14047961SNatalie.Li@Sun.COM  */
14057961SNatalie.Li@Sun.COM static void
smb_shr_cache_delent(char * sharename)14067961SNatalie.Li@Sun.COM smb_shr_cache_delent(char *sharename)
14077961SNatalie.Li@Sun.COM {
140810966SJordan.Brown@Sun.COM 	(void) smb_strlwr(sharename);
14097961SNatalie.Li@Sun.COM 	(void) ht_remove_item(smb_shr_cache.sc_cache, sharename);
14107961SNatalie.Li@Sun.COM }
14117961SNatalie.Li@Sun.COM 
14127961SNatalie.Li@Sun.COM /*
14137961SNatalie.Li@Sun.COM  * Call back to free the given cache entry.
14147961SNatalie.Li@Sun.COM  */
14157961SNatalie.Li@Sun.COM static void
smb_shr_cache_freent(HT_ITEM * item)14167961SNatalie.Li@Sun.COM smb_shr_cache_freent(HT_ITEM *item)
14177961SNatalie.Li@Sun.COM {
14187961SNatalie.Li@Sun.COM 	if (item && item->hi_data)
14197961SNatalie.Li@Sun.COM 		free(item->hi_data);
14207961SNatalie.Li@Sun.COM }
14217961SNatalie.Li@Sun.COM 
14227961SNatalie.Li@Sun.COM /*
14237961SNatalie.Li@Sun.COM  * ============================================
14247961SNatalie.Li@Sun.COM  * Interfaces to sharemgr
14257961SNatalie.Li@Sun.COM  *
14267961SNatalie.Li@Sun.COM  * All functions in this section are private
14277961SNatalie.Li@Sun.COM  * ============================================
14287961SNatalie.Li@Sun.COM  */
14297961SNatalie.Li@Sun.COM 
14307961SNatalie.Li@Sun.COM /*
14317961SNatalie.Li@Sun.COM  * Load shares from sharemgr
14327961SNatalie.Li@Sun.COM  */
14337961SNatalie.Li@Sun.COM /*ARGSUSED*/
1434*13082SJoyce.McIntosh@Sun.COM void *
smb_shr_load(void * args)1435*13082SJoyce.McIntosh@Sun.COM smb_shr_load(void *args)
14367961SNatalie.Li@Sun.COM {
14377961SNatalie.Li@Sun.COM 	sa_handle_t handle;
14387961SNatalie.Li@Sun.COM 	sa_group_t group, subgroup;
14397961SNatalie.Li@Sun.COM 	char *gstate;
14407961SNatalie.Li@Sun.COM 	boolean_t gdisabled;
1441*13082SJoyce.McIntosh@Sun.COM 
1442*13082SJoyce.McIntosh@Sun.COM 	(void) mutex_lock(&smb_shr_exec_mtx);
1443*13082SJoyce.McIntosh@Sun.COM 	(void) smb_config_get_execinfo(smb_shr_exec_map, smb_shr_exec_unmap,
1444*13082SJoyce.McIntosh@Sun.COM 	    MAXPATHLEN);
1445*13082SJoyce.McIntosh@Sun.COM 	(void) mutex_unlock(&smb_shr_exec_mtx);
144612890SJoyce.McIntosh@Sun.COM 
144712890SJoyce.McIntosh@Sun.COM 	if ((handle = smb_shr_sa_enter()) == NULL) {
1448*13082SJoyce.McIntosh@Sun.COM 		syslog(LOG_ERR, "smb_shr_load: load failed");
14497961SNatalie.Li@Sun.COM 		return (NULL);
145012890SJoyce.McIntosh@Sun.COM 	}
14517348SJose.Borrego@Sun.COM 
14527961SNatalie.Li@Sun.COM 	for (group = sa_get_group(handle, NULL);
14537961SNatalie.Li@Sun.COM 	    group != NULL; group = sa_get_next_group(group)) {
14547961SNatalie.Li@Sun.COM 		gstate = sa_get_group_attr(group, "state");
14557961SNatalie.Li@Sun.COM 		if (gstate == NULL)
14567961SNatalie.Li@Sun.COM 			continue;
14577961SNatalie.Li@Sun.COM 
14587961SNatalie.Li@Sun.COM 		gdisabled = (strcasecmp(gstate, "disabled") == 0);
14597961SNatalie.Li@Sun.COM 		sa_free_attr_string(gstate);
14607961SNatalie.Li@Sun.COM 		if (gdisabled)
14617961SNatalie.Li@Sun.COM 			continue;
14627961SNatalie.Li@Sun.COM 
14637961SNatalie.Li@Sun.COM 		smb_shr_sa_loadgrp(group);
14647961SNatalie.Li@Sun.COM 
14657961SNatalie.Li@Sun.COM 		for (subgroup = sa_get_sub_group(group);
14667961SNatalie.Li@Sun.COM 		    subgroup != NULL;
14677961SNatalie.Li@Sun.COM 		    subgroup = sa_get_next_group(subgroup)) {
14687961SNatalie.Li@Sun.COM 			smb_shr_sa_loadgrp(subgroup);
14697961SNatalie.Li@Sun.COM 		}
14707961SNatalie.Li@Sun.COM 
14717348SJose.Borrego@Sun.COM 	}
14728474SJose.Borrego@Sun.COM 	smb_shr_sa_exit();
14737961SNatalie.Li@Sun.COM 	return (NULL);
14747348SJose.Borrego@Sun.COM }
14757348SJose.Borrego@Sun.COM 
14767961SNatalie.Li@Sun.COM /*
14777961SNatalie.Li@Sun.COM  * Load the shares contained in the specified group.
14787961SNatalie.Li@Sun.COM  *
14797961SNatalie.Li@Sun.COM  * Don't process groups on which the smb protocol is disabled.
14807961SNatalie.Li@Sun.COM  * The top level ZFS group won't have the smb protocol enabled
14817961SNatalie.Li@Sun.COM  * but sub-groups will.
14827961SNatalie.Li@Sun.COM  *
14837961SNatalie.Li@Sun.COM  * We will tolerate a limited number of errors and then give
14847961SNatalie.Li@Sun.COM  * up on the current group.  A typical error might be that the
14857961SNatalie.Li@Sun.COM  * shared directory no longer exists.
14867961SNatalie.Li@Sun.COM  */
14877961SNatalie.Li@Sun.COM static void
smb_shr_sa_loadgrp(sa_group_t group)14887961SNatalie.Li@Sun.COM smb_shr_sa_loadgrp(sa_group_t group)
14897961SNatalie.Li@Sun.COM {
14907961SNatalie.Li@Sun.COM 	sa_share_t share;
14917961SNatalie.Li@Sun.COM 	sa_resource_t resource;
14927961SNatalie.Li@Sun.COM 	int error_count = 0;
14937961SNatalie.Li@Sun.COM 
14947961SNatalie.Li@Sun.COM 	if (sa_get_optionset(group, SMB_PROTOCOL_NAME) == NULL)
14957961SNatalie.Li@Sun.COM 		return;
14967961SNatalie.Li@Sun.COM 
14977961SNatalie.Li@Sun.COM 	for (share = sa_get_share(group, NULL);
14987961SNatalie.Li@Sun.COM 	    share != NULL;
14997961SNatalie.Li@Sun.COM 	    share = sa_get_next_share(share)) {
15007961SNatalie.Li@Sun.COM 		for (resource = sa_get_share_resource(share, NULL);
15017961SNatalie.Li@Sun.COM 		    resource != NULL;
15027961SNatalie.Li@Sun.COM 		    resource = sa_get_next_resource(resource)) {
15037961SNatalie.Li@Sun.COM 			if (smb_shr_sa_load(share, resource))
15047961SNatalie.Li@Sun.COM 				++error_count;
15057961SNatalie.Li@Sun.COM 
15067961SNatalie.Li@Sun.COM 			if (error_count > SMB_SHR_ERROR_THRESHOLD)
15077961SNatalie.Li@Sun.COM 				break;
15087961SNatalie.Li@Sun.COM 		}
15097961SNatalie.Li@Sun.COM 
15107961SNatalie.Li@Sun.COM 		if (error_count > SMB_SHR_ERROR_THRESHOLD)
15117961SNatalie.Li@Sun.COM 			break;
15127961SNatalie.Li@Sun.COM 	}
15137961SNatalie.Li@Sun.COM }
15147961SNatalie.Li@Sun.COM 
15157961SNatalie.Li@Sun.COM /*
15167961SNatalie.Li@Sun.COM  * Load a share definition from sharemgr and add it to the cache.
15178334SJose.Borrego@Sun.COM  * If the share is already in the cache then it doesn't do anything.
15188334SJose.Borrego@Sun.COM  *
15198334SJose.Borrego@Sun.COM  * This function does not report duplicate shares as error since
15208334SJose.Borrego@Sun.COM  * a share might have been added by smb_shr_get() while load is
15218334SJose.Borrego@Sun.COM  * in progress.
15227961SNatalie.Li@Sun.COM  */
15237348SJose.Borrego@Sun.COM static uint32_t
smb_shr_sa_load(sa_share_t share,sa_resource_t resource)15247961SNatalie.Li@Sun.COM smb_shr_sa_load(sa_share_t share, sa_resource_t resource)
15257961SNatalie.Li@Sun.COM {
15267961SNatalie.Li@Sun.COM 	smb_share_t si;
15278334SJose.Borrego@Sun.COM 	char *sharename;
15287961SNatalie.Li@Sun.COM 	uint32_t status;
15298334SJose.Borrego@Sun.COM 	boolean_t loaded;
15308334SJose.Borrego@Sun.COM 
15318334SJose.Borrego@Sun.COM 	if ((sharename = sa_get_resource_attr(resource, "name")) == NULL)
15328334SJose.Borrego@Sun.COM 		return (NERR_InternalError);
15338334SJose.Borrego@Sun.COM 
15348334SJose.Borrego@Sun.COM 	loaded = smb_shr_exists(sharename);
15358334SJose.Borrego@Sun.COM 	sa_free_attr_string(sharename);
15368334SJose.Borrego@Sun.COM 
15378334SJose.Borrego@Sun.COM 	if (loaded)
15388334SJose.Borrego@Sun.COM 		return (NERR_Success);
15397961SNatalie.Li@Sun.COM 
15407961SNatalie.Li@Sun.COM 	if ((status = smb_shr_sa_get(share, resource, &si)) != NERR_Success) {
15417961SNatalie.Li@Sun.COM 		syslog(LOG_DEBUG, "share: failed to load %s (%d)",
15427961SNatalie.Li@Sun.COM 		    si.shr_name, status);
15437961SNatalie.Li@Sun.COM 		return (status);
15447961SNatalie.Li@Sun.COM 	}
15457961SNatalie.Li@Sun.COM 
15468334SJose.Borrego@Sun.COM 	status = smb_shr_add(&si);
15478334SJose.Borrego@Sun.COM 	if ((status != NERR_Success) && (status != NERR_DuplicateShare)) {
15487961SNatalie.Li@Sun.COM 		syslog(LOG_DEBUG, "share: failed to cache %s (%d)",
15497961SNatalie.Li@Sun.COM 		    si.shr_name, status);
15507961SNatalie.Li@Sun.COM 		return (status);
15517961SNatalie.Li@Sun.COM 	}
15527961SNatalie.Li@Sun.COM 
15537961SNatalie.Li@Sun.COM 	return (NERR_Success);
15547961SNatalie.Li@Sun.COM }
15557961SNatalie.Li@Sun.COM 
155611963SAfshin.Ardakani@Sun.COM static char *
smb_shr_sa_getprop(sa_optionset_t opts,char * propname)155711963SAfshin.Ardakani@Sun.COM smb_shr_sa_getprop(sa_optionset_t opts, char *propname)
155811963SAfshin.Ardakani@Sun.COM {
155911963SAfshin.Ardakani@Sun.COM 	sa_property_t prop;
156011963SAfshin.Ardakani@Sun.COM 	char *val = NULL;
156111963SAfshin.Ardakani@Sun.COM 
156211963SAfshin.Ardakani@Sun.COM 	prop = sa_get_property(opts, propname);
156311963SAfshin.Ardakani@Sun.COM 	if (prop != NULL)
156411963SAfshin.Ardakani@Sun.COM 		val = sa_get_property_attr(prop, "value");
156511963SAfshin.Ardakani@Sun.COM 
156611963SAfshin.Ardakani@Sun.COM 	return (val);
156711963SAfshin.Ardakani@Sun.COM }
156811963SAfshin.Ardakani@Sun.COM 
15697961SNatalie.Li@Sun.COM /*
15707961SNatalie.Li@Sun.COM  * Read the specified share information from sharemgr and return
15717961SNatalie.Li@Sun.COM  * it in the given smb_share_t structure.
15727961SNatalie.Li@Sun.COM  *
15737961SNatalie.Li@Sun.COM  * Shares read from sharemgr are marked as permanent/persistent.
15747961SNatalie.Li@Sun.COM  */
15757961SNatalie.Li@Sun.COM static uint32_t
smb_shr_sa_get(sa_share_t share,sa_resource_t resource,smb_share_t * si)15767961SNatalie.Li@Sun.COM smb_shr_sa_get(sa_share_t share, sa_resource_t resource, smb_share_t *si)
15777348SJose.Borrego@Sun.COM {
15787348SJose.Borrego@Sun.COM 	sa_optionset_t opts;
15797348SJose.Borrego@Sun.COM 	char *val = NULL;
15807348SJose.Borrego@Sun.COM 	char *path;
15817348SJose.Borrego@Sun.COM 	char *rname;
15827348SJose.Borrego@Sun.COM 
15837348SJose.Borrego@Sun.COM 	if ((path = sa_get_share_attr(share, "path")) == NULL)
15847348SJose.Borrego@Sun.COM 		return (NERR_InternalError);
15857348SJose.Borrego@Sun.COM 
15867348SJose.Borrego@Sun.COM 	if ((rname = sa_get_resource_attr(resource, "name")) == NULL) {
15877348SJose.Borrego@Sun.COM 		sa_free_attr_string(path);
15887348SJose.Borrego@Sun.COM 		return (NERR_InternalError);
15897348SJose.Borrego@Sun.COM 	}
15907348SJose.Borrego@Sun.COM 
15917348SJose.Borrego@Sun.COM 	bzero(si, sizeof (smb_share_t));
15927348SJose.Borrego@Sun.COM 	si->shr_flags = SMB_SHRF_PERM;
15937348SJose.Borrego@Sun.COM 
15947348SJose.Borrego@Sun.COM 	(void) strlcpy(si->shr_path, path, sizeof (si->shr_path));
15957348SJose.Borrego@Sun.COM 	(void) strlcpy(si->shr_name, rname, sizeof (si->shr_name));
15967348SJose.Borrego@Sun.COM 	sa_free_attr_string(path);
15977348SJose.Borrego@Sun.COM 	sa_free_attr_string(rname);
15987348SJose.Borrego@Sun.COM 
15997348SJose.Borrego@Sun.COM 	val = sa_get_resource_description(resource);
16007348SJose.Borrego@Sun.COM 	if (val == NULL)
16017348SJose.Borrego@Sun.COM 		val = sa_get_share_description(share);
16027348SJose.Borrego@Sun.COM 
16037348SJose.Borrego@Sun.COM 	if (val != NULL) {
16047348SJose.Borrego@Sun.COM 		(void) strlcpy(si->shr_cmnt, val, sizeof (si->shr_cmnt));
16057348SJose.Borrego@Sun.COM 		sa_free_share_description(val);
16067348SJose.Borrego@Sun.COM 	}
16077348SJose.Borrego@Sun.COM 
16087348SJose.Borrego@Sun.COM 	opts = sa_get_derived_optionset(resource, SMB_PROTOCOL_NAME, 1);
16097348SJose.Borrego@Sun.COM 	if (opts == NULL)
16107348SJose.Borrego@Sun.COM 		return (NERR_Success);
16117348SJose.Borrego@Sun.COM 
161211963SAfshin.Ardakani@Sun.COM 	val = smb_shr_sa_getprop(opts, SHOPT_AD_CONTAINER);
161311963SAfshin.Ardakani@Sun.COM 	if (val != NULL) {
161411963SAfshin.Ardakani@Sun.COM 		(void) strlcpy(si->shr_container, val,
161511963SAfshin.Ardakani@Sun.COM 		    sizeof (si->shr_container));
161611963SAfshin.Ardakani@Sun.COM 		free(val);
16177348SJose.Borrego@Sun.COM 	}
16187348SJose.Borrego@Sun.COM 
161911963SAfshin.Ardakani@Sun.COM 	val = smb_shr_sa_getprop(opts, SHOPT_CATIA);
162011963SAfshin.Ardakani@Sun.COM 	if (val != NULL) {
162111963SAfshin.Ardakani@Sun.COM 		smb_shr_sa_setflag(val, si, SMB_SHRF_CATIA);
162211963SAfshin.Ardakani@Sun.COM 		free(val);
16239231SAfshin.Ardakani@Sun.COM 	}
16249231SAfshin.Ardakani@Sun.COM 
162511963SAfshin.Ardakani@Sun.COM 	val = smb_shr_sa_getprop(opts, SHOPT_ABE);
162611963SAfshin.Ardakani@Sun.COM 	if (val != NULL) {
162711963SAfshin.Ardakani@Sun.COM 		smb_shr_sa_setflag(val, si, SMB_SHRF_ABE);
162811963SAfshin.Ardakani@Sun.COM 		free(val);
162910504SKeyur.Desai@Sun.COM 	}
163010504SKeyur.Desai@Sun.COM 
163111963SAfshin.Ardakani@Sun.COM 	val = smb_shr_sa_getprop(opts, SHOPT_GUEST);
163211963SAfshin.Ardakani@Sun.COM 	if (val != NULL) {
163311963SAfshin.Ardakani@Sun.COM 		smb_shr_sa_setflag(val, si, SMB_SHRF_GUEST_OK);
163411963SAfshin.Ardakani@Sun.COM 		free(val);
16358334SJose.Borrego@Sun.COM 	}
16368334SJose.Borrego@Sun.COM 
163711963SAfshin.Ardakani@Sun.COM 	val = smb_shr_sa_getprop(opts, SHOPT_DFSROOT);
163811963SAfshin.Ardakani@Sun.COM 	if (val != NULL) {
163911963SAfshin.Ardakani@Sun.COM 		smb_shr_sa_setflag(val, si, SMB_SHRF_DFSROOT);
164011963SAfshin.Ardakani@Sun.COM 		free(val);
16419832Samw@Sun.COM 	}
16429832Samw@Sun.COM 
164311963SAfshin.Ardakani@Sun.COM 	val = smb_shr_sa_getprop(opts, SHOPT_CSC);
164411963SAfshin.Ardakani@Sun.COM 	if (val != NULL) {
164511963SAfshin.Ardakani@Sun.COM 		smb_shr_sa_csc_option(val, si);
164611963SAfshin.Ardakani@Sun.COM 		free(val);
16477348SJose.Borrego@Sun.COM 	}
16487348SJose.Borrego@Sun.COM 
164911963SAfshin.Ardakani@Sun.COM 	val = smb_shr_sa_getprop(opts, SHOPT_NONE);
165011963SAfshin.Ardakani@Sun.COM 	if (val != NULL) {
165111963SAfshin.Ardakani@Sun.COM 		(void) strlcpy(si->shr_access_none, val,
165211963SAfshin.Ardakani@Sun.COM 		    sizeof (si->shr_access_none));
165311963SAfshin.Ardakani@Sun.COM 		free(val);
165411963SAfshin.Ardakani@Sun.COM 		si->shr_flags |= SMB_SHRF_ACC_NONE;
16557348SJose.Borrego@Sun.COM 	}
16567348SJose.Borrego@Sun.COM 
165711963SAfshin.Ardakani@Sun.COM 	val = smb_shr_sa_getprop(opts, SHOPT_RO);
165811963SAfshin.Ardakani@Sun.COM 	if (val != NULL) {
165911963SAfshin.Ardakani@Sun.COM 		(void) strlcpy(si->shr_access_ro, val,
166011963SAfshin.Ardakani@Sun.COM 		    sizeof (si->shr_access_ro));
166111963SAfshin.Ardakani@Sun.COM 		free(val);
166211963SAfshin.Ardakani@Sun.COM 		si->shr_flags |= SMB_SHRF_ACC_RO;
166311963SAfshin.Ardakani@Sun.COM 	}
166411963SAfshin.Ardakani@Sun.COM 
166511963SAfshin.Ardakani@Sun.COM 	val = smb_shr_sa_getprop(opts, SHOPT_RW);
166611963SAfshin.Ardakani@Sun.COM 	if (val != NULL) {
166711963SAfshin.Ardakani@Sun.COM 		(void) strlcpy(si->shr_access_rw, val,
166811963SAfshin.Ardakani@Sun.COM 		    sizeof (si->shr_access_rw));
166911963SAfshin.Ardakani@Sun.COM 		free(val);
167011963SAfshin.Ardakani@Sun.COM 		si->shr_flags |= SMB_SHRF_ACC_RW;
16717961SNatalie.Li@Sun.COM 	}
16727961SNatalie.Li@Sun.COM 
16737961SNatalie.Li@Sun.COM 	sa_free_derived_optionset(opts);
16747961SNatalie.Li@Sun.COM 	return (NERR_Success);
16757348SJose.Borrego@Sun.COM }
16767348SJose.Borrego@Sun.COM 
16777348SJose.Borrego@Sun.COM /*
16788334SJose.Borrego@Sun.COM  * Map a client-side caching (CSC) option to the appropriate share
16798334SJose.Borrego@Sun.COM  * flag.  Only one option is allowed; an error will be logged if
16808334SJose.Borrego@Sun.COM  * multiple options have been specified.  We don't need to do anything
16818334SJose.Borrego@Sun.COM  * about multiple values here because the SRVSVC will not recognize
16828334SJose.Borrego@Sun.COM  * a value containing multiple flags and will return the default value.
16838334SJose.Borrego@Sun.COM  *
16848334SJose.Borrego@Sun.COM  * If the option value is not recognized, it will be ignored: invalid
16858334SJose.Borrego@Sun.COM  * values will typically be caught and rejected by sharemgr.
16868334SJose.Borrego@Sun.COM  */
16878474SJose.Borrego@Sun.COM void
smb_shr_sa_csc_option(const char * value,smb_share_t * si)16888334SJose.Borrego@Sun.COM smb_shr_sa_csc_option(const char *value, smb_share_t *si)
16898334SJose.Borrego@Sun.COM {
16908334SJose.Borrego@Sun.COM 	int i;
16918334SJose.Borrego@Sun.COM 
16928334SJose.Borrego@Sun.COM 	for (i = 0; i < (sizeof (cscopt) / sizeof (cscopt[0])); ++i) {
16938334SJose.Borrego@Sun.COM 		if (strcasecmp(value, cscopt[i].value) == 0) {
16948334SJose.Borrego@Sun.COM 			si->shr_flags |= cscopt[i].flag;
16958334SJose.Borrego@Sun.COM 			break;
16968334SJose.Borrego@Sun.COM 		}
16978334SJose.Borrego@Sun.COM 	}
16988334SJose.Borrego@Sun.COM 
16998334SJose.Borrego@Sun.COM 	switch (si->shr_flags & SMB_SHRF_CSC_MASK) {
17008334SJose.Borrego@Sun.COM 	case 0:
17018334SJose.Borrego@Sun.COM 	case SMB_SHRF_CSC_DISABLED:
17028334SJose.Borrego@Sun.COM 	case SMB_SHRF_CSC_MANUAL:
17038334SJose.Borrego@Sun.COM 	case SMB_SHRF_CSC_AUTO:
17048334SJose.Borrego@Sun.COM 	case SMB_SHRF_CSC_VDO:
17058334SJose.Borrego@Sun.COM 		break;
17068334SJose.Borrego@Sun.COM 
17078334SJose.Borrego@Sun.COM 	default:
17088474SJose.Borrego@Sun.COM 		syslog(LOG_INFO, "csc option conflict: 0x%08x",
17098474SJose.Borrego@Sun.COM 		    si->shr_flags & SMB_SHRF_CSC_MASK);
17108334SJose.Borrego@Sun.COM 		break;
17118334SJose.Borrego@Sun.COM 	}
17128334SJose.Borrego@Sun.COM }
17138334SJose.Borrego@Sun.COM 
17148334SJose.Borrego@Sun.COM /*
17159832Samw@Sun.COM  * Return the option name for the first CSC flag (there should be only
17169832Samw@Sun.COM  * one) encountered in the share flags.
17179832Samw@Sun.COM  */
17189832Samw@Sun.COM char *
smb_shr_sa_csc_name(const smb_share_t * si)17199832Samw@Sun.COM smb_shr_sa_csc_name(const smb_share_t *si)
17209832Samw@Sun.COM {
17219832Samw@Sun.COM 	int i;
17229832Samw@Sun.COM 
17239832Samw@Sun.COM 	for (i = 0; i < (sizeof (cscopt) / sizeof (cscopt[0])); ++i) {
17249832Samw@Sun.COM 		if (si->shr_flags & cscopt[i].flag)
17259832Samw@Sun.COM 			return (cscopt[i].value);
17269832Samw@Sun.COM 	}
17279832Samw@Sun.COM 
17289832Samw@Sun.COM 	return (NULL);
17299832Samw@Sun.COM }
17309832Samw@Sun.COM 
17319832Samw@Sun.COM /*
173211963SAfshin.Ardakani@Sun.COM  * Takes the value of a boolean share property and set/clear the
173311963SAfshin.Ardakani@Sun.COM  * specified flag based on the property's value.
173410504SKeyur.Desai@Sun.COM  */
173510504SKeyur.Desai@Sun.COM void
smb_shr_sa_setflag(const char * value,smb_share_t * si,uint32_t flag)173611963SAfshin.Ardakani@Sun.COM smb_shr_sa_setflag(const char *value, smb_share_t *si, uint32_t flag)
173710504SKeyur.Desai@Sun.COM {
173811963SAfshin.Ardakani@Sun.COM 	if ((strcasecmp(value, "true") == 0) || (strcmp(value, "1") == 0))
173911963SAfshin.Ardakani@Sun.COM 		si->shr_flags |= flag;
174011963SAfshin.Ardakani@Sun.COM 	else
174111963SAfshin.Ardakani@Sun.COM 		si->shr_flags &= ~flag;
17429832Samw@Sun.COM }
17439832Samw@Sun.COM 
17449832Samw@Sun.COM /*
17458334SJose.Borrego@Sun.COM  * looks up sharemgr for the given share (resource) and loads
17468334SJose.Borrego@Sun.COM  * the definition into cache if lookup is successful
17478334SJose.Borrego@Sun.COM  */
17488334SJose.Borrego@Sun.COM static uint32_t
smb_shr_sa_loadbyname(char * sharename)17498334SJose.Borrego@Sun.COM smb_shr_sa_loadbyname(char *sharename)
17508334SJose.Borrego@Sun.COM {
17518334SJose.Borrego@Sun.COM 	sa_handle_t handle;
17528334SJose.Borrego@Sun.COM 	sa_share_t share;
17538334SJose.Borrego@Sun.COM 	sa_resource_t resource;
17548334SJose.Borrego@Sun.COM 	uint32_t status;
17558334SJose.Borrego@Sun.COM 
17568474SJose.Borrego@Sun.COM 	if ((handle = smb_shr_sa_enter()) == NULL)
17578334SJose.Borrego@Sun.COM 		return (NERR_InternalError);
17588334SJose.Borrego@Sun.COM 
17598334SJose.Borrego@Sun.COM 	resource = sa_find_resource(handle, sharename);
17608334SJose.Borrego@Sun.COM 	if (resource == NULL) {
17618474SJose.Borrego@Sun.COM 		smb_shr_sa_exit();
17628334SJose.Borrego@Sun.COM 		return (NERR_NetNameNotFound);
17638334SJose.Borrego@Sun.COM 	}
17648334SJose.Borrego@Sun.COM 
17658334SJose.Borrego@Sun.COM 	share = sa_get_resource_parent(resource);
17668334SJose.Borrego@Sun.COM 	if (share == NULL) {
17678474SJose.Borrego@Sun.COM 		smb_shr_sa_exit();
17688334SJose.Borrego@Sun.COM 		return (NERR_InternalError);
17698334SJose.Borrego@Sun.COM 	}
17708334SJose.Borrego@Sun.COM 
17718334SJose.Borrego@Sun.COM 	status = smb_shr_sa_load(share, resource);
17728334SJose.Borrego@Sun.COM 
17738474SJose.Borrego@Sun.COM 	smb_shr_sa_exit();
17748334SJose.Borrego@Sun.COM 	return (status);
17758334SJose.Borrego@Sun.COM }
17768334SJose.Borrego@Sun.COM 
17778334SJose.Borrego@Sun.COM /*
17787348SJose.Borrego@Sun.COM  * ============================================
17797348SJose.Borrego@Sun.COM  * Share publishing functions
17807961SNatalie.Li@Sun.COM  *
17817961SNatalie.Li@Sun.COM  * All the functions are private
17827348SJose.Borrego@Sun.COM  * ============================================
17837348SJose.Borrego@Sun.COM  */
17847348SJose.Borrego@Sun.COM 
17857961SNatalie.Li@Sun.COM static void
smb_shr_publish(const char * sharename,const char * container)17867961SNatalie.Li@Sun.COM smb_shr_publish(const char *sharename, const char *container)
17877961SNatalie.Li@Sun.COM {
17887961SNatalie.Li@Sun.COM 	smb_shr_publisher_queue(sharename, container, SMB_SHR_PUBLISH);
17897961SNatalie.Li@Sun.COM }
17907961SNatalie.Li@Sun.COM 
17917961SNatalie.Li@Sun.COM static void
smb_shr_unpublish(const char * sharename,const char * container)17927961SNatalie.Li@Sun.COM smb_shr_unpublish(const char *sharename, const char *container)
17937961SNatalie.Li@Sun.COM {
17947961SNatalie.Li@Sun.COM 	smb_shr_publisher_queue(sharename, container, SMB_SHR_UNPUBLISH);
17957961SNatalie.Li@Sun.COM }
17967961SNatalie.Li@Sun.COM 
17977348SJose.Borrego@Sun.COM /*
17987961SNatalie.Li@Sun.COM  * In domain mode, put a share on the publisher queue.
17997961SNatalie.Li@Sun.COM  * This is a no-op if the smb service is in Workgroup mode.
18007348SJose.Borrego@Sun.COM  */
18017348SJose.Borrego@Sun.COM static void
smb_shr_publisher_queue(const char * sharename,const char * container,char op)18027961SNatalie.Li@Sun.COM smb_shr_publisher_queue(const char *sharename, const char *container, char op)
18037348SJose.Borrego@Sun.COM {
18047348SJose.Borrego@Sun.COM 	smb_shr_pitem_t *item = NULL;
18057348SJose.Borrego@Sun.COM 
18067348SJose.Borrego@Sun.COM 	if (container == NULL || *container == '\0')
18077348SJose.Borrego@Sun.COM 		return;
18087348SJose.Borrego@Sun.COM 
18097961SNatalie.Li@Sun.COM 	if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN)
18107961SNatalie.Li@Sun.COM 		return;
18117961SNatalie.Li@Sun.COM 
18127348SJose.Borrego@Sun.COM 	(void) mutex_lock(&ad_queue.spq_mtx);
18137348SJose.Borrego@Sun.COM 	switch (ad_queue.spq_state) {
18147348SJose.Borrego@Sun.COM 	case SMB_SHR_PQS_READY:
18157348SJose.Borrego@Sun.COM 	case SMB_SHR_PQS_PUBLISHING:
18167348SJose.Borrego@Sun.COM 		break;
18177348SJose.Borrego@Sun.COM 	default:
18187348SJose.Borrego@Sun.COM 		(void) mutex_unlock(&ad_queue.spq_mtx);
18197348SJose.Borrego@Sun.COM 		return;
18207348SJose.Borrego@Sun.COM 	}
18217348SJose.Borrego@Sun.COM 	(void) mutex_unlock(&ad_queue.spq_mtx);
18227348SJose.Borrego@Sun.COM 
18237961SNatalie.Li@Sun.COM 	if ((item = malloc(sizeof (smb_shr_pitem_t))) == NULL)
18247348SJose.Borrego@Sun.COM 		return;
18257348SJose.Borrego@Sun.COM 
18267348SJose.Borrego@Sun.COM 	item->spi_op = op;
18277348SJose.Borrego@Sun.COM 	(void) strlcpy(item->spi_name, sharename, sizeof (item->spi_name));
18287348SJose.Borrego@Sun.COM 	(void) strlcpy(item->spi_container, container,
18297348SJose.Borrego@Sun.COM 	    sizeof (item->spi_container));
18307348SJose.Borrego@Sun.COM 
18317348SJose.Borrego@Sun.COM 	(void) mutex_lock(&ad_queue.spq_mtx);
18327348SJose.Borrego@Sun.COM 	list_insert_tail(&ad_queue.spq_list, item);
18337348SJose.Borrego@Sun.COM 	(void) cond_signal(&ad_queue.spq_cv);
18347348SJose.Borrego@Sun.COM 	(void) mutex_unlock(&ad_queue.spq_mtx);
18357348SJose.Borrego@Sun.COM }
18367348SJose.Borrego@Sun.COM 
18377961SNatalie.Li@Sun.COM /*
18387961SNatalie.Li@Sun.COM  * Publishing won't be activated if the smb service is running in
18397961SNatalie.Li@Sun.COM  * Workgroup mode.
18407961SNatalie.Li@Sun.COM  */
18417348SJose.Borrego@Sun.COM static int
smb_shr_publisher_start(void)18427348SJose.Borrego@Sun.COM smb_shr_publisher_start(void)
18437348SJose.Borrego@Sun.COM {
18447961SNatalie.Li@Sun.COM 	pthread_t publish_thr;
18457348SJose.Borrego@Sun.COM 	pthread_attr_t tattr;
18467348SJose.Borrego@Sun.COM 	int rc;
18477348SJose.Borrego@Sun.COM 
18487961SNatalie.Li@Sun.COM 	if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN)
18497961SNatalie.Li@Sun.COM 		return (0);
18507961SNatalie.Li@Sun.COM 
18517348SJose.Borrego@Sun.COM 	(void) mutex_lock(&ad_queue.spq_mtx);
18527348SJose.Borrego@Sun.COM 	if (ad_queue.spq_state != SMB_SHR_PQS_NOQUEUE) {
18537348SJose.Borrego@Sun.COM 		(void) mutex_unlock(&ad_queue.spq_mtx);
18547348SJose.Borrego@Sun.COM 		errno = EINVAL;
18557348SJose.Borrego@Sun.COM 		return (-1);
18567348SJose.Borrego@Sun.COM 	}
18577348SJose.Borrego@Sun.COM 
18587348SJose.Borrego@Sun.COM 	list_create(&ad_queue.spq_list, sizeof (smb_shr_pitem_t),
18597348SJose.Borrego@Sun.COM 	    offsetof(smb_shr_pitem_t, spi_lnd));
18607348SJose.Borrego@Sun.COM 	ad_queue.spq_state = SMB_SHR_PQS_READY;
18617348SJose.Borrego@Sun.COM 	(void) mutex_unlock(&ad_queue.spq_mtx);
18627348SJose.Borrego@Sun.COM 
18637348SJose.Borrego@Sun.COM 	(void) pthread_attr_init(&tattr);
18647348SJose.Borrego@Sun.COM 	(void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
18657961SNatalie.Li@Sun.COM 	rc = pthread_create(&publish_thr, &tattr, smb_shr_publisher, 0);
18667348SJose.Borrego@Sun.COM 	(void) pthread_attr_destroy(&tattr);
18677348SJose.Borrego@Sun.COM 
18687348SJose.Borrego@Sun.COM 	return (rc);
18697348SJose.Borrego@Sun.COM }
18707348SJose.Borrego@Sun.COM 
18717348SJose.Borrego@Sun.COM static void
smb_shr_publisher_stop(void)18727348SJose.Borrego@Sun.COM smb_shr_publisher_stop(void)
18737348SJose.Borrego@Sun.COM {
18747961SNatalie.Li@Sun.COM 	if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN)
18757961SNatalie.Li@Sun.COM 		return;
18767961SNatalie.Li@Sun.COM 
18777348SJose.Borrego@Sun.COM 	(void) mutex_lock(&ad_queue.spq_mtx);
18787348SJose.Borrego@Sun.COM 	switch (ad_queue.spq_state) {
18797348SJose.Borrego@Sun.COM 	case SMB_SHR_PQS_READY:
18807348SJose.Borrego@Sun.COM 	case SMB_SHR_PQS_PUBLISHING:
18817348SJose.Borrego@Sun.COM 		ad_queue.spq_state = SMB_SHR_PQS_STOPPING;
18827348SJose.Borrego@Sun.COM 		(void) cond_signal(&ad_queue.spq_cv);
18837348SJose.Borrego@Sun.COM 		break;
18847348SJose.Borrego@Sun.COM 	default:
18857348SJose.Borrego@Sun.COM 		break;
18867348SJose.Borrego@Sun.COM 	}
18877348SJose.Borrego@Sun.COM 	(void) mutex_unlock(&ad_queue.spq_mtx);
18887348SJose.Borrego@Sun.COM }
18897348SJose.Borrego@Sun.COM 
18907348SJose.Borrego@Sun.COM /*
18917961SNatalie.Li@Sun.COM  * This is the publisher daemon thread.  While running, the thread waits
18927961SNatalie.Li@Sun.COM  * on a conditional variable until notified that a share needs to be
18937961SNatalie.Li@Sun.COM  * [un]published or that the thread should be terminated.
18947961SNatalie.Li@Sun.COM  *
18957961SNatalie.Li@Sun.COM  * Entries may remain in the outgoing queue if the Active Directory
18967961SNatalie.Li@Sun.COM  * service is inaccessible, in which case the thread wakes up every 60
18977961SNatalie.Li@Sun.COM  * seconds to retry.
18987348SJose.Borrego@Sun.COM  */
18997348SJose.Borrego@Sun.COM /*ARGSUSED*/
19007348SJose.Borrego@Sun.COM static void *
smb_shr_publisher(void * arg)19017348SJose.Borrego@Sun.COM smb_shr_publisher(void *arg)
19027348SJose.Borrego@Sun.COM {
19037348SJose.Borrego@Sun.COM 	smb_ads_handle_t *ah;
19047348SJose.Borrego@Sun.COM 	smb_shr_pitem_t *shr;
19057348SJose.Borrego@Sun.COM 	list_t publist;
19067961SNatalie.Li@Sun.COM 	timestruc_t pubretry;
19077348SJose.Borrego@Sun.COM 	char hostname[MAXHOSTNAMELEN];
19087348SJose.Borrego@Sun.COM 
19097348SJose.Borrego@Sun.COM 	(void) mutex_lock(&ad_queue.spq_mtx);
19107961SNatalie.Li@Sun.COM 	if (ad_queue.spq_state != SMB_SHR_PQS_READY) {
19117348SJose.Borrego@Sun.COM 		(void) mutex_unlock(&ad_queue.spq_mtx);
19127348SJose.Borrego@Sun.COM 		return (NULL);
19137348SJose.Borrego@Sun.COM 	}
19147961SNatalie.Li@Sun.COM 	ad_queue.spq_state = SMB_SHR_PQS_PUBLISHING;
19157348SJose.Borrego@Sun.COM 	(void) mutex_unlock(&ad_queue.spq_mtx);
19167348SJose.Borrego@Sun.COM 
191711963SAfshin.Ardakani@Sun.COM 	(void) smb_gethostname(hostname, MAXHOSTNAMELEN,
191811963SAfshin.Ardakani@Sun.COM 	    SMB_CASE_PRESERVE);
19197961SNatalie.Li@Sun.COM 
19207348SJose.Borrego@Sun.COM 	list_create(&publist, sizeof (smb_shr_pitem_t),
19217348SJose.Borrego@Sun.COM 	    offsetof(smb_shr_pitem_t, spi_lnd));
19227348SJose.Borrego@Sun.COM 
19237348SJose.Borrego@Sun.COM 	for (;;) {
19247348SJose.Borrego@Sun.COM 		(void) mutex_lock(&ad_queue.spq_mtx);
19257961SNatalie.Li@Sun.COM 
19267961SNatalie.Li@Sun.COM 		while (list_is_empty(&ad_queue.spq_list) &&
19277961SNatalie.Li@Sun.COM 		    (ad_queue.spq_state == SMB_SHR_PQS_PUBLISHING)) {
19287961SNatalie.Li@Sun.COM 			if (list_is_empty(&publist)) {
19297961SNatalie.Li@Sun.COM 				(void) cond_wait(&ad_queue.spq_cv,
19307961SNatalie.Li@Sun.COM 				    &ad_queue.spq_mtx);
19317961SNatalie.Li@Sun.COM 			} else {
19327961SNatalie.Li@Sun.COM 				pubretry.tv_sec = 60;
19337961SNatalie.Li@Sun.COM 				pubretry.tv_nsec = 0;
19347961SNatalie.Li@Sun.COM 				(void) cond_reltimedwait(&ad_queue.spq_cv,
19357961SNatalie.Li@Sun.COM 				    &ad_queue.spq_mtx, &pubretry);
19367961SNatalie.Li@Sun.COM 				break;
19377961SNatalie.Li@Sun.COM 			}
19387961SNatalie.Li@Sun.COM 		}
19397348SJose.Borrego@Sun.COM 
19407348SJose.Borrego@Sun.COM 		if (ad_queue.spq_state != SMB_SHR_PQS_PUBLISHING) {
19417348SJose.Borrego@Sun.COM 			(void) mutex_unlock(&ad_queue.spq_mtx);
19427348SJose.Borrego@Sun.COM 			break;
19437348SJose.Borrego@Sun.COM 		}
19447348SJose.Borrego@Sun.COM 
19457348SJose.Borrego@Sun.COM 		/*
19467961SNatalie.Li@Sun.COM 		 * Transfer queued items to the local list so that
19477961SNatalie.Li@Sun.COM 		 * the mutex can be released.
19487348SJose.Borrego@Sun.COM 		 */
19497348SJose.Borrego@Sun.COM 		while ((shr = list_head(&ad_queue.spq_list)) != NULL) {
19507348SJose.Borrego@Sun.COM 			list_remove(&ad_queue.spq_list, shr);
19517348SJose.Borrego@Sun.COM 			list_insert_tail(&publist, shr);
19527348SJose.Borrego@Sun.COM 		}
19537961SNatalie.Li@Sun.COM 
19547348SJose.Borrego@Sun.COM 		(void) mutex_unlock(&ad_queue.spq_mtx);
19557348SJose.Borrego@Sun.COM 
19567961SNatalie.Li@Sun.COM 		if ((ah = smb_ads_open()) != NULL) {
19577961SNatalie.Li@Sun.COM 			smb_shr_publisher_send(ah, &publist, hostname);
19587961SNatalie.Li@Sun.COM 			smb_ads_close(ah);
19597961SNatalie.Li@Sun.COM 		}
19607348SJose.Borrego@Sun.COM 	}
19617348SJose.Borrego@Sun.COM 
19627348SJose.Borrego@Sun.COM 	(void) mutex_lock(&ad_queue.spq_mtx);
19637961SNatalie.Li@Sun.COM 	smb_shr_publisher_flush(&ad_queue.spq_list);
19647348SJose.Borrego@Sun.COM 	list_destroy(&ad_queue.spq_list);
19657348SJose.Borrego@Sun.COM 	ad_queue.spq_state = SMB_SHR_PQS_NOQUEUE;
19667348SJose.Borrego@Sun.COM 	(void) mutex_unlock(&ad_queue.spq_mtx);
19677348SJose.Borrego@Sun.COM 
19687961SNatalie.Li@Sun.COM 	smb_shr_publisher_flush(&publist);
19697348SJose.Borrego@Sun.COM 	list_destroy(&publist);
19707348SJose.Borrego@Sun.COM 	return (NULL);
19717348SJose.Borrego@Sun.COM }
19727348SJose.Borrego@Sun.COM 
19737348SJose.Borrego@Sun.COM /*
19747961SNatalie.Li@Sun.COM  * Remove items from the specified queue and [un]publish them.
19757348SJose.Borrego@Sun.COM  */
19767348SJose.Borrego@Sun.COM static void
smb_shr_publisher_send(smb_ads_handle_t * ah,list_t * publist,const char * host)19777348SJose.Borrego@Sun.COM smb_shr_publisher_send(smb_ads_handle_t *ah, list_t *publist, const char *host)
19787348SJose.Borrego@Sun.COM {
19797348SJose.Borrego@Sun.COM 	smb_shr_pitem_t *shr;
19807348SJose.Borrego@Sun.COM 
19817348SJose.Borrego@Sun.COM 	while ((shr = list_head(publist)) != NULL) {
19827961SNatalie.Li@Sun.COM 		(void) mutex_lock(&ad_queue.spq_mtx);
19837961SNatalie.Li@Sun.COM 		if (ad_queue.spq_state != SMB_SHR_PQS_PUBLISHING) {
19847348SJose.Borrego@Sun.COM 			(void) mutex_unlock(&ad_queue.spq_mtx);
19857961SNatalie.Li@Sun.COM 			return;
19867961SNatalie.Li@Sun.COM 		}
19877961SNatalie.Li@Sun.COM 		(void) mutex_unlock(&ad_queue.spq_mtx);
19887348SJose.Borrego@Sun.COM 
19897961SNatalie.Li@Sun.COM 		list_remove(publist, shr);
19907961SNatalie.Li@Sun.COM 
19917961SNatalie.Li@Sun.COM 		if (shr->spi_op == SMB_SHR_PUBLISH)
19927961SNatalie.Li@Sun.COM 			(void) smb_ads_publish_share(ah, shr->spi_name,
19937961SNatalie.Li@Sun.COM 			    NULL, shr->spi_container, host);
19947961SNatalie.Li@Sun.COM 		else
19957961SNatalie.Li@Sun.COM 			(void) smb_ads_remove_share(ah, shr->spi_name,
19967961SNatalie.Li@Sun.COM 			    NULL, shr->spi_container, host);
19977961SNatalie.Li@Sun.COM 
19987348SJose.Borrego@Sun.COM 		free(shr);
19997348SJose.Borrego@Sun.COM 	}
20007348SJose.Borrego@Sun.COM }
20017961SNatalie.Li@Sun.COM 
20027961SNatalie.Li@Sun.COM /*
20037961SNatalie.Li@Sun.COM  * Flush all remaining items from the specified list/queue.
20047961SNatalie.Li@Sun.COM  */
20057961SNatalie.Li@Sun.COM static void
smb_shr_publisher_flush(list_t * lst)20067961SNatalie.Li@Sun.COM smb_shr_publisher_flush(list_t *lst)
20077961SNatalie.Li@Sun.COM {
20087961SNatalie.Li@Sun.COM 	smb_shr_pitem_t *shr;
20097961SNatalie.Li@Sun.COM 
20107961SNatalie.Li@Sun.COM 	while ((shr = list_head(lst)) != NULL) {
20117961SNatalie.Li@Sun.COM 		list_remove(lst, shr);
20127961SNatalie.Li@Sun.COM 		free(shr);
20137961SNatalie.Li@Sun.COM 	}
20147961SNatalie.Li@Sun.COM }
20158845Samw@Sun.COM 
20168845Samw@Sun.COM /*
20178871Samw@Sun.COM  * If the share path refers to a ZFS file system, add the
201811963SAfshin.Ardakani@Sun.COM  * .zfs/shares/<share> object and call smb_quota_add_fs()
201911963SAfshin.Ardakani@Sun.COM  * to initialize quota support for the share.
20208845Samw@Sun.COM  */
20218845Samw@Sun.COM static void
smb_shr_zfs_add(smb_share_t * si)20228845Samw@Sun.COM smb_shr_zfs_add(smb_share_t *si)
20238845Samw@Sun.COM {
20248871Samw@Sun.COM 	libzfs_handle_t *libhd;
20258871Samw@Sun.COM 	zfs_handle_t *zfshd;
20268871Samw@Sun.COM 	int ret;
202711963SAfshin.Ardakani@Sun.COM 	char buf[MAXPATHLEN];	/* dataset or mountpoint */
20288845Samw@Sun.COM 
202911963SAfshin.Ardakani@Sun.COM 	if (smb_getdataset(si->shr_path, buf, MAXPATHLEN) != 0)
20308871Samw@Sun.COM 		return;
20318871Samw@Sun.COM 
20328871Samw@Sun.COM 	if ((libhd = libzfs_init()) == NULL)
20338871Samw@Sun.COM 		return;
20348871Samw@Sun.COM 
203511963SAfshin.Ardakani@Sun.COM 	if ((zfshd = zfs_open(libhd, buf, ZFS_TYPE_FILESYSTEM)) == NULL) {
20368871Samw@Sun.COM 		libzfs_fini(libhd);
20378871Samw@Sun.COM 		return;
20388845Samw@Sun.COM 	}
20398871Samw@Sun.COM 
20408871Samw@Sun.COM 	errno = 0;
204111963SAfshin.Ardakani@Sun.COM 	ret = zfs_smb_acl_add(libhd, buf, si->shr_path, si->shr_name);
20428871Samw@Sun.COM 	if (ret != 0 && errno != EAGAIN && errno != EEXIST)
20438871Samw@Sun.COM 		syslog(LOG_INFO, "share: failed to add ACL object: %s: %s\n",
20448871Samw@Sun.COM 		    si->shr_name, strerror(errno));
20458871Samw@Sun.COM 
204611963SAfshin.Ardakani@Sun.COM 	if (zfs_prop_get(zfshd, ZFS_PROP_MOUNTPOINT, buf, MAXPATHLEN,
204711963SAfshin.Ardakani@Sun.COM 	    NULL, NULL, 0, B_FALSE) == 0) {
204811963SAfshin.Ardakani@Sun.COM 		smb_quota_add_fs(buf);
204911963SAfshin.Ardakani@Sun.COM 	}
205011963SAfshin.Ardakani@Sun.COM 
205111963SAfshin.Ardakani@Sun.COM 
20528871Samw@Sun.COM 	zfs_close(zfshd);
20538871Samw@Sun.COM 	libzfs_fini(libhd);
20548845Samw@Sun.COM }
20558845Samw@Sun.COM 
20568845Samw@Sun.COM /*
20578871Samw@Sun.COM  * If the share path refers to a ZFS file system, remove the
205811963SAfshin.Ardakani@Sun.COM  * .zfs/shares/<share> object, and call smb_quota_remove_fs()
205911963SAfshin.Ardakani@Sun.COM  * to end quota support for the share.
20608845Samw@Sun.COM  */
20618845Samw@Sun.COM static void
smb_shr_zfs_remove(smb_share_t * si)20628845Samw@Sun.COM smb_shr_zfs_remove(smb_share_t *si)
20638845Samw@Sun.COM {
20648871Samw@Sun.COM 	libzfs_handle_t *libhd;
20658871Samw@Sun.COM 	zfs_handle_t *zfshd;
20668871Samw@Sun.COM 	int ret;
206711963SAfshin.Ardakani@Sun.COM 	char buf[MAXPATHLEN];	/* dataset or mountpoint */
20688845Samw@Sun.COM 
206911963SAfshin.Ardakani@Sun.COM 	if (smb_getdataset(si->shr_path, buf, MAXPATHLEN) != 0)
20708871Samw@Sun.COM 		return;
20718871Samw@Sun.COM 
20728871Samw@Sun.COM 	if ((libhd = libzfs_init()) == NULL)
20738871Samw@Sun.COM 		return;
20748871Samw@Sun.COM 
207511963SAfshin.Ardakani@Sun.COM 	if ((zfshd = zfs_open(libhd, buf, ZFS_TYPE_FILESYSTEM)) == NULL) {
20768871Samw@Sun.COM 		libzfs_fini(libhd);
20778871Samw@Sun.COM 		return;
20788845Samw@Sun.COM 	}
20798871Samw@Sun.COM 
20808871Samw@Sun.COM 	errno = 0;
208111963SAfshin.Ardakani@Sun.COM 	ret = zfs_smb_acl_remove(libhd, buf, si->shr_path, si->shr_name);
20828871Samw@Sun.COM 	if (ret != 0 && errno != EAGAIN)
20838871Samw@Sun.COM 		syslog(LOG_INFO, "share: failed to remove ACL object: %s: %s\n",
20848871Samw@Sun.COM 		    si->shr_name, strerror(errno));
20858871Samw@Sun.COM 
208611963SAfshin.Ardakani@Sun.COM 	if (zfs_prop_get(zfshd, ZFS_PROP_MOUNTPOINT, buf, MAXPATHLEN,
208711963SAfshin.Ardakani@Sun.COM 	    NULL, NULL, 0, B_FALSE) == 0) {
208811963SAfshin.Ardakani@Sun.COM 		smb_quota_remove_fs(buf);
208911963SAfshin.Ardakani@Sun.COM 	}
209011963SAfshin.Ardakani@Sun.COM 
20918871Samw@Sun.COM 	zfs_close(zfshd);
20928871Samw@Sun.COM 	libzfs_fini(libhd);
20938845Samw@Sun.COM }
20948845Samw@Sun.COM 
20958845Samw@Sun.COM /*
20968871Samw@Sun.COM  * If the share path refers to a ZFS file system, rename the
20978845Samw@Sun.COM  * .zfs/shares/<share> object.
20988845Samw@Sun.COM  */
20998845Samw@Sun.COM static void
smb_shr_zfs_rename(smb_share_t * from,smb_share_t * to)21008845Samw@Sun.COM smb_shr_zfs_rename(smb_share_t *from, smb_share_t *to)
21018845Samw@Sun.COM {
21028871Samw@Sun.COM 	libzfs_handle_t *libhd;
21038871Samw@Sun.COM 	zfs_handle_t *zfshd;
21048871Samw@Sun.COM 	int ret;
21058845Samw@Sun.COM 	char dataset[MAXPATHLEN];
21068845Samw@Sun.COM 
21078871Samw@Sun.COM 	if (smb_getdataset(from->shr_path, dataset, MAXPATHLEN) != 0)
21088871Samw@Sun.COM 		return;
21098871Samw@Sun.COM 
21108871Samw@Sun.COM 	if ((libhd = libzfs_init()) == NULL)
21118871Samw@Sun.COM 		return;
21128871Samw@Sun.COM 
21138871Samw@Sun.COM 	if ((zfshd = zfs_open(libhd, dataset, ZFS_TYPE_FILESYSTEM)) == NULL) {
21148871Samw@Sun.COM 		libzfs_fini(libhd);
21158871Samw@Sun.COM 		return;
21168845Samw@Sun.COM 	}
21178871Samw@Sun.COM 
21188871Samw@Sun.COM 	errno = 0;
21198871Samw@Sun.COM 	ret = zfs_smb_acl_rename(libhd, dataset, from->shr_path,
21208871Samw@Sun.COM 	    from->shr_name, to->shr_name);
21218871Samw@Sun.COM 	if (ret != 0 && errno != EAGAIN)
21228871Samw@Sun.COM 		syslog(LOG_INFO, "share: failed to rename ACL object: %s: %s\n",
21238871Samw@Sun.COM 		    from->shr_name, strerror(errno));
21248871Samw@Sun.COM 
21258871Samw@Sun.COM 	zfs_close(zfshd);
21268871Samw@Sun.COM 	libzfs_fini(libhd);
21278845Samw@Sun.COM }
21289832Samw@Sun.COM 
21299832Samw@Sun.COM /*
21309832Samw@Sun.COM  * Enable all privileges in the inheritable set to execute command.
21319832Samw@Sun.COM  */
21329832Samw@Sun.COM static int
smb_shr_enable_all_privs(void)21339832Samw@Sun.COM smb_shr_enable_all_privs(void)
21349832Samw@Sun.COM {
21359832Samw@Sun.COM 	priv_set_t *pset;
21369832Samw@Sun.COM 
21379832Samw@Sun.COM 	pset = priv_allocset();
21389832Samw@Sun.COM 	if (pset == NULL)
21399832Samw@Sun.COM 		return (-1);
21409832Samw@Sun.COM 
21419832Samw@Sun.COM 	if (getppriv(PRIV_LIMIT, pset)) {
21429832Samw@Sun.COM 		priv_freeset(pset);
21439832Samw@Sun.COM 		return (-1);
21449832Samw@Sun.COM 	}
21459832Samw@Sun.COM 
21469832Samw@Sun.COM 	if (setppriv(PRIV_ON, PRIV_INHERITABLE, pset)) {
21479832Samw@Sun.COM 		priv_freeset(pset);
21489832Samw@Sun.COM 		return (-1);
21499832Samw@Sun.COM 	}
21509832Samw@Sun.COM 
21519832Samw@Sun.COM 	priv_freeset(pset);
21529832Samw@Sun.COM 	return (0);
21539832Samw@Sun.COM }
21549832Samw@Sun.COM 
21559832Samw@Sun.COM /*
21569832Samw@Sun.COM  * Tokenizes the command string and returns the list of tokens in an array.
21579832Samw@Sun.COM  *
21589832Samw@Sun.COM  * Returns NULL if there are no tokens.
21599832Samw@Sun.COM  */
21609832Samw@Sun.COM static char **
smb_shr_tokenize_cmd(char * cmdstr)21619832Samw@Sun.COM smb_shr_tokenize_cmd(char *cmdstr)
21629832Samw@Sun.COM {
21639832Samw@Sun.COM 	char *cmd, *buf, *bp, *value;
21649832Samw@Sun.COM 	char **argv, **ap;
21659832Samw@Sun.COM 	int argc, i;
21669832Samw@Sun.COM 
21679832Samw@Sun.COM 	if (cmdstr == NULL || *cmdstr == '\0')
21689832Samw@Sun.COM 		return (NULL);
21699832Samw@Sun.COM 
21709832Samw@Sun.COM 	if ((buf = malloc(MAXPATHLEN)) == NULL)
21719832Samw@Sun.COM 		return (NULL);
21729832Samw@Sun.COM 
21739832Samw@Sun.COM 	(void) strlcpy(buf, cmdstr, MAXPATHLEN);
21749832Samw@Sun.COM 
21759832Samw@Sun.COM 	for (argc = 2, bp = cmdstr; *bp != '\0'; ++bp)
21769832Samw@Sun.COM 		if (*bp == ' ')
21779832Samw@Sun.COM 			++argc;
21789832Samw@Sun.COM 
21799832Samw@Sun.COM 	if ((argv = calloc(argc, sizeof (char *))) == NULL) {
21809832Samw@Sun.COM 		free(buf);
21819832Samw@Sun.COM 		return (NULL);
21829832Samw@Sun.COM 	}
21839832Samw@Sun.COM 
21849832Samw@Sun.COM 	ap = argv;
21859832Samw@Sun.COM 	for (bp = buf, i = 0; i < argc; ++i) {
21869832Samw@Sun.COM 		do {
21879832Samw@Sun.COM 			if ((value = strsep(&bp, " ")) == NULL)
21889832Samw@Sun.COM 				break;
21899832Samw@Sun.COM 		} while (*value == '\0');
21909832Samw@Sun.COM 
21919832Samw@Sun.COM 		if (value == NULL)
21929832Samw@Sun.COM 			break;
21939832Samw@Sun.COM 
21949832Samw@Sun.COM 		*ap++ = value;
21959832Samw@Sun.COM 	}
21969832Samw@Sun.COM 
21979832Samw@Sun.COM 	/* get the filename of the command from the path */
21989832Samw@Sun.COM 	if ((cmd = strrchr(argv[0], '/')) != NULL)
21999832Samw@Sun.COM 		(void) strlcpy(argv[0], ++cmd, strlen(argv[0]));
22009832Samw@Sun.COM 
22019832Samw@Sun.COM 	return (argv);
22029832Samw@Sun.COM }
22039832Samw@Sun.COM 
22049832Samw@Sun.COM /*
22059832Samw@Sun.COM  * Expands the command string for the following substitution tokens:
22069832Samw@Sun.COM  *
22079832Samw@Sun.COM  * %U - Windows username
22089832Samw@Sun.COM  * %D - Name of the domain or workgroup of %U
22099832Samw@Sun.COM  * %h - The server hostname
22109832Samw@Sun.COM  * %M - The client hostname
22119832Samw@Sun.COM  * %L - The server NetBIOS name
22129832Samw@Sun.COM  * %m - The client NetBIOS name. This option is only valid for NetBIOS
22139832Samw@Sun.COM  *      connections (port 139).
22149832Samw@Sun.COM  * %I - The IP address of the client machine
22159832Samw@Sun.COM  * %i - The local IP address to which the client is connected
22169832Samw@Sun.COM  * %S - The name of the share
22179832Samw@Sun.COM  * %P - The root directory of the share
22189832Samw@Sun.COM  * %u - The UID of the Unix user
22199832Samw@Sun.COM  *
22209832Samw@Sun.COM  * Returns 0 on success.  Otherwise -1.
22219832Samw@Sun.COM  */
22229832Samw@Sun.COM static int
smb_shr_expand_subs(char ** cmd_toks,smb_share_t * si,smb_shr_execinfo_t * subs)222312508Samw@Sun.COM smb_shr_expand_subs(char **cmd_toks, smb_share_t *si, smb_shr_execinfo_t *subs)
22249832Samw@Sun.COM {
22259832Samw@Sun.COM 	char *fmt, *sub_chr, *ptr;
22269832Samw@Sun.COM 	boolean_t unknown;
22279832Samw@Sun.COM 	char hostname[MAXHOSTNAMELEN];
22289832Samw@Sun.COM 	char ip_str[INET6_ADDRSTRLEN];
22299832Samw@Sun.COM 	char name[SMB_PI_MAX_HOST];
223010966SJordan.Brown@Sun.COM 	smb_wchar_t wbuf[SMB_PI_MAX_HOST];
22319832Samw@Sun.COM 	int i;
22329832Samw@Sun.COM 
22339832Samw@Sun.COM 	if (cmd_toks == NULL || *cmd_toks == NULL)
22349832Samw@Sun.COM 		return (-1);
22359832Samw@Sun.COM 
22369832Samw@Sun.COM 	for (i = 1; cmd_toks[i]; i++) {
22379832Samw@Sun.COM 		fmt = cmd_toks[i];
22389832Samw@Sun.COM 		if (*fmt == '%') {
22399832Samw@Sun.COM 			sub_chr = fmt + 1;
22409832Samw@Sun.COM 			unknown = B_FALSE;
22419832Samw@Sun.COM 
22429832Samw@Sun.COM 			switch (*sub_chr) {
22439832Samw@Sun.COM 			case 'U':
22449832Samw@Sun.COM 				ptr = strdup(subs->e_winname);
22459832Samw@Sun.COM 				break;
22469832Samw@Sun.COM 			case 'D':
22479832Samw@Sun.COM 				ptr = strdup(subs->e_userdom);
22489832Samw@Sun.COM 				break;
22499832Samw@Sun.COM 			case 'h':
22509832Samw@Sun.COM 				if (gethostname(hostname, MAXHOSTNAMELEN) != 0)
22519832Samw@Sun.COM 					unknown = B_TRUE;
22529832Samw@Sun.COM 				else
22539832Samw@Sun.COM 					ptr = strdup(hostname);
22549832Samw@Sun.COM 				break;
22559832Samw@Sun.COM 			case 'M':
22569832Samw@Sun.COM 				if (smb_getnameinfo(&subs->e_cli_ipaddr,
22579832Samw@Sun.COM 				    hostname, sizeof (hostname), 0) != 0)
22589832Samw@Sun.COM 					unknown = B_TRUE;
22599832Samw@Sun.COM 				else
22609832Samw@Sun.COM 					ptr = strdup(hostname);
22619832Samw@Sun.COM 				break;
22629832Samw@Sun.COM 			case 'L':
22639832Samw@Sun.COM 				if (smb_getnetbiosname(hostname,
22649832Samw@Sun.COM 				    NETBIOS_NAME_SZ) != 0)
22659832Samw@Sun.COM 					unknown = B_TRUE;
22669832Samw@Sun.COM 				else
22679832Samw@Sun.COM 					ptr = strdup(hostname);
22689832Samw@Sun.COM 				break;
22699832Samw@Sun.COM 			case 'm':
22709832Samw@Sun.COM 				if (*subs->e_cli_netbiosname == '\0')
22719832Samw@Sun.COM 					unknown = B_TRUE;
22729832Samw@Sun.COM 				else {
227310966SJordan.Brown@Sun.COM 					(void) smb_mbstowcs(wbuf,
22749832Samw@Sun.COM 					    subs->e_cli_netbiosname,
22759832Samw@Sun.COM 					    SMB_PI_MAX_HOST - 1);
22769832Samw@Sun.COM 
227710966SJordan.Brown@Sun.COM 					if (ucstooem(name, wbuf,
227810966SJordan.Brown@Sun.COM 					    SMB_PI_MAX_HOST, OEM_CPG_850) == 0)
22799832Samw@Sun.COM 						(void) strlcpy(name,
22809832Samw@Sun.COM 						    subs->e_cli_netbiosname,
22819832Samw@Sun.COM 						    SMB_PI_MAX_HOST);
22829832Samw@Sun.COM 
22839832Samw@Sun.COM 					ptr = strdup(name);
22849832Samw@Sun.COM 				}
22859832Samw@Sun.COM 				break;
22869832Samw@Sun.COM 			case 'I':
22879832Samw@Sun.COM 				if (smb_inet_ntop(&subs->e_cli_ipaddr, ip_str,
22889832Samw@Sun.COM 				    SMB_IPSTRLEN(subs->e_cli_ipaddr.a_family))
22899832Samw@Sun.COM 				    != NULL)
22909832Samw@Sun.COM 					ptr = strdup(ip_str);
22919832Samw@Sun.COM 				else
22929832Samw@Sun.COM 					unknown = B_TRUE;
22939832Samw@Sun.COM 				break;
22949832Samw@Sun.COM 			case 'i':
22959832Samw@Sun.COM 				if (smb_inet_ntop(&subs->e_srv_ipaddr, ip_str,
22969832Samw@Sun.COM 				    SMB_IPSTRLEN(subs->e_srv_ipaddr.a_family))
22979832Samw@Sun.COM 				    != NULL)
22989832Samw@Sun.COM 					ptr = strdup(ip_str);
22999832Samw@Sun.COM 				else
23009832Samw@Sun.COM 					unknown = B_TRUE;
23019832Samw@Sun.COM 				break;
23029832Samw@Sun.COM 			case 'S':
23039832Samw@Sun.COM 				ptr = strdup(si->shr_name);
23049832Samw@Sun.COM 				break;
23059832Samw@Sun.COM 			case 'P':
23069832Samw@Sun.COM 				ptr = strdup(si->shr_path);
23079832Samw@Sun.COM 				break;
23089832Samw@Sun.COM 			case 'u':
23099832Samw@Sun.COM 				(void) snprintf(name, sizeof (name), "%u",
23109832Samw@Sun.COM 				    subs->e_uid);
23119832Samw@Sun.COM 				ptr = strdup(name);
23129832Samw@Sun.COM 				break;
23139832Samw@Sun.COM 			default:
23149832Samw@Sun.COM 				/* unknown sub char */
23159832Samw@Sun.COM 				unknown = B_TRUE;
23169832Samw@Sun.COM 				break;
23179832Samw@Sun.COM 			}
23189832Samw@Sun.COM 
23199832Samw@Sun.COM 			if (unknown)
23209832Samw@Sun.COM 				ptr = strdup("");
23219832Samw@Sun.COM 
23229832Samw@Sun.COM 		} else  /* first char of cmd's arg is not '%' char */
23239832Samw@Sun.COM 			ptr = strdup("");
23249832Samw@Sun.COM 
23259832Samw@Sun.COM 		cmd_toks[i] = ptr;
23269832Samw@Sun.COM 
23279832Samw@Sun.COM 		if (ptr == NULL) {
23289832Samw@Sun.COM 			for (i = 1; cmd_toks[i]; i++)
23299832Samw@Sun.COM 				free(cmd_toks[i]);
23309832Samw@Sun.COM 
23319832Samw@Sun.COM 			return (-1);
23329832Samw@Sun.COM 		}
23339832Samw@Sun.COM 	}
23349832Samw@Sun.COM 
23359832Samw@Sun.COM 	return (0);
23369832Samw@Sun.COM }
23379832Samw@Sun.COM 
23389832Samw@Sun.COM /*ARGSUSED*/
23399832Samw@Sun.COM static void
smb_shr_sig_abnormal_term(int sig_val)23409832Samw@Sun.COM smb_shr_sig_abnormal_term(int sig_val)
23419832Samw@Sun.COM {
23429832Samw@Sun.COM 	/*
23439832Samw@Sun.COM 	 * Calling _exit() prevents parent process from getting SIGTERM/SIGINT
23449832Samw@Sun.COM 	 * signal.
23459832Samw@Sun.COM 	 */
23469832Samw@Sun.COM 	_exit(-1);
23479832Samw@Sun.COM }
23489832Samw@Sun.COM 
23499832Samw@Sun.COM /*ARGSUSED*/
23509832Samw@Sun.COM static void
smb_shr_sig_child(int sig_val)23519832Samw@Sun.COM smb_shr_sig_child(int sig_val)
23529832Samw@Sun.COM {
23539832Samw@Sun.COM 	/*
23549832Samw@Sun.COM 	 * Catch the signal and allow the exit status of the child process
23559832Samw@Sun.COM 	 * to be available for reaping.
23569832Samw@Sun.COM 	 */
23579832Samw@Sun.COM }
23589832Samw@Sun.COM 
23599832Samw@Sun.COM /*
236012508Samw@Sun.COM  * This is a temporary function which converts the given smb_share_t
236112508Samw@Sun.COM  * structure to the nvlist format that will be provided by libsharev2
23629832Samw@Sun.COM  */
236312508Samw@Sun.COM static int
smb_shr_encode(smb_share_t * si,nvlist_t ** nvlist)236412508Samw@Sun.COM smb_shr_encode(smb_share_t *si, nvlist_t **nvlist)
23659832Samw@Sun.COM {
236612508Samw@Sun.COM 	nvlist_t *list;
236712508Samw@Sun.COM 	nvlist_t *share;
236812508Samw@Sun.COM 	nvlist_t *smb;
236912508Samw@Sun.COM 	char *csc;
237012508Samw@Sun.COM 	int rc = 0;
237112508Samw@Sun.COM 
237212508Samw@Sun.COM 	*nvlist = NULL;
23739832Samw@Sun.COM 
237412508Samw@Sun.COM 	if ((rc = nvlist_alloc(&list, NV_UNIQUE_NAME, 0)) != 0)
237512508Samw@Sun.COM 		return (rc);
23769832Samw@Sun.COM 
237712508Samw@Sun.COM 	if ((rc = nvlist_alloc(&share, NV_UNIQUE_NAME, 0)) != 0) {
237812508Samw@Sun.COM 		nvlist_free(list);
237912508Samw@Sun.COM 		return (rc);
238012508Samw@Sun.COM 	}
23819832Samw@Sun.COM 
238212508Samw@Sun.COM 	if ((rc = nvlist_alloc(&smb, NV_UNIQUE_NAME, 0)) != 0) {
238312508Samw@Sun.COM 		nvlist_free(share);
238412508Samw@Sun.COM 		nvlist_free(list);
238512508Samw@Sun.COM 		return (rc);
238612508Samw@Sun.COM 	}
238712508Samw@Sun.COM 
238812508Samw@Sun.COM 	/* global share properties */
238912508Samw@Sun.COM 	rc |= nvlist_add_string(share, "name", si->shr_name);
239012508Samw@Sun.COM 	rc |= nvlist_add_string(share, "path", si->shr_path);
239112508Samw@Sun.COM 	rc |= nvlist_add_string(share, "desc", si->shr_cmnt);
23929832Samw@Sun.COM 
239312508Samw@Sun.COM 	/* smb protocol properties */
239412508Samw@Sun.COM 	rc = nvlist_add_string(smb, SHOPT_AD_CONTAINER, si->shr_container);
239512508Samw@Sun.COM 	if ((si->shr_flags & SMB_SHRF_ACC_NONE) != 0)
239612508Samw@Sun.COM 		rc |= nvlist_add_string(smb, SHOPT_NONE, si->shr_access_none);
239712508Samw@Sun.COM 	if ((si->shr_flags & SMB_SHRF_ACC_RO) != 0)
239812508Samw@Sun.COM 		rc |= nvlist_add_string(smb, SHOPT_RO, si->shr_access_ro);
239912508Samw@Sun.COM 	if ((si->shr_flags & SMB_SHRF_ACC_RW) != 0)
240012508Samw@Sun.COM 		rc |= nvlist_add_string(smb, SHOPT_RW, si->shr_access_rw);
24019832Samw@Sun.COM 
240212508Samw@Sun.COM 	if ((si->shr_flags & SMB_SHRF_ABE) != 0)
240312508Samw@Sun.COM 		rc |= nvlist_add_string(smb, SHOPT_ABE, "true");
240412508Samw@Sun.COM 	if ((si->shr_flags & SMB_SHRF_CATIA) != 0)
240512508Samw@Sun.COM 		rc |= nvlist_add_string(smb, SHOPT_CATIA, "true");
240612508Samw@Sun.COM 	if ((si->shr_flags & SMB_SHRF_GUEST_OK) != 0)
240712508Samw@Sun.COM 		rc |= nvlist_add_string(smb, SHOPT_GUEST, "true");
240812508Samw@Sun.COM 	if ((si->shr_flags & SMB_SHRF_DFSROOT) != 0)
240912508Samw@Sun.COM 		rc |= nvlist_add_string(smb, SHOPT_DFSROOT, "true");
24109832Samw@Sun.COM 
241112508Samw@Sun.COM 	if ((si->shr_flags & SMB_SHRF_AUTOHOME) != 0) {
241212508Samw@Sun.COM 		rc |= nvlist_add_string(smb, "Autohome", "true");
241312508Samw@Sun.COM 		rc |= nvlist_add_uint32(smb, "uid", si->shr_uid);
241412508Samw@Sun.COM 		rc |= nvlist_add_uint32(smb, "gid", si->shr_gid);
241512508Samw@Sun.COM 	}
241612508Samw@Sun.COM 
241712508Samw@Sun.COM 	if ((csc = smb_shr_sa_csc_name(si)) != NULL)
241812508Samw@Sun.COM 		rc |= nvlist_add_string(smb, SHOPT_CSC, csc);
24199832Samw@Sun.COM 
242012890SJoyce.McIntosh@Sun.COM 	rc |= nvlist_add_uint32(smb, "type", si->shr_type);
242112890SJoyce.McIntosh@Sun.COM 
242212508Samw@Sun.COM 	rc |= nvlist_add_nvlist(share, "smb", smb);
242312508Samw@Sun.COM 	rc |= nvlist_add_nvlist(list, si->shr_name, share);
242412508Samw@Sun.COM 
242512508Samw@Sun.COM 	nvlist_free(share);
242612508Samw@Sun.COM 	nvlist_free(smb);
242712508Samw@Sun.COM 
242812508Samw@Sun.COM 	if (rc != 0)
242912508Samw@Sun.COM 		nvlist_free(list);
243012508Samw@Sun.COM 	else
243112508Samw@Sun.COM 		*nvlist = list;
243212508Samw@Sun.COM 
243312508Samw@Sun.COM 	return (rc);
24349832Samw@Sun.COM }
2435