xref: /onnv-gate/usr/src/lib/smbsrv/libmlsvc/common/smb_share.c (revision 10122:96eda55bfd54)
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 /*
228474SJose.Borrego@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237052Samw  * Use is subject to license terms.
247052Samw  */
257052Samw 
267052Samw /*
277961SNatalie.Li@Sun.COM  * SMB/CIFS share cache implementation.
287052Samw  */
297052Samw 
307052Samw #include <errno.h>
317052Samw #include <synch.h>
327052Samw #include <stdlib.h>
337052Samw #include <strings.h>
347052Samw #include <syslog.h>
357052Samw #include <thread.h>
367052Samw #include <pthread.h>
377348SJose.Borrego@Sun.COM #include <assert.h>
387961SNatalie.Li@Sun.COM #include <libshare.h>
398845Samw@Sun.COM #include <libzfs.h>
409832Samw@Sun.COM #include <priv_utils.h>
419832Samw@Sun.COM #include <sys/types.h>
429832Samw@Sun.COM #include <sys/wait.h>
439832Samw@Sun.COM #include <unistd.h>
449832Samw@Sun.COM #include <pwd.h>
459832Samw@Sun.COM #include <signal.h>
467052Samw 
477052Samw #include <smbsrv/libsmb.h>
487052Samw #include <smbsrv/libsmbns.h>
497588Samw@Sun.COM #include <smbsrv/libmlsvc.h>
507052Samw 
517052Samw #include <smbsrv/lm.h>
527052Samw #include <smbsrv/smb_share.h>
537052Samw #include <smbsrv/cifs.h>
547961SNatalie.Li@Sun.COM #include <smbsrv/nterror.h>
557052Samw 
567961SNatalie.Li@Sun.COM #define	SMB_SHR_ERROR_THRESHOLD		3
577052Samw 
588334SJose.Borrego@Sun.COM #define	SMB_SHR_CSC_BUFSZ		64
598334SJose.Borrego@Sun.COM 
609832Samw@Sun.COM static struct {
619832Samw@Sun.COM 	char *value;
629832Samw@Sun.COM 	uint32_t flag;
639832Samw@Sun.COM } cscopt[] = {
649832Samw@Sun.COM 	{ "disabled",	SMB_SHRF_CSC_DISABLED },
659832Samw@Sun.COM 	{ "manual",	SMB_SHRF_CSC_MANUAL },
669832Samw@Sun.COM 	{ "auto",	SMB_SHRF_CSC_AUTO },
679832Samw@Sun.COM 	{ "vdo",	SMB_SHRF_CSC_VDO }
689832Samw@Sun.COM };
699832Samw@Sun.COM 
707348SJose.Borrego@Sun.COM /*
717348SJose.Borrego@Sun.COM  * Cache functions and vars
727348SJose.Borrego@Sun.COM  */
737961SNatalie.Li@Sun.COM #define	SMB_SHR_HTAB_SZ			1024
747052Samw 
757961SNatalie.Li@Sun.COM /*
767961SNatalie.Li@Sun.COM  * Cache handle
777961SNatalie.Li@Sun.COM  *
787961SNatalie.Li@Sun.COM  * Shares cache is a hash table.
797961SNatalie.Li@Sun.COM  *
807961SNatalie.Li@Sun.COM  * sc_cache		pointer to hash table handle
817961SNatalie.Li@Sun.COM  * sc_cache_lck		synchronize cache read/write accesses
827961SNatalie.Li@Sun.COM  * sc_state		cache state machine values
837961SNatalie.Li@Sun.COM  * sc_nops		number of inflight/pending cache operations
847961SNatalie.Li@Sun.COM  * sc_mtx		protects handle fields
857961SNatalie.Li@Sun.COM  */
867961SNatalie.Li@Sun.COM typedef struct smb_shr_cache {
877961SNatalie.Li@Sun.COM 	HT_HANDLE	*sc_cache;
887961SNatalie.Li@Sun.COM 	rwlock_t	sc_cache_lck;
897961SNatalie.Li@Sun.COM 	mutex_t		sc_mtx;
907961SNatalie.Li@Sun.COM 	cond_t		sc_cv;
917961SNatalie.Li@Sun.COM 	uint32_t	sc_state;
927961SNatalie.Li@Sun.COM 	uint32_t	sc_nops;
937961SNatalie.Li@Sun.COM } smb_shr_cache_t;
947961SNatalie.Li@Sun.COM 
957961SNatalie.Li@Sun.COM /*
967961SNatalie.Li@Sun.COM  * Cache states
977961SNatalie.Li@Sun.COM  */
987961SNatalie.Li@Sun.COM #define	SMB_SHR_CACHE_STATE_NONE	0
997961SNatalie.Li@Sun.COM #define	SMB_SHR_CACHE_STATE_CREATED	1
1007961SNatalie.Li@Sun.COM #define	SMB_SHR_CACHE_STATE_DESTROYING	2
1017961SNatalie.Li@Sun.COM 
1027961SNatalie.Li@Sun.COM /*
1037961SNatalie.Li@Sun.COM  * Cache lock modes
1047961SNatalie.Li@Sun.COM  */
1057961SNatalie.Li@Sun.COM #define	SMB_SHR_CACHE_RDLOCK	0
1067961SNatalie.Li@Sun.COM #define	SMB_SHR_CACHE_WRLOCK	1
1077961SNatalie.Li@Sun.COM 
1087961SNatalie.Li@Sun.COM static smb_shr_cache_t smb_shr_cache;
1097052Samw 
1107052Samw static uint32_t smb_shr_cache_create(void);
1117348SJose.Borrego@Sun.COM static void smb_shr_cache_destroy(void);
1127961SNatalie.Li@Sun.COM static uint32_t smb_shr_cache_lock(int);
1137961SNatalie.Li@Sun.COM static void smb_shr_cache_unlock(void);
1147961SNatalie.Li@Sun.COM static int smb_shr_cache_count(void);
1157961SNatalie.Li@Sun.COM static smb_share_t *smb_shr_cache_iterate(smb_shriter_t *);
1167961SNatalie.Li@Sun.COM 
1177961SNatalie.Li@Sun.COM static smb_share_t *smb_shr_cache_findent(char *);
1187348SJose.Borrego@Sun.COM static uint32_t smb_shr_cache_addent(smb_share_t *);
1197348SJose.Borrego@Sun.COM static void smb_shr_cache_delent(char *);
1207348SJose.Borrego@Sun.COM static void smb_shr_cache_freent(HT_ITEM *);
1217052Samw 
1227348SJose.Borrego@Sun.COM /*
1237348SJose.Borrego@Sun.COM  * sharemgr functions
1247348SJose.Borrego@Sun.COM  */
1257961SNatalie.Li@Sun.COM static void *smb_shr_sa_loadall(void *);
1267961SNatalie.Li@Sun.COM static void smb_shr_sa_loadgrp(sa_group_t);
1277961SNatalie.Li@Sun.COM static uint32_t smb_shr_sa_load(sa_share_t, sa_resource_t);
1288334SJose.Borrego@Sun.COM static uint32_t smb_shr_sa_loadbyname(char *);
1297961SNatalie.Li@Sun.COM static uint32_t smb_shr_sa_get(sa_share_t, sa_resource_t, smb_share_t *);
1307052Samw 
1317052Samw /*
1328845Samw@Sun.COM  * .ZFS management functions
1338845Samw@Sun.COM  */
1348845Samw@Sun.COM static void smb_shr_zfs_add(smb_share_t *);
1358845Samw@Sun.COM static void smb_shr_zfs_remove(smb_share_t *);
1368845Samw@Sun.COM static void smb_shr_zfs_rename(smb_share_t *, smb_share_t *);
1378845Samw@Sun.COM 
1388845Samw@Sun.COM /*
1397348SJose.Borrego@Sun.COM  * share publishing
1407348SJose.Borrego@Sun.COM  */
1417348SJose.Borrego@Sun.COM #define	SMB_SHR_PUBLISH		0
1427348SJose.Borrego@Sun.COM #define	SMB_SHR_UNPUBLISH	1
1437348SJose.Borrego@Sun.COM 
1447348SJose.Borrego@Sun.COM typedef struct smb_shr_pitem {
1457348SJose.Borrego@Sun.COM 	list_node_t	spi_lnd;
1467348SJose.Borrego@Sun.COM 	char		spi_name[MAXNAMELEN];
1477348SJose.Borrego@Sun.COM 	char		spi_container[MAXPATHLEN];
1487348SJose.Borrego@Sun.COM 	char		spi_op;
1497348SJose.Borrego@Sun.COM } smb_shr_pitem_t;
1507348SJose.Borrego@Sun.COM 
1517348SJose.Borrego@Sun.COM /*
1527348SJose.Borrego@Sun.COM  * publish queue states
1537348SJose.Borrego@Sun.COM  */
1547348SJose.Borrego@Sun.COM #define	SMB_SHR_PQS_NOQUEUE	0
1557348SJose.Borrego@Sun.COM #define	SMB_SHR_PQS_READY	1	/* the queue is ready */
1567348SJose.Borrego@Sun.COM #define	SMB_SHR_PQS_PUBLISHING	2	/* publisher thread is running */
1577348SJose.Borrego@Sun.COM #define	SMB_SHR_PQS_STOPPING	3
1587348SJose.Borrego@Sun.COM 
1597348SJose.Borrego@Sun.COM /*
1607348SJose.Borrego@Sun.COM  * share publishing queue
1617348SJose.Borrego@Sun.COM  */
1627348SJose.Borrego@Sun.COM typedef struct smb_shr_pqueue {
1637348SJose.Borrego@Sun.COM 	list_t		spq_list;
1647348SJose.Borrego@Sun.COM 	mutex_t		spq_mtx;
1657348SJose.Borrego@Sun.COM 	cond_t		spq_cv;
1667348SJose.Borrego@Sun.COM 	uint32_t	spq_state;
1677348SJose.Borrego@Sun.COM } smb_shr_pqueue_t;
1687348SJose.Borrego@Sun.COM 
1697348SJose.Borrego@Sun.COM static smb_shr_pqueue_t ad_queue;
1707348SJose.Borrego@Sun.COM 
1717348SJose.Borrego@Sun.COM static int smb_shr_publisher_start(void);
1727348SJose.Borrego@Sun.COM static void smb_shr_publisher_stop(void);
1737348SJose.Borrego@Sun.COM static void smb_shr_publisher_send(smb_ads_handle_t *, list_t *, const char *);
1747961SNatalie.Li@Sun.COM static void smb_shr_publisher_queue(const char *, const char *, char);
1757348SJose.Borrego@Sun.COM static void *smb_shr_publisher(void *);
1767961SNatalie.Li@Sun.COM static void smb_shr_publisher_flush(list_t *);
1777961SNatalie.Li@Sun.COM static void smb_shr_publish(const char *, const char *);
1787961SNatalie.Li@Sun.COM static void smb_shr_unpublish(const char *, const char *);
1797348SJose.Borrego@Sun.COM 
1807348SJose.Borrego@Sun.COM /*
1817961SNatalie.Li@Sun.COM  * Utility/helper functions
1827961SNatalie.Li@Sun.COM  */
1838334SJose.Borrego@Sun.COM static uint32_t smb_shr_lookup(char *, smb_share_t *);
1847961SNatalie.Li@Sun.COM static uint32_t smb_shr_addipc(void);
1857961SNatalie.Li@Sun.COM static void smb_shr_set_oemname(smb_share_t *);
1869832Samw@Sun.COM static int smb_shr_enable_all_privs(void);
1879832Samw@Sun.COM static int smb_shr_expand_subs(char **, smb_share_t *, smb_execsub_info_t *);
1889832Samw@Sun.COM static char **smb_shr_tokenize_cmd(char *);
1899832Samw@Sun.COM static void smb_shr_sig_abnormal_term(int);
1909832Samw@Sun.COM static void smb_shr_sig_child(int);
1919832Samw@Sun.COM static void smb_shr_get_exec_info(void);
1929832Samw@Sun.COM static void smb_shr_set_exec_flags(smb_share_t *);
1939832Samw@Sun.COM static void smb_shr_sa_guest_option(const char *, smb_share_t *);
1947961SNatalie.Li@Sun.COM 
1958474SJose.Borrego@Sun.COM 
1968474SJose.Borrego@Sun.COM /*
1978474SJose.Borrego@Sun.COM  * libshare handle and synchronization
1988474SJose.Borrego@Sun.COM  */
1998474SJose.Borrego@Sun.COM typedef struct smb_sa_handle {
2008474SJose.Borrego@Sun.COM 	sa_handle_t	sa_handle;
2018474SJose.Borrego@Sun.COM 	mutex_t		sa_mtx;
2028474SJose.Borrego@Sun.COM 	boolean_t	sa_in_service;
2038474SJose.Borrego@Sun.COM } smb_sa_handle_t;
2048474SJose.Borrego@Sun.COM 
2058474SJose.Borrego@Sun.COM static smb_sa_handle_t smb_sa_handle;
2068474SJose.Borrego@Sun.COM 
2079832Samw@Sun.COM static int smb_shr_exec_flags;
2089832Samw@Sun.COM static char smb_shr_exec_map[MAXPATHLEN];
2099832Samw@Sun.COM static char smb_shr_exec_unmap[MAXPATHLEN];
2109832Samw@Sun.COM static mutex_t smb_shr_exec_mtx;
2119832Samw@Sun.COM 
2127961SNatalie.Li@Sun.COM /*
2138334SJose.Borrego@Sun.COM  * Creates and initializes the cache and starts the publisher
2148334SJose.Borrego@Sun.COM  * thread.
2157052Samw  */
2167052Samw int
2177052Samw smb_shr_start(void)
2187052Samw {
2198474SJose.Borrego@Sun.COM 	(void) mutex_lock(&smb_sa_handle.sa_mtx);
2208474SJose.Borrego@Sun.COM 	smb_sa_handle.sa_in_service = B_TRUE;
2218474SJose.Borrego@Sun.COM 	(void) mutex_unlock(&smb_sa_handle.sa_mtx);
2228474SJose.Borrego@Sun.COM 
2237961SNatalie.Li@Sun.COM 	if (smb_shr_cache_create() != NERR_Success)
2247961SNatalie.Li@Sun.COM 		return (ENOMEM);
2257961SNatalie.Li@Sun.COM 
2267961SNatalie.Li@Sun.COM 	if (smb_shr_addipc() != NERR_Success)
2277961SNatalie.Li@Sun.COM 		return (ENOMEM);
2287961SNatalie.Li@Sun.COM 
2298334SJose.Borrego@Sun.COM 	return (smb_shr_publisher_start());
2308334SJose.Borrego@Sun.COM }
2318334SJose.Borrego@Sun.COM 
2328334SJose.Borrego@Sun.COM void
2338334SJose.Borrego@Sun.COM smb_shr_stop(void)
2348334SJose.Borrego@Sun.COM {
2358334SJose.Borrego@Sun.COM 	smb_shr_cache_destroy();
2368334SJose.Borrego@Sun.COM 	smb_shr_publisher_stop();
2378474SJose.Borrego@Sun.COM 
2388474SJose.Borrego@Sun.COM 	(void) mutex_lock(&smb_sa_handle.sa_mtx);
2398474SJose.Borrego@Sun.COM 	smb_sa_handle.sa_in_service = B_FALSE;
2408474SJose.Borrego@Sun.COM 
2418474SJose.Borrego@Sun.COM 	if (smb_sa_handle.sa_handle != NULL) {
2428474SJose.Borrego@Sun.COM 		sa_fini(smb_sa_handle.sa_handle);
2438474SJose.Borrego@Sun.COM 		smb_sa_handle.sa_handle = NULL;
2448474SJose.Borrego@Sun.COM 	}
2458474SJose.Borrego@Sun.COM 
2468474SJose.Borrego@Sun.COM 	(void) mutex_unlock(&smb_sa_handle.sa_mtx);
2478474SJose.Borrego@Sun.COM }
2488474SJose.Borrego@Sun.COM 
2498474SJose.Borrego@Sun.COM /*
2508474SJose.Borrego@Sun.COM  * Get a handle and exclusive access to the libshare API.
2518474SJose.Borrego@Sun.COM  */
2528474SJose.Borrego@Sun.COM sa_handle_t
2538474SJose.Borrego@Sun.COM smb_shr_sa_enter(void)
2548474SJose.Borrego@Sun.COM {
2558474SJose.Borrego@Sun.COM 	(void) mutex_lock(&smb_sa_handle.sa_mtx);
2568474SJose.Borrego@Sun.COM 	if (!smb_sa_handle.sa_in_service) {
2578474SJose.Borrego@Sun.COM 		(void) mutex_unlock(&smb_sa_handle.sa_mtx);
2588474SJose.Borrego@Sun.COM 		return (NULL);
2598474SJose.Borrego@Sun.COM 	}
2608474SJose.Borrego@Sun.COM 
2618474SJose.Borrego@Sun.COM 	if (smb_sa_handle.sa_handle == NULL) {
2628474SJose.Borrego@Sun.COM 		smb_sa_handle.sa_handle = sa_init(SA_INIT_SHARE_API);
2638474SJose.Borrego@Sun.COM 		if (smb_sa_handle.sa_handle == NULL) {
2648474SJose.Borrego@Sun.COM 			syslog(LOG_ERR, "share: failed to get libshare handle");
2658474SJose.Borrego@Sun.COM 			(void) mutex_unlock(&smb_sa_handle.sa_mtx);
2668474SJose.Borrego@Sun.COM 			return (NULL);
2678474SJose.Borrego@Sun.COM 		}
2688474SJose.Borrego@Sun.COM 	}
2698474SJose.Borrego@Sun.COM 
2708474SJose.Borrego@Sun.COM 	return (smb_sa_handle.sa_handle);
2718474SJose.Borrego@Sun.COM }
2728474SJose.Borrego@Sun.COM 
2738474SJose.Borrego@Sun.COM /*
2748474SJose.Borrego@Sun.COM  * Release exclusive access to the libshare API.
2758474SJose.Borrego@Sun.COM  */
2768474SJose.Borrego@Sun.COM void
2778474SJose.Borrego@Sun.COM smb_shr_sa_exit(void)
2788474SJose.Borrego@Sun.COM {
2798474SJose.Borrego@Sun.COM 	(void) mutex_unlock(&smb_sa_handle.sa_mtx);
2808334SJose.Borrego@Sun.COM }
2818334SJose.Borrego@Sun.COM 
2828334SJose.Borrego@Sun.COM /*
2838334SJose.Borrego@Sun.COM  * Launches a thread to populate the share cache by share information
2848334SJose.Borrego@Sun.COM  * stored in sharemgr
2858334SJose.Borrego@Sun.COM  */
2868334SJose.Borrego@Sun.COM int
2878334SJose.Borrego@Sun.COM smb_shr_load(void)
2888334SJose.Borrego@Sun.COM {
2898334SJose.Borrego@Sun.COM 	pthread_t load_thr;
2908334SJose.Borrego@Sun.COM 	pthread_attr_t tattr;
2918334SJose.Borrego@Sun.COM 	int rc;
2928334SJose.Borrego@Sun.COM 
2937348SJose.Borrego@Sun.COM 	(void) pthread_attr_init(&tattr);
2947348SJose.Borrego@Sun.COM 	(void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
2957961SNatalie.Li@Sun.COM 	rc = pthread_create(&load_thr, &tattr, smb_shr_sa_loadall, 0);
2967348SJose.Borrego@Sun.COM 	(void) pthread_attr_destroy(&tattr);
2977052Samw 
2989832Samw@Sun.COM 	smb_shr_get_exec_info();
2999832Samw@Sun.COM 
3007052Samw 	return (rc);
3017052Samw }
3027052Samw 
3037052Samw /*
3047348SJose.Borrego@Sun.COM  * Return the total number of shares
3057052Samw  */
3067052Samw int
3077052Samw smb_shr_count(void)
3087052Samw {
3097961SNatalie.Li@Sun.COM 	int n_shares = 0;
3107052Samw 
3117961SNatalie.Li@Sun.COM 	if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) {
3127961SNatalie.Li@Sun.COM 		n_shares = smb_shr_cache_count();
3137961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
3147961SNatalie.Li@Sun.COM 	}
3157052Samw 
3167052Samw 	return (n_shares);
3177052Samw }
3187052Samw 
3197052Samw /*
3207052Samw  * smb_shr_iterinit
3217052Samw  *
3227348SJose.Borrego@Sun.COM  * Initialize given iterator for traversing hash table.
3237052Samw  */
3247052Samw void
3257348SJose.Borrego@Sun.COM smb_shr_iterinit(smb_shriter_t *shi)
3267052Samw {
3277052Samw 	bzero(shi, sizeof (smb_shriter_t));
3287348SJose.Borrego@Sun.COM 	shi->si_first = B_TRUE;
3297052Samw }
3307052Samw 
3317052Samw /*
3327052Samw  * smb_shr_iterate
3337052Samw  *
3347052Samw  * Iterate on the shares in the hash table. The iterator must be initialized
3357052Samw  * before the first iteration. On subsequent calls, the iterator must be
3367052Samw  * passed unchanged.
3377052Samw  *
3387052Samw  * Returns NULL on failure or when all shares are visited, otherwise
3397052Samw  * returns information of visited share.
3407052Samw  */
3417052Samw smb_share_t *
3427052Samw smb_shr_iterate(smb_shriter_t *shi)
3437052Samw {
3447348SJose.Borrego@Sun.COM 	smb_share_t *share = NULL;
3457961SNatalie.Li@Sun.COM 	smb_share_t *cached_si;
3467052Samw 
3477961SNatalie.Li@Sun.COM 	if (shi == NULL)
3487052Samw 		return (NULL);
3497052Samw 
3507961SNatalie.Li@Sun.COM 	if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) {
3517961SNatalie.Li@Sun.COM 		if ((cached_si = smb_shr_cache_iterate(shi)) != NULL) {
3527961SNatalie.Li@Sun.COM 			share = &shi->si_share;
3537961SNatalie.Li@Sun.COM 			bcopy(cached_si, share, sizeof (smb_share_t));
3549832Samw@Sun.COM 			smb_shr_set_exec_flags(share);
3557961SNatalie.Li@Sun.COM 		}
3567961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
3577052Samw 	}
3587052Samw 
3597348SJose.Borrego@Sun.COM 	return (share);
3607052Samw }
3617052Samw 
3627052Samw /*
3637961SNatalie.Li@Sun.COM  * Adds the given share to cache, publishes the share in ADS
3647961SNatalie.Li@Sun.COM  * if it has an AD container, calls kernel to take a hold on
3657961SNatalie.Li@Sun.COM  * the shared file system. If it can't take a hold on the
3667961SNatalie.Li@Sun.COM  * shared file system, it's either because shared directory
3677961SNatalie.Li@Sun.COM  * does not exist or some other error has occurred, in any
3687961SNatalie.Li@Sun.COM  * case the share is removed from the cache.
3697052Samw  *
3707961SNatalie.Li@Sun.COM  * If the specified share is an autohome share which already
3717961SNatalie.Li@Sun.COM  * exists in the cache, just increments the reference count.
3727052Samw  */
3737052Samw uint32_t
3747961SNatalie.Li@Sun.COM smb_shr_add(smb_share_t *si)
3757052Samw {
3767961SNatalie.Li@Sun.COM 	smb_share_t *cached_si;
3777961SNatalie.Li@Sun.COM 	uint32_t status;
3787348SJose.Borrego@Sun.COM 	int rc;
3797052Samw 
3807348SJose.Borrego@Sun.COM 	assert(si != NULL);
3817052Samw 
3827348SJose.Borrego@Sun.COM 	if (!smb_shr_chkname(si->shr_name))
3837348SJose.Borrego@Sun.COM 		return (ERROR_INVALID_NAME);
3847052Samw 
3857961SNatalie.Li@Sun.COM 	if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success)
3867961SNatalie.Li@Sun.COM 		return (NERR_InternalError);
3877052Samw 
3887961SNatalie.Li@Sun.COM 	cached_si = smb_shr_cache_findent(si->shr_name);
3897961SNatalie.Li@Sun.COM 	if (cached_si) {
3907961SNatalie.Li@Sun.COM 		if (si->shr_flags & SMB_SHRF_AUTOHOME) {
3917961SNatalie.Li@Sun.COM 			cached_si->shr_refcnt++;
3927961SNatalie.Li@Sun.COM 			status = NERR_Success;
3937961SNatalie.Li@Sun.COM 		} else {
3947961SNatalie.Li@Sun.COM 			status = NERR_DuplicateShare;
3957961SNatalie.Li@Sun.COM 		}
3967961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
3977052Samw 		return (status);
3987052Samw 	}
3997052Samw 
4007961SNatalie.Li@Sun.COM 	if ((status = smb_shr_cache_addent(si)) != NERR_Success) {
4017961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
4027961SNatalie.Li@Sun.COM 		return (status);
4037961SNatalie.Li@Sun.COM 	}
4047961SNatalie.Li@Sun.COM 
4057961SNatalie.Li@Sun.COM 	/* don't hold the lock across door call */
4067961SNatalie.Li@Sun.COM 	smb_shr_cache_unlock();
4077961SNatalie.Li@Sun.COM 
4087961SNatalie.Li@Sun.COM 	/* call kernel to take a hold on the shared file system */
409*10122SJordan.Brown@Sun.COM 	rc = smb_kmod_share(si->shr_path, si->shr_name);
4107348SJose.Borrego@Sun.COM 
4117348SJose.Borrego@Sun.COM 	if (rc == 0) {
4127961SNatalie.Li@Sun.COM 		smb_shr_publish(si->shr_name, si->shr_container);
4138845Samw@Sun.COM 
4148845Samw@Sun.COM 		/* If path is ZFS, add the .zfs/shares/<share> entry. */
4158845Samw@Sun.COM 		smb_shr_zfs_add(si);
4168845Samw@Sun.COM 
4177961SNatalie.Li@Sun.COM 		return (NERR_Success);
4187052Samw 	}
4197052Samw 
4207961SNatalie.Li@Sun.COM 	if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) == NERR_Success) {
4217961SNatalie.Li@Sun.COM 		smb_shr_cache_delent(si->shr_name);
4227961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
4237961SNatalie.Li@Sun.COM 	}
4247052Samw 
4257052Samw 	/*
4267348SJose.Borrego@Sun.COM 	 * rc == ENOENT means the shared directory doesn't exist
4277052Samw 	 */
4287348SJose.Borrego@Sun.COM 	return ((rc == ENOENT) ? NERR_UnknownDevDir : NERR_InternalError);
4297052Samw }
4307052Samw 
4317052Samw /*
4327961SNatalie.Li@Sun.COM  * Removes the specified share from cache, removes it from AD
4337961SNatalie.Li@Sun.COM  * if it has an AD container, and calls the kernel to release
4347961SNatalie.Li@Sun.COM  * the hold on the shared file system.
4357052Samw  *
4367961SNatalie.Li@Sun.COM  * If this is an autohome share then decrement the reference
4377961SNatalie.Li@Sun.COM  * count. If it reaches 0 then it proceeds with removing steps.
4387052Samw  */
4397348SJose.Borrego@Sun.COM uint32_t
4407961SNatalie.Li@Sun.COM smb_shr_remove(char *sharename)
4417052Samw {
4427961SNatalie.Li@Sun.COM 	smb_share_t *si;
4437961SNatalie.Li@Sun.COM 	char path[MAXPATHLEN];
4447961SNatalie.Li@Sun.COM 	char container[MAXPATHLEN];
4457348SJose.Borrego@Sun.COM 
4467348SJose.Borrego@Sun.COM 	assert(sharename != NULL);
4477348SJose.Borrego@Sun.COM 
4487961SNatalie.Li@Sun.COM 	if (!smb_shr_chkname(sharename))
4497961SNatalie.Li@Sun.COM 		return (ERROR_INVALID_NAME);
4507052Samw 
4517961SNatalie.Li@Sun.COM 	if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success)
4527961SNatalie.Li@Sun.COM 		return (NERR_InternalError);
4537961SNatalie.Li@Sun.COM 
4547961SNatalie.Li@Sun.COM 	if ((si = smb_shr_cache_findent(sharename)) == NULL) {
4557961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
4567961SNatalie.Li@Sun.COM 		return (NERR_NetNameNotFound);
4577961SNatalie.Li@Sun.COM 	}
4587348SJose.Borrego@Sun.COM 
4597961SNatalie.Li@Sun.COM 	if (si->shr_type & STYPE_IPC) {
4607961SNatalie.Li@Sun.COM 		/* IPC$ share cannot be removed */
4617961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
4627961SNatalie.Li@Sun.COM 		return (ERROR_ACCESS_DENIED);
4637961SNatalie.Li@Sun.COM 	}
4647961SNatalie.Li@Sun.COM 
4657961SNatalie.Li@Sun.COM 	if (si->shr_flags & SMB_SHRF_AUTOHOME) {
4667961SNatalie.Li@Sun.COM 		if ((--si->shr_refcnt) > 0) {
4677961SNatalie.Li@Sun.COM 			smb_shr_cache_unlock();
4687961SNatalie.Li@Sun.COM 			return (NERR_Success);
4697348SJose.Borrego@Sun.COM 		}
4707052Samw 	}
4717052Samw 
4728845Samw@Sun.COM 	/*
4738845Samw@Sun.COM 	 * If path is ZFS, remove the .zfs/shares/<share> entry.  Need
4748845Samw@Sun.COM 	 * to remove before cleanup of cache occurs.
4758845Samw@Sun.COM 	 */
4768845Samw@Sun.COM 	smb_shr_zfs_remove(si);
4778845Samw@Sun.COM 
4787961SNatalie.Li@Sun.COM 	(void) strlcpy(path, si->shr_path, sizeof (path));
4797961SNatalie.Li@Sun.COM 	(void) strlcpy(container, si->shr_container, sizeof (container));
4807961SNatalie.Li@Sun.COM 	smb_shr_cache_delent(sharename);
4817961SNatalie.Li@Sun.COM 	smb_shr_cache_unlock();
4827348SJose.Borrego@Sun.COM 
4837961SNatalie.Li@Sun.COM 	smb_shr_unpublish(sharename, container);
4847961SNatalie.Li@Sun.COM 
4857961SNatalie.Li@Sun.COM 	/* call kernel to release the hold on the shared file system */
486*10122SJordan.Brown@Sun.COM 	(void) smb_kmod_unshare(path, sharename);
4877348SJose.Borrego@Sun.COM 
4887052Samw 	return (NERR_Success);
4897052Samw }
4907052Samw 
4917052Samw /*
4927052Samw  * Rename a share. Check that the current name exists and the new name
4937052Samw  * doesn't exist. The rename is performed by deleting the current share
4947052Samw  * definition and creating a new share with the new name.
4957052Samw  */
4967052Samw uint32_t
4977348SJose.Borrego@Sun.COM smb_shr_rename(char *from_name, char *to_name)
4987052Samw {
4997961SNatalie.Li@Sun.COM 	smb_share_t *from_si;
5007961SNatalie.Li@Sun.COM 	smb_share_t to_si;
5017348SJose.Borrego@Sun.COM 	uint32_t status;
5027348SJose.Borrego@Sun.COM 
5037348SJose.Borrego@Sun.COM 	assert((from_name != NULL) && (to_name != NULL));
5047052Samw 
5057348SJose.Borrego@Sun.COM 	if (!smb_shr_chkname(from_name) || !smb_shr_chkname(to_name))
5067348SJose.Borrego@Sun.COM 		return (ERROR_INVALID_NAME);
5077052Samw 
5087961SNatalie.Li@Sun.COM 	if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success)
5097961SNatalie.Li@Sun.COM 		return (NERR_InternalError);
5107961SNatalie.Li@Sun.COM 
5117961SNatalie.Li@Sun.COM 	if ((from_si = smb_shr_cache_findent(from_name)) == NULL) {
5127961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
5137052Samw 		return (NERR_NetNameNotFound);
5147961SNatalie.Li@Sun.COM 	}
5157052Samw 
5167961SNatalie.Li@Sun.COM 	if (from_si->shr_type & STYPE_IPC) {
5177961SNatalie.Li@Sun.COM 		/* IPC$ share cannot be renamed */
5187961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
5197961SNatalie.Li@Sun.COM 		return (ERROR_ACCESS_DENIED);
5207961SNatalie.Li@Sun.COM 	}
5217961SNatalie.Li@Sun.COM 
5227961SNatalie.Li@Sun.COM 	if (smb_shr_cache_findent(to_name) != NULL) {
5237961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
5247052Samw 		return (NERR_DuplicateShare);
5257961SNatalie.Li@Sun.COM 	}
5267052Samw 
5277961SNatalie.Li@Sun.COM 	bcopy(from_si, &to_si, sizeof (smb_share_t));
5287961SNatalie.Li@Sun.COM 	(void) strlcpy(to_si.shr_name, to_name, sizeof (to_si.shr_name));
5297961SNatalie.Li@Sun.COM 
5308845Samw@Sun.COM 	/* If path is ZFS, rename the .zfs/shares/<share> entry. */
5318845Samw@Sun.COM 	smb_shr_zfs_rename(from_si, &to_si);
5328845Samw@Sun.COM 
5337961SNatalie.Li@Sun.COM 	if ((status = smb_shr_cache_addent(&to_si)) != NERR_Success) {
5347961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
5357348SJose.Borrego@Sun.COM 		return (status);
5367961SNatalie.Li@Sun.COM 	}
5377348SJose.Borrego@Sun.COM 
5387348SJose.Borrego@Sun.COM 	smb_shr_cache_delent(from_name);
5397961SNatalie.Li@Sun.COM 	smb_shr_cache_unlock();
5407961SNatalie.Li@Sun.COM 
5417961SNatalie.Li@Sun.COM 	smb_shr_unpublish(from_name, to_si.shr_container);
5427961SNatalie.Li@Sun.COM 	smb_shr_publish(to_name, to_si.shr_container);
5437348SJose.Borrego@Sun.COM 
5447348SJose.Borrego@Sun.COM 	return (NERR_Success);
5457348SJose.Borrego@Sun.COM }
5467348SJose.Borrego@Sun.COM 
5477348SJose.Borrego@Sun.COM /*
5487348SJose.Borrego@Sun.COM  * Load the information for the specified share into the supplied share
5497348SJose.Borrego@Sun.COM  * info structure.
5508334SJose.Borrego@Sun.COM  *
5518334SJose.Borrego@Sun.COM  * First looks up the cache to see if the specified share exists, if there
5528334SJose.Borrego@Sun.COM  * is a miss then it looks up sharemgr.
5537348SJose.Borrego@Sun.COM  */
5547348SJose.Borrego@Sun.COM uint32_t
5557348SJose.Borrego@Sun.COM smb_shr_get(char *sharename, smb_share_t *si)
5567348SJose.Borrego@Sun.COM {
5578334SJose.Borrego@Sun.COM 	uint32_t status;
5587348SJose.Borrego@Sun.COM 
5597961SNatalie.Li@Sun.COM 	if (sharename == NULL || *sharename == '\0')
5607961SNatalie.Li@Sun.COM 		return (NERR_NetNameNotFound);
5617348SJose.Borrego@Sun.COM 
5628334SJose.Borrego@Sun.COM 	if ((status = smb_shr_lookup(sharename, si)) == NERR_Success)
5638334SJose.Borrego@Sun.COM 		return (status);
5647961SNatalie.Li@Sun.COM 
5658334SJose.Borrego@Sun.COM 	if ((status = smb_shr_sa_loadbyname(sharename)) == NERR_Success)
5668334SJose.Borrego@Sun.COM 		status = smb_shr_lookup(sharename, si);
5677348SJose.Borrego@Sun.COM 
5687961SNatalie.Li@Sun.COM 	return (status);
5697348SJose.Borrego@Sun.COM }
5707348SJose.Borrego@Sun.COM 
5717348SJose.Borrego@Sun.COM /*
5727348SJose.Borrego@Sun.COM  * Modifies an existing share. Properties that can be modified are:
5737348SJose.Borrego@Sun.COM  *
5747348SJose.Borrego@Sun.COM  *   o comment
5757348SJose.Borrego@Sun.COM  *   o AD container
5767961SNatalie.Li@Sun.COM  *   o host access
5777348SJose.Borrego@Sun.COM  */
5787348SJose.Borrego@Sun.COM uint32_t
5797961SNatalie.Li@Sun.COM smb_shr_modify(smb_share_t *new_si)
5807348SJose.Borrego@Sun.COM {
5817961SNatalie.Li@Sun.COM 	smb_share_t *si;
5827348SJose.Borrego@Sun.COM 	boolean_t adc_changed = B_FALSE;
5837961SNatalie.Li@Sun.COM 	char old_container[MAXPATHLEN];
5849231SAfshin.Ardakani@Sun.COM 	uint32_t catia;
5859832Samw@Sun.COM 	uint32_t cscflg;
5867961SNatalie.Li@Sun.COM 	uint32_t access;
5877348SJose.Borrego@Sun.COM 
5887961SNatalie.Li@Sun.COM 	assert(new_si != NULL);
5897348SJose.Borrego@Sun.COM 
5907961SNatalie.Li@Sun.COM 	if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success)
5917961SNatalie.Li@Sun.COM 		return (NERR_InternalError);
5927348SJose.Borrego@Sun.COM 
5937961SNatalie.Li@Sun.COM 	if ((si = smb_shr_cache_findent(new_si->shr_name)) == NULL) {
5947961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
5957961SNatalie.Li@Sun.COM 		return (NERR_NetNameNotFound);
5967961SNatalie.Li@Sun.COM 	}
5977348SJose.Borrego@Sun.COM 
5987961SNatalie.Li@Sun.COM 	if (si->shr_type & STYPE_IPC) {
5997961SNatalie.Li@Sun.COM 		/* IPC$ share cannot be modified */
6007961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
6017961SNatalie.Li@Sun.COM 		return (ERROR_ACCESS_DENIED);
6027348SJose.Borrego@Sun.COM 	}
6037348SJose.Borrego@Sun.COM 
6048474SJose.Borrego@Sun.COM 	(void) strlcpy(si->shr_cmnt, new_si->shr_cmnt, sizeof (si->shr_cmnt));
6057961SNatalie.Li@Sun.COM 
6067961SNatalie.Li@Sun.COM 	adc_changed = (strcmp(new_si->shr_container, si->shr_container) != 0);
6077961SNatalie.Li@Sun.COM 	if (adc_changed) {
6087961SNatalie.Li@Sun.COM 		/* save current container - needed for unpublishing */
6097961SNatalie.Li@Sun.COM 		(void) strlcpy(old_container, si->shr_container,
6107961SNatalie.Li@Sun.COM 		    sizeof (old_container));
6117961SNatalie.Li@Sun.COM 		(void) strlcpy(si->shr_container, new_si->shr_container,
6127961SNatalie.Li@Sun.COM 		    sizeof (si->shr_container));
6137348SJose.Borrego@Sun.COM 	}
6147348SJose.Borrego@Sun.COM 
6159231SAfshin.Ardakani@Sun.COM 	catia = (new_si->shr_flags & SMB_SHRF_CATIA);
6169231SAfshin.Ardakani@Sun.COM 	si->shr_flags &= ~SMB_SHRF_CATIA;
6179231SAfshin.Ardakani@Sun.COM 	si->shr_flags |= catia;
6189231SAfshin.Ardakani@Sun.COM 
6199832Samw@Sun.COM 	cscflg = (new_si->shr_flags & SMB_SHRF_CSC_MASK);
6208334SJose.Borrego@Sun.COM 	si->shr_flags &= ~SMB_SHRF_CSC_MASK;
6219832Samw@Sun.COM 	si->shr_flags |= cscflg;
6229832Samw@Sun.COM 
6239832Samw@Sun.COM 	if (new_si->shr_flags & SMB_SHRF_GUEST_OK)
6249832Samw@Sun.COM 		si->shr_flags |= SMB_SHRF_GUEST_OK;
6259832Samw@Sun.COM 	else
6269832Samw@Sun.COM 		si->shr_flags &= ~SMB_SHRF_GUEST_OK;
6278334SJose.Borrego@Sun.COM 
6287961SNatalie.Li@Sun.COM 	access = (new_si->shr_flags & SMB_SHRF_ACC_ALL);
6298474SJose.Borrego@Sun.COM 	si->shr_flags &= ~SMB_SHRF_ACC_ALL;
6307961SNatalie.Li@Sun.COM 	si->shr_flags |= access;
6317961SNatalie.Li@Sun.COM 
6327961SNatalie.Li@Sun.COM 	if (access & SMB_SHRF_ACC_NONE)
6337961SNatalie.Li@Sun.COM 		(void) strlcpy(si->shr_access_none, new_si->shr_access_none,
6347961SNatalie.Li@Sun.COM 		    sizeof (si->shr_access_none));
6357348SJose.Borrego@Sun.COM 
6367961SNatalie.Li@Sun.COM 	if (access & SMB_SHRF_ACC_RO)
6377961SNatalie.Li@Sun.COM 		(void) strlcpy(si->shr_access_ro, new_si->shr_access_ro,
6387961SNatalie.Li@Sun.COM 		    sizeof (si->shr_access_ro));
6397348SJose.Borrego@Sun.COM 
6407961SNatalie.Li@Sun.COM 	if (access & SMB_SHRF_ACC_RW)
6417961SNatalie.Li@Sun.COM 		(void) strlcpy(si->shr_access_rw, new_si->shr_access_rw,
6427961SNatalie.Li@Sun.COM 		    sizeof (si->shr_access_rw));
6437961SNatalie.Li@Sun.COM 
6447961SNatalie.Li@Sun.COM 	smb_shr_cache_unlock();
6457052Samw 
6467348SJose.Borrego@Sun.COM 	if (adc_changed) {
6477961SNatalie.Li@Sun.COM 		smb_shr_unpublish(new_si->shr_name, old_container);
6487961SNatalie.Li@Sun.COM 		smb_shr_publish(new_si->shr_name, new_si->shr_container);
6497348SJose.Borrego@Sun.COM 	}
6507348SJose.Borrego@Sun.COM 
6517348SJose.Borrego@Sun.COM 	return (NERR_Success);
6527052Samw }
6537052Samw 
6547052Samw /*
6557052Samw  * smb_shr_exists
6567052Samw  *
6577348SJose.Borrego@Sun.COM  * Returns B_TRUE if the share exists. Otherwise returns B_FALSE
6587052Samw  */
6597348SJose.Borrego@Sun.COM boolean_t
6607348SJose.Borrego@Sun.COM smb_shr_exists(char *sharename)
6617052Samw {
6627961SNatalie.Li@Sun.COM 	boolean_t exists = B_FALSE;
6637348SJose.Borrego@Sun.COM 
6647348SJose.Borrego@Sun.COM 	if (sharename == NULL || *sharename == '\0')
6657348SJose.Borrego@Sun.COM 		return (B_FALSE);
6667052Samw 
6677961SNatalie.Li@Sun.COM 	if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) {
6687961SNatalie.Li@Sun.COM 		exists = (smb_shr_cache_findent(sharename) != NULL);
6697961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
6707961SNatalie.Li@Sun.COM 	}
6717348SJose.Borrego@Sun.COM 
6727348SJose.Borrego@Sun.COM 	return (exists);
6737052Samw }
6747052Samw 
6757052Samw /*
6767961SNatalie.Li@Sun.COM  * If the shared directory does not begin with a /, one will be
6777961SNatalie.Li@Sun.COM  * inserted as a prefix. If ipaddr is not zero, then also return
6787961SNatalie.Li@Sun.COM  * information about access based on the host level access lists, if
6797961SNatalie.Li@Sun.COM  * present. Also return access check if there is an IP address and
6807961SNatalie.Li@Sun.COM  * shr_accflags.
6817961SNatalie.Li@Sun.COM  *
6827961SNatalie.Li@Sun.COM  * The value of smb_chk_hostaccess is checked for an access match.
6837961SNatalie.Li@Sun.COM  * -1 is wildcard match
6847961SNatalie.Li@Sun.COM  * 0 is no match
6857961SNatalie.Li@Sun.COM  * 1 is match
6867961SNatalie.Li@Sun.COM  *
6877961SNatalie.Li@Sun.COM  * Precedence is none is checked first followed by ro then rw if
6887961SNatalie.Li@Sun.COM  * needed.  If x is wildcard (< 0) then check to see if the other
6897961SNatalie.Li@Sun.COM  * values are a match. If a match, that wins.
6908670SJose.Borrego@Sun.COM  *
6918670SJose.Borrego@Sun.COM  * ipv6 is wide open for now, see smb_chk_hostaccess
6927961SNatalie.Li@Sun.COM  */
6937961SNatalie.Li@Sun.COM void
6948670SJose.Borrego@Sun.COM smb_shr_hostaccess(smb_share_t *si, smb_inaddr_t *ipaddr)
6957961SNatalie.Li@Sun.COM {
6967961SNatalie.Li@Sun.COM 	int acc = SMB_SHRF_ACC_OPEN;
6977961SNatalie.Li@Sun.COM 
6987961SNatalie.Li@Sun.COM 	/*
6997961SNatalie.Li@Sun.COM 	 * Check to see if there area any share level access
7007961SNatalie.Li@Sun.COM 	 * restrictions.
7017961SNatalie.Li@Sun.COM 	 */
7028670SJose.Borrego@Sun.COM 	if ((!smb_inet_iszero(ipaddr)) &&
7038670SJose.Borrego@Sun.COM 	    (si->shr_flags & SMB_SHRF_ACC_ALL) != 0) {
7047961SNatalie.Li@Sun.COM 		int none = SMB_SHRF_ACC_OPEN;
7057961SNatalie.Li@Sun.COM 		int rw = SMB_SHRF_ACC_OPEN;
7067961SNatalie.Li@Sun.COM 		int ro = SMB_SHRF_ACC_OPEN;
7077961SNatalie.Li@Sun.COM 
7087961SNatalie.Li@Sun.COM 		if (si->shr_flags & SMB_SHRF_ACC_NONE)
7097961SNatalie.Li@Sun.COM 			none = smb_chk_hostaccess(ipaddr, si->shr_access_none);
7107961SNatalie.Li@Sun.COM 		if (si->shr_flags & SMB_SHRF_ACC_RW)
7117961SNatalie.Li@Sun.COM 			rw = smb_chk_hostaccess(ipaddr, si->shr_access_rw);
7127961SNatalie.Li@Sun.COM 		if (si->shr_flags & SMB_SHRF_ACC_RO)
7137961SNatalie.Li@Sun.COM 			ro = smb_chk_hostaccess(ipaddr, si->shr_access_ro);
7147961SNatalie.Li@Sun.COM 		/* make first pass to get basic value */
7157961SNatalie.Li@Sun.COM 		if (none != 0)
7167961SNatalie.Li@Sun.COM 			acc = SMB_SHRF_ACC_NONE;
7177961SNatalie.Li@Sun.COM 		else if (ro != 0)
7187961SNatalie.Li@Sun.COM 			acc = SMB_SHRF_ACC_RO;
7197961SNatalie.Li@Sun.COM 		else if (rw != 0)
7207961SNatalie.Li@Sun.COM 			acc = SMB_SHRF_ACC_RW;
7217961SNatalie.Li@Sun.COM 
7227961SNatalie.Li@Sun.COM 		/* make second pass to handle '*' case */
7237961SNatalie.Li@Sun.COM 		if (none < 0) {
7247961SNatalie.Li@Sun.COM 			acc = SMB_SHRF_ACC_NONE;
7257961SNatalie.Li@Sun.COM 			if (ro > 0)
7267961SNatalie.Li@Sun.COM 				acc = SMB_SHRF_ACC_RO;
7277961SNatalie.Li@Sun.COM 			else if (rw > 0)
7287961SNatalie.Li@Sun.COM 				acc = SMB_SHRF_ACC_RW;
7297961SNatalie.Li@Sun.COM 		} else if (ro < 0) {
7307961SNatalie.Li@Sun.COM 			acc = SMB_SHRF_ACC_RO;
7317961SNatalie.Li@Sun.COM 			if (none > 0)
7327961SNatalie.Li@Sun.COM 				acc = SMB_SHRF_ACC_NONE;
7337961SNatalie.Li@Sun.COM 			else if (rw > 0)
7347961SNatalie.Li@Sun.COM 				acc = SMB_SHRF_ACC_RW;
7357961SNatalie.Li@Sun.COM 		} else if (rw < 0) {
7367961SNatalie.Li@Sun.COM 			acc = SMB_SHRF_ACC_RW;
7377961SNatalie.Li@Sun.COM 			if (none > 0)
7387961SNatalie.Li@Sun.COM 				acc = SMB_SHRF_ACC_NONE;
7397961SNatalie.Li@Sun.COM 			else if (ro > 0)
7407961SNatalie.Li@Sun.COM 				acc = SMB_SHRF_ACC_RO;
7417961SNatalie.Li@Sun.COM 		}
7427961SNatalie.Li@Sun.COM 	}
7437961SNatalie.Li@Sun.COM 	si->shr_access_value = acc;	/* return access here */
7447961SNatalie.Li@Sun.COM }
7457961SNatalie.Li@Sun.COM 
7467961SNatalie.Li@Sun.COM /*
7477052Samw  * smb_shr_is_special
7487052Samw  *
7497348SJose.Borrego@Sun.COM  * Special share reserved for interprocess communication (IPC$) or
7507348SJose.Borrego@Sun.COM  * remote administration of the server (ADMIN$). Can also refer to
7517348SJose.Borrego@Sun.COM  * administrative shares such as C$, D$, E$, and so forth.
7527052Samw  */
7537052Samw int
7547348SJose.Borrego@Sun.COM smb_shr_is_special(char *sharename)
7557052Samw {
7567052Samw 	int len;
7577052Samw 
7587348SJose.Borrego@Sun.COM 	if (sharename == NULL)
7597052Samw 		return (0);
7607052Samw 
7617348SJose.Borrego@Sun.COM 	if ((len = strlen(sharename)) == 0)
7627052Samw 		return (0);
7637052Samw 
7647348SJose.Borrego@Sun.COM 	if (sharename[len - 1] == '$')
7657052Samw 		return (STYPE_SPECIAL);
7667348SJose.Borrego@Sun.COM 
7677348SJose.Borrego@Sun.COM 	return (0);
7687052Samw }
7697052Samw 
7707052Samw /*
7717052Samw  * smb_shr_is_restricted
7727052Samw  *
7737052Samw  * Check whether or not there is a restriction on a share. Restricted
7747052Samw  * shares are generally STYPE_SPECIAL, for example, IPC$. All the
7757348SJose.Borrego@Sun.COM  * administration share names are restricted: C$, D$ etc. Returns B_TRUE
7767348SJose.Borrego@Sun.COM  * if the share is restricted. Otherwise B_FALSE is returned to indicate
7777052Samw  * that there are no restrictions.
7787052Samw  */
7797348SJose.Borrego@Sun.COM boolean_t
7807348SJose.Borrego@Sun.COM smb_shr_is_restricted(char *sharename)
7817052Samw {
7827052Samw 	static char *restricted[] = {
7837052Samw 		"IPC$"
7847052Samw 	};
7857052Samw 
7867052Samw 	int i;
7877052Samw 
7887348SJose.Borrego@Sun.COM 	if (sharename == NULL)
7897348SJose.Borrego@Sun.COM 		return (B_FALSE);
7907348SJose.Borrego@Sun.COM 
7917052Samw 	for (i = 0; i < sizeof (restricted)/sizeof (restricted[0]); i++) {
7927348SJose.Borrego@Sun.COM 		if (utf8_strcasecmp(restricted[i], sharename) == 0)
7937348SJose.Borrego@Sun.COM 			return (B_TRUE);
7947052Samw 	}
7957052Samw 
7967348SJose.Borrego@Sun.COM 	return (smb_shr_is_admin(sharename));
7977052Samw }
7987052Samw 
7997052Samw /*
8007052Samw  * smb_shr_is_admin
8017052Samw  *
8027052Samw  * Check whether or not access to the share should be restricted to
8037052Samw  * administrators. This is a bit of a hack because what we're doing
8047052Samw  * is checking for the default admin shares: C$, D$ etc.. There are
8057052Samw  * other shares that have restrictions: see smb_shr_is_restricted().
8067052Samw  *
8077348SJose.Borrego@Sun.COM  * Returns B_TRUE if the shares is an admin share. Otherwise B_FALSE
8087348SJose.Borrego@Sun.COM  * is returned to indicate that there are no restrictions.
8097052Samw  */
8107348SJose.Borrego@Sun.COM boolean_t
8117348SJose.Borrego@Sun.COM smb_shr_is_admin(char *sharename)
8127052Samw {
8137348SJose.Borrego@Sun.COM 	if (sharename == NULL)
8147348SJose.Borrego@Sun.COM 		return (B_FALSE);
8157052Samw 
8167348SJose.Borrego@Sun.COM 	if (strlen(sharename) == 2 &&
8177348SJose.Borrego@Sun.COM 	    mts_isalpha(sharename[0]) && sharename[1] == '$') {
8187348SJose.Borrego@Sun.COM 		return (B_TRUE);
8197052Samw 	}
8207052Samw 
8217348SJose.Borrego@Sun.COM 	return (B_FALSE);
8227052Samw }
8237052Samw 
8247052Samw /*
8257348SJose.Borrego@Sun.COM  * smb_shr_chkname
8267052Samw  *
8277961SNatalie.Li@Sun.COM  * Check for invalid characters in a share name.  The list of invalid
8287961SNatalie.Li@Sun.COM  * characters includes control characters and the following:
8297052Samw  *
8307052Samw  * " / \ [ ] : | < > + ; , ? * =
8317052Samw  */
8327348SJose.Borrego@Sun.COM boolean_t
8337348SJose.Borrego@Sun.COM smb_shr_chkname(char *sharename)
8347052Samw {
8357052Samw 	char *invalid = "\"/\\[]:|<>+;,?*=";
8367052Samw 	char *cp;
8377052Samw 
8387348SJose.Borrego@Sun.COM 	if (sharename == NULL)
8397348SJose.Borrego@Sun.COM 		return (B_FALSE);
8407052Samw 
8417348SJose.Borrego@Sun.COM 	if (strpbrk(sharename, invalid))
8427348SJose.Borrego@Sun.COM 		return (B_FALSE);
8437052Samw 
8447348SJose.Borrego@Sun.COM 	for (cp = sharename; *cp != '\0'; cp++) {
8457348SJose.Borrego@Sun.COM 		if (iscntrl(*cp))
8467348SJose.Borrego@Sun.COM 			return (B_FALSE);
8477052Samw 	}
8487052Samw 
8497348SJose.Borrego@Sun.COM 	return (B_TRUE);
8507052Samw }
8517052Samw 
8527052Samw /*
8537052Samw  * smb_shr_get_realpath
8547052Samw  *
8557961SNatalie.Li@Sun.COM  * Derive the real path for a share from the path provided by a client.
8567961SNatalie.Li@Sun.COM  * For instance, the real path of C:\ may be /cvol or the real path of
8577961SNatalie.Li@Sun.COM  * F:\home may be /vol1/home.
8587052Samw  *
8597961SNatalie.Li@Sun.COM  * clntpath - path provided by the Windows client is in the
8607052Samw  *            format of <drive letter>:\<dir>
8617052Samw  * realpath - path that will be stored as the directory field of
8627052Samw  *            the smb_share_t structure of the share.
8637961SNatalie.Li@Sun.COM  * maxlen   - maximum length of the realpath buffer
8647052Samw  *
8657052Samw  * Return LAN Manager network error code.
8667052Samw  */
8677052Samw uint32_t
8687961SNatalie.Li@Sun.COM smb_shr_get_realpath(const char *clntpath, char *realpath, int maxlen)
8697052Samw {
8707961SNatalie.Li@Sun.COM 	const char *p;
8717961SNatalie.Li@Sun.COM 	int len;
8727348SJose.Borrego@Sun.COM 
8737961SNatalie.Li@Sun.COM 	if ((p = strchr(clntpath, ':')) != NULL)
8747961SNatalie.Li@Sun.COM 		++p;
8757961SNatalie.Li@Sun.COM 	else
8767961SNatalie.Li@Sun.COM 		p = clntpath;
8777348SJose.Borrego@Sun.COM 
8787961SNatalie.Li@Sun.COM 	(void) strlcpy(realpath, p, maxlen);
8797961SNatalie.Li@Sun.COM 	(void) strcanon(realpath, "/\\");
8807961SNatalie.Li@Sun.COM 	(void) strsubst(realpath, '\\', '/');
8817348SJose.Borrego@Sun.COM 
8827961SNatalie.Li@Sun.COM 	len = strlen(realpath);
8837961SNatalie.Li@Sun.COM 	if ((len > 1) && (realpath[len - 1] == '/'))
8847961SNatalie.Li@Sun.COM 		realpath[len - 1] = '\0';
8857348SJose.Borrego@Sun.COM 
8867348SJose.Borrego@Sun.COM 	return (NERR_Success);
8877348SJose.Borrego@Sun.COM }
8887348SJose.Borrego@Sun.COM 
8897961SNatalie.Li@Sun.COM void
8907961SNatalie.Li@Sun.COM smb_shr_list(int offset, smb_shrlist_t *list)
8917348SJose.Borrego@Sun.COM {
8927961SNatalie.Li@Sun.COM 	smb_shriter_t iterator;
8937961SNatalie.Li@Sun.COM 	smb_share_t *si;
8947961SNatalie.Li@Sun.COM 	int n = 0;
8957961SNatalie.Li@Sun.COM 
8967961SNatalie.Li@Sun.COM 	bzero(list, sizeof (smb_shrlist_t));
8977961SNatalie.Li@Sun.COM 	smb_shr_iterinit(&iterator);
8987961SNatalie.Li@Sun.COM 
8997961SNatalie.Li@Sun.COM 	while ((si = smb_shr_iterate(&iterator)) != NULL) {
9007961SNatalie.Li@Sun.COM 		if (--offset > 0)
9017961SNatalie.Li@Sun.COM 			continue;
9027961SNatalie.Li@Sun.COM 
9037961SNatalie.Li@Sun.COM 		if ((si->shr_flags & SMB_SHRF_TRANS) &&
9047961SNatalie.Li@Sun.COM 		    ((si->shr_type & STYPE_IPC) == 0)) {
9057961SNatalie.Li@Sun.COM 			bcopy(si, &list->sl_shares[n], sizeof (smb_share_t));
9067961SNatalie.Li@Sun.COM 			if (++n == LMSHARES_PER_REQUEST)
9077961SNatalie.Li@Sun.COM 				break;
9087961SNatalie.Li@Sun.COM 		}
9097348SJose.Borrego@Sun.COM 	}
9107961SNatalie.Li@Sun.COM 
9117961SNatalie.Li@Sun.COM 	list->sl_cnt = n;
9127348SJose.Borrego@Sun.COM }
9137348SJose.Borrego@Sun.COM 
9147348SJose.Borrego@Sun.COM /*
9159832Samw@Sun.COM  * Executes the map/unmap command associated with a share.
9169832Samw@Sun.COM  *
9179832Samw@Sun.COM  * Returns 0 on success.  Otherwise non-zero for errors.
9189832Samw@Sun.COM  */
9199832Samw@Sun.COM int
9209832Samw@Sun.COM smb_shr_exec(char *share, smb_execsub_info_t *subs, int exec_type)
9219832Samw@Sun.COM {
9229832Samw@Sun.COM 	char cmd[MAXPATHLEN], **cmd_tokens, *path, *ptr;
9239832Samw@Sun.COM 	pid_t child_pid;
9249832Samw@Sun.COM 	int child_status;
9259832Samw@Sun.COM 	struct sigaction pact, cact;
9269832Samw@Sun.COM 	smb_share_t si;
9279832Samw@Sun.COM 
9289832Samw@Sun.COM 	if (smb_shr_get(share, &si) != 0)
9299832Samw@Sun.COM 		return (-1);
9309832Samw@Sun.COM 
9319832Samw@Sun.COM 	*cmd = '\0';
9329832Samw@Sun.COM 
9339832Samw@Sun.COM 	(void) mutex_lock(&smb_shr_exec_mtx);
9349832Samw@Sun.COM 
9359832Samw@Sun.COM 	switch (exec_type) {
9369832Samw@Sun.COM 	case SMB_SHR_MAP:
9379832Samw@Sun.COM 		(void) strlcpy(cmd, smb_shr_exec_map, sizeof (cmd));
9389832Samw@Sun.COM 		break;
9399832Samw@Sun.COM 	case SMB_SHR_UNMAP:
9409832Samw@Sun.COM 		(void) strlcpy(cmd, smb_shr_exec_unmap, sizeof (cmd));
9419832Samw@Sun.COM 		break;
9429832Samw@Sun.COM 	default:
9439832Samw@Sun.COM 		(void) mutex_unlock(&smb_shr_exec_mtx);
9449832Samw@Sun.COM 		return (-1);
9459832Samw@Sun.COM 	}
9469832Samw@Sun.COM 
9479832Samw@Sun.COM 	(void) mutex_unlock(&smb_shr_exec_mtx);
9489832Samw@Sun.COM 
9499832Samw@Sun.COM 	if (*cmd == '\0')
9509832Samw@Sun.COM 		return (0);
9519832Samw@Sun.COM 
9529832Samw@Sun.COM 	pact.sa_handler = smb_shr_sig_child;
9539832Samw@Sun.COM 	pact.sa_flags = 0;
9549832Samw@Sun.COM 	(void) sigemptyset(&pact.sa_mask);
9559832Samw@Sun.COM 	sigaction(SIGCHLD, &pact, NULL);
9569832Samw@Sun.COM 
9579832Samw@Sun.COM 	(void) priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_FORK, NULL);
9589832Samw@Sun.COM 
9599832Samw@Sun.COM 	if ((child_pid = fork()) == -1) {
9609832Samw@Sun.COM 		(void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_FORK, NULL);
9619832Samw@Sun.COM 		return (-1);
9629832Samw@Sun.COM 	}
9639832Samw@Sun.COM 
9649832Samw@Sun.COM 	if (child_pid == 0) {
9659832Samw@Sun.COM 
9669832Samw@Sun.COM 		/* child process */
9679832Samw@Sun.COM 
9689832Samw@Sun.COM 		cact.sa_handler = smb_shr_sig_abnormal_term;
9699832Samw@Sun.COM 		cact.sa_flags = 0;
9709832Samw@Sun.COM 		(void) sigemptyset(&cact.sa_mask);
9719832Samw@Sun.COM 		sigaction(SIGTERM, &cact, NULL);
9729832Samw@Sun.COM 		sigaction(SIGABRT, &cact, NULL);
9739832Samw@Sun.COM 		sigaction(SIGSEGV, &cact, NULL);
9749832Samw@Sun.COM 
9759832Samw@Sun.COM 		if (priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_EXEC,
9769832Samw@Sun.COM 		    PRIV_FILE_DAC_EXECUTE, NULL))
9779832Samw@Sun.COM 			_exit(-1);
9789832Samw@Sun.COM 
9799832Samw@Sun.COM 		if (smb_shr_enable_all_privs())
9809832Samw@Sun.COM 			_exit(-1);
9819832Samw@Sun.COM 
9829832Samw@Sun.COM 		(void) trim_whitespace(cmd);
9839832Samw@Sun.COM 		(void) strcanon(cmd, " ");
9849832Samw@Sun.COM 
9859832Samw@Sun.COM 		if ((cmd_tokens = smb_shr_tokenize_cmd(cmd)) != NULL) {
9869832Samw@Sun.COM 
9879832Samw@Sun.COM 			if (smb_shr_expand_subs(cmd_tokens, &si, subs) != 0) {
9889832Samw@Sun.COM 				free(cmd_tokens[0]);
9899832Samw@Sun.COM 				free(cmd_tokens);
9909832Samw@Sun.COM 				_exit(-1);
9919832Samw@Sun.COM 			}
9929832Samw@Sun.COM 
9939832Samw@Sun.COM 			ptr = cmd;
9949832Samw@Sun.COM 			path = strsep(&ptr, " ");
9959832Samw@Sun.COM 
9969832Samw@Sun.COM 			(void) execv(path, cmd_tokens);
9979832Samw@Sun.COM 		}
9989832Samw@Sun.COM 
9999832Samw@Sun.COM 		_exit(-1);
10009832Samw@Sun.COM 	}
10019832Samw@Sun.COM 
10029832Samw@Sun.COM 	/* parent process */
10039832Samw@Sun.COM 
10049832Samw@Sun.COM 	while (waitpid(child_pid, &child_status, 0) < 0) {
10059832Samw@Sun.COM 		if (errno != EINTR)
10069832Samw@Sun.COM 			break;
10079832Samw@Sun.COM 
10089832Samw@Sun.COM 		/* continue if waitpid got interrupted by a signal */
10099832Samw@Sun.COM 		errno = 0;
10109832Samw@Sun.COM 		continue;
10119832Samw@Sun.COM 	}
10129832Samw@Sun.COM 
10139832Samw@Sun.COM 	(void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_FORK, NULL);
10149832Samw@Sun.COM 
10159832Samw@Sun.COM 	if (WIFEXITED(child_status))
10169832Samw@Sun.COM 		return (WEXITSTATUS(child_status));
10179832Samw@Sun.COM 
10189832Samw@Sun.COM 	return (child_status);
10199832Samw@Sun.COM }
10209832Samw@Sun.COM 
10219832Samw@Sun.COM /*
10227961SNatalie.Li@Sun.COM  * ============================================
10237961SNatalie.Li@Sun.COM  * Private helper/utility functions
10247961SNatalie.Li@Sun.COM  * ============================================
10257348SJose.Borrego@Sun.COM  */
10267348SJose.Borrego@Sun.COM 
10277961SNatalie.Li@Sun.COM /*
10288334SJose.Borrego@Sun.COM  * Looks up the given share in the cache and return
10298334SJose.Borrego@Sun.COM  * the info in 'si'
10308334SJose.Borrego@Sun.COM  */
10318334SJose.Borrego@Sun.COM static uint32_t
10328334SJose.Borrego@Sun.COM smb_shr_lookup(char *sharename, smb_share_t *si)
10338334SJose.Borrego@Sun.COM {
10348334SJose.Borrego@Sun.COM 	smb_share_t *cached_si;
10358334SJose.Borrego@Sun.COM 	uint32_t status = NERR_NetNameNotFound;
10368334SJose.Borrego@Sun.COM 
10378334SJose.Borrego@Sun.COM 	if (sharename == NULL || *sharename == '\0')
10388334SJose.Borrego@Sun.COM 		return (NERR_NetNameNotFound);
10398334SJose.Borrego@Sun.COM 	if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) {
10408334SJose.Borrego@Sun.COM 		cached_si = smb_shr_cache_findent(sharename);
10418334SJose.Borrego@Sun.COM 		if (cached_si != NULL) {
10428334SJose.Borrego@Sun.COM 			bcopy(cached_si, si, sizeof (smb_share_t));
10439832Samw@Sun.COM 			smb_shr_set_exec_flags(si);
10448334SJose.Borrego@Sun.COM 			status = NERR_Success;
10458334SJose.Borrego@Sun.COM 		}
10468334SJose.Borrego@Sun.COM 
10478334SJose.Borrego@Sun.COM 		smb_shr_cache_unlock();
10488334SJose.Borrego@Sun.COM 	}
10498334SJose.Borrego@Sun.COM 	return (status);
10508334SJose.Borrego@Sun.COM }
10518334SJose.Borrego@Sun.COM 
10528334SJose.Borrego@Sun.COM /*
10537961SNatalie.Li@Sun.COM  * Add IPC$ to the cache upon startup.
10547961SNatalie.Li@Sun.COM  */
10557348SJose.Borrego@Sun.COM static uint32_t
10567961SNatalie.Li@Sun.COM smb_shr_addipc(void)
10577348SJose.Borrego@Sun.COM {
10587348SJose.Borrego@Sun.COM 	smb_share_t ipc;
10597961SNatalie.Li@Sun.COM 	uint32_t status = NERR_InternalError;
10607348SJose.Borrego@Sun.COM 
10617348SJose.Borrego@Sun.COM 	bzero(&ipc, sizeof (smb_share_t));
10627348SJose.Borrego@Sun.COM 	(void) strcpy(ipc.shr_name, "IPC$");
10637348SJose.Borrego@Sun.COM 	(void) strcpy(ipc.shr_cmnt, "Remote IPC");
10647348SJose.Borrego@Sun.COM 	ipc.shr_flags = SMB_SHRF_TRANS;
10657348SJose.Borrego@Sun.COM 	ipc.shr_type = STYPE_IPC;
10667348SJose.Borrego@Sun.COM 
10677961SNatalie.Li@Sun.COM 	if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) == NERR_Success) {
10687961SNatalie.Li@Sun.COM 		status = smb_shr_cache_addent(&ipc);
10697961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
10707348SJose.Borrego@Sun.COM 	}
10717348SJose.Borrego@Sun.COM 
10727348SJose.Borrego@Sun.COM 	return (status);
10737348SJose.Borrego@Sun.COM }
10747348SJose.Borrego@Sun.COM 
10757348SJose.Borrego@Sun.COM /*
10767052Samw  * smb_shr_set_oemname
10777052Samw  *
10787961SNatalie.Li@Sun.COM  * Generate the OEM name for the specified share.  If the name is
10797961SNatalie.Li@Sun.COM  * shorter than 13 bytes the oemname will be saved in si->shr_oemname.
10807961SNatalie.Li@Sun.COM  * Otherwise si->shr_oemname will be empty and SMB_SHRF_LONGNAME will
10817961SNatalie.Li@Sun.COM  * be set in si->shr_flags.
10827052Samw  */
10837052Samw static void
10847052Samw smb_shr_set_oemname(smb_share_t *si)
10857052Samw {
10867052Samw 	unsigned int cpid = oem_get_smb_cpid();
10877052Samw 	mts_wchar_t *unibuf;
10887052Samw 	char *oem_name;
10897052Samw 	int length;
10907052Samw 
10917052Samw 	length = strlen(si->shr_name) + 1;
10927052Samw 
10937052Samw 	oem_name = malloc(length);
10947052Samw 	unibuf = malloc(length * sizeof (mts_wchar_t));
10957052Samw 	if ((oem_name == NULL) || (unibuf == NULL)) {
10967052Samw 		free(oem_name);
10977052Samw 		free(unibuf);
10987052Samw 		return;
10997052Samw 	}
11007052Samw 
11017052Samw 	(void) mts_mbstowcs(unibuf, si->shr_name, length);
11027052Samw 
11037052Samw 	if (unicodestooems(oem_name, unibuf, length, cpid) == 0)
11047052Samw 		(void) strcpy(oem_name, si->shr_name);
11057052Samw 
11067052Samw 	free(unibuf);
11077052Samw 
11087052Samw 	if (strlen(oem_name) + 1 > SMB_SHARE_OEMNAME_MAX) {
11097052Samw 		si->shr_flags |= SMB_SHRF_LONGNAME;
11107052Samw 		*si->shr_oemname = '\0';
11117052Samw 	} else {
11127052Samw 		si->shr_flags &= ~SMB_SHRF_LONGNAME;
11137052Samw 		(void) strlcpy(si->shr_oemname, oem_name,
11147052Samw 		    SMB_SHARE_OEMNAME_MAX);
11157052Samw 	}
11167052Samw 
11177052Samw 	free(oem_name);
11187052Samw }
11197348SJose.Borrego@Sun.COM 
11207348SJose.Borrego@Sun.COM /*
11217348SJose.Borrego@Sun.COM  * ============================================
11227961SNatalie.Li@Sun.COM  * Cache management functions
11237961SNatalie.Li@Sun.COM  *
11247961SNatalie.Li@Sun.COM  * All cache functions are private
11257348SJose.Borrego@Sun.COM  * ============================================
11267348SJose.Borrego@Sun.COM  */
11277348SJose.Borrego@Sun.COM 
11287348SJose.Borrego@Sun.COM /*
11297961SNatalie.Li@Sun.COM  * Create the share cache (hash table).
11307348SJose.Borrego@Sun.COM  */
11317348SJose.Borrego@Sun.COM static uint32_t
11327961SNatalie.Li@Sun.COM smb_shr_cache_create(void)
11337348SJose.Borrego@Sun.COM {
11347961SNatalie.Li@Sun.COM 	uint32_t status = NERR_Success;
11357348SJose.Borrego@Sun.COM 
11367961SNatalie.Li@Sun.COM 	(void) mutex_lock(&smb_shr_cache.sc_mtx);
11377961SNatalie.Li@Sun.COM 	switch (smb_shr_cache.sc_state) {
11387961SNatalie.Li@Sun.COM 	case SMB_SHR_CACHE_STATE_NONE:
11397961SNatalie.Li@Sun.COM 		smb_shr_cache.sc_cache = ht_create_table(SMB_SHR_HTAB_SZ,
11407961SNatalie.Li@Sun.COM 		    MAXNAMELEN, 0);
11417961SNatalie.Li@Sun.COM 		if (smb_shr_cache.sc_cache == NULL) {
11427961SNatalie.Li@Sun.COM 			status = NERR_InternalError;
11437961SNatalie.Li@Sun.COM 			break;
11447348SJose.Borrego@Sun.COM 		}
11457348SJose.Borrego@Sun.COM 
11467961SNatalie.Li@Sun.COM 		(void) ht_register_callback(smb_shr_cache.sc_cache,
11477961SNatalie.Li@Sun.COM 		    smb_shr_cache_freent);
11487961SNatalie.Li@Sun.COM 		smb_shr_cache.sc_nops = 0;
11497961SNatalie.Li@Sun.COM 		smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_CREATED;
11507961SNatalie.Li@Sun.COM 		break;
11517961SNatalie.Li@Sun.COM 
11527961SNatalie.Li@Sun.COM 	default:
11537961SNatalie.Li@Sun.COM 		assert(0);
11547961SNatalie.Li@Sun.COM 		status = NERR_InternalError;
11557961SNatalie.Li@Sun.COM 		break;
11567961SNatalie.Li@Sun.COM 	}
11577961SNatalie.Li@Sun.COM 	(void) mutex_unlock(&smb_shr_cache.sc_mtx);
11587961SNatalie.Li@Sun.COM 
11597961SNatalie.Li@Sun.COM 	return (status);
11607961SNatalie.Li@Sun.COM }
11617961SNatalie.Li@Sun.COM 
11627961SNatalie.Li@Sun.COM /*
11637961SNatalie.Li@Sun.COM  * Destroy the share cache (hash table).
11647961SNatalie.Li@Sun.COM  * Wait for inflight/pending operations to finish or abort before
11657961SNatalie.Li@Sun.COM  * destroying the cache.
11667961SNatalie.Li@Sun.COM  */
11677961SNatalie.Li@Sun.COM static void
11687961SNatalie.Li@Sun.COM smb_shr_cache_destroy(void)
11697961SNatalie.Li@Sun.COM {
11707961SNatalie.Li@Sun.COM 	(void) mutex_lock(&smb_shr_cache.sc_mtx);
11717961SNatalie.Li@Sun.COM 	if (smb_shr_cache.sc_state == SMB_SHR_CACHE_STATE_CREATED) {
11727961SNatalie.Li@Sun.COM 		smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_DESTROYING;
11737961SNatalie.Li@Sun.COM 		while (smb_shr_cache.sc_nops > 0)
11747961SNatalie.Li@Sun.COM 			(void) cond_wait(&smb_shr_cache.sc_cv,
11757961SNatalie.Li@Sun.COM 			    &smb_shr_cache.sc_mtx);
11767961SNatalie.Li@Sun.COM 
11777961SNatalie.Li@Sun.COM 		smb_shr_cache.sc_cache = NULL;
11787961SNatalie.Li@Sun.COM 		smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_NONE;
11797961SNatalie.Li@Sun.COM 	}
11807961SNatalie.Li@Sun.COM 	(void) mutex_unlock(&smb_shr_cache.sc_mtx);
11817961SNatalie.Li@Sun.COM }
11827961SNatalie.Li@Sun.COM 
11837961SNatalie.Li@Sun.COM /*
11847961SNatalie.Li@Sun.COM  * If the cache is in "created" state, lock the cache for read
11857961SNatalie.Li@Sun.COM  * or read/write based on the specified mode.
11867961SNatalie.Li@Sun.COM  *
11877961SNatalie.Li@Sun.COM  * Whenever a lock is granted, the number of inflight cache
11887961SNatalie.Li@Sun.COM  * operations is incremented.
11897961SNatalie.Li@Sun.COM  */
11907961SNatalie.Li@Sun.COM static uint32_t
11917961SNatalie.Li@Sun.COM smb_shr_cache_lock(int mode)
11927961SNatalie.Li@Sun.COM {
11937961SNatalie.Li@Sun.COM 	(void) mutex_lock(&smb_shr_cache.sc_mtx);
11948334SJose.Borrego@Sun.COM 	if (smb_shr_cache.sc_state != SMB_SHR_CACHE_STATE_CREATED) {
11957961SNatalie.Li@Sun.COM 		(void) mutex_unlock(&smb_shr_cache.sc_mtx);
11967961SNatalie.Li@Sun.COM 		return (NERR_InternalError);
11977961SNatalie.Li@Sun.COM 	}
11988334SJose.Borrego@Sun.COM 	smb_shr_cache.sc_nops++;
11997961SNatalie.Li@Sun.COM 	(void) mutex_unlock(&smb_shr_cache.sc_mtx);
12007961SNatalie.Li@Sun.COM 
12017961SNatalie.Li@Sun.COM 	/*
12027961SNatalie.Li@Sun.COM 	 * Lock has to be taken outside the mutex otherwise
12037961SNatalie.Li@Sun.COM 	 * there could be a deadlock
12047961SNatalie.Li@Sun.COM 	 */
12057961SNatalie.Li@Sun.COM 	if (mode == SMB_SHR_CACHE_RDLOCK)
12067961SNatalie.Li@Sun.COM 		(void) rw_rdlock(&smb_shr_cache.sc_cache_lck);
12077961SNatalie.Li@Sun.COM 	else
12087961SNatalie.Li@Sun.COM 		(void) rw_wrlock(&smb_shr_cache.sc_cache_lck);
12097961SNatalie.Li@Sun.COM 
12107961SNatalie.Li@Sun.COM 	return (NERR_Success);
12117961SNatalie.Li@Sun.COM }
12127961SNatalie.Li@Sun.COM 
12137961SNatalie.Li@Sun.COM /*
12147961SNatalie.Li@Sun.COM  * Decrement the number of inflight operations and then unlock.
12157961SNatalie.Li@Sun.COM  */
12167961SNatalie.Li@Sun.COM static void
12177961SNatalie.Li@Sun.COM smb_shr_cache_unlock(void)
12187961SNatalie.Li@Sun.COM {
12197961SNatalie.Li@Sun.COM 	(void) mutex_lock(&smb_shr_cache.sc_mtx);
12207961SNatalie.Li@Sun.COM 	assert(smb_shr_cache.sc_nops > 0);
12217961SNatalie.Li@Sun.COM 	smb_shr_cache.sc_nops--;
12227961SNatalie.Li@Sun.COM 	(void) cond_broadcast(&smb_shr_cache.sc_cv);
12237961SNatalie.Li@Sun.COM 	(void) mutex_unlock(&smb_shr_cache.sc_mtx);
12247961SNatalie.Li@Sun.COM 
12257961SNatalie.Li@Sun.COM 	(void) rw_unlock(&smb_shr_cache.sc_cache_lck);
12267961SNatalie.Li@Sun.COM }
12277961SNatalie.Li@Sun.COM 
12287961SNatalie.Li@Sun.COM /*
12297961SNatalie.Li@Sun.COM  * Return the total number of shares
12307961SNatalie.Li@Sun.COM  */
12317961SNatalie.Li@Sun.COM static int
12327961SNatalie.Li@Sun.COM smb_shr_cache_count(void)
12337961SNatalie.Li@Sun.COM {
12347961SNatalie.Li@Sun.COM 	return (ht_get_total_items(smb_shr_cache.sc_cache));
12357961SNatalie.Li@Sun.COM }
12367961SNatalie.Li@Sun.COM 
12377961SNatalie.Li@Sun.COM /*
12387961SNatalie.Li@Sun.COM  * looks up the given share name in the cache and if it
12397961SNatalie.Li@Sun.COM  * finds a match returns a pointer to the cached entry.
12407961SNatalie.Li@Sun.COM  * Note that since a pointer is returned this function
12417961SNatalie.Li@Sun.COM  * MUST be protected by smb_shr_cache_lock/unlock pair
12427961SNatalie.Li@Sun.COM  */
12437961SNatalie.Li@Sun.COM static smb_share_t *
12447961SNatalie.Li@Sun.COM smb_shr_cache_findent(char *sharename)
12457961SNatalie.Li@Sun.COM {
12467961SNatalie.Li@Sun.COM 	HT_ITEM *item;
12477961SNatalie.Li@Sun.COM 
12487961SNatalie.Li@Sun.COM 	(void) utf8_strlwr(sharename);
12497961SNatalie.Li@Sun.COM 	item = ht_find_item(smb_shr_cache.sc_cache, sharename);
12507961SNatalie.Li@Sun.COM 	if (item && item->hi_data)
12517961SNatalie.Li@Sun.COM 		return ((smb_share_t *)item->hi_data);
12527961SNatalie.Li@Sun.COM 
12537961SNatalie.Li@Sun.COM 	return (NULL);
12547961SNatalie.Li@Sun.COM }
12557961SNatalie.Li@Sun.COM 
12567961SNatalie.Li@Sun.COM /*
12577961SNatalie.Li@Sun.COM  * Return a pointer to the first/next entry in
12587961SNatalie.Li@Sun.COM  * the cache based on the given iterator.
12597961SNatalie.Li@Sun.COM  *
12607961SNatalie.Li@Sun.COM  * Calls to this function MUST be protected by
12617961SNatalie.Li@Sun.COM  * smb_shr_cache_lock/unlock.
12627961SNatalie.Li@Sun.COM  */
12637961SNatalie.Li@Sun.COM static smb_share_t *
12647961SNatalie.Li@Sun.COM smb_shr_cache_iterate(smb_shriter_t *shi)
12657961SNatalie.Li@Sun.COM {
12667961SNatalie.Li@Sun.COM 	HT_ITEM *item;
12677961SNatalie.Li@Sun.COM 
12687961SNatalie.Li@Sun.COM 	if (shi->si_first) {
12697961SNatalie.Li@Sun.COM 		item = ht_findfirst(smb_shr_cache.sc_cache, &shi->si_hashiter);
12707961SNatalie.Li@Sun.COM 		shi->si_first = B_FALSE;
12717961SNatalie.Li@Sun.COM 	} else {
12727961SNatalie.Li@Sun.COM 		item = ht_findnext(&shi->si_hashiter);
12737348SJose.Borrego@Sun.COM 	}
12747348SJose.Borrego@Sun.COM 
12757961SNatalie.Li@Sun.COM 	if (item && item->hi_data)
12767961SNatalie.Li@Sun.COM 		return ((smb_share_t *)item->hi_data);
12777961SNatalie.Li@Sun.COM 
12787961SNatalie.Li@Sun.COM 	return (NULL);
12797961SNatalie.Li@Sun.COM }
12807961SNatalie.Li@Sun.COM 
12817961SNatalie.Li@Sun.COM /*
12827961SNatalie.Li@Sun.COM  * Add the specified share to the cache.  Memory needs to be allocated
12837961SNatalie.Li@Sun.COM  * for the cache entry and the passed information is copied to the
12847961SNatalie.Li@Sun.COM  * allocated space.
12857961SNatalie.Li@Sun.COM  */
12867961SNatalie.Li@Sun.COM static uint32_t
12877961SNatalie.Li@Sun.COM smb_shr_cache_addent(smb_share_t *si)
12887961SNatalie.Li@Sun.COM {
12897961SNatalie.Li@Sun.COM 	smb_share_t *cache_ent;
12907961SNatalie.Li@Sun.COM 	uint32_t status = NERR_Success;
12917961SNatalie.Li@Sun.COM 
12927961SNatalie.Li@Sun.COM 	if ((cache_ent = malloc(sizeof (smb_share_t))) == NULL)
12937961SNatalie.Li@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
12947961SNatalie.Li@Sun.COM 
12957961SNatalie.Li@Sun.COM 	bcopy(si, cache_ent, sizeof (smb_share_t));
12967961SNatalie.Li@Sun.COM 
12977961SNatalie.Li@Sun.COM 	(void) utf8_strlwr(cache_ent->shr_name);
12987961SNatalie.Li@Sun.COM 	smb_shr_set_oemname(cache_ent);
12997961SNatalie.Li@Sun.COM 
13007961SNatalie.Li@Sun.COM 	if ((si->shr_type & STYPE_IPC) == 0)
13017961SNatalie.Li@Sun.COM 		cache_ent->shr_type = STYPE_DISKTREE;
13027961SNatalie.Li@Sun.COM 	cache_ent->shr_type |= smb_shr_is_special(cache_ent->shr_name);
13037961SNatalie.Li@Sun.COM 
13047961SNatalie.Li@Sun.COM 	if (smb_shr_is_admin(cache_ent->shr_name))
13057961SNatalie.Li@Sun.COM 		cache_ent->shr_flags |= SMB_SHRF_ADMIN;
13067961SNatalie.Li@Sun.COM 
13077961SNatalie.Li@Sun.COM 	if (si->shr_flags & SMB_SHRF_AUTOHOME)
13087961SNatalie.Li@Sun.COM 		cache_ent->shr_refcnt = 1;
13097961SNatalie.Li@Sun.COM 
13107961SNatalie.Li@Sun.COM 	if (ht_add_item(smb_shr_cache.sc_cache, cache_ent->shr_name, cache_ent)
13117961SNatalie.Li@Sun.COM 	    == NULL) {
13127961SNatalie.Li@Sun.COM 		syslog(LOG_DEBUG, "share: %s: cache update failed",
13137961SNatalie.Li@Sun.COM 		    cache_ent->shr_name);
13147961SNatalie.Li@Sun.COM 		free(cache_ent);
13157961SNatalie.Li@Sun.COM 		status = NERR_InternalError;
13167348SJose.Borrego@Sun.COM 	}
13177348SJose.Borrego@Sun.COM 
13187961SNatalie.Li@Sun.COM 	return (status);
13197961SNatalie.Li@Sun.COM }
13207961SNatalie.Li@Sun.COM 
13217961SNatalie.Li@Sun.COM /*
13227961SNatalie.Li@Sun.COM  * Delete the specified share from the cache.
13237961SNatalie.Li@Sun.COM  */
13247961SNatalie.Li@Sun.COM static void
13257961SNatalie.Li@Sun.COM smb_shr_cache_delent(char *sharename)
13267961SNatalie.Li@Sun.COM {
13277961SNatalie.Li@Sun.COM 	(void) utf8_strlwr(sharename);
13287961SNatalie.Li@Sun.COM 	(void) ht_remove_item(smb_shr_cache.sc_cache, sharename);
13297961SNatalie.Li@Sun.COM }
13307961SNatalie.Li@Sun.COM 
13317961SNatalie.Li@Sun.COM /*
13327961SNatalie.Li@Sun.COM  * Call back to free the given cache entry.
13337961SNatalie.Li@Sun.COM  */
13347961SNatalie.Li@Sun.COM static void
13357961SNatalie.Li@Sun.COM smb_shr_cache_freent(HT_ITEM *item)
13367961SNatalie.Li@Sun.COM {
13377961SNatalie.Li@Sun.COM 	if (item && item->hi_data)
13387961SNatalie.Li@Sun.COM 		free(item->hi_data);
13397961SNatalie.Li@Sun.COM }
13407961SNatalie.Li@Sun.COM 
13417961SNatalie.Li@Sun.COM /*
13427961SNatalie.Li@Sun.COM  * ============================================
13437961SNatalie.Li@Sun.COM  * Interfaces to sharemgr
13447961SNatalie.Li@Sun.COM  *
13457961SNatalie.Li@Sun.COM  * All functions in this section are private
13467961SNatalie.Li@Sun.COM  * ============================================
13477961SNatalie.Li@Sun.COM  */
13487961SNatalie.Li@Sun.COM 
13497961SNatalie.Li@Sun.COM /*
13507961SNatalie.Li@Sun.COM  * Load shares from sharemgr
13517961SNatalie.Li@Sun.COM  */
13527961SNatalie.Li@Sun.COM /*ARGSUSED*/
13537961SNatalie.Li@Sun.COM static void *
13547961SNatalie.Li@Sun.COM smb_shr_sa_loadall(void *args)
13557961SNatalie.Li@Sun.COM {
13567961SNatalie.Li@Sun.COM 	sa_handle_t handle;
13577961SNatalie.Li@Sun.COM 	sa_group_t group, subgroup;
13587961SNatalie.Li@Sun.COM 	char *gstate;
13597961SNatalie.Li@Sun.COM 	boolean_t gdisabled;
13607961SNatalie.Li@Sun.COM 
13618474SJose.Borrego@Sun.COM 	if ((handle = smb_shr_sa_enter()) == NULL)
13627961SNatalie.Li@Sun.COM 		return (NULL);
13637348SJose.Borrego@Sun.COM 
13647961SNatalie.Li@Sun.COM 	for (group = sa_get_group(handle, NULL);
13657961SNatalie.Li@Sun.COM 	    group != NULL; group = sa_get_next_group(group)) {
13667961SNatalie.Li@Sun.COM 		gstate = sa_get_group_attr(group, "state");
13677961SNatalie.Li@Sun.COM 		if (gstate == NULL)
13687961SNatalie.Li@Sun.COM 			continue;
13697961SNatalie.Li@Sun.COM 
13707961SNatalie.Li@Sun.COM 		gdisabled = (strcasecmp(gstate, "disabled") == 0);
13717961SNatalie.Li@Sun.COM 		sa_free_attr_string(gstate);
13727961SNatalie.Li@Sun.COM 		if (gdisabled)
13737961SNatalie.Li@Sun.COM 			continue;
13747961SNatalie.Li@Sun.COM 
13757961SNatalie.Li@Sun.COM 		smb_shr_sa_loadgrp(group);
13767961SNatalie.Li@Sun.COM 
13777961SNatalie.Li@Sun.COM 		for (subgroup = sa_get_sub_group(group);
13787961SNatalie.Li@Sun.COM 		    subgroup != NULL;
13797961SNatalie.Li@Sun.COM 		    subgroup = sa_get_next_group(subgroup)) {
13807961SNatalie.Li@Sun.COM 			smb_shr_sa_loadgrp(subgroup);
13817961SNatalie.Li@Sun.COM 		}
13827961SNatalie.Li@Sun.COM 
13837348SJose.Borrego@Sun.COM 	}
13847348SJose.Borrego@Sun.COM 
13858474SJose.Borrego@Sun.COM 	smb_shr_sa_exit();
13867961SNatalie.Li@Sun.COM 	return (NULL);
13877348SJose.Borrego@Sun.COM }
13887348SJose.Borrego@Sun.COM 
13897961SNatalie.Li@Sun.COM /*
13907961SNatalie.Li@Sun.COM  * Load the shares contained in the specified group.
13917961SNatalie.Li@Sun.COM  *
13927961SNatalie.Li@Sun.COM  * Don't process groups on which the smb protocol is disabled.
13937961SNatalie.Li@Sun.COM  * The top level ZFS group won't have the smb protocol enabled
13947961SNatalie.Li@Sun.COM  * but sub-groups will.
13957961SNatalie.Li@Sun.COM  *
13967961SNatalie.Li@Sun.COM  * We will tolerate a limited number of errors and then give
13977961SNatalie.Li@Sun.COM  * up on the current group.  A typical error might be that the
13987961SNatalie.Li@Sun.COM  * shared directory no longer exists.
13997961SNatalie.Li@Sun.COM  */
14007961SNatalie.Li@Sun.COM static void
14017961SNatalie.Li@Sun.COM smb_shr_sa_loadgrp(sa_group_t group)
14027961SNatalie.Li@Sun.COM {
14037961SNatalie.Li@Sun.COM 	sa_share_t share;
14047961SNatalie.Li@Sun.COM 	sa_resource_t resource;
14057961SNatalie.Li@Sun.COM 	int error_count = 0;
14067961SNatalie.Li@Sun.COM 
14077961SNatalie.Li@Sun.COM 	if (sa_get_optionset(group, SMB_PROTOCOL_NAME) == NULL)
14087961SNatalie.Li@Sun.COM 		return;
14097961SNatalie.Li@Sun.COM 
14107961SNatalie.Li@Sun.COM 	for (share = sa_get_share(group, NULL);
14117961SNatalie.Li@Sun.COM 	    share != NULL;
14127961SNatalie.Li@Sun.COM 	    share = sa_get_next_share(share)) {
14137961SNatalie.Li@Sun.COM 		for (resource = sa_get_share_resource(share, NULL);
14147961SNatalie.Li@Sun.COM 		    resource != NULL;
14157961SNatalie.Li@Sun.COM 		    resource = sa_get_next_resource(resource)) {
14167961SNatalie.Li@Sun.COM 			if (smb_shr_sa_load(share, resource))
14177961SNatalie.Li@Sun.COM 				++error_count;
14187961SNatalie.Li@Sun.COM 
14197961SNatalie.Li@Sun.COM 			if (error_count > SMB_SHR_ERROR_THRESHOLD)
14207961SNatalie.Li@Sun.COM 				break;
14217961SNatalie.Li@Sun.COM 		}
14227961SNatalie.Li@Sun.COM 
14237961SNatalie.Li@Sun.COM 		if (error_count > SMB_SHR_ERROR_THRESHOLD)
14247961SNatalie.Li@Sun.COM 			break;
14257961SNatalie.Li@Sun.COM 	}
14267961SNatalie.Li@Sun.COM }
14277961SNatalie.Li@Sun.COM 
14287961SNatalie.Li@Sun.COM /*
14297961SNatalie.Li@Sun.COM  * Load a share definition from sharemgr and add it to the cache.
14308334SJose.Borrego@Sun.COM  * If the share is already in the cache then it doesn't do anything.
14318334SJose.Borrego@Sun.COM  *
14328334SJose.Borrego@Sun.COM  * This function does not report duplicate shares as error since
14338334SJose.Borrego@Sun.COM  * a share might have been added by smb_shr_get() while load is
14348334SJose.Borrego@Sun.COM  * in progress.
14357961SNatalie.Li@Sun.COM  */
14367348SJose.Borrego@Sun.COM static uint32_t
14377961SNatalie.Li@Sun.COM smb_shr_sa_load(sa_share_t share, sa_resource_t resource)
14387961SNatalie.Li@Sun.COM {
14397961SNatalie.Li@Sun.COM 	smb_share_t si;
14408334SJose.Borrego@Sun.COM 	char *sharename;
14417961SNatalie.Li@Sun.COM 	uint32_t status;
14428334SJose.Borrego@Sun.COM 	boolean_t loaded;
14438334SJose.Borrego@Sun.COM 
14448334SJose.Borrego@Sun.COM 	if ((sharename = sa_get_resource_attr(resource, "name")) == NULL)
14458334SJose.Borrego@Sun.COM 		return (NERR_InternalError);
14468334SJose.Borrego@Sun.COM 
14478334SJose.Borrego@Sun.COM 	loaded = smb_shr_exists(sharename);
14488334SJose.Borrego@Sun.COM 	sa_free_attr_string(sharename);
14498334SJose.Borrego@Sun.COM 
14508334SJose.Borrego@Sun.COM 	if (loaded)
14518334SJose.Borrego@Sun.COM 		return (NERR_Success);
14527961SNatalie.Li@Sun.COM 
14537961SNatalie.Li@Sun.COM 	if ((status = smb_shr_sa_get(share, resource, &si)) != NERR_Success) {
14547961SNatalie.Li@Sun.COM 		syslog(LOG_DEBUG, "share: failed to load %s (%d)",
14557961SNatalie.Li@Sun.COM 		    si.shr_name, status);
14567961SNatalie.Li@Sun.COM 		return (status);
14577961SNatalie.Li@Sun.COM 	}
14587961SNatalie.Li@Sun.COM 
14598334SJose.Borrego@Sun.COM 	status = smb_shr_add(&si);
14608334SJose.Borrego@Sun.COM 	if ((status != NERR_Success) && (status != NERR_DuplicateShare)) {
14617961SNatalie.Li@Sun.COM 		syslog(LOG_DEBUG, "share: failed to cache %s (%d)",
14627961SNatalie.Li@Sun.COM 		    si.shr_name, status);
14637961SNatalie.Li@Sun.COM 		return (status);
14647961SNatalie.Li@Sun.COM 	}
14657961SNatalie.Li@Sun.COM 
14667961SNatalie.Li@Sun.COM 	return (NERR_Success);
14677961SNatalie.Li@Sun.COM }
14687961SNatalie.Li@Sun.COM 
14697961SNatalie.Li@Sun.COM /*
14707961SNatalie.Li@Sun.COM  * Read the specified share information from sharemgr and return
14717961SNatalie.Li@Sun.COM  * it in the given smb_share_t structure.
14727961SNatalie.Li@Sun.COM  *
14737961SNatalie.Li@Sun.COM  * Shares read from sharemgr are marked as permanent/persistent.
14747961SNatalie.Li@Sun.COM  */
14757961SNatalie.Li@Sun.COM static uint32_t
14767961SNatalie.Li@Sun.COM smb_shr_sa_get(sa_share_t share, sa_resource_t resource, smb_share_t *si)
14777348SJose.Borrego@Sun.COM {
14787348SJose.Borrego@Sun.COM 	sa_property_t prop;
14797348SJose.Borrego@Sun.COM 	sa_optionset_t opts;
14807348SJose.Borrego@Sun.COM 	char *val = NULL;
14817348SJose.Borrego@Sun.COM 	char *path;
14827348SJose.Borrego@Sun.COM 	char *rname;
14837348SJose.Borrego@Sun.COM 
14847348SJose.Borrego@Sun.COM 	if ((path = sa_get_share_attr(share, "path")) == NULL)
14857348SJose.Borrego@Sun.COM 		return (NERR_InternalError);
14867348SJose.Borrego@Sun.COM 
14877348SJose.Borrego@Sun.COM 	if ((rname = sa_get_resource_attr(resource, "name")) == NULL) {
14887348SJose.Borrego@Sun.COM 		sa_free_attr_string(path);
14897348SJose.Borrego@Sun.COM 		return (NERR_InternalError);
14907348SJose.Borrego@Sun.COM 	}
14917348SJose.Borrego@Sun.COM 
14927348SJose.Borrego@Sun.COM 	bzero(si, sizeof (smb_share_t));
14937348SJose.Borrego@Sun.COM 	si->shr_flags = SMB_SHRF_PERM;
14947348SJose.Borrego@Sun.COM 
14957348SJose.Borrego@Sun.COM 	(void) strlcpy(si->shr_path, path, sizeof (si->shr_path));
14967348SJose.Borrego@Sun.COM 	(void) strlcpy(si->shr_name, rname, sizeof (si->shr_name));
14977348SJose.Borrego@Sun.COM 	sa_free_attr_string(path);
14987348SJose.Borrego@Sun.COM 	sa_free_attr_string(rname);
14997348SJose.Borrego@Sun.COM 
15007348SJose.Borrego@Sun.COM 	val = sa_get_resource_description(resource);
15017348SJose.Borrego@Sun.COM 	if (val == NULL)
15027348SJose.Borrego@Sun.COM 		val = sa_get_share_description(share);
15037348SJose.Borrego@Sun.COM 
15047348SJose.Borrego@Sun.COM 	if (val != NULL) {
15057348SJose.Borrego@Sun.COM 		(void) strlcpy(si->shr_cmnt, val, sizeof (si->shr_cmnt));
15067348SJose.Borrego@Sun.COM 		sa_free_share_description(val);
15077348SJose.Borrego@Sun.COM 	}
15087348SJose.Borrego@Sun.COM 
15097348SJose.Borrego@Sun.COM 	opts = sa_get_derived_optionset(resource, SMB_PROTOCOL_NAME, 1);
15107348SJose.Borrego@Sun.COM 	if (opts == NULL)
15117348SJose.Borrego@Sun.COM 		return (NERR_Success);
15127348SJose.Borrego@Sun.COM 
15138334SJose.Borrego@Sun.COM 	prop = (sa_property_t)sa_get_property(opts, SHOPT_AD_CONTAINER);
15147348SJose.Borrego@Sun.COM 	if (prop != NULL) {
15157348SJose.Borrego@Sun.COM 		if ((val = sa_get_property_attr(prop, "value")) != NULL) {
15167348SJose.Borrego@Sun.COM 			(void) strlcpy(si->shr_container, val,
15177348SJose.Borrego@Sun.COM 			    sizeof (si->shr_container));
15187348SJose.Borrego@Sun.COM 			free(val);
15197348SJose.Borrego@Sun.COM 		}
15207348SJose.Borrego@Sun.COM 	}
15217348SJose.Borrego@Sun.COM 
15229231SAfshin.Ardakani@Sun.COM 	prop = (sa_property_t)sa_get_property(opts, SHOPT_CATIA);
15239231SAfshin.Ardakani@Sun.COM 	if (prop != NULL) {
15249231SAfshin.Ardakani@Sun.COM 		if ((val = sa_get_property_attr(prop, "value")) != NULL) {
15259231SAfshin.Ardakani@Sun.COM 			smb_shr_sa_catia_option(val, si);
15269231SAfshin.Ardakani@Sun.COM 			free(val);
15279231SAfshin.Ardakani@Sun.COM 		}
15289231SAfshin.Ardakani@Sun.COM 	}
15299231SAfshin.Ardakani@Sun.COM 
15308334SJose.Borrego@Sun.COM 	prop = (sa_property_t)sa_get_property(opts, SHOPT_CSC);
15318334SJose.Borrego@Sun.COM 	if (prop != NULL) {
15328334SJose.Borrego@Sun.COM 		if ((val = sa_get_property_attr(prop, "value")) != NULL) {
15338334SJose.Borrego@Sun.COM 			smb_shr_sa_csc_option(val, si);
15348334SJose.Borrego@Sun.COM 			free(val);
15358334SJose.Borrego@Sun.COM 		}
15368334SJose.Borrego@Sun.COM 	}
15378334SJose.Borrego@Sun.COM 
15389832Samw@Sun.COM 	prop = (sa_property_t)sa_get_property(opts, SHOPT_GUEST);
15399832Samw@Sun.COM 	if (prop != NULL) {
15409832Samw@Sun.COM 		if ((val = sa_get_property_attr(prop, "value")) != NULL) {
15419832Samw@Sun.COM 			smb_shr_sa_guest_option(val, si);
15429832Samw@Sun.COM 			free(val);
15439832Samw@Sun.COM 		}
15449832Samw@Sun.COM 	}
15459832Samw@Sun.COM 
15467961SNatalie.Li@Sun.COM 	prop = (sa_property_t)sa_get_property(opts, SHOPT_NONE);
15477961SNatalie.Li@Sun.COM 	if (prop != NULL) {
15487961SNatalie.Li@Sun.COM 		if ((val = sa_get_property_attr(prop, "value")) != NULL) {
15497961SNatalie.Li@Sun.COM 			(void) strlcpy(si->shr_access_none, val,
15507961SNatalie.Li@Sun.COM 			    sizeof (si->shr_access_none));
15517961SNatalie.Li@Sun.COM 			free(val);
15527961SNatalie.Li@Sun.COM 			si->shr_flags |= SMB_SHRF_ACC_NONE;
15537961SNatalie.Li@Sun.COM 		}
15547348SJose.Borrego@Sun.COM 	}
15557348SJose.Borrego@Sun.COM 
15567961SNatalie.Li@Sun.COM 	prop = (sa_property_t)sa_get_property(opts, SHOPT_RO);
15577961SNatalie.Li@Sun.COM 	if (prop != NULL) {
15587961SNatalie.Li@Sun.COM 		if ((val = sa_get_property_attr(prop, "value")) != NULL) {
15597961SNatalie.Li@Sun.COM 			(void) strlcpy(si->shr_access_ro, val,
15607961SNatalie.Li@Sun.COM 			    sizeof (si->shr_access_ro));
15617961SNatalie.Li@Sun.COM 			free(val);
15627961SNatalie.Li@Sun.COM 			si->shr_flags |= SMB_SHRF_ACC_RO;
15637961SNatalie.Li@Sun.COM 		}
15647348SJose.Borrego@Sun.COM 	}
15657348SJose.Borrego@Sun.COM 
15667961SNatalie.Li@Sun.COM 	prop = (sa_property_t)sa_get_property(opts, SHOPT_RW);
15677961SNatalie.Li@Sun.COM 	if (prop != NULL) {
15687961SNatalie.Li@Sun.COM 		if ((val = sa_get_property_attr(prop, "value")) != NULL) {
15697961SNatalie.Li@Sun.COM 			(void) strlcpy(si->shr_access_rw, val,
15707961SNatalie.Li@Sun.COM 			    sizeof (si->shr_access_rw));
15717961SNatalie.Li@Sun.COM 			free(val);
15727961SNatalie.Li@Sun.COM 			si->shr_flags |= SMB_SHRF_ACC_RW;
15737961SNatalie.Li@Sun.COM 		}
15747961SNatalie.Li@Sun.COM 	}
15757961SNatalie.Li@Sun.COM 
15767961SNatalie.Li@Sun.COM 	sa_free_derived_optionset(opts);
15777961SNatalie.Li@Sun.COM 	return (NERR_Success);
15787348SJose.Borrego@Sun.COM }
15797348SJose.Borrego@Sun.COM 
15807348SJose.Borrego@Sun.COM /*
15818334SJose.Borrego@Sun.COM  * Map a client-side caching (CSC) option to the appropriate share
15828334SJose.Borrego@Sun.COM  * flag.  Only one option is allowed; an error will be logged if
15838334SJose.Borrego@Sun.COM  * multiple options have been specified.  We don't need to do anything
15848334SJose.Borrego@Sun.COM  * about multiple values here because the SRVSVC will not recognize
15858334SJose.Borrego@Sun.COM  * a value containing multiple flags and will return the default value.
15868334SJose.Borrego@Sun.COM  *
15878334SJose.Borrego@Sun.COM  * If the option value is not recognized, it will be ignored: invalid
15888334SJose.Borrego@Sun.COM  * values will typically be caught and rejected by sharemgr.
15898334SJose.Borrego@Sun.COM  */
15908474SJose.Borrego@Sun.COM void
15918334SJose.Borrego@Sun.COM smb_shr_sa_csc_option(const char *value, smb_share_t *si)
15928334SJose.Borrego@Sun.COM {
15938334SJose.Borrego@Sun.COM 	int i;
15948334SJose.Borrego@Sun.COM 
15958334SJose.Borrego@Sun.COM 	for (i = 0; i < (sizeof (cscopt) / sizeof (cscopt[0])); ++i) {
15968334SJose.Borrego@Sun.COM 		if (strcasecmp(value, cscopt[i].value) == 0) {
15978334SJose.Borrego@Sun.COM 			si->shr_flags |= cscopt[i].flag;
15988334SJose.Borrego@Sun.COM 			break;
15998334SJose.Borrego@Sun.COM 		}
16008334SJose.Borrego@Sun.COM 	}
16018334SJose.Borrego@Sun.COM 
16028334SJose.Borrego@Sun.COM 	switch (si->shr_flags & SMB_SHRF_CSC_MASK) {
16038334SJose.Borrego@Sun.COM 	case 0:
16048334SJose.Borrego@Sun.COM 	case SMB_SHRF_CSC_DISABLED:
16058334SJose.Borrego@Sun.COM 	case SMB_SHRF_CSC_MANUAL:
16068334SJose.Borrego@Sun.COM 	case SMB_SHRF_CSC_AUTO:
16078334SJose.Borrego@Sun.COM 	case SMB_SHRF_CSC_VDO:
16088334SJose.Borrego@Sun.COM 		break;
16098334SJose.Borrego@Sun.COM 
16108334SJose.Borrego@Sun.COM 	default:
16118474SJose.Borrego@Sun.COM 		syslog(LOG_INFO, "csc option conflict: 0x%08x",
16128474SJose.Borrego@Sun.COM 		    si->shr_flags & SMB_SHRF_CSC_MASK);
16138334SJose.Borrego@Sun.COM 		break;
16148334SJose.Borrego@Sun.COM 	}
16158334SJose.Borrego@Sun.COM }
16168334SJose.Borrego@Sun.COM 
16178334SJose.Borrego@Sun.COM /*
16189832Samw@Sun.COM  * Return the option name for the first CSC flag (there should be only
16199832Samw@Sun.COM  * one) encountered in the share flags.
16209832Samw@Sun.COM  */
16219832Samw@Sun.COM char *
16229832Samw@Sun.COM smb_shr_sa_csc_name(const smb_share_t *si)
16239832Samw@Sun.COM {
16249832Samw@Sun.COM 	int i;
16259832Samw@Sun.COM 
16269832Samw@Sun.COM 	for (i = 0; i < (sizeof (cscopt) / sizeof (cscopt[0])); ++i) {
16279832Samw@Sun.COM 		if (si->shr_flags & cscopt[i].flag)
16289832Samw@Sun.COM 			return (cscopt[i].value);
16299832Samw@Sun.COM 	}
16309832Samw@Sun.COM 
16319832Samw@Sun.COM 	return (NULL);
16329832Samw@Sun.COM }
16339832Samw@Sun.COM 
16349832Samw@Sun.COM /*
16359231SAfshin.Ardakani@Sun.COM  * set SMB_SHRF_CATIA in accordance with catia property value
16369231SAfshin.Ardakani@Sun.COM  */
16379231SAfshin.Ardakani@Sun.COM void
16389231SAfshin.Ardakani@Sun.COM smb_shr_sa_catia_option(const char *value, smb_share_t *si)
16399231SAfshin.Ardakani@Sun.COM {
16409231SAfshin.Ardakani@Sun.COM 	if ((strcasecmp(value, "true") == 0) || (strcmp(value, "1") == 0)) {
16419231SAfshin.Ardakani@Sun.COM 		si->shr_flags |= SMB_SHRF_CATIA;
16429231SAfshin.Ardakani@Sun.COM 	} else {
16439231SAfshin.Ardakani@Sun.COM 		si->shr_flags &= ~SMB_SHRF_CATIA;
16449231SAfshin.Ardakani@Sun.COM 	}
16459231SAfshin.Ardakani@Sun.COM }
16469231SAfshin.Ardakani@Sun.COM 
16479231SAfshin.Ardakani@Sun.COM /*
16489832Samw@Sun.COM  * set SMB_SHRF_GUEST_OK in accordance with guestok property value
16499832Samw@Sun.COM  */
16509832Samw@Sun.COM static void
16519832Samw@Sun.COM smb_shr_sa_guest_option(const char *value, smb_share_t *si)
16529832Samw@Sun.COM {
16539832Samw@Sun.COM 	if ((strcasecmp(value, "true") == 0) || (strcmp(value, "1") == 0)) {
16549832Samw@Sun.COM 		si->shr_flags |= SMB_SHRF_GUEST_OK;
16559832Samw@Sun.COM 	} else {
16569832Samw@Sun.COM 		si->shr_flags &= ~SMB_SHRF_GUEST_OK;
16579832Samw@Sun.COM 	}
16589832Samw@Sun.COM }
16599832Samw@Sun.COM 
16609832Samw@Sun.COM /*
16618334SJose.Borrego@Sun.COM  * looks up sharemgr for the given share (resource) and loads
16628334SJose.Borrego@Sun.COM  * the definition into cache if lookup is successful
16638334SJose.Borrego@Sun.COM  */
16648334SJose.Borrego@Sun.COM static uint32_t
16658334SJose.Borrego@Sun.COM smb_shr_sa_loadbyname(char *sharename)
16668334SJose.Borrego@Sun.COM {
16678334SJose.Borrego@Sun.COM 	sa_handle_t handle;
16688334SJose.Borrego@Sun.COM 	sa_share_t share;
16698334SJose.Borrego@Sun.COM 	sa_resource_t resource;
16708334SJose.Borrego@Sun.COM 	uint32_t status;
16718334SJose.Borrego@Sun.COM 
16728474SJose.Borrego@Sun.COM 	if ((handle = smb_shr_sa_enter()) == NULL)
16738334SJose.Borrego@Sun.COM 		return (NERR_InternalError);
16748334SJose.Borrego@Sun.COM 
16758334SJose.Borrego@Sun.COM 	resource = sa_find_resource(handle, sharename);
16768334SJose.Borrego@Sun.COM 	if (resource == NULL) {
16778474SJose.Borrego@Sun.COM 		smb_shr_sa_exit();
16788334SJose.Borrego@Sun.COM 		return (NERR_NetNameNotFound);
16798334SJose.Borrego@Sun.COM 	}
16808334SJose.Borrego@Sun.COM 
16818334SJose.Borrego@Sun.COM 	share = sa_get_resource_parent(resource);
16828334SJose.Borrego@Sun.COM 	if (share == NULL) {
16838474SJose.Borrego@Sun.COM 		smb_shr_sa_exit();
16848334SJose.Borrego@Sun.COM 		return (NERR_InternalError);
16858334SJose.Borrego@Sun.COM 	}
16868334SJose.Borrego@Sun.COM 
16878334SJose.Borrego@Sun.COM 	status = smb_shr_sa_load(share, resource);
16888334SJose.Borrego@Sun.COM 
16898474SJose.Borrego@Sun.COM 	smb_shr_sa_exit();
16908334SJose.Borrego@Sun.COM 	return (status);
16918334SJose.Borrego@Sun.COM }
16928334SJose.Borrego@Sun.COM 
16938334SJose.Borrego@Sun.COM /*
16947348SJose.Borrego@Sun.COM  * ============================================
16957348SJose.Borrego@Sun.COM  * Share publishing functions
16967961SNatalie.Li@Sun.COM  *
16977961SNatalie.Li@Sun.COM  * All the functions are private
16987348SJose.Borrego@Sun.COM  * ============================================
16997348SJose.Borrego@Sun.COM  */
17007348SJose.Borrego@Sun.COM 
17017961SNatalie.Li@Sun.COM static void
17027961SNatalie.Li@Sun.COM smb_shr_publish(const char *sharename, const char *container)
17037961SNatalie.Li@Sun.COM {
17047961SNatalie.Li@Sun.COM 	smb_shr_publisher_queue(sharename, container, SMB_SHR_PUBLISH);
17057961SNatalie.Li@Sun.COM }
17067961SNatalie.Li@Sun.COM 
17077961SNatalie.Li@Sun.COM static void
17087961SNatalie.Li@Sun.COM smb_shr_unpublish(const char *sharename, const char *container)
17097961SNatalie.Li@Sun.COM {
17107961SNatalie.Li@Sun.COM 	smb_shr_publisher_queue(sharename, container, SMB_SHR_UNPUBLISH);
17117961SNatalie.Li@Sun.COM }
17127961SNatalie.Li@Sun.COM 
17137348SJose.Borrego@Sun.COM /*
17147961SNatalie.Li@Sun.COM  * In domain mode, put a share on the publisher queue.
17157961SNatalie.Li@Sun.COM  * This is a no-op if the smb service is in Workgroup mode.
17167348SJose.Borrego@Sun.COM  */
17177348SJose.Borrego@Sun.COM static void
17187961SNatalie.Li@Sun.COM smb_shr_publisher_queue(const char *sharename, const char *container, char op)
17197348SJose.Borrego@Sun.COM {
17207348SJose.Borrego@Sun.COM 	smb_shr_pitem_t *item = NULL;
17217348SJose.Borrego@Sun.COM 
17227348SJose.Borrego@Sun.COM 	if (container == NULL || *container == '\0')
17237348SJose.Borrego@Sun.COM 		return;
17247348SJose.Borrego@Sun.COM 
17257961SNatalie.Li@Sun.COM 	if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN)
17267961SNatalie.Li@Sun.COM 		return;
17277961SNatalie.Li@Sun.COM 
17287348SJose.Borrego@Sun.COM 	(void) mutex_lock(&ad_queue.spq_mtx);
17297348SJose.Borrego@Sun.COM 	switch (ad_queue.spq_state) {
17307348SJose.Borrego@Sun.COM 	case SMB_SHR_PQS_READY:
17317348SJose.Borrego@Sun.COM 	case SMB_SHR_PQS_PUBLISHING:
17327348SJose.Borrego@Sun.COM 		break;
17337348SJose.Borrego@Sun.COM 	default:
17347348SJose.Borrego@Sun.COM 		(void) mutex_unlock(&ad_queue.spq_mtx);
17357348SJose.Borrego@Sun.COM 		return;
17367348SJose.Borrego@Sun.COM 	}
17377348SJose.Borrego@Sun.COM 	(void) mutex_unlock(&ad_queue.spq_mtx);
17387348SJose.Borrego@Sun.COM 
17397961SNatalie.Li@Sun.COM 	if ((item = malloc(sizeof (smb_shr_pitem_t))) == NULL)
17407348SJose.Borrego@Sun.COM 		return;
17417348SJose.Borrego@Sun.COM 
17427348SJose.Borrego@Sun.COM 	item->spi_op = op;
17437348SJose.Borrego@Sun.COM 	(void) strlcpy(item->spi_name, sharename, sizeof (item->spi_name));
17447348SJose.Borrego@Sun.COM 	(void) strlcpy(item->spi_container, container,
17457348SJose.Borrego@Sun.COM 	    sizeof (item->spi_container));
17467348SJose.Borrego@Sun.COM 
17477348SJose.Borrego@Sun.COM 	(void) mutex_lock(&ad_queue.spq_mtx);
17487348SJose.Borrego@Sun.COM 	list_insert_tail(&ad_queue.spq_list, item);
17497348SJose.Borrego@Sun.COM 	(void) cond_signal(&ad_queue.spq_cv);
17507348SJose.Borrego@Sun.COM 	(void) mutex_unlock(&ad_queue.spq_mtx);
17517348SJose.Borrego@Sun.COM }
17527348SJose.Borrego@Sun.COM 
17537961SNatalie.Li@Sun.COM /*
17547961SNatalie.Li@Sun.COM  * Publishing won't be activated if the smb service is running in
17557961SNatalie.Li@Sun.COM  * Workgroup mode.
17567961SNatalie.Li@Sun.COM  */
17577348SJose.Borrego@Sun.COM static int
17587348SJose.Borrego@Sun.COM smb_shr_publisher_start(void)
17597348SJose.Borrego@Sun.COM {
17607961SNatalie.Li@Sun.COM 	pthread_t publish_thr;
17617348SJose.Borrego@Sun.COM 	pthread_attr_t tattr;
17627348SJose.Borrego@Sun.COM 	int rc;
17637348SJose.Borrego@Sun.COM 
17647961SNatalie.Li@Sun.COM 	if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN)
17657961SNatalie.Li@Sun.COM 		return (0);
17667961SNatalie.Li@Sun.COM 
17677348SJose.Borrego@Sun.COM 	(void) mutex_lock(&ad_queue.spq_mtx);
17687348SJose.Borrego@Sun.COM 	if (ad_queue.spq_state != SMB_SHR_PQS_NOQUEUE) {
17697348SJose.Borrego@Sun.COM 		(void) mutex_unlock(&ad_queue.spq_mtx);
17707348SJose.Borrego@Sun.COM 		errno = EINVAL;
17717348SJose.Borrego@Sun.COM 		return (-1);
17727348SJose.Borrego@Sun.COM 	}
17737348SJose.Borrego@Sun.COM 
17747348SJose.Borrego@Sun.COM 	list_create(&ad_queue.spq_list, sizeof (smb_shr_pitem_t),
17757348SJose.Borrego@Sun.COM 	    offsetof(smb_shr_pitem_t, spi_lnd));
17767348SJose.Borrego@Sun.COM 	ad_queue.spq_state = SMB_SHR_PQS_READY;
17777348SJose.Borrego@Sun.COM 	(void) mutex_unlock(&ad_queue.spq_mtx);
17787348SJose.Borrego@Sun.COM 
17797348SJose.Borrego@Sun.COM 	(void) pthread_attr_init(&tattr);
17807348SJose.Borrego@Sun.COM 	(void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
17817961SNatalie.Li@Sun.COM 	rc = pthread_create(&publish_thr, &tattr, smb_shr_publisher, 0);
17827348SJose.Borrego@Sun.COM 	(void) pthread_attr_destroy(&tattr);
17837348SJose.Borrego@Sun.COM 
17847348SJose.Borrego@Sun.COM 	return (rc);
17857348SJose.Borrego@Sun.COM }
17867348SJose.Borrego@Sun.COM 
17877348SJose.Borrego@Sun.COM static void
17887348SJose.Borrego@Sun.COM smb_shr_publisher_stop(void)
17897348SJose.Borrego@Sun.COM {
17907961SNatalie.Li@Sun.COM 	if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN)
17917961SNatalie.Li@Sun.COM 		return;
17927961SNatalie.Li@Sun.COM 
17937348SJose.Borrego@Sun.COM 	(void) mutex_lock(&ad_queue.spq_mtx);
17947348SJose.Borrego@Sun.COM 	switch (ad_queue.spq_state) {
17957348SJose.Borrego@Sun.COM 	case SMB_SHR_PQS_READY:
17967348SJose.Borrego@Sun.COM 	case SMB_SHR_PQS_PUBLISHING:
17977348SJose.Borrego@Sun.COM 		ad_queue.spq_state = SMB_SHR_PQS_STOPPING;
17987348SJose.Borrego@Sun.COM 		(void) cond_signal(&ad_queue.spq_cv);
17997348SJose.Borrego@Sun.COM 		break;
18007348SJose.Borrego@Sun.COM 	default:
18017348SJose.Borrego@Sun.COM 		break;
18027348SJose.Borrego@Sun.COM 	}
18037348SJose.Borrego@Sun.COM 	(void) mutex_unlock(&ad_queue.spq_mtx);
18047348SJose.Borrego@Sun.COM }
18057348SJose.Borrego@Sun.COM 
18067348SJose.Borrego@Sun.COM /*
18077961SNatalie.Li@Sun.COM  * This is the publisher daemon thread.  While running, the thread waits
18087961SNatalie.Li@Sun.COM  * on a conditional variable until notified that a share needs to be
18097961SNatalie.Li@Sun.COM  * [un]published or that the thread should be terminated.
18107961SNatalie.Li@Sun.COM  *
18117961SNatalie.Li@Sun.COM  * Entries may remain in the outgoing queue if the Active Directory
18127961SNatalie.Li@Sun.COM  * service is inaccessible, in which case the thread wakes up every 60
18137961SNatalie.Li@Sun.COM  * seconds to retry.
18147348SJose.Borrego@Sun.COM  */
18157348SJose.Borrego@Sun.COM /*ARGSUSED*/
18167348SJose.Borrego@Sun.COM static void *
18177348SJose.Borrego@Sun.COM smb_shr_publisher(void *arg)
18187348SJose.Borrego@Sun.COM {
18197348SJose.Borrego@Sun.COM 	smb_ads_handle_t *ah;
18207348SJose.Borrego@Sun.COM 	smb_shr_pitem_t *shr;
18217348SJose.Borrego@Sun.COM 	list_t publist;
18227961SNatalie.Li@Sun.COM 	timestruc_t pubretry;
18237348SJose.Borrego@Sun.COM 	char hostname[MAXHOSTNAMELEN];
18247348SJose.Borrego@Sun.COM 
18257348SJose.Borrego@Sun.COM 	(void) mutex_lock(&ad_queue.spq_mtx);
18267961SNatalie.Li@Sun.COM 	if (ad_queue.spq_state != SMB_SHR_PQS_READY) {
18277348SJose.Borrego@Sun.COM 		(void) mutex_unlock(&ad_queue.spq_mtx);
18287348SJose.Borrego@Sun.COM 		return (NULL);
18297348SJose.Borrego@Sun.COM 	}
18307961SNatalie.Li@Sun.COM 	ad_queue.spq_state = SMB_SHR_PQS_PUBLISHING;
18317348SJose.Borrego@Sun.COM 	(void) mutex_unlock(&ad_queue.spq_mtx);
18327348SJose.Borrego@Sun.COM 
18337348SJose.Borrego@Sun.COM 	(void) smb_gethostname(hostname, MAXHOSTNAMELEN, 0);
18347961SNatalie.Li@Sun.COM 
18357348SJose.Borrego@Sun.COM 	list_create(&publist, sizeof (smb_shr_pitem_t),
18367348SJose.Borrego@Sun.COM 	    offsetof(smb_shr_pitem_t, spi_lnd));
18377348SJose.Borrego@Sun.COM 
18387348SJose.Borrego@Sun.COM 	for (;;) {
18397348SJose.Borrego@Sun.COM 		(void) mutex_lock(&ad_queue.spq_mtx);
18407961SNatalie.Li@Sun.COM 
18417961SNatalie.Li@Sun.COM 		while (list_is_empty(&ad_queue.spq_list) &&
18427961SNatalie.Li@Sun.COM 		    (ad_queue.spq_state == SMB_SHR_PQS_PUBLISHING)) {
18437961SNatalie.Li@Sun.COM 			if (list_is_empty(&publist)) {
18447961SNatalie.Li@Sun.COM 				(void) cond_wait(&ad_queue.spq_cv,
18457961SNatalie.Li@Sun.COM 				    &ad_queue.spq_mtx);
18467961SNatalie.Li@Sun.COM 			} else {
18477961SNatalie.Li@Sun.COM 				pubretry.tv_sec = 60;
18487961SNatalie.Li@Sun.COM 				pubretry.tv_nsec = 0;
18497961SNatalie.Li@Sun.COM 				(void) cond_reltimedwait(&ad_queue.spq_cv,
18507961SNatalie.Li@Sun.COM 				    &ad_queue.spq_mtx, &pubretry);
18517961SNatalie.Li@Sun.COM 				break;
18527961SNatalie.Li@Sun.COM 			}
18537961SNatalie.Li@Sun.COM 		}
18547348SJose.Borrego@Sun.COM 
18557348SJose.Borrego@Sun.COM 		if (ad_queue.spq_state != SMB_SHR_PQS_PUBLISHING) {
18567348SJose.Borrego@Sun.COM 			(void) mutex_unlock(&ad_queue.spq_mtx);
18577348SJose.Borrego@Sun.COM 			break;
18587348SJose.Borrego@Sun.COM 		}
18597348SJose.Borrego@Sun.COM 
18607348SJose.Borrego@Sun.COM 		/*
18617961SNatalie.Li@Sun.COM 		 * Transfer queued items to the local list so that
18627961SNatalie.Li@Sun.COM 		 * the mutex can be released.
18637348SJose.Borrego@Sun.COM 		 */
18647348SJose.Borrego@Sun.COM 		while ((shr = list_head(&ad_queue.spq_list)) != NULL) {
18657348SJose.Borrego@Sun.COM 			list_remove(&ad_queue.spq_list, shr);
18667348SJose.Borrego@Sun.COM 			list_insert_tail(&publist, shr);
18677348SJose.Borrego@Sun.COM 		}
18687961SNatalie.Li@Sun.COM 
18697348SJose.Borrego@Sun.COM 		(void) mutex_unlock(&ad_queue.spq_mtx);
18707348SJose.Borrego@Sun.COM 
18717961SNatalie.Li@Sun.COM 		if ((ah = smb_ads_open()) != NULL) {
18727961SNatalie.Li@Sun.COM 			smb_shr_publisher_send(ah, &publist, hostname);
18737961SNatalie.Li@Sun.COM 			smb_ads_close(ah);
18747961SNatalie.Li@Sun.COM 		}
18757348SJose.Borrego@Sun.COM 	}
18767348SJose.Borrego@Sun.COM 
18777348SJose.Borrego@Sun.COM 	(void) mutex_lock(&ad_queue.spq_mtx);
18787961SNatalie.Li@Sun.COM 	smb_shr_publisher_flush(&ad_queue.spq_list);
18797348SJose.Borrego@Sun.COM 	list_destroy(&ad_queue.spq_list);
18807348SJose.Borrego@Sun.COM 	ad_queue.spq_state = SMB_SHR_PQS_NOQUEUE;
18817348SJose.Borrego@Sun.COM 	(void) mutex_unlock(&ad_queue.spq_mtx);
18827348SJose.Borrego@Sun.COM 
18837961SNatalie.Li@Sun.COM 	smb_shr_publisher_flush(&publist);
18847348SJose.Borrego@Sun.COM 	list_destroy(&publist);
18857348SJose.Borrego@Sun.COM 	return (NULL);
18867348SJose.Borrego@Sun.COM }
18877348SJose.Borrego@Sun.COM 
18887348SJose.Borrego@Sun.COM /*
18897961SNatalie.Li@Sun.COM  * Remove items from the specified queue and [un]publish them.
18907348SJose.Borrego@Sun.COM  */
18917348SJose.Borrego@Sun.COM static void
18927348SJose.Borrego@Sun.COM smb_shr_publisher_send(smb_ads_handle_t *ah, list_t *publist, const char *host)
18937348SJose.Borrego@Sun.COM {
18947348SJose.Borrego@Sun.COM 	smb_shr_pitem_t *shr;
18957348SJose.Borrego@Sun.COM 
18967348SJose.Borrego@Sun.COM 	while ((shr = list_head(publist)) != NULL) {
18977961SNatalie.Li@Sun.COM 		(void) mutex_lock(&ad_queue.spq_mtx);
18987961SNatalie.Li@Sun.COM 		if (ad_queue.spq_state != SMB_SHR_PQS_PUBLISHING) {
18997348SJose.Borrego@Sun.COM 			(void) mutex_unlock(&ad_queue.spq_mtx);
19007961SNatalie.Li@Sun.COM 			return;
19017961SNatalie.Li@Sun.COM 		}
19027961SNatalie.Li@Sun.COM 		(void) mutex_unlock(&ad_queue.spq_mtx);
19037348SJose.Borrego@Sun.COM 
19047961SNatalie.Li@Sun.COM 		list_remove(publist, shr);
19057961SNatalie.Li@Sun.COM 
19067961SNatalie.Li@Sun.COM 		if (shr->spi_op == SMB_SHR_PUBLISH)
19077961SNatalie.Li@Sun.COM 			(void) smb_ads_publish_share(ah, shr->spi_name,
19087961SNatalie.Li@Sun.COM 			    NULL, shr->spi_container, host);
19097961SNatalie.Li@Sun.COM 		else
19107961SNatalie.Li@Sun.COM 			(void) smb_ads_remove_share(ah, shr->spi_name,
19117961SNatalie.Li@Sun.COM 			    NULL, shr->spi_container, host);
19127961SNatalie.Li@Sun.COM 
19137348SJose.Borrego@Sun.COM 		free(shr);
19147348SJose.Borrego@Sun.COM 	}
19157348SJose.Borrego@Sun.COM }
19167961SNatalie.Li@Sun.COM 
19177961SNatalie.Li@Sun.COM /*
19187961SNatalie.Li@Sun.COM  * Flush all remaining items from the specified list/queue.
19197961SNatalie.Li@Sun.COM  */
19207961SNatalie.Li@Sun.COM static void
19217961SNatalie.Li@Sun.COM smb_shr_publisher_flush(list_t *lst)
19227961SNatalie.Li@Sun.COM {
19237961SNatalie.Li@Sun.COM 	smb_shr_pitem_t *shr;
19247961SNatalie.Li@Sun.COM 
19257961SNatalie.Li@Sun.COM 	while ((shr = list_head(lst)) != NULL) {
19267961SNatalie.Li@Sun.COM 		list_remove(lst, shr);
19277961SNatalie.Li@Sun.COM 		free(shr);
19287961SNatalie.Li@Sun.COM 	}
19297961SNatalie.Li@Sun.COM }
19308845Samw@Sun.COM 
19318845Samw@Sun.COM /*
19328871Samw@Sun.COM  * If the share path refers to a ZFS file system, add the
19338845Samw@Sun.COM  * .zfs/shares/<share> object.
19348845Samw@Sun.COM  */
19358845Samw@Sun.COM 
19368845Samw@Sun.COM static void
19378845Samw@Sun.COM smb_shr_zfs_add(smb_share_t *si)
19388845Samw@Sun.COM {
19398871Samw@Sun.COM 	libzfs_handle_t *libhd;
19408871Samw@Sun.COM 	zfs_handle_t *zfshd;
19418871Samw@Sun.COM 	int ret;
19428845Samw@Sun.COM 	char dataset[MAXPATHLEN];
19438845Samw@Sun.COM 
19448871Samw@Sun.COM 	if (smb_getdataset(si->shr_path, dataset, MAXPATHLEN) != 0)
19458871Samw@Sun.COM 		return;
19468871Samw@Sun.COM 
19478871Samw@Sun.COM 	if ((libhd = libzfs_init()) == NULL)
19488871Samw@Sun.COM 		return;
19498871Samw@Sun.COM 
19508871Samw@Sun.COM 	if ((zfshd = zfs_open(libhd, dataset, ZFS_TYPE_FILESYSTEM)) == NULL) {
19518871Samw@Sun.COM 		libzfs_fini(libhd);
19528871Samw@Sun.COM 		return;
19538845Samw@Sun.COM 	}
19548871Samw@Sun.COM 
19558871Samw@Sun.COM 	errno = 0;
19568871Samw@Sun.COM 	ret = zfs_smb_acl_add(libhd, dataset, si->shr_path, si->shr_name);
19578871Samw@Sun.COM 	if (ret != 0 && errno != EAGAIN && errno != EEXIST)
19588871Samw@Sun.COM 		syslog(LOG_INFO, "share: failed to add ACL object: %s: %s\n",
19598871Samw@Sun.COM 		    si->shr_name, strerror(errno));
19608871Samw@Sun.COM 
19618871Samw@Sun.COM 	zfs_close(zfshd);
19628871Samw@Sun.COM 	libzfs_fini(libhd);
19638845Samw@Sun.COM }
19648845Samw@Sun.COM 
19658845Samw@Sun.COM /*
19668871Samw@Sun.COM  * If the share path refers to a ZFS file system, remove the
19678845Samw@Sun.COM  * .zfs/shares/<share> object.
19688845Samw@Sun.COM  */
19698845Samw@Sun.COM 
19708845Samw@Sun.COM static void
19718845Samw@Sun.COM smb_shr_zfs_remove(smb_share_t *si)
19728845Samw@Sun.COM {
19738871Samw@Sun.COM 	libzfs_handle_t *libhd;
19748871Samw@Sun.COM 	zfs_handle_t *zfshd;
19758871Samw@Sun.COM 	int ret;
19768845Samw@Sun.COM 	char dataset[MAXPATHLEN];
19778845Samw@Sun.COM 
19788871Samw@Sun.COM 	if (smb_getdataset(si->shr_path, dataset, MAXPATHLEN) != 0)
19798871Samw@Sun.COM 		return;
19808871Samw@Sun.COM 
19818871Samw@Sun.COM 	if ((libhd = libzfs_init()) == NULL)
19828871Samw@Sun.COM 		return;
19838871Samw@Sun.COM 
19848871Samw@Sun.COM 	if ((zfshd = zfs_open(libhd, dataset, ZFS_TYPE_FILESYSTEM)) == NULL) {
19858871Samw@Sun.COM 		libzfs_fini(libhd);
19868871Samw@Sun.COM 		return;
19878845Samw@Sun.COM 	}
19888871Samw@Sun.COM 
19898871Samw@Sun.COM 	errno = 0;
19908871Samw@Sun.COM 	ret = zfs_smb_acl_remove(libhd, dataset, si->shr_path, si->shr_name);
19918871Samw@Sun.COM 	if (ret != 0 && errno != EAGAIN)
19928871Samw@Sun.COM 		syslog(LOG_INFO, "share: failed to remove ACL object: %s: %s\n",
19938871Samw@Sun.COM 		    si->shr_name, strerror(errno));
19948871Samw@Sun.COM 
19958871Samw@Sun.COM 	zfs_close(zfshd);
19968871Samw@Sun.COM 	libzfs_fini(libhd);
19978845Samw@Sun.COM }
19988845Samw@Sun.COM 
19998845Samw@Sun.COM /*
20008871Samw@Sun.COM  * If the share path refers to a ZFS file system, rename the
20018845Samw@Sun.COM  * .zfs/shares/<share> object.
20028845Samw@Sun.COM  */
20038845Samw@Sun.COM 
20048845Samw@Sun.COM static void
20058845Samw@Sun.COM smb_shr_zfs_rename(smb_share_t *from, smb_share_t *to)
20068845Samw@Sun.COM {
20078871Samw@Sun.COM 	libzfs_handle_t *libhd;
20088871Samw@Sun.COM 	zfs_handle_t *zfshd;
20098871Samw@Sun.COM 	int ret;
20108845Samw@Sun.COM 	char dataset[MAXPATHLEN];
20118845Samw@Sun.COM 
20128871Samw@Sun.COM 	if (smb_getdataset(from->shr_path, dataset, MAXPATHLEN) != 0)
20138871Samw@Sun.COM 		return;
20148871Samw@Sun.COM 
20158871Samw@Sun.COM 	if ((libhd = libzfs_init()) == NULL)
20168871Samw@Sun.COM 		return;
20178871Samw@Sun.COM 
20188871Samw@Sun.COM 	if ((zfshd = zfs_open(libhd, dataset, ZFS_TYPE_FILESYSTEM)) == NULL) {
20198871Samw@Sun.COM 		libzfs_fini(libhd);
20208871Samw@Sun.COM 		return;
20218845Samw@Sun.COM 	}
20228871Samw@Sun.COM 
20238871Samw@Sun.COM 	errno = 0;
20248871Samw@Sun.COM 	ret = zfs_smb_acl_rename(libhd, dataset, from->shr_path,
20258871Samw@Sun.COM 	    from->shr_name, to->shr_name);
20268871Samw@Sun.COM 	if (ret != 0 && errno != EAGAIN)
20278871Samw@Sun.COM 		syslog(LOG_INFO, "share: failed to rename ACL object: %s: %s\n",
20288871Samw@Sun.COM 		    from->shr_name, strerror(errno));
20298871Samw@Sun.COM 
20308871Samw@Sun.COM 	zfs_close(zfshd);
20318871Samw@Sun.COM 	libzfs_fini(libhd);
20328845Samw@Sun.COM }
20339832Samw@Sun.COM 
20349832Samw@Sun.COM /*
20359832Samw@Sun.COM  * Enable all privileges in the inheritable set to execute command.
20369832Samw@Sun.COM  */
20379832Samw@Sun.COM static int
20389832Samw@Sun.COM smb_shr_enable_all_privs(void)
20399832Samw@Sun.COM {
20409832Samw@Sun.COM 	priv_set_t *pset;
20419832Samw@Sun.COM 
20429832Samw@Sun.COM 	pset = priv_allocset();
20439832Samw@Sun.COM 	if (pset == NULL)
20449832Samw@Sun.COM 		return (-1);
20459832Samw@Sun.COM 
20469832Samw@Sun.COM 	if (getppriv(PRIV_LIMIT, pset)) {
20479832Samw@Sun.COM 		priv_freeset(pset);
20489832Samw@Sun.COM 		return (-1);
20499832Samw@Sun.COM 	}
20509832Samw@Sun.COM 
20519832Samw@Sun.COM 	if (setppriv(PRIV_ON, PRIV_INHERITABLE, pset)) {
20529832Samw@Sun.COM 		priv_freeset(pset);
20539832Samw@Sun.COM 		return (-1);
20549832Samw@Sun.COM 	}
20559832Samw@Sun.COM 
20569832Samw@Sun.COM 	priv_freeset(pset);
20579832Samw@Sun.COM 	return (0);
20589832Samw@Sun.COM }
20599832Samw@Sun.COM 
20609832Samw@Sun.COM /*
20619832Samw@Sun.COM  * Tokenizes the command string and returns the list of tokens in an array.
20629832Samw@Sun.COM  *
20639832Samw@Sun.COM  * Returns NULL if there are no tokens.
20649832Samw@Sun.COM  */
20659832Samw@Sun.COM static char **
20669832Samw@Sun.COM smb_shr_tokenize_cmd(char *cmdstr)
20679832Samw@Sun.COM {
20689832Samw@Sun.COM 	char *cmd, *buf, *bp, *value;
20699832Samw@Sun.COM 	char **argv, **ap;
20709832Samw@Sun.COM 	int argc, i;
20719832Samw@Sun.COM 
20729832Samw@Sun.COM 	if (cmdstr == NULL || *cmdstr == '\0')
20739832Samw@Sun.COM 		return (NULL);
20749832Samw@Sun.COM 
20759832Samw@Sun.COM 	if ((buf = malloc(MAXPATHLEN)) == NULL)
20769832Samw@Sun.COM 		return (NULL);
20779832Samw@Sun.COM 
20789832Samw@Sun.COM 	(void) strlcpy(buf, cmdstr, MAXPATHLEN);
20799832Samw@Sun.COM 
20809832Samw@Sun.COM 	for (argc = 2, bp = cmdstr; *bp != '\0'; ++bp)
20819832Samw@Sun.COM 		if (*bp == ' ')
20829832Samw@Sun.COM 			++argc;
20839832Samw@Sun.COM 
20849832Samw@Sun.COM 	if ((argv = calloc(argc, sizeof (char *))) == NULL) {
20859832Samw@Sun.COM 		free(buf);
20869832Samw@Sun.COM 		return (NULL);
20879832Samw@Sun.COM 	}
20889832Samw@Sun.COM 
20899832Samw@Sun.COM 	ap = argv;
20909832Samw@Sun.COM 	for (bp = buf, i = 0; i < argc; ++i) {
20919832Samw@Sun.COM 		do {
20929832Samw@Sun.COM 			if ((value = strsep(&bp, " ")) == NULL)
20939832Samw@Sun.COM 				break;
20949832Samw@Sun.COM 		} while (*value == '\0');
20959832Samw@Sun.COM 
20969832Samw@Sun.COM 		if (value == NULL)
20979832Samw@Sun.COM 			break;
20989832Samw@Sun.COM 
20999832Samw@Sun.COM 		*ap++ = value;
21009832Samw@Sun.COM 	}
21019832Samw@Sun.COM 
21029832Samw@Sun.COM 	/* get the filename of the command from the path */
21039832Samw@Sun.COM 	if ((cmd = strrchr(argv[0], '/')) != NULL)
21049832Samw@Sun.COM 		(void) strlcpy(argv[0], ++cmd, strlen(argv[0]));
21059832Samw@Sun.COM 
21069832Samw@Sun.COM 	return (argv);
21079832Samw@Sun.COM }
21089832Samw@Sun.COM 
21099832Samw@Sun.COM /*
21109832Samw@Sun.COM  * Expands the command string for the following substitution tokens:
21119832Samw@Sun.COM  *
21129832Samw@Sun.COM  * %U - Windows username
21139832Samw@Sun.COM  * %D - Name of the domain or workgroup of %U
21149832Samw@Sun.COM  * %h - The server hostname
21159832Samw@Sun.COM  * %M - The client hostname
21169832Samw@Sun.COM  * %L - The server NetBIOS name
21179832Samw@Sun.COM  * %m - The client NetBIOS name. This option is only valid for NetBIOS
21189832Samw@Sun.COM  *      connections (port 139).
21199832Samw@Sun.COM  * %I - The IP address of the client machine
21209832Samw@Sun.COM  * %i - The local IP address to which the client is connected
21219832Samw@Sun.COM  * %S - The name of the share
21229832Samw@Sun.COM  * %P - The root directory of the share
21239832Samw@Sun.COM  * %u - The UID of the Unix user
21249832Samw@Sun.COM  *
21259832Samw@Sun.COM  * Returns 0 on success.  Otherwise -1.
21269832Samw@Sun.COM  */
21279832Samw@Sun.COM static int
21289832Samw@Sun.COM smb_shr_expand_subs(char **cmd_toks, smb_share_t *si, smb_execsub_info_t *subs)
21299832Samw@Sun.COM {
21309832Samw@Sun.COM 	char *fmt, *sub_chr, *ptr;
21319832Samw@Sun.COM 	boolean_t unknown;
21329832Samw@Sun.COM 	char hostname[MAXHOSTNAMELEN];
21339832Samw@Sun.COM 	char ip_str[INET6_ADDRSTRLEN];
21349832Samw@Sun.COM 	char name[SMB_PI_MAX_HOST];
21359832Samw@Sun.COM 	mts_wchar_t wbuf[SMB_PI_MAX_HOST];
21369832Samw@Sun.COM 	unsigned int cpid = oem_get_smb_cpid();
21379832Samw@Sun.COM 	int i;
21389832Samw@Sun.COM 
21399832Samw@Sun.COM 	if (cmd_toks == NULL || *cmd_toks == NULL)
21409832Samw@Sun.COM 		return (-1);
21419832Samw@Sun.COM 
21429832Samw@Sun.COM 	for (i = 1; cmd_toks[i]; i++) {
21439832Samw@Sun.COM 		fmt = cmd_toks[i];
21449832Samw@Sun.COM 		if (*fmt == '%') {
21459832Samw@Sun.COM 			sub_chr = fmt + 1;
21469832Samw@Sun.COM 			unknown = B_FALSE;
21479832Samw@Sun.COM 
21489832Samw@Sun.COM 			switch (*sub_chr) {
21499832Samw@Sun.COM 			case 'U':
21509832Samw@Sun.COM 				ptr = strdup(subs->e_winname);
21519832Samw@Sun.COM 				break;
21529832Samw@Sun.COM 			case 'D':
21539832Samw@Sun.COM 				ptr = strdup(subs->e_userdom);
21549832Samw@Sun.COM 				break;
21559832Samw@Sun.COM 			case 'h':
21569832Samw@Sun.COM 				if (gethostname(hostname, MAXHOSTNAMELEN) != 0)
21579832Samw@Sun.COM 					unknown = B_TRUE;
21589832Samw@Sun.COM 				else
21599832Samw@Sun.COM 					ptr = strdup(hostname);
21609832Samw@Sun.COM 				break;
21619832Samw@Sun.COM 			case 'M':
21629832Samw@Sun.COM 				if (smb_getnameinfo(&subs->e_cli_ipaddr,
21639832Samw@Sun.COM 				    hostname, sizeof (hostname), 0) != 0)
21649832Samw@Sun.COM 					unknown = B_TRUE;
21659832Samw@Sun.COM 				else
21669832Samw@Sun.COM 					ptr = strdup(hostname);
21679832Samw@Sun.COM 				break;
21689832Samw@Sun.COM 			case 'L':
21699832Samw@Sun.COM 				if (smb_getnetbiosname(hostname,
21709832Samw@Sun.COM 				    NETBIOS_NAME_SZ) != 0)
21719832Samw@Sun.COM 					unknown = B_TRUE;
21729832Samw@Sun.COM 				else
21739832Samw@Sun.COM 					ptr = strdup(hostname);
21749832Samw@Sun.COM 				break;
21759832Samw@Sun.COM 			case 'm':
21769832Samw@Sun.COM 				if (*subs->e_cli_netbiosname == '\0')
21779832Samw@Sun.COM 					unknown = B_TRUE;
21789832Samw@Sun.COM 				else {
21799832Samw@Sun.COM 					(void) mts_mbstowcs(wbuf,
21809832Samw@Sun.COM 					    subs->e_cli_netbiosname,
21819832Samw@Sun.COM 					    SMB_PI_MAX_HOST - 1);
21829832Samw@Sun.COM 
21839832Samw@Sun.COM 					if (unicodestooems(name, wbuf,
21849832Samw@Sun.COM 					    SMB_PI_MAX_HOST, cpid) == 0)
21859832Samw@Sun.COM 						(void) strlcpy(name,
21869832Samw@Sun.COM 						    subs->e_cli_netbiosname,
21879832Samw@Sun.COM 						    SMB_PI_MAX_HOST);
21889832Samw@Sun.COM 
21899832Samw@Sun.COM 					ptr = strdup(name);
21909832Samw@Sun.COM 				}
21919832Samw@Sun.COM 				break;
21929832Samw@Sun.COM 			case 'I':
21939832Samw@Sun.COM 				if (smb_inet_ntop(&subs->e_cli_ipaddr, ip_str,
21949832Samw@Sun.COM 				    SMB_IPSTRLEN(subs->e_cli_ipaddr.a_family))
21959832Samw@Sun.COM 				    != NULL)
21969832Samw@Sun.COM 					ptr = strdup(ip_str);
21979832Samw@Sun.COM 				else
21989832Samw@Sun.COM 					unknown = B_TRUE;
21999832Samw@Sun.COM 				break;
22009832Samw@Sun.COM 			case 'i':
22019832Samw@Sun.COM 				if (smb_inet_ntop(&subs->e_srv_ipaddr, ip_str,
22029832Samw@Sun.COM 				    SMB_IPSTRLEN(subs->e_srv_ipaddr.a_family))
22039832Samw@Sun.COM 				    != NULL)
22049832Samw@Sun.COM 					ptr = strdup(ip_str);
22059832Samw@Sun.COM 				else
22069832Samw@Sun.COM 					unknown = B_TRUE;
22079832Samw@Sun.COM 				break;
22089832Samw@Sun.COM 			case 'S':
22099832Samw@Sun.COM 				ptr = strdup(si->shr_name);
22109832Samw@Sun.COM 				break;
22119832Samw@Sun.COM 			case 'P':
22129832Samw@Sun.COM 				ptr = strdup(si->shr_path);
22139832Samw@Sun.COM 				break;
22149832Samw@Sun.COM 			case 'u':
22159832Samw@Sun.COM 				(void) snprintf(name, sizeof (name), "%u",
22169832Samw@Sun.COM 				    subs->e_uid);
22179832Samw@Sun.COM 				ptr = strdup(name);
22189832Samw@Sun.COM 				break;
22199832Samw@Sun.COM 			default:
22209832Samw@Sun.COM 				/* unknown sub char */
22219832Samw@Sun.COM 				unknown = B_TRUE;
22229832Samw@Sun.COM 				break;
22239832Samw@Sun.COM 			}
22249832Samw@Sun.COM 
22259832Samw@Sun.COM 			if (unknown)
22269832Samw@Sun.COM 				ptr = strdup("");
22279832Samw@Sun.COM 
22289832Samw@Sun.COM 		} else  /* first char of cmd's arg is not '%' char */
22299832Samw@Sun.COM 			ptr = strdup("");
22309832Samw@Sun.COM 
22319832Samw@Sun.COM 		cmd_toks[i] = ptr;
22329832Samw@Sun.COM 
22339832Samw@Sun.COM 		if (ptr == NULL) {
22349832Samw@Sun.COM 			for (i = 1; cmd_toks[i]; i++)
22359832Samw@Sun.COM 				free(cmd_toks[i]);
22369832Samw@Sun.COM 
22379832Samw@Sun.COM 			return (-1);
22389832Samw@Sun.COM 		}
22399832Samw@Sun.COM 	}
22409832Samw@Sun.COM 
22419832Samw@Sun.COM 	return (0);
22429832Samw@Sun.COM }
22439832Samw@Sun.COM 
22449832Samw@Sun.COM /*ARGSUSED*/
22459832Samw@Sun.COM static void
22469832Samw@Sun.COM smb_shr_sig_abnormal_term(int sig_val)
22479832Samw@Sun.COM {
22489832Samw@Sun.COM 	/*
22499832Samw@Sun.COM 	 * Calling _exit() prevents parent process from getting SIGTERM/SIGINT
22509832Samw@Sun.COM 	 * signal.
22519832Samw@Sun.COM 	 */
22529832Samw@Sun.COM 	_exit(-1);
22539832Samw@Sun.COM }
22549832Samw@Sun.COM 
22559832Samw@Sun.COM /*ARGSUSED*/
22569832Samw@Sun.COM static void
22579832Samw@Sun.COM smb_shr_sig_child(int sig_val)
22589832Samw@Sun.COM {
22599832Samw@Sun.COM 	/*
22609832Samw@Sun.COM 	 * Catch the signal and allow the exit status of the child process
22619832Samw@Sun.COM 	 * to be available for reaping.
22629832Samw@Sun.COM 	 */
22639832Samw@Sun.COM }
22649832Samw@Sun.COM 
22659832Samw@Sun.COM /*
22669832Samw@Sun.COM  *  Gets the exec bit flags for each share.
22679832Samw@Sun.COM  */
22689832Samw@Sun.COM static void
22699832Samw@Sun.COM smb_shr_get_exec_info(void)
22709832Samw@Sun.COM {
22719832Samw@Sun.COM 	char buf[MAXPATHLEN];
22729832Samw@Sun.COM 
22739832Samw@Sun.COM 	(void) mutex_lock(&smb_shr_exec_mtx);
22749832Samw@Sun.COM 
22759832Samw@Sun.COM 	smb_shr_exec_flags = 0;
22769832Samw@Sun.COM 
22779832Samw@Sun.COM 	*smb_shr_exec_map = '\0';
22789832Samw@Sun.COM 	(void) smb_config_getstr(SMB_CI_MAP, smb_shr_exec_map,
22799832Samw@Sun.COM 	    sizeof (smb_shr_exec_map));
22809832Samw@Sun.COM 	if (*smb_shr_exec_map != '\0')
22819832Samw@Sun.COM 		smb_shr_exec_flags |= SMB_SHRF_MAP;
22829832Samw@Sun.COM 
22839832Samw@Sun.COM 	*smb_shr_exec_unmap = '\0';
22849832Samw@Sun.COM 	(void) smb_config_getstr(SMB_CI_UNMAP, smb_shr_exec_unmap,
22859832Samw@Sun.COM 	    sizeof (smb_shr_exec_unmap));
22869832Samw@Sun.COM 	if (*smb_shr_exec_unmap != '\0')
22879832Samw@Sun.COM 		smb_shr_exec_flags |= SMB_SHRF_UNMAP;
22889832Samw@Sun.COM 
22899832Samw@Sun.COM 	*buf = '\0';
22909832Samw@Sun.COM 	(void) smb_config_getstr(SMB_CI_DISPOSITION, buf, sizeof (buf));
22919832Samw@Sun.COM 	if (*buf != '\0')
22929832Samw@Sun.COM 		if (strcasecmp(buf, SMB_SHR_DISP_TERM_STR) == 0)
22939832Samw@Sun.COM 			smb_shr_exec_flags |= SMB_SHRF_DISP_TERM;
22949832Samw@Sun.COM 
22959832Samw@Sun.COM 	(void) mutex_unlock(&smb_shr_exec_mtx);
22969832Samw@Sun.COM }
22979832Samw@Sun.COM 
22989832Samw@Sun.COM /*
22999832Samw@Sun.COM  *  Sets the exec bit flags for each share.
23009832Samw@Sun.COM  */
23019832Samw@Sun.COM static void
23029832Samw@Sun.COM smb_shr_set_exec_flags(smb_share_t *si)
23039832Samw@Sun.COM {
23049832Samw@Sun.COM 	(void) mutex_lock(&smb_shr_exec_mtx);
23059832Samw@Sun.COM 	si->shr_flags &= ~SMB_SHRF_EXEC_MASK;
23069832Samw@Sun.COM 	si->shr_flags |= smb_shr_exec_flags;
23079832Samw@Sun.COM 	(void) mutex_unlock(&smb_shr_exec_mtx);
23089832Samw@Sun.COM }
2309