xref: /onnv-gate/usr/src/lib/smbsrv/libmlsvc/common/smb_share.c (revision 9231:152b6e0d9b1a)
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>
407052Samw 
417052Samw #include <smbsrv/libsmb.h>
427052Samw #include <smbsrv/libsmbns.h>
437588Samw@Sun.COM #include <smbsrv/libmlsvc.h>
447052Samw 
457052Samw #include <smbsrv/lm.h>
467052Samw #include <smbsrv/smb_share.h>
477052Samw #include <smbsrv/cifs.h>
487961SNatalie.Li@Sun.COM #include <smbsrv/nterror.h>
497052Samw 
507961SNatalie.Li@Sun.COM #define	SMB_SHR_ERROR_THRESHOLD		3
517052Samw 
528334SJose.Borrego@Sun.COM #define	SMB_SHR_CSC_BUFSZ		64
538334SJose.Borrego@Sun.COM 
547348SJose.Borrego@Sun.COM /*
557348SJose.Borrego@Sun.COM  * Cache functions and vars
567348SJose.Borrego@Sun.COM  */
577961SNatalie.Li@Sun.COM #define	SMB_SHR_HTAB_SZ			1024
587052Samw 
597961SNatalie.Li@Sun.COM /*
607961SNatalie.Li@Sun.COM  * Cache handle
617961SNatalie.Li@Sun.COM  *
627961SNatalie.Li@Sun.COM  * Shares cache is a hash table.
637961SNatalie.Li@Sun.COM  *
647961SNatalie.Li@Sun.COM  * sc_cache		pointer to hash table handle
657961SNatalie.Li@Sun.COM  * sc_cache_lck		synchronize cache read/write accesses
667961SNatalie.Li@Sun.COM  * sc_state		cache state machine values
677961SNatalie.Li@Sun.COM  * sc_nops		number of inflight/pending cache operations
687961SNatalie.Li@Sun.COM  * sc_mtx		protects handle fields
697961SNatalie.Li@Sun.COM  */
707961SNatalie.Li@Sun.COM typedef struct smb_shr_cache {
717961SNatalie.Li@Sun.COM 	HT_HANDLE	*sc_cache;
727961SNatalie.Li@Sun.COM 	rwlock_t	sc_cache_lck;
737961SNatalie.Li@Sun.COM 	mutex_t		sc_mtx;
747961SNatalie.Li@Sun.COM 	cond_t		sc_cv;
757961SNatalie.Li@Sun.COM 	uint32_t	sc_state;
767961SNatalie.Li@Sun.COM 	uint32_t	sc_nops;
777961SNatalie.Li@Sun.COM } smb_shr_cache_t;
787961SNatalie.Li@Sun.COM 
797961SNatalie.Li@Sun.COM /*
807961SNatalie.Li@Sun.COM  * Cache states
817961SNatalie.Li@Sun.COM  */
827961SNatalie.Li@Sun.COM #define	SMB_SHR_CACHE_STATE_NONE	0
837961SNatalie.Li@Sun.COM #define	SMB_SHR_CACHE_STATE_CREATED	1
847961SNatalie.Li@Sun.COM #define	SMB_SHR_CACHE_STATE_DESTROYING	2
857961SNatalie.Li@Sun.COM 
867961SNatalie.Li@Sun.COM /*
877961SNatalie.Li@Sun.COM  * Cache lock modes
887961SNatalie.Li@Sun.COM  */
897961SNatalie.Li@Sun.COM #define	SMB_SHR_CACHE_RDLOCK	0
907961SNatalie.Li@Sun.COM #define	SMB_SHR_CACHE_WRLOCK	1
917961SNatalie.Li@Sun.COM 
927961SNatalie.Li@Sun.COM static smb_shr_cache_t smb_shr_cache;
937052Samw 
947052Samw static uint32_t smb_shr_cache_create(void);
957348SJose.Borrego@Sun.COM static void smb_shr_cache_destroy(void);
967961SNatalie.Li@Sun.COM static uint32_t smb_shr_cache_lock(int);
977961SNatalie.Li@Sun.COM static void smb_shr_cache_unlock(void);
987961SNatalie.Li@Sun.COM static int smb_shr_cache_count(void);
997961SNatalie.Li@Sun.COM static smb_share_t *smb_shr_cache_iterate(smb_shriter_t *);
1007961SNatalie.Li@Sun.COM 
1017961SNatalie.Li@Sun.COM static smb_share_t *smb_shr_cache_findent(char *);
1027348SJose.Borrego@Sun.COM static uint32_t smb_shr_cache_addent(smb_share_t *);
1037348SJose.Borrego@Sun.COM static void smb_shr_cache_delent(char *);
1047348SJose.Borrego@Sun.COM static void smb_shr_cache_freent(HT_ITEM *);
1057052Samw 
1067348SJose.Borrego@Sun.COM /*
1077348SJose.Borrego@Sun.COM  * sharemgr functions
1087348SJose.Borrego@Sun.COM  */
1097961SNatalie.Li@Sun.COM static void *smb_shr_sa_loadall(void *);
1107961SNatalie.Li@Sun.COM static void smb_shr_sa_loadgrp(sa_group_t);
1117961SNatalie.Li@Sun.COM static uint32_t smb_shr_sa_load(sa_share_t, sa_resource_t);
1128334SJose.Borrego@Sun.COM static uint32_t smb_shr_sa_loadbyname(char *);
1137961SNatalie.Li@Sun.COM static uint32_t smb_shr_sa_get(sa_share_t, sa_resource_t, smb_share_t *);
1147052Samw 
1157052Samw /*
1168845Samw@Sun.COM  * .ZFS management functions
1178845Samw@Sun.COM  */
1188845Samw@Sun.COM static void smb_shr_zfs_add(smb_share_t *);
1198845Samw@Sun.COM static void smb_shr_zfs_remove(smb_share_t *);
1208845Samw@Sun.COM static void smb_shr_zfs_rename(smb_share_t *, smb_share_t *);
1218845Samw@Sun.COM 
1228845Samw@Sun.COM /*
1237348SJose.Borrego@Sun.COM  * share publishing
1247348SJose.Borrego@Sun.COM  */
1257348SJose.Borrego@Sun.COM #define	SMB_SHR_PUBLISH		0
1267348SJose.Borrego@Sun.COM #define	SMB_SHR_UNPUBLISH	1
1277348SJose.Borrego@Sun.COM 
1287348SJose.Borrego@Sun.COM typedef struct smb_shr_pitem {
1297348SJose.Borrego@Sun.COM 	list_node_t	spi_lnd;
1307348SJose.Borrego@Sun.COM 	char		spi_name[MAXNAMELEN];
1317348SJose.Borrego@Sun.COM 	char		spi_container[MAXPATHLEN];
1327348SJose.Borrego@Sun.COM 	char		spi_op;
1337348SJose.Borrego@Sun.COM } smb_shr_pitem_t;
1347348SJose.Borrego@Sun.COM 
1357348SJose.Borrego@Sun.COM /*
1367348SJose.Borrego@Sun.COM  * publish queue states
1377348SJose.Borrego@Sun.COM  */
1387348SJose.Borrego@Sun.COM #define	SMB_SHR_PQS_NOQUEUE	0
1397348SJose.Borrego@Sun.COM #define	SMB_SHR_PQS_READY	1	/* the queue is ready */
1407348SJose.Borrego@Sun.COM #define	SMB_SHR_PQS_PUBLISHING	2	/* publisher thread is running */
1417348SJose.Borrego@Sun.COM #define	SMB_SHR_PQS_STOPPING	3
1427348SJose.Borrego@Sun.COM 
1437348SJose.Borrego@Sun.COM /*
1447348SJose.Borrego@Sun.COM  * share publishing queue
1457348SJose.Borrego@Sun.COM  */
1467348SJose.Borrego@Sun.COM typedef struct smb_shr_pqueue {
1477348SJose.Borrego@Sun.COM 	list_t		spq_list;
1487348SJose.Borrego@Sun.COM 	mutex_t		spq_mtx;
1497348SJose.Borrego@Sun.COM 	cond_t		spq_cv;
1507348SJose.Borrego@Sun.COM 	uint32_t	spq_state;
1517348SJose.Borrego@Sun.COM } smb_shr_pqueue_t;
1527348SJose.Borrego@Sun.COM 
1537348SJose.Borrego@Sun.COM static smb_shr_pqueue_t ad_queue;
1547348SJose.Borrego@Sun.COM 
1557348SJose.Borrego@Sun.COM static int smb_shr_publisher_start(void);
1567348SJose.Borrego@Sun.COM static void smb_shr_publisher_stop(void);
1577348SJose.Borrego@Sun.COM static void smb_shr_publisher_send(smb_ads_handle_t *, list_t *, const char *);
1587961SNatalie.Li@Sun.COM static void smb_shr_publisher_queue(const char *, const char *, char);
1597348SJose.Borrego@Sun.COM static void *smb_shr_publisher(void *);
1607961SNatalie.Li@Sun.COM static void smb_shr_publisher_flush(list_t *);
1617961SNatalie.Li@Sun.COM static void smb_shr_publish(const char *, const char *);
1627961SNatalie.Li@Sun.COM static void smb_shr_unpublish(const char *, const char *);
1637348SJose.Borrego@Sun.COM 
1647348SJose.Borrego@Sun.COM /*
1657961SNatalie.Li@Sun.COM  * Utility/helper functions
1667961SNatalie.Li@Sun.COM  */
1678334SJose.Borrego@Sun.COM static uint32_t smb_shr_lookup(char *, smb_share_t *);
1687961SNatalie.Li@Sun.COM static uint32_t smb_shr_addipc(void);
1697961SNatalie.Li@Sun.COM static void smb_shr_set_oemname(smb_share_t *);
1707961SNatalie.Li@Sun.COM 
1718474SJose.Borrego@Sun.COM 
1728474SJose.Borrego@Sun.COM /*
1738474SJose.Borrego@Sun.COM  * libshare handle and synchronization
1748474SJose.Borrego@Sun.COM  */
1758474SJose.Borrego@Sun.COM typedef struct smb_sa_handle {
1768474SJose.Borrego@Sun.COM 	sa_handle_t	sa_handle;
1778474SJose.Borrego@Sun.COM 	mutex_t		sa_mtx;
1788474SJose.Borrego@Sun.COM 	boolean_t	sa_in_service;
1798474SJose.Borrego@Sun.COM } smb_sa_handle_t;
1808474SJose.Borrego@Sun.COM 
1818474SJose.Borrego@Sun.COM static smb_sa_handle_t smb_sa_handle;
1828474SJose.Borrego@Sun.COM 
1837961SNatalie.Li@Sun.COM /*
1848334SJose.Borrego@Sun.COM  * Creates and initializes the cache and starts the publisher
1858334SJose.Borrego@Sun.COM  * thread.
1867052Samw  */
1877052Samw int
1887052Samw smb_shr_start(void)
1897052Samw {
1908474SJose.Borrego@Sun.COM 	(void) mutex_lock(&smb_sa_handle.sa_mtx);
1918474SJose.Borrego@Sun.COM 	smb_sa_handle.sa_in_service = B_TRUE;
1928474SJose.Borrego@Sun.COM 	(void) mutex_unlock(&smb_sa_handle.sa_mtx);
1938474SJose.Borrego@Sun.COM 
1947961SNatalie.Li@Sun.COM 	if (smb_shr_cache_create() != NERR_Success)
1957961SNatalie.Li@Sun.COM 		return (ENOMEM);
1967961SNatalie.Li@Sun.COM 
1977961SNatalie.Li@Sun.COM 	if (smb_shr_addipc() != NERR_Success)
1987961SNatalie.Li@Sun.COM 		return (ENOMEM);
1997961SNatalie.Li@Sun.COM 
2008334SJose.Borrego@Sun.COM 	return (smb_shr_publisher_start());
2018334SJose.Borrego@Sun.COM }
2028334SJose.Borrego@Sun.COM 
2038334SJose.Borrego@Sun.COM void
2048334SJose.Borrego@Sun.COM smb_shr_stop(void)
2058334SJose.Borrego@Sun.COM {
2068334SJose.Borrego@Sun.COM 	smb_shr_cache_destroy();
2078334SJose.Borrego@Sun.COM 	smb_shr_publisher_stop();
2088474SJose.Borrego@Sun.COM 
2098474SJose.Borrego@Sun.COM 	(void) mutex_lock(&smb_sa_handle.sa_mtx);
2108474SJose.Borrego@Sun.COM 	smb_sa_handle.sa_in_service = B_FALSE;
2118474SJose.Borrego@Sun.COM 
2128474SJose.Borrego@Sun.COM 	if (smb_sa_handle.sa_handle != NULL) {
2138474SJose.Borrego@Sun.COM 		sa_fini(smb_sa_handle.sa_handle);
2148474SJose.Borrego@Sun.COM 		smb_sa_handle.sa_handle = NULL;
2158474SJose.Borrego@Sun.COM 	}
2168474SJose.Borrego@Sun.COM 
2178474SJose.Borrego@Sun.COM 	(void) mutex_unlock(&smb_sa_handle.sa_mtx);
2188474SJose.Borrego@Sun.COM }
2198474SJose.Borrego@Sun.COM 
2208474SJose.Borrego@Sun.COM /*
2218474SJose.Borrego@Sun.COM  * Get a handle and exclusive access to the libshare API.
2228474SJose.Borrego@Sun.COM  */
2238474SJose.Borrego@Sun.COM sa_handle_t
2248474SJose.Borrego@Sun.COM smb_shr_sa_enter(void)
2258474SJose.Borrego@Sun.COM {
2268474SJose.Borrego@Sun.COM 	(void) mutex_lock(&smb_sa_handle.sa_mtx);
2278474SJose.Borrego@Sun.COM 	if (!smb_sa_handle.sa_in_service) {
2288474SJose.Borrego@Sun.COM 		(void) mutex_unlock(&smb_sa_handle.sa_mtx);
2298474SJose.Borrego@Sun.COM 		return (NULL);
2308474SJose.Borrego@Sun.COM 	}
2318474SJose.Borrego@Sun.COM 
2328474SJose.Borrego@Sun.COM 	if (smb_sa_handle.sa_handle == NULL) {
2338474SJose.Borrego@Sun.COM 		smb_sa_handle.sa_handle = sa_init(SA_INIT_SHARE_API);
2348474SJose.Borrego@Sun.COM 		if (smb_sa_handle.sa_handle == NULL) {
2358474SJose.Borrego@Sun.COM 			syslog(LOG_ERR, "share: failed to get libshare handle");
2368474SJose.Borrego@Sun.COM 			(void) mutex_unlock(&smb_sa_handle.sa_mtx);
2378474SJose.Borrego@Sun.COM 			return (NULL);
2388474SJose.Borrego@Sun.COM 		}
2398474SJose.Borrego@Sun.COM 	}
2408474SJose.Borrego@Sun.COM 
2418474SJose.Borrego@Sun.COM 	return (smb_sa_handle.sa_handle);
2428474SJose.Borrego@Sun.COM }
2438474SJose.Borrego@Sun.COM 
2448474SJose.Borrego@Sun.COM /*
2458474SJose.Borrego@Sun.COM  * Release exclusive access to the libshare API.
2468474SJose.Borrego@Sun.COM  */
2478474SJose.Borrego@Sun.COM void
2488474SJose.Borrego@Sun.COM smb_shr_sa_exit(void)
2498474SJose.Borrego@Sun.COM {
2508474SJose.Borrego@Sun.COM 	(void) mutex_unlock(&smb_sa_handle.sa_mtx);
2518334SJose.Borrego@Sun.COM }
2528334SJose.Borrego@Sun.COM 
2538334SJose.Borrego@Sun.COM /*
2548334SJose.Borrego@Sun.COM  * Launches a thread to populate the share cache by share information
2558334SJose.Borrego@Sun.COM  * stored in sharemgr
2568334SJose.Borrego@Sun.COM  */
2578334SJose.Borrego@Sun.COM int
2588334SJose.Borrego@Sun.COM smb_shr_load(void)
2598334SJose.Borrego@Sun.COM {
2608334SJose.Borrego@Sun.COM 	pthread_t load_thr;
2618334SJose.Borrego@Sun.COM 	pthread_attr_t tattr;
2628334SJose.Borrego@Sun.COM 	int rc;
2638334SJose.Borrego@Sun.COM 
2647348SJose.Borrego@Sun.COM 	(void) pthread_attr_init(&tattr);
2657348SJose.Borrego@Sun.COM 	(void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
2667961SNatalie.Li@Sun.COM 	rc = pthread_create(&load_thr, &tattr, smb_shr_sa_loadall, 0);
2677348SJose.Borrego@Sun.COM 	(void) pthread_attr_destroy(&tattr);
2687052Samw 
2697052Samw 	return (rc);
2707052Samw }
2717052Samw 
2727052Samw /*
2737348SJose.Borrego@Sun.COM  * Return the total number of shares
2747052Samw  */
2757052Samw int
2767052Samw smb_shr_count(void)
2777052Samw {
2787961SNatalie.Li@Sun.COM 	int n_shares = 0;
2797052Samw 
2807961SNatalie.Li@Sun.COM 	if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) {
2817961SNatalie.Li@Sun.COM 		n_shares = smb_shr_cache_count();
2827961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
2837961SNatalie.Li@Sun.COM 	}
2847052Samw 
2857052Samw 	return (n_shares);
2867052Samw }
2877052Samw 
2887052Samw /*
2897052Samw  * smb_shr_iterinit
2907052Samw  *
2917348SJose.Borrego@Sun.COM  * Initialize given iterator for traversing hash table.
2927052Samw  */
2937052Samw void
2947348SJose.Borrego@Sun.COM smb_shr_iterinit(smb_shriter_t *shi)
2957052Samw {
2967052Samw 	bzero(shi, sizeof (smb_shriter_t));
2977348SJose.Borrego@Sun.COM 	shi->si_first = B_TRUE;
2987052Samw }
2997052Samw 
3007052Samw /*
3017052Samw  * smb_shr_iterate
3027052Samw  *
3037052Samw  * Iterate on the shares in the hash table. The iterator must be initialized
3047052Samw  * before the first iteration. On subsequent calls, the iterator must be
3057052Samw  * passed unchanged.
3067052Samw  *
3077052Samw  * Returns NULL on failure or when all shares are visited, otherwise
3087052Samw  * returns information of visited share.
3097052Samw  */
3107052Samw smb_share_t *
3117052Samw smb_shr_iterate(smb_shriter_t *shi)
3127052Samw {
3137348SJose.Borrego@Sun.COM 	smb_share_t *share = NULL;
3147961SNatalie.Li@Sun.COM 	smb_share_t *cached_si;
3157052Samw 
3167961SNatalie.Li@Sun.COM 	if (shi == NULL)
3177052Samw 		return (NULL);
3187052Samw 
3197961SNatalie.Li@Sun.COM 	if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) {
3207961SNatalie.Li@Sun.COM 		if ((cached_si = smb_shr_cache_iterate(shi)) != NULL) {
3217961SNatalie.Li@Sun.COM 			share = &shi->si_share;
3227961SNatalie.Li@Sun.COM 			bcopy(cached_si, share, sizeof (smb_share_t));
3237961SNatalie.Li@Sun.COM 		}
3247961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
3257052Samw 	}
3267052Samw 
3277348SJose.Borrego@Sun.COM 	return (share);
3287052Samw }
3297052Samw 
3307052Samw /*
3317961SNatalie.Li@Sun.COM  * Adds the given share to cache, publishes the share in ADS
3327961SNatalie.Li@Sun.COM  * if it has an AD container, calls kernel to take a hold on
3337961SNatalie.Li@Sun.COM  * the shared file system. If it can't take a hold on the
3347961SNatalie.Li@Sun.COM  * shared file system, it's either because shared directory
3357961SNatalie.Li@Sun.COM  * does not exist or some other error has occurred, in any
3367961SNatalie.Li@Sun.COM  * case the share is removed from the cache.
3377052Samw  *
3387961SNatalie.Li@Sun.COM  * If the specified share is an autohome share which already
3397961SNatalie.Li@Sun.COM  * exists in the cache, just increments the reference count.
3407052Samw  */
3417052Samw uint32_t
3427961SNatalie.Li@Sun.COM smb_shr_add(smb_share_t *si)
3437052Samw {
3447961SNatalie.Li@Sun.COM 	smb_share_t *cached_si;
3457961SNatalie.Li@Sun.COM 	uint32_t status;
3467348SJose.Borrego@Sun.COM 	int rc;
3477052Samw 
3487348SJose.Borrego@Sun.COM 	assert(si != NULL);
3497052Samw 
3507348SJose.Borrego@Sun.COM 	if (!smb_shr_chkname(si->shr_name))
3517348SJose.Borrego@Sun.COM 		return (ERROR_INVALID_NAME);
3527052Samw 
3537961SNatalie.Li@Sun.COM 	if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success)
3547961SNatalie.Li@Sun.COM 		return (NERR_InternalError);
3557052Samw 
3567961SNatalie.Li@Sun.COM 	cached_si = smb_shr_cache_findent(si->shr_name);
3577961SNatalie.Li@Sun.COM 	if (cached_si) {
3587961SNatalie.Li@Sun.COM 		if (si->shr_flags & SMB_SHRF_AUTOHOME) {
3597961SNatalie.Li@Sun.COM 			cached_si->shr_refcnt++;
3607961SNatalie.Li@Sun.COM 			status = NERR_Success;
3617961SNatalie.Li@Sun.COM 		} else {
3627961SNatalie.Li@Sun.COM 			status = NERR_DuplicateShare;
3637961SNatalie.Li@Sun.COM 		}
3647961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
3657052Samw 		return (status);
3667052Samw 	}
3677052Samw 
3687961SNatalie.Li@Sun.COM 	if ((status = smb_shr_cache_addent(si)) != NERR_Success) {
3697961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
3707961SNatalie.Li@Sun.COM 		return (status);
3717961SNatalie.Li@Sun.COM 	}
3727961SNatalie.Li@Sun.COM 
3737961SNatalie.Li@Sun.COM 	/* don't hold the lock across door call */
3747961SNatalie.Li@Sun.COM 	smb_shr_cache_unlock();
3757961SNatalie.Li@Sun.COM 
3767961SNatalie.Li@Sun.COM 	/* call kernel to take a hold on the shared file system */
3777588Samw@Sun.COM 	rc = mlsvc_set_share(SMB_SHROP_ADD, si->shr_path, si->shr_name);
3787348SJose.Borrego@Sun.COM 
3797348SJose.Borrego@Sun.COM 	if (rc == 0) {
3807961SNatalie.Li@Sun.COM 		smb_shr_publish(si->shr_name, si->shr_container);
3818845Samw@Sun.COM 
3828845Samw@Sun.COM 		/* If path is ZFS, add the .zfs/shares/<share> entry. */
3838845Samw@Sun.COM 		smb_shr_zfs_add(si);
3848845Samw@Sun.COM 
3857961SNatalie.Li@Sun.COM 		return (NERR_Success);
3867052Samw 	}
3877052Samw 
3887961SNatalie.Li@Sun.COM 	if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) == NERR_Success) {
3897961SNatalie.Li@Sun.COM 		smb_shr_cache_delent(si->shr_name);
3907961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
3917961SNatalie.Li@Sun.COM 	}
3927052Samw 
3937052Samw 	/*
3947348SJose.Borrego@Sun.COM 	 * rc == ENOENT means the shared directory doesn't exist
3957052Samw 	 */
3967348SJose.Borrego@Sun.COM 	return ((rc == ENOENT) ? NERR_UnknownDevDir : NERR_InternalError);
3977052Samw }
3987052Samw 
3997052Samw /*
4007961SNatalie.Li@Sun.COM  * Removes the specified share from cache, removes it from AD
4017961SNatalie.Li@Sun.COM  * if it has an AD container, and calls the kernel to release
4027961SNatalie.Li@Sun.COM  * the hold on the shared file system.
4037052Samw  *
4047961SNatalie.Li@Sun.COM  * If this is an autohome share then decrement the reference
4057961SNatalie.Li@Sun.COM  * count. If it reaches 0 then it proceeds with removing steps.
4067052Samw  */
4077348SJose.Borrego@Sun.COM uint32_t
4087961SNatalie.Li@Sun.COM smb_shr_remove(char *sharename)
4097052Samw {
4107961SNatalie.Li@Sun.COM 	smb_share_t *si;
4117961SNatalie.Li@Sun.COM 	char path[MAXPATHLEN];
4127961SNatalie.Li@Sun.COM 	char container[MAXPATHLEN];
4137348SJose.Borrego@Sun.COM 
4147348SJose.Borrego@Sun.COM 	assert(sharename != NULL);
4157348SJose.Borrego@Sun.COM 
4167961SNatalie.Li@Sun.COM 	if (!smb_shr_chkname(sharename))
4177961SNatalie.Li@Sun.COM 		return (ERROR_INVALID_NAME);
4187052Samw 
4197961SNatalie.Li@Sun.COM 	if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success)
4207961SNatalie.Li@Sun.COM 		return (NERR_InternalError);
4217961SNatalie.Li@Sun.COM 
4227961SNatalie.Li@Sun.COM 	if ((si = smb_shr_cache_findent(sharename)) == NULL) {
4237961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
4247961SNatalie.Li@Sun.COM 		return (NERR_NetNameNotFound);
4257961SNatalie.Li@Sun.COM 	}
4267348SJose.Borrego@Sun.COM 
4277961SNatalie.Li@Sun.COM 	if (si->shr_type & STYPE_IPC) {
4287961SNatalie.Li@Sun.COM 		/* IPC$ share cannot be removed */
4297961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
4307961SNatalie.Li@Sun.COM 		return (ERROR_ACCESS_DENIED);
4317961SNatalie.Li@Sun.COM 	}
4327961SNatalie.Li@Sun.COM 
4337961SNatalie.Li@Sun.COM 	if (si->shr_flags & SMB_SHRF_AUTOHOME) {
4347961SNatalie.Li@Sun.COM 		if ((--si->shr_refcnt) > 0) {
4357961SNatalie.Li@Sun.COM 			smb_shr_cache_unlock();
4367961SNatalie.Li@Sun.COM 			return (NERR_Success);
4377348SJose.Borrego@Sun.COM 		}
4387052Samw 	}
4397052Samw 
4408845Samw@Sun.COM 	/*
4418845Samw@Sun.COM 	 * If path is ZFS, remove the .zfs/shares/<share> entry.  Need
4428845Samw@Sun.COM 	 * to remove before cleanup of cache occurs.
4438845Samw@Sun.COM 	 */
4448845Samw@Sun.COM 	smb_shr_zfs_remove(si);
4458845Samw@Sun.COM 
4467961SNatalie.Li@Sun.COM 	(void) strlcpy(path, si->shr_path, sizeof (path));
4477961SNatalie.Li@Sun.COM 	(void) strlcpy(container, si->shr_container, sizeof (container));
4487961SNatalie.Li@Sun.COM 	smb_shr_cache_delent(sharename);
4497961SNatalie.Li@Sun.COM 	smb_shr_cache_unlock();
4507348SJose.Borrego@Sun.COM 
4517961SNatalie.Li@Sun.COM 	smb_shr_unpublish(sharename, container);
4527961SNatalie.Li@Sun.COM 
4537961SNatalie.Li@Sun.COM 	/* call kernel to release the hold on the shared file system */
4547961SNatalie.Li@Sun.COM 	(void) mlsvc_set_share(SMB_SHROP_DELETE, path, sharename);
4557348SJose.Borrego@Sun.COM 
4567052Samw 	return (NERR_Success);
4577052Samw }
4587052Samw 
4597052Samw /*
4607052Samw  * Rename a share. Check that the current name exists and the new name
4617052Samw  * doesn't exist. The rename is performed by deleting the current share
4627052Samw  * definition and creating a new share with the new name.
4637052Samw  */
4647052Samw uint32_t
4657348SJose.Borrego@Sun.COM smb_shr_rename(char *from_name, char *to_name)
4667052Samw {
4677961SNatalie.Li@Sun.COM 	smb_share_t *from_si;
4687961SNatalie.Li@Sun.COM 	smb_share_t to_si;
4697348SJose.Borrego@Sun.COM 	uint32_t status;
4707348SJose.Borrego@Sun.COM 
4717348SJose.Borrego@Sun.COM 	assert((from_name != NULL) && (to_name != NULL));
4727052Samw 
4737348SJose.Borrego@Sun.COM 	if (!smb_shr_chkname(from_name) || !smb_shr_chkname(to_name))
4747348SJose.Borrego@Sun.COM 		return (ERROR_INVALID_NAME);
4757052Samw 
4767961SNatalie.Li@Sun.COM 	if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success)
4777961SNatalie.Li@Sun.COM 		return (NERR_InternalError);
4787961SNatalie.Li@Sun.COM 
4797961SNatalie.Li@Sun.COM 	if ((from_si = smb_shr_cache_findent(from_name)) == NULL) {
4807961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
4817052Samw 		return (NERR_NetNameNotFound);
4827961SNatalie.Li@Sun.COM 	}
4837052Samw 
4847961SNatalie.Li@Sun.COM 	if (from_si->shr_type & STYPE_IPC) {
4857961SNatalie.Li@Sun.COM 		/* IPC$ share cannot be renamed */
4867961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
4877961SNatalie.Li@Sun.COM 		return (ERROR_ACCESS_DENIED);
4887961SNatalie.Li@Sun.COM 	}
4897961SNatalie.Li@Sun.COM 
4907961SNatalie.Li@Sun.COM 	if (smb_shr_cache_findent(to_name) != NULL) {
4917961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
4927052Samw 		return (NERR_DuplicateShare);
4937961SNatalie.Li@Sun.COM 	}
4947052Samw 
4957961SNatalie.Li@Sun.COM 	bcopy(from_si, &to_si, sizeof (smb_share_t));
4967961SNatalie.Li@Sun.COM 	(void) strlcpy(to_si.shr_name, to_name, sizeof (to_si.shr_name));
4977961SNatalie.Li@Sun.COM 
4988845Samw@Sun.COM 	/* If path is ZFS, rename the .zfs/shares/<share> entry. */
4998845Samw@Sun.COM 	smb_shr_zfs_rename(from_si, &to_si);
5008845Samw@Sun.COM 
5017961SNatalie.Li@Sun.COM 	if ((status = smb_shr_cache_addent(&to_si)) != NERR_Success) {
5027961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
5037348SJose.Borrego@Sun.COM 		return (status);
5047961SNatalie.Li@Sun.COM 	}
5057348SJose.Borrego@Sun.COM 
5067348SJose.Borrego@Sun.COM 	smb_shr_cache_delent(from_name);
5077961SNatalie.Li@Sun.COM 	smb_shr_cache_unlock();
5087961SNatalie.Li@Sun.COM 
5097961SNatalie.Li@Sun.COM 	smb_shr_unpublish(from_name, to_si.shr_container);
5107961SNatalie.Li@Sun.COM 	smb_shr_publish(to_name, to_si.shr_container);
5117348SJose.Borrego@Sun.COM 
5127348SJose.Borrego@Sun.COM 	return (NERR_Success);
5137348SJose.Borrego@Sun.COM }
5147348SJose.Borrego@Sun.COM 
5157348SJose.Borrego@Sun.COM /*
5167348SJose.Borrego@Sun.COM  * Load the information for the specified share into the supplied share
5177348SJose.Borrego@Sun.COM  * info structure.
5188334SJose.Borrego@Sun.COM  *
5198334SJose.Borrego@Sun.COM  * First looks up the cache to see if the specified share exists, if there
5208334SJose.Borrego@Sun.COM  * is a miss then it looks up sharemgr.
5217348SJose.Borrego@Sun.COM  */
5227348SJose.Borrego@Sun.COM uint32_t
5237348SJose.Borrego@Sun.COM smb_shr_get(char *sharename, smb_share_t *si)
5247348SJose.Borrego@Sun.COM {
5258334SJose.Borrego@Sun.COM 	uint32_t status;
5267348SJose.Borrego@Sun.COM 
5277961SNatalie.Li@Sun.COM 	if (sharename == NULL || *sharename == '\0')
5287961SNatalie.Li@Sun.COM 		return (NERR_NetNameNotFound);
5297348SJose.Borrego@Sun.COM 
5308334SJose.Borrego@Sun.COM 	if ((status = smb_shr_lookup(sharename, si)) == NERR_Success)
5318334SJose.Borrego@Sun.COM 		return (status);
5327961SNatalie.Li@Sun.COM 
5338334SJose.Borrego@Sun.COM 	if ((status = smb_shr_sa_loadbyname(sharename)) == NERR_Success)
5348334SJose.Borrego@Sun.COM 		status = smb_shr_lookup(sharename, si);
5357348SJose.Borrego@Sun.COM 
5367961SNatalie.Li@Sun.COM 	return (status);
5377348SJose.Borrego@Sun.COM }
5387348SJose.Borrego@Sun.COM 
5397348SJose.Borrego@Sun.COM /*
5407348SJose.Borrego@Sun.COM  * Modifies an existing share. Properties that can be modified are:
5417348SJose.Borrego@Sun.COM  *
5427348SJose.Borrego@Sun.COM  *   o comment
5437348SJose.Borrego@Sun.COM  *   o AD container
5447961SNatalie.Li@Sun.COM  *   o host access
5457348SJose.Borrego@Sun.COM  */
5467348SJose.Borrego@Sun.COM uint32_t
5477961SNatalie.Li@Sun.COM smb_shr_modify(smb_share_t *new_si)
5487348SJose.Borrego@Sun.COM {
5497961SNatalie.Li@Sun.COM 	smb_share_t *si;
5507348SJose.Borrego@Sun.COM 	boolean_t adc_changed = B_FALSE;
5517961SNatalie.Li@Sun.COM 	char old_container[MAXPATHLEN];
552*9231SAfshin.Ardakani@Sun.COM 	uint32_t catia;
5538334SJose.Borrego@Sun.COM 	uint32_t cscopt;
5547961SNatalie.Li@Sun.COM 	uint32_t access;
5557348SJose.Borrego@Sun.COM 
5567961SNatalie.Li@Sun.COM 	assert(new_si != NULL);
5577348SJose.Borrego@Sun.COM 
5587961SNatalie.Li@Sun.COM 	if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success)
5597961SNatalie.Li@Sun.COM 		return (NERR_InternalError);
5607348SJose.Borrego@Sun.COM 
5617961SNatalie.Li@Sun.COM 	if ((si = smb_shr_cache_findent(new_si->shr_name)) == NULL) {
5627961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
5637961SNatalie.Li@Sun.COM 		return (NERR_NetNameNotFound);
5647961SNatalie.Li@Sun.COM 	}
5657348SJose.Borrego@Sun.COM 
5667961SNatalie.Li@Sun.COM 	if (si->shr_type & STYPE_IPC) {
5677961SNatalie.Li@Sun.COM 		/* IPC$ share cannot be modified */
5687961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
5697961SNatalie.Li@Sun.COM 		return (ERROR_ACCESS_DENIED);
5707348SJose.Borrego@Sun.COM 	}
5717348SJose.Borrego@Sun.COM 
5728474SJose.Borrego@Sun.COM 	(void) strlcpy(si->shr_cmnt, new_si->shr_cmnt, sizeof (si->shr_cmnt));
5737961SNatalie.Li@Sun.COM 
5747961SNatalie.Li@Sun.COM 	adc_changed = (strcmp(new_si->shr_container, si->shr_container) != 0);
5757961SNatalie.Li@Sun.COM 	if (adc_changed) {
5767961SNatalie.Li@Sun.COM 		/* save current container - needed for unpublishing */
5777961SNatalie.Li@Sun.COM 		(void) strlcpy(old_container, si->shr_container,
5787961SNatalie.Li@Sun.COM 		    sizeof (old_container));
5797961SNatalie.Li@Sun.COM 		(void) strlcpy(si->shr_container, new_si->shr_container,
5807961SNatalie.Li@Sun.COM 		    sizeof (si->shr_container));
5817348SJose.Borrego@Sun.COM 	}
5827348SJose.Borrego@Sun.COM 
583*9231SAfshin.Ardakani@Sun.COM 	catia = (new_si->shr_flags & SMB_SHRF_CATIA);
584*9231SAfshin.Ardakani@Sun.COM 	si->shr_flags &= ~SMB_SHRF_CATIA;
585*9231SAfshin.Ardakani@Sun.COM 	si->shr_flags |= catia;
586*9231SAfshin.Ardakani@Sun.COM 
5878334SJose.Borrego@Sun.COM 	cscopt = (new_si->shr_flags & SMB_SHRF_CSC_MASK);
5888334SJose.Borrego@Sun.COM 	si->shr_flags &= ~SMB_SHRF_CSC_MASK;
5898334SJose.Borrego@Sun.COM 	si->shr_flags |= cscopt;
5908334SJose.Borrego@Sun.COM 
5917961SNatalie.Li@Sun.COM 	access = (new_si->shr_flags & SMB_SHRF_ACC_ALL);
5928474SJose.Borrego@Sun.COM 	si->shr_flags &= ~SMB_SHRF_ACC_ALL;
5937961SNatalie.Li@Sun.COM 	si->shr_flags |= access;
5947961SNatalie.Li@Sun.COM 
5957961SNatalie.Li@Sun.COM 	if (access & SMB_SHRF_ACC_NONE)
5967961SNatalie.Li@Sun.COM 		(void) strlcpy(si->shr_access_none, new_si->shr_access_none,
5977961SNatalie.Li@Sun.COM 		    sizeof (si->shr_access_none));
5987348SJose.Borrego@Sun.COM 
5997961SNatalie.Li@Sun.COM 	if (access & SMB_SHRF_ACC_RO)
6007961SNatalie.Li@Sun.COM 		(void) strlcpy(si->shr_access_ro, new_si->shr_access_ro,
6017961SNatalie.Li@Sun.COM 		    sizeof (si->shr_access_ro));
6027348SJose.Borrego@Sun.COM 
6037961SNatalie.Li@Sun.COM 	if (access & SMB_SHRF_ACC_RW)
6047961SNatalie.Li@Sun.COM 		(void) strlcpy(si->shr_access_rw, new_si->shr_access_rw,
6057961SNatalie.Li@Sun.COM 		    sizeof (si->shr_access_rw));
6067961SNatalie.Li@Sun.COM 
6077961SNatalie.Li@Sun.COM 	smb_shr_cache_unlock();
6087052Samw 
6097348SJose.Borrego@Sun.COM 	if (adc_changed) {
6107961SNatalie.Li@Sun.COM 		smb_shr_unpublish(new_si->shr_name, old_container);
6117961SNatalie.Li@Sun.COM 		smb_shr_publish(new_si->shr_name, new_si->shr_container);
6127348SJose.Borrego@Sun.COM 	}
6137348SJose.Borrego@Sun.COM 
6147348SJose.Borrego@Sun.COM 	return (NERR_Success);
6157052Samw }
6167052Samw 
6177052Samw /*
6187052Samw  * smb_shr_exists
6197052Samw  *
6207348SJose.Borrego@Sun.COM  * Returns B_TRUE if the share exists. Otherwise returns B_FALSE
6217052Samw  */
6227348SJose.Borrego@Sun.COM boolean_t
6237348SJose.Borrego@Sun.COM smb_shr_exists(char *sharename)
6247052Samw {
6257961SNatalie.Li@Sun.COM 	boolean_t exists = B_FALSE;
6267348SJose.Borrego@Sun.COM 
6277348SJose.Borrego@Sun.COM 	if (sharename == NULL || *sharename == '\0')
6287348SJose.Borrego@Sun.COM 		return (B_FALSE);
6297052Samw 
6307961SNatalie.Li@Sun.COM 	if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) {
6317961SNatalie.Li@Sun.COM 		exists = (smb_shr_cache_findent(sharename) != NULL);
6327961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
6337961SNatalie.Li@Sun.COM 	}
6347348SJose.Borrego@Sun.COM 
6357348SJose.Borrego@Sun.COM 	return (exists);
6367052Samw }
6377052Samw 
6387052Samw /*
6397961SNatalie.Li@Sun.COM  * If the shared directory does not begin with a /, one will be
6407961SNatalie.Li@Sun.COM  * inserted as a prefix. If ipaddr is not zero, then also return
6417961SNatalie.Li@Sun.COM  * information about access based on the host level access lists, if
6427961SNatalie.Li@Sun.COM  * present. Also return access check if there is an IP address and
6437961SNatalie.Li@Sun.COM  * shr_accflags.
6447961SNatalie.Li@Sun.COM  *
6457961SNatalie.Li@Sun.COM  * The value of smb_chk_hostaccess is checked for an access match.
6467961SNatalie.Li@Sun.COM  * -1 is wildcard match
6477961SNatalie.Li@Sun.COM  * 0 is no match
6487961SNatalie.Li@Sun.COM  * 1 is match
6497961SNatalie.Li@Sun.COM  *
6507961SNatalie.Li@Sun.COM  * Precedence is none is checked first followed by ro then rw if
6517961SNatalie.Li@Sun.COM  * needed.  If x is wildcard (< 0) then check to see if the other
6527961SNatalie.Li@Sun.COM  * values are a match. If a match, that wins.
6538670SJose.Borrego@Sun.COM  *
6548670SJose.Borrego@Sun.COM  * ipv6 is wide open for now, see smb_chk_hostaccess
6557961SNatalie.Li@Sun.COM  */
6567961SNatalie.Li@Sun.COM void
6578670SJose.Borrego@Sun.COM smb_shr_hostaccess(smb_share_t *si, smb_inaddr_t *ipaddr)
6587961SNatalie.Li@Sun.COM {
6597961SNatalie.Li@Sun.COM 	int acc = SMB_SHRF_ACC_OPEN;
6607961SNatalie.Li@Sun.COM 
6617961SNatalie.Li@Sun.COM 	/*
6627961SNatalie.Li@Sun.COM 	 * Check to see if there area any share level access
6637961SNatalie.Li@Sun.COM 	 * restrictions.
6647961SNatalie.Li@Sun.COM 	 */
6658670SJose.Borrego@Sun.COM 	if ((!smb_inet_iszero(ipaddr)) &&
6668670SJose.Borrego@Sun.COM 	    (si->shr_flags & SMB_SHRF_ACC_ALL) != 0) {
6677961SNatalie.Li@Sun.COM 		int none = SMB_SHRF_ACC_OPEN;
6687961SNatalie.Li@Sun.COM 		int rw = SMB_SHRF_ACC_OPEN;
6697961SNatalie.Li@Sun.COM 		int ro = SMB_SHRF_ACC_OPEN;
6707961SNatalie.Li@Sun.COM 
6717961SNatalie.Li@Sun.COM 		if (si->shr_flags & SMB_SHRF_ACC_NONE)
6727961SNatalie.Li@Sun.COM 			none = smb_chk_hostaccess(ipaddr, si->shr_access_none);
6737961SNatalie.Li@Sun.COM 		if (si->shr_flags & SMB_SHRF_ACC_RW)
6747961SNatalie.Li@Sun.COM 			rw = smb_chk_hostaccess(ipaddr, si->shr_access_rw);
6757961SNatalie.Li@Sun.COM 		if (si->shr_flags & SMB_SHRF_ACC_RO)
6767961SNatalie.Li@Sun.COM 			ro = smb_chk_hostaccess(ipaddr, si->shr_access_ro);
6777961SNatalie.Li@Sun.COM 		/* make first pass to get basic value */
6787961SNatalie.Li@Sun.COM 		if (none != 0)
6797961SNatalie.Li@Sun.COM 			acc = SMB_SHRF_ACC_NONE;
6807961SNatalie.Li@Sun.COM 		else if (ro != 0)
6817961SNatalie.Li@Sun.COM 			acc = SMB_SHRF_ACC_RO;
6827961SNatalie.Li@Sun.COM 		else if (rw != 0)
6837961SNatalie.Li@Sun.COM 			acc = SMB_SHRF_ACC_RW;
6847961SNatalie.Li@Sun.COM 
6857961SNatalie.Li@Sun.COM 		/* make second pass to handle '*' case */
6867961SNatalie.Li@Sun.COM 		if (none < 0) {
6877961SNatalie.Li@Sun.COM 			acc = SMB_SHRF_ACC_NONE;
6887961SNatalie.Li@Sun.COM 			if (ro > 0)
6897961SNatalie.Li@Sun.COM 				acc = SMB_SHRF_ACC_RO;
6907961SNatalie.Li@Sun.COM 			else if (rw > 0)
6917961SNatalie.Li@Sun.COM 				acc = SMB_SHRF_ACC_RW;
6927961SNatalie.Li@Sun.COM 		} else if (ro < 0) {
6937961SNatalie.Li@Sun.COM 			acc = SMB_SHRF_ACC_RO;
6947961SNatalie.Li@Sun.COM 			if (none > 0)
6957961SNatalie.Li@Sun.COM 				acc = SMB_SHRF_ACC_NONE;
6967961SNatalie.Li@Sun.COM 			else if (rw > 0)
6977961SNatalie.Li@Sun.COM 				acc = SMB_SHRF_ACC_RW;
6987961SNatalie.Li@Sun.COM 		} else if (rw < 0) {
6997961SNatalie.Li@Sun.COM 			acc = SMB_SHRF_ACC_RW;
7007961SNatalie.Li@Sun.COM 			if (none > 0)
7017961SNatalie.Li@Sun.COM 				acc = SMB_SHRF_ACC_NONE;
7027961SNatalie.Li@Sun.COM 			else if (ro > 0)
7037961SNatalie.Li@Sun.COM 				acc = SMB_SHRF_ACC_RO;
7047961SNatalie.Li@Sun.COM 		}
7057961SNatalie.Li@Sun.COM 	}
7067961SNatalie.Li@Sun.COM 	si->shr_access_value = acc;	/* return access here */
7077961SNatalie.Li@Sun.COM }
7087961SNatalie.Li@Sun.COM 
7097961SNatalie.Li@Sun.COM /*
7107052Samw  * smb_shr_is_special
7117052Samw  *
7127348SJose.Borrego@Sun.COM  * Special share reserved for interprocess communication (IPC$) or
7137348SJose.Borrego@Sun.COM  * remote administration of the server (ADMIN$). Can also refer to
7147348SJose.Borrego@Sun.COM  * administrative shares such as C$, D$, E$, and so forth.
7157052Samw  */
7167052Samw int
7177348SJose.Borrego@Sun.COM smb_shr_is_special(char *sharename)
7187052Samw {
7197052Samw 	int len;
7207052Samw 
7217348SJose.Borrego@Sun.COM 	if (sharename == NULL)
7227052Samw 		return (0);
7237052Samw 
7247348SJose.Borrego@Sun.COM 	if ((len = strlen(sharename)) == 0)
7257052Samw 		return (0);
7267052Samw 
7277348SJose.Borrego@Sun.COM 	if (sharename[len - 1] == '$')
7287052Samw 		return (STYPE_SPECIAL);
7297348SJose.Borrego@Sun.COM 
7307348SJose.Borrego@Sun.COM 	return (0);
7317052Samw }
7327052Samw 
7337052Samw /*
7347052Samw  * smb_shr_is_restricted
7357052Samw  *
7367052Samw  * Check whether or not there is a restriction on a share. Restricted
7377052Samw  * shares are generally STYPE_SPECIAL, for example, IPC$. All the
7387348SJose.Borrego@Sun.COM  * administration share names are restricted: C$, D$ etc. Returns B_TRUE
7397348SJose.Borrego@Sun.COM  * if the share is restricted. Otherwise B_FALSE is returned to indicate
7407052Samw  * that there are no restrictions.
7417052Samw  */
7427348SJose.Borrego@Sun.COM boolean_t
7437348SJose.Borrego@Sun.COM smb_shr_is_restricted(char *sharename)
7447052Samw {
7457052Samw 	static char *restricted[] = {
7467052Samw 		"IPC$"
7477052Samw 	};
7487052Samw 
7497052Samw 	int i;
7507052Samw 
7517348SJose.Borrego@Sun.COM 	if (sharename == NULL)
7527348SJose.Borrego@Sun.COM 		return (B_FALSE);
7537348SJose.Borrego@Sun.COM 
7547052Samw 	for (i = 0; i < sizeof (restricted)/sizeof (restricted[0]); i++) {
7557348SJose.Borrego@Sun.COM 		if (utf8_strcasecmp(restricted[i], sharename) == 0)
7567348SJose.Borrego@Sun.COM 			return (B_TRUE);
7577052Samw 	}
7587052Samw 
7597348SJose.Borrego@Sun.COM 	return (smb_shr_is_admin(sharename));
7607052Samw }
7617052Samw 
7627052Samw /*
7637052Samw  * smb_shr_is_admin
7647052Samw  *
7657052Samw  * Check whether or not access to the share should be restricted to
7667052Samw  * administrators. This is a bit of a hack because what we're doing
7677052Samw  * is checking for the default admin shares: C$, D$ etc.. There are
7687052Samw  * other shares that have restrictions: see smb_shr_is_restricted().
7697052Samw  *
7707348SJose.Borrego@Sun.COM  * Returns B_TRUE if the shares is an admin share. Otherwise B_FALSE
7717348SJose.Borrego@Sun.COM  * is returned to indicate that there are no restrictions.
7727052Samw  */
7737348SJose.Borrego@Sun.COM boolean_t
7747348SJose.Borrego@Sun.COM smb_shr_is_admin(char *sharename)
7757052Samw {
7767348SJose.Borrego@Sun.COM 	if (sharename == NULL)
7777348SJose.Borrego@Sun.COM 		return (B_FALSE);
7787052Samw 
7797348SJose.Borrego@Sun.COM 	if (strlen(sharename) == 2 &&
7807348SJose.Borrego@Sun.COM 	    mts_isalpha(sharename[0]) && sharename[1] == '$') {
7817348SJose.Borrego@Sun.COM 		return (B_TRUE);
7827052Samw 	}
7837052Samw 
7847348SJose.Borrego@Sun.COM 	return (B_FALSE);
7857052Samw }
7867052Samw 
7877052Samw /*
7887348SJose.Borrego@Sun.COM  * smb_shr_chkname
7897052Samw  *
7907961SNatalie.Li@Sun.COM  * Check for invalid characters in a share name.  The list of invalid
7917961SNatalie.Li@Sun.COM  * characters includes control characters and the following:
7927052Samw  *
7937052Samw  * " / \ [ ] : | < > + ; , ? * =
7947052Samw  */
7957348SJose.Borrego@Sun.COM boolean_t
7967348SJose.Borrego@Sun.COM smb_shr_chkname(char *sharename)
7977052Samw {
7987052Samw 	char *invalid = "\"/\\[]:|<>+;,?*=";
7997052Samw 	char *cp;
8007052Samw 
8017348SJose.Borrego@Sun.COM 	if (sharename == NULL)
8027348SJose.Borrego@Sun.COM 		return (B_FALSE);
8037052Samw 
8047348SJose.Borrego@Sun.COM 	if (strpbrk(sharename, invalid))
8057348SJose.Borrego@Sun.COM 		return (B_FALSE);
8067052Samw 
8077348SJose.Borrego@Sun.COM 	for (cp = sharename; *cp != '\0'; cp++) {
8087348SJose.Borrego@Sun.COM 		if (iscntrl(*cp))
8097348SJose.Borrego@Sun.COM 			return (B_FALSE);
8107052Samw 	}
8117052Samw 
8127348SJose.Borrego@Sun.COM 	return (B_TRUE);
8137052Samw }
8147052Samw 
8157052Samw /*
8167052Samw  * smb_shr_get_realpath
8177052Samw  *
8187961SNatalie.Li@Sun.COM  * Derive the real path for a share from the path provided by a client.
8197961SNatalie.Li@Sun.COM  * For instance, the real path of C:\ may be /cvol or the real path of
8207961SNatalie.Li@Sun.COM  * F:\home may be /vol1/home.
8217052Samw  *
8227961SNatalie.Li@Sun.COM  * clntpath - path provided by the Windows client is in the
8237052Samw  *            format of <drive letter>:\<dir>
8247052Samw  * realpath - path that will be stored as the directory field of
8257052Samw  *            the smb_share_t structure of the share.
8267961SNatalie.Li@Sun.COM  * maxlen   - maximum length of the realpath buffer
8277052Samw  *
8287052Samw  * Return LAN Manager network error code.
8297052Samw  */
8307052Samw uint32_t
8317961SNatalie.Li@Sun.COM smb_shr_get_realpath(const char *clntpath, char *realpath, int maxlen)
8327052Samw {
8337961SNatalie.Li@Sun.COM 	const char *p;
8347961SNatalie.Li@Sun.COM 	int len;
8357348SJose.Borrego@Sun.COM 
8367961SNatalie.Li@Sun.COM 	if ((p = strchr(clntpath, ':')) != NULL)
8377961SNatalie.Li@Sun.COM 		++p;
8387961SNatalie.Li@Sun.COM 	else
8397961SNatalie.Li@Sun.COM 		p = clntpath;
8407348SJose.Borrego@Sun.COM 
8417961SNatalie.Li@Sun.COM 	(void) strlcpy(realpath, p, maxlen);
8427961SNatalie.Li@Sun.COM 	(void) strcanon(realpath, "/\\");
8437961SNatalie.Li@Sun.COM 	(void) strsubst(realpath, '\\', '/');
8447348SJose.Borrego@Sun.COM 
8457961SNatalie.Li@Sun.COM 	len = strlen(realpath);
8467961SNatalie.Li@Sun.COM 	if ((len > 1) && (realpath[len - 1] == '/'))
8477961SNatalie.Li@Sun.COM 		realpath[len - 1] = '\0';
8487348SJose.Borrego@Sun.COM 
8497348SJose.Borrego@Sun.COM 	return (NERR_Success);
8507348SJose.Borrego@Sun.COM }
8517348SJose.Borrego@Sun.COM 
8527961SNatalie.Li@Sun.COM void
8537961SNatalie.Li@Sun.COM smb_shr_list(int offset, smb_shrlist_t *list)
8547348SJose.Borrego@Sun.COM {
8557961SNatalie.Li@Sun.COM 	smb_shriter_t iterator;
8567961SNatalie.Li@Sun.COM 	smb_share_t *si;
8577961SNatalie.Li@Sun.COM 	int n = 0;
8587961SNatalie.Li@Sun.COM 
8597961SNatalie.Li@Sun.COM 	bzero(list, sizeof (smb_shrlist_t));
8607961SNatalie.Li@Sun.COM 	smb_shr_iterinit(&iterator);
8617961SNatalie.Li@Sun.COM 
8627961SNatalie.Li@Sun.COM 	while ((si = smb_shr_iterate(&iterator)) != NULL) {
8637961SNatalie.Li@Sun.COM 		if (--offset > 0)
8647961SNatalie.Li@Sun.COM 			continue;
8657961SNatalie.Li@Sun.COM 
8667961SNatalie.Li@Sun.COM 		if ((si->shr_flags & SMB_SHRF_TRANS) &&
8677961SNatalie.Li@Sun.COM 		    ((si->shr_type & STYPE_IPC) == 0)) {
8687961SNatalie.Li@Sun.COM 			bcopy(si, &list->sl_shares[n], sizeof (smb_share_t));
8697961SNatalie.Li@Sun.COM 			if (++n == LMSHARES_PER_REQUEST)
8707961SNatalie.Li@Sun.COM 				break;
8717961SNatalie.Li@Sun.COM 		}
8727348SJose.Borrego@Sun.COM 	}
8737961SNatalie.Li@Sun.COM 
8747961SNatalie.Li@Sun.COM 	list->sl_cnt = n;
8757348SJose.Borrego@Sun.COM }
8767348SJose.Borrego@Sun.COM 
8777348SJose.Borrego@Sun.COM /*
8787961SNatalie.Li@Sun.COM  * ============================================
8797961SNatalie.Li@Sun.COM  * Private helper/utility functions
8807961SNatalie.Li@Sun.COM  * ============================================
8817348SJose.Borrego@Sun.COM  */
8827348SJose.Borrego@Sun.COM 
8837961SNatalie.Li@Sun.COM /*
8848334SJose.Borrego@Sun.COM  * Looks up the given share in the cache and return
8858334SJose.Borrego@Sun.COM  * the info in 'si'
8868334SJose.Borrego@Sun.COM  */
8878334SJose.Borrego@Sun.COM static uint32_t
8888334SJose.Borrego@Sun.COM smb_shr_lookup(char *sharename, smb_share_t *si)
8898334SJose.Borrego@Sun.COM {
8908334SJose.Borrego@Sun.COM 	smb_share_t *cached_si;
8918334SJose.Borrego@Sun.COM 	uint32_t status = NERR_NetNameNotFound;
8928334SJose.Borrego@Sun.COM 
8938334SJose.Borrego@Sun.COM 	if (sharename == NULL || *sharename == '\0')
8948334SJose.Borrego@Sun.COM 		return (NERR_NetNameNotFound);
8958334SJose.Borrego@Sun.COM 	if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) {
8968334SJose.Borrego@Sun.COM 		cached_si = smb_shr_cache_findent(sharename);
8978334SJose.Borrego@Sun.COM 		if (cached_si != NULL) {
8988334SJose.Borrego@Sun.COM 			bcopy(cached_si, si, sizeof (smb_share_t));
8998334SJose.Borrego@Sun.COM 			status = NERR_Success;
9008334SJose.Borrego@Sun.COM 		}
9018334SJose.Borrego@Sun.COM 
9028334SJose.Borrego@Sun.COM 		smb_shr_cache_unlock();
9038334SJose.Borrego@Sun.COM 	}
9048334SJose.Borrego@Sun.COM 	return (status);
9058334SJose.Borrego@Sun.COM }
9068334SJose.Borrego@Sun.COM 
9078334SJose.Borrego@Sun.COM /*
9087961SNatalie.Li@Sun.COM  * Add IPC$ to the cache upon startup.
9097961SNatalie.Li@Sun.COM  */
9107348SJose.Borrego@Sun.COM static uint32_t
9117961SNatalie.Li@Sun.COM smb_shr_addipc(void)
9127348SJose.Borrego@Sun.COM {
9137348SJose.Borrego@Sun.COM 	smb_share_t ipc;
9147961SNatalie.Li@Sun.COM 	uint32_t status = NERR_InternalError;
9157348SJose.Borrego@Sun.COM 
9167348SJose.Borrego@Sun.COM 	bzero(&ipc, sizeof (smb_share_t));
9177348SJose.Borrego@Sun.COM 	(void) strcpy(ipc.shr_name, "IPC$");
9187348SJose.Borrego@Sun.COM 	(void) strcpy(ipc.shr_cmnt, "Remote IPC");
9197348SJose.Borrego@Sun.COM 	ipc.shr_flags = SMB_SHRF_TRANS;
9207348SJose.Borrego@Sun.COM 	ipc.shr_type = STYPE_IPC;
9217348SJose.Borrego@Sun.COM 
9227961SNatalie.Li@Sun.COM 	if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) == NERR_Success) {
9237961SNatalie.Li@Sun.COM 		status = smb_shr_cache_addent(&ipc);
9247961SNatalie.Li@Sun.COM 		smb_shr_cache_unlock();
9257348SJose.Borrego@Sun.COM 	}
9267348SJose.Borrego@Sun.COM 
9277348SJose.Borrego@Sun.COM 	return (status);
9287348SJose.Borrego@Sun.COM }
9297348SJose.Borrego@Sun.COM 
9307348SJose.Borrego@Sun.COM /*
9317052Samw  * smb_shr_set_oemname
9327052Samw  *
9337961SNatalie.Li@Sun.COM  * Generate the OEM name for the specified share.  If the name is
9347961SNatalie.Li@Sun.COM  * shorter than 13 bytes the oemname will be saved in si->shr_oemname.
9357961SNatalie.Li@Sun.COM  * Otherwise si->shr_oemname will be empty and SMB_SHRF_LONGNAME will
9367961SNatalie.Li@Sun.COM  * be set in si->shr_flags.
9377052Samw  */
9387052Samw static void
9397052Samw smb_shr_set_oemname(smb_share_t *si)
9407052Samw {
9417052Samw 	unsigned int cpid = oem_get_smb_cpid();
9427052Samw 	mts_wchar_t *unibuf;
9437052Samw 	char *oem_name;
9447052Samw 	int length;
9457052Samw 
9467052Samw 	length = strlen(si->shr_name) + 1;
9477052Samw 
9487052Samw 	oem_name = malloc(length);
9497052Samw 	unibuf = malloc(length * sizeof (mts_wchar_t));
9507052Samw 	if ((oem_name == NULL) || (unibuf == NULL)) {
9517052Samw 		free(oem_name);
9527052Samw 		free(unibuf);
9537052Samw 		return;
9547052Samw 	}
9557052Samw 
9567052Samw 	(void) mts_mbstowcs(unibuf, si->shr_name, length);
9577052Samw 
9587052Samw 	if (unicodestooems(oem_name, unibuf, length, cpid) == 0)
9597052Samw 		(void) strcpy(oem_name, si->shr_name);
9607052Samw 
9617052Samw 	free(unibuf);
9627052Samw 
9637052Samw 	if (strlen(oem_name) + 1 > SMB_SHARE_OEMNAME_MAX) {
9647052Samw 		si->shr_flags |= SMB_SHRF_LONGNAME;
9657052Samw 		*si->shr_oemname = '\0';
9667052Samw 	} else {
9677052Samw 		si->shr_flags &= ~SMB_SHRF_LONGNAME;
9687052Samw 		(void) strlcpy(si->shr_oemname, oem_name,
9697052Samw 		    SMB_SHARE_OEMNAME_MAX);
9707052Samw 	}
9717052Samw 
9727052Samw 	free(oem_name);
9737052Samw }
9747348SJose.Borrego@Sun.COM 
9757348SJose.Borrego@Sun.COM /*
9767348SJose.Borrego@Sun.COM  * ============================================
9777961SNatalie.Li@Sun.COM  * Cache management functions
9787961SNatalie.Li@Sun.COM  *
9797961SNatalie.Li@Sun.COM  * All cache functions are private
9807348SJose.Borrego@Sun.COM  * ============================================
9817348SJose.Borrego@Sun.COM  */
9827348SJose.Borrego@Sun.COM 
9837348SJose.Borrego@Sun.COM /*
9847961SNatalie.Li@Sun.COM  * Create the share cache (hash table).
9857348SJose.Borrego@Sun.COM  */
9867348SJose.Borrego@Sun.COM static uint32_t
9877961SNatalie.Li@Sun.COM smb_shr_cache_create(void)
9887348SJose.Borrego@Sun.COM {
9897961SNatalie.Li@Sun.COM 	uint32_t status = NERR_Success;
9907348SJose.Borrego@Sun.COM 
9917961SNatalie.Li@Sun.COM 	(void) mutex_lock(&smb_shr_cache.sc_mtx);
9927961SNatalie.Li@Sun.COM 	switch (smb_shr_cache.sc_state) {
9937961SNatalie.Li@Sun.COM 	case SMB_SHR_CACHE_STATE_NONE:
9947961SNatalie.Li@Sun.COM 		smb_shr_cache.sc_cache = ht_create_table(SMB_SHR_HTAB_SZ,
9957961SNatalie.Li@Sun.COM 		    MAXNAMELEN, 0);
9967961SNatalie.Li@Sun.COM 		if (smb_shr_cache.sc_cache == NULL) {
9977961SNatalie.Li@Sun.COM 			status = NERR_InternalError;
9987961SNatalie.Li@Sun.COM 			break;
9997348SJose.Borrego@Sun.COM 		}
10007348SJose.Borrego@Sun.COM 
10017961SNatalie.Li@Sun.COM 		(void) ht_register_callback(smb_shr_cache.sc_cache,
10027961SNatalie.Li@Sun.COM 		    smb_shr_cache_freent);
10037961SNatalie.Li@Sun.COM 		smb_shr_cache.sc_nops = 0;
10047961SNatalie.Li@Sun.COM 		smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_CREATED;
10057961SNatalie.Li@Sun.COM 		break;
10067961SNatalie.Li@Sun.COM 
10077961SNatalie.Li@Sun.COM 	default:
10087961SNatalie.Li@Sun.COM 		assert(0);
10097961SNatalie.Li@Sun.COM 		status = NERR_InternalError;
10107961SNatalie.Li@Sun.COM 		break;
10117961SNatalie.Li@Sun.COM 	}
10127961SNatalie.Li@Sun.COM 	(void) mutex_unlock(&smb_shr_cache.sc_mtx);
10137961SNatalie.Li@Sun.COM 
10147961SNatalie.Li@Sun.COM 	return (status);
10157961SNatalie.Li@Sun.COM }
10167961SNatalie.Li@Sun.COM 
10177961SNatalie.Li@Sun.COM /*
10187961SNatalie.Li@Sun.COM  * Destroy the share cache (hash table).
10197961SNatalie.Li@Sun.COM  * Wait for inflight/pending operations to finish or abort before
10207961SNatalie.Li@Sun.COM  * destroying the cache.
10217961SNatalie.Li@Sun.COM  */
10227961SNatalie.Li@Sun.COM static void
10237961SNatalie.Li@Sun.COM smb_shr_cache_destroy(void)
10247961SNatalie.Li@Sun.COM {
10257961SNatalie.Li@Sun.COM 	(void) mutex_lock(&smb_shr_cache.sc_mtx);
10267961SNatalie.Li@Sun.COM 	if (smb_shr_cache.sc_state == SMB_SHR_CACHE_STATE_CREATED) {
10277961SNatalie.Li@Sun.COM 		smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_DESTROYING;
10287961SNatalie.Li@Sun.COM 		while (smb_shr_cache.sc_nops > 0)
10297961SNatalie.Li@Sun.COM 			(void) cond_wait(&smb_shr_cache.sc_cv,
10307961SNatalie.Li@Sun.COM 			    &smb_shr_cache.sc_mtx);
10317961SNatalie.Li@Sun.COM 
10327961SNatalie.Li@Sun.COM 		smb_shr_cache.sc_cache = NULL;
10337961SNatalie.Li@Sun.COM 		smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_NONE;
10347961SNatalie.Li@Sun.COM 	}
10357961SNatalie.Li@Sun.COM 	(void) mutex_unlock(&smb_shr_cache.sc_mtx);
10367961SNatalie.Li@Sun.COM }
10377961SNatalie.Li@Sun.COM 
10387961SNatalie.Li@Sun.COM /*
10397961SNatalie.Li@Sun.COM  * If the cache is in "created" state, lock the cache for read
10407961SNatalie.Li@Sun.COM  * or read/write based on the specified mode.
10417961SNatalie.Li@Sun.COM  *
10427961SNatalie.Li@Sun.COM  * Whenever a lock is granted, the number of inflight cache
10437961SNatalie.Li@Sun.COM  * operations is incremented.
10447961SNatalie.Li@Sun.COM  */
10457961SNatalie.Li@Sun.COM static uint32_t
10467961SNatalie.Li@Sun.COM smb_shr_cache_lock(int mode)
10477961SNatalie.Li@Sun.COM {
10487961SNatalie.Li@Sun.COM 	(void) mutex_lock(&smb_shr_cache.sc_mtx);
10498334SJose.Borrego@Sun.COM 	if (smb_shr_cache.sc_state != SMB_SHR_CACHE_STATE_CREATED) {
10507961SNatalie.Li@Sun.COM 		(void) mutex_unlock(&smb_shr_cache.sc_mtx);
10517961SNatalie.Li@Sun.COM 		return (NERR_InternalError);
10527961SNatalie.Li@Sun.COM 	}
10538334SJose.Borrego@Sun.COM 	smb_shr_cache.sc_nops++;
10547961SNatalie.Li@Sun.COM 	(void) mutex_unlock(&smb_shr_cache.sc_mtx);
10557961SNatalie.Li@Sun.COM 
10567961SNatalie.Li@Sun.COM 	/*
10577961SNatalie.Li@Sun.COM 	 * Lock has to be taken outside the mutex otherwise
10587961SNatalie.Li@Sun.COM 	 * there could be a deadlock
10597961SNatalie.Li@Sun.COM 	 */
10607961SNatalie.Li@Sun.COM 	if (mode == SMB_SHR_CACHE_RDLOCK)
10617961SNatalie.Li@Sun.COM 		(void) rw_rdlock(&smb_shr_cache.sc_cache_lck);
10627961SNatalie.Li@Sun.COM 	else
10637961SNatalie.Li@Sun.COM 		(void) rw_wrlock(&smb_shr_cache.sc_cache_lck);
10647961SNatalie.Li@Sun.COM 
10657961SNatalie.Li@Sun.COM 	return (NERR_Success);
10667961SNatalie.Li@Sun.COM }
10677961SNatalie.Li@Sun.COM 
10687961SNatalie.Li@Sun.COM /*
10697961SNatalie.Li@Sun.COM  * Decrement the number of inflight operations and then unlock.
10707961SNatalie.Li@Sun.COM  */
10717961SNatalie.Li@Sun.COM static void
10727961SNatalie.Li@Sun.COM smb_shr_cache_unlock(void)
10737961SNatalie.Li@Sun.COM {
10747961SNatalie.Li@Sun.COM 	(void) mutex_lock(&smb_shr_cache.sc_mtx);
10757961SNatalie.Li@Sun.COM 	assert(smb_shr_cache.sc_nops > 0);
10767961SNatalie.Li@Sun.COM 	smb_shr_cache.sc_nops--;
10777961SNatalie.Li@Sun.COM 	(void) cond_broadcast(&smb_shr_cache.sc_cv);
10787961SNatalie.Li@Sun.COM 	(void) mutex_unlock(&smb_shr_cache.sc_mtx);
10797961SNatalie.Li@Sun.COM 
10807961SNatalie.Li@Sun.COM 	(void) rw_unlock(&smb_shr_cache.sc_cache_lck);
10817961SNatalie.Li@Sun.COM }
10827961SNatalie.Li@Sun.COM 
10837961SNatalie.Li@Sun.COM /*
10847961SNatalie.Li@Sun.COM  * Return the total number of shares
10857961SNatalie.Li@Sun.COM  */
10867961SNatalie.Li@Sun.COM static int
10877961SNatalie.Li@Sun.COM smb_shr_cache_count(void)
10887961SNatalie.Li@Sun.COM {
10897961SNatalie.Li@Sun.COM 	return (ht_get_total_items(smb_shr_cache.sc_cache));
10907961SNatalie.Li@Sun.COM }
10917961SNatalie.Li@Sun.COM 
10927961SNatalie.Li@Sun.COM /*
10937961SNatalie.Li@Sun.COM  * looks up the given share name in the cache and if it
10947961SNatalie.Li@Sun.COM  * finds a match returns a pointer to the cached entry.
10957961SNatalie.Li@Sun.COM  * Note that since a pointer is returned this function
10967961SNatalie.Li@Sun.COM  * MUST be protected by smb_shr_cache_lock/unlock pair
10977961SNatalie.Li@Sun.COM  */
10987961SNatalie.Li@Sun.COM static smb_share_t *
10997961SNatalie.Li@Sun.COM smb_shr_cache_findent(char *sharename)
11007961SNatalie.Li@Sun.COM {
11017961SNatalie.Li@Sun.COM 	HT_ITEM *item;
11027961SNatalie.Li@Sun.COM 
11037961SNatalie.Li@Sun.COM 	(void) utf8_strlwr(sharename);
11047961SNatalie.Li@Sun.COM 	item = ht_find_item(smb_shr_cache.sc_cache, sharename);
11057961SNatalie.Li@Sun.COM 	if (item && item->hi_data)
11067961SNatalie.Li@Sun.COM 		return ((smb_share_t *)item->hi_data);
11077961SNatalie.Li@Sun.COM 
11087961SNatalie.Li@Sun.COM 	return (NULL);
11097961SNatalie.Li@Sun.COM }
11107961SNatalie.Li@Sun.COM 
11117961SNatalie.Li@Sun.COM /*
11127961SNatalie.Li@Sun.COM  * Return a pointer to the first/next entry in
11137961SNatalie.Li@Sun.COM  * the cache based on the given iterator.
11147961SNatalie.Li@Sun.COM  *
11157961SNatalie.Li@Sun.COM  * Calls to this function MUST be protected by
11167961SNatalie.Li@Sun.COM  * smb_shr_cache_lock/unlock.
11177961SNatalie.Li@Sun.COM  */
11187961SNatalie.Li@Sun.COM static smb_share_t *
11197961SNatalie.Li@Sun.COM smb_shr_cache_iterate(smb_shriter_t *shi)
11207961SNatalie.Li@Sun.COM {
11217961SNatalie.Li@Sun.COM 	HT_ITEM *item;
11227961SNatalie.Li@Sun.COM 
11237961SNatalie.Li@Sun.COM 	if (shi->si_first) {
11247961SNatalie.Li@Sun.COM 		item = ht_findfirst(smb_shr_cache.sc_cache, &shi->si_hashiter);
11257961SNatalie.Li@Sun.COM 		shi->si_first = B_FALSE;
11267961SNatalie.Li@Sun.COM 	} else {
11277961SNatalie.Li@Sun.COM 		item = ht_findnext(&shi->si_hashiter);
11287348SJose.Borrego@Sun.COM 	}
11297348SJose.Borrego@Sun.COM 
11307961SNatalie.Li@Sun.COM 	if (item && item->hi_data)
11317961SNatalie.Li@Sun.COM 		return ((smb_share_t *)item->hi_data);
11327961SNatalie.Li@Sun.COM 
11337961SNatalie.Li@Sun.COM 	return (NULL);
11347961SNatalie.Li@Sun.COM }
11357961SNatalie.Li@Sun.COM 
11367961SNatalie.Li@Sun.COM /*
11377961SNatalie.Li@Sun.COM  * Add the specified share to the cache.  Memory needs to be allocated
11387961SNatalie.Li@Sun.COM  * for the cache entry and the passed information is copied to the
11397961SNatalie.Li@Sun.COM  * allocated space.
11407961SNatalie.Li@Sun.COM  */
11417961SNatalie.Li@Sun.COM static uint32_t
11427961SNatalie.Li@Sun.COM smb_shr_cache_addent(smb_share_t *si)
11437961SNatalie.Li@Sun.COM {
11447961SNatalie.Li@Sun.COM 	smb_share_t *cache_ent;
11457961SNatalie.Li@Sun.COM 	uint32_t status = NERR_Success;
11467961SNatalie.Li@Sun.COM 
11477961SNatalie.Li@Sun.COM 	if ((cache_ent = malloc(sizeof (smb_share_t))) == NULL)
11487961SNatalie.Li@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
11497961SNatalie.Li@Sun.COM 
11507961SNatalie.Li@Sun.COM 	bcopy(si, cache_ent, sizeof (smb_share_t));
11517961SNatalie.Li@Sun.COM 
11527961SNatalie.Li@Sun.COM 	(void) utf8_strlwr(cache_ent->shr_name);
11537961SNatalie.Li@Sun.COM 	smb_shr_set_oemname(cache_ent);
11547961SNatalie.Li@Sun.COM 
11557961SNatalie.Li@Sun.COM 	if ((si->shr_type & STYPE_IPC) == 0)
11567961SNatalie.Li@Sun.COM 		cache_ent->shr_type = STYPE_DISKTREE;
11577961SNatalie.Li@Sun.COM 	cache_ent->shr_type |= smb_shr_is_special(cache_ent->shr_name);
11587961SNatalie.Li@Sun.COM 
11597961SNatalie.Li@Sun.COM 	if (smb_shr_is_admin(cache_ent->shr_name))
11607961SNatalie.Li@Sun.COM 		cache_ent->shr_flags |= SMB_SHRF_ADMIN;
11617961SNatalie.Li@Sun.COM 
11627961SNatalie.Li@Sun.COM 	if (si->shr_flags & SMB_SHRF_AUTOHOME)
11637961SNatalie.Li@Sun.COM 		cache_ent->shr_refcnt = 1;
11647961SNatalie.Li@Sun.COM 
11657961SNatalie.Li@Sun.COM 	if (ht_add_item(smb_shr_cache.sc_cache, cache_ent->shr_name, cache_ent)
11667961SNatalie.Li@Sun.COM 	    == NULL) {
11677961SNatalie.Li@Sun.COM 		syslog(LOG_DEBUG, "share: %s: cache update failed",
11687961SNatalie.Li@Sun.COM 		    cache_ent->shr_name);
11697961SNatalie.Li@Sun.COM 		free(cache_ent);
11707961SNatalie.Li@Sun.COM 		status = NERR_InternalError;
11717348SJose.Borrego@Sun.COM 	}
11727348SJose.Borrego@Sun.COM 
11737961SNatalie.Li@Sun.COM 	return (status);
11747961SNatalie.Li@Sun.COM }
11757961SNatalie.Li@Sun.COM 
11767961SNatalie.Li@Sun.COM /*
11777961SNatalie.Li@Sun.COM  * Delete the specified share from the cache.
11787961SNatalie.Li@Sun.COM  */
11797961SNatalie.Li@Sun.COM static void
11807961SNatalie.Li@Sun.COM smb_shr_cache_delent(char *sharename)
11817961SNatalie.Li@Sun.COM {
11827961SNatalie.Li@Sun.COM 	(void) utf8_strlwr(sharename);
11837961SNatalie.Li@Sun.COM 	(void) ht_remove_item(smb_shr_cache.sc_cache, sharename);
11847961SNatalie.Li@Sun.COM }
11857961SNatalie.Li@Sun.COM 
11867961SNatalie.Li@Sun.COM /*
11877961SNatalie.Li@Sun.COM  * Call back to free the given cache entry.
11887961SNatalie.Li@Sun.COM  */
11897961SNatalie.Li@Sun.COM static void
11907961SNatalie.Li@Sun.COM smb_shr_cache_freent(HT_ITEM *item)
11917961SNatalie.Li@Sun.COM {
11927961SNatalie.Li@Sun.COM 	if (item && item->hi_data)
11937961SNatalie.Li@Sun.COM 		free(item->hi_data);
11947961SNatalie.Li@Sun.COM }
11957961SNatalie.Li@Sun.COM 
11967961SNatalie.Li@Sun.COM /*
11977961SNatalie.Li@Sun.COM  * ============================================
11987961SNatalie.Li@Sun.COM  * Interfaces to sharemgr
11997961SNatalie.Li@Sun.COM  *
12007961SNatalie.Li@Sun.COM  * All functions in this section are private
12017961SNatalie.Li@Sun.COM  * ============================================
12027961SNatalie.Li@Sun.COM  */
12037961SNatalie.Li@Sun.COM 
12047961SNatalie.Li@Sun.COM /*
12057961SNatalie.Li@Sun.COM  * Load shares from sharemgr
12067961SNatalie.Li@Sun.COM  */
12077961SNatalie.Li@Sun.COM /*ARGSUSED*/
12087961SNatalie.Li@Sun.COM static void *
12097961SNatalie.Li@Sun.COM smb_shr_sa_loadall(void *args)
12107961SNatalie.Li@Sun.COM {
12117961SNatalie.Li@Sun.COM 	sa_handle_t handle;
12127961SNatalie.Li@Sun.COM 	sa_group_t group, subgroup;
12137961SNatalie.Li@Sun.COM 	char *gstate;
12147961SNatalie.Li@Sun.COM 	boolean_t gdisabled;
12157961SNatalie.Li@Sun.COM 
12168474SJose.Borrego@Sun.COM 	if ((handle = smb_shr_sa_enter()) == NULL)
12177961SNatalie.Li@Sun.COM 		return (NULL);
12187348SJose.Borrego@Sun.COM 
12197961SNatalie.Li@Sun.COM 	for (group = sa_get_group(handle, NULL);
12207961SNatalie.Li@Sun.COM 	    group != NULL; group = sa_get_next_group(group)) {
12217961SNatalie.Li@Sun.COM 		gstate = sa_get_group_attr(group, "state");
12227961SNatalie.Li@Sun.COM 		if (gstate == NULL)
12237961SNatalie.Li@Sun.COM 			continue;
12247961SNatalie.Li@Sun.COM 
12257961SNatalie.Li@Sun.COM 		gdisabled = (strcasecmp(gstate, "disabled") == 0);
12267961SNatalie.Li@Sun.COM 		sa_free_attr_string(gstate);
12277961SNatalie.Li@Sun.COM 		if (gdisabled)
12287961SNatalie.Li@Sun.COM 			continue;
12297961SNatalie.Li@Sun.COM 
12307961SNatalie.Li@Sun.COM 		smb_shr_sa_loadgrp(group);
12317961SNatalie.Li@Sun.COM 
12327961SNatalie.Li@Sun.COM 		for (subgroup = sa_get_sub_group(group);
12337961SNatalie.Li@Sun.COM 		    subgroup != NULL;
12347961SNatalie.Li@Sun.COM 		    subgroup = sa_get_next_group(subgroup)) {
12357961SNatalie.Li@Sun.COM 			smb_shr_sa_loadgrp(subgroup);
12367961SNatalie.Li@Sun.COM 		}
12377961SNatalie.Li@Sun.COM 
12387348SJose.Borrego@Sun.COM 	}
12397348SJose.Borrego@Sun.COM 
12408474SJose.Borrego@Sun.COM 	smb_shr_sa_exit();
12417961SNatalie.Li@Sun.COM 	return (NULL);
12427348SJose.Borrego@Sun.COM }
12437348SJose.Borrego@Sun.COM 
12447961SNatalie.Li@Sun.COM /*
12457961SNatalie.Li@Sun.COM  * Load the shares contained in the specified group.
12467961SNatalie.Li@Sun.COM  *
12477961SNatalie.Li@Sun.COM  * Don't process groups on which the smb protocol is disabled.
12487961SNatalie.Li@Sun.COM  * The top level ZFS group won't have the smb protocol enabled
12497961SNatalie.Li@Sun.COM  * but sub-groups will.
12507961SNatalie.Li@Sun.COM  *
12517961SNatalie.Li@Sun.COM  * We will tolerate a limited number of errors and then give
12527961SNatalie.Li@Sun.COM  * up on the current group.  A typical error might be that the
12537961SNatalie.Li@Sun.COM  * shared directory no longer exists.
12547961SNatalie.Li@Sun.COM  */
12557961SNatalie.Li@Sun.COM static void
12567961SNatalie.Li@Sun.COM smb_shr_sa_loadgrp(sa_group_t group)
12577961SNatalie.Li@Sun.COM {
12587961SNatalie.Li@Sun.COM 	sa_share_t share;
12597961SNatalie.Li@Sun.COM 	sa_resource_t resource;
12607961SNatalie.Li@Sun.COM 	int error_count = 0;
12617961SNatalie.Li@Sun.COM 
12627961SNatalie.Li@Sun.COM 	if (sa_get_optionset(group, SMB_PROTOCOL_NAME) == NULL)
12637961SNatalie.Li@Sun.COM 		return;
12647961SNatalie.Li@Sun.COM 
12657961SNatalie.Li@Sun.COM 	for (share = sa_get_share(group, NULL);
12667961SNatalie.Li@Sun.COM 	    share != NULL;
12677961SNatalie.Li@Sun.COM 	    share = sa_get_next_share(share)) {
12687961SNatalie.Li@Sun.COM 		for (resource = sa_get_share_resource(share, NULL);
12697961SNatalie.Li@Sun.COM 		    resource != NULL;
12707961SNatalie.Li@Sun.COM 		    resource = sa_get_next_resource(resource)) {
12717961SNatalie.Li@Sun.COM 			if (smb_shr_sa_load(share, resource))
12727961SNatalie.Li@Sun.COM 				++error_count;
12737961SNatalie.Li@Sun.COM 
12747961SNatalie.Li@Sun.COM 			if (error_count > SMB_SHR_ERROR_THRESHOLD)
12757961SNatalie.Li@Sun.COM 				break;
12767961SNatalie.Li@Sun.COM 		}
12777961SNatalie.Li@Sun.COM 
12787961SNatalie.Li@Sun.COM 		if (error_count > SMB_SHR_ERROR_THRESHOLD)
12797961SNatalie.Li@Sun.COM 			break;
12807961SNatalie.Li@Sun.COM 	}
12817961SNatalie.Li@Sun.COM }
12827961SNatalie.Li@Sun.COM 
12837961SNatalie.Li@Sun.COM /*
12847961SNatalie.Li@Sun.COM  * Load a share definition from sharemgr and add it to the cache.
12858334SJose.Borrego@Sun.COM  * If the share is already in the cache then it doesn't do anything.
12868334SJose.Borrego@Sun.COM  *
12878334SJose.Borrego@Sun.COM  * This function does not report duplicate shares as error since
12888334SJose.Borrego@Sun.COM  * a share might have been added by smb_shr_get() while load is
12898334SJose.Borrego@Sun.COM  * in progress.
12907961SNatalie.Li@Sun.COM  */
12917348SJose.Borrego@Sun.COM static uint32_t
12927961SNatalie.Li@Sun.COM smb_shr_sa_load(sa_share_t share, sa_resource_t resource)
12937961SNatalie.Li@Sun.COM {
12947961SNatalie.Li@Sun.COM 	smb_share_t si;
12958334SJose.Borrego@Sun.COM 	char *sharename;
12967961SNatalie.Li@Sun.COM 	uint32_t status;
12978334SJose.Borrego@Sun.COM 	boolean_t loaded;
12988334SJose.Borrego@Sun.COM 
12998334SJose.Borrego@Sun.COM 	if ((sharename = sa_get_resource_attr(resource, "name")) == NULL)
13008334SJose.Borrego@Sun.COM 		return (NERR_InternalError);
13018334SJose.Borrego@Sun.COM 
13028334SJose.Borrego@Sun.COM 	loaded = smb_shr_exists(sharename);
13038334SJose.Borrego@Sun.COM 	sa_free_attr_string(sharename);
13048334SJose.Borrego@Sun.COM 
13058334SJose.Borrego@Sun.COM 	if (loaded)
13068334SJose.Borrego@Sun.COM 		return (NERR_Success);
13077961SNatalie.Li@Sun.COM 
13087961SNatalie.Li@Sun.COM 	if ((status = smb_shr_sa_get(share, resource, &si)) != NERR_Success) {
13097961SNatalie.Li@Sun.COM 		syslog(LOG_DEBUG, "share: failed to load %s (%d)",
13107961SNatalie.Li@Sun.COM 		    si.shr_name, status);
13117961SNatalie.Li@Sun.COM 		return (status);
13127961SNatalie.Li@Sun.COM 	}
13137961SNatalie.Li@Sun.COM 
13148334SJose.Borrego@Sun.COM 	status = smb_shr_add(&si);
13158334SJose.Borrego@Sun.COM 	if ((status != NERR_Success) && (status != NERR_DuplicateShare)) {
13167961SNatalie.Li@Sun.COM 		syslog(LOG_DEBUG, "share: failed to cache %s (%d)",
13177961SNatalie.Li@Sun.COM 		    si.shr_name, status);
13187961SNatalie.Li@Sun.COM 		return (status);
13197961SNatalie.Li@Sun.COM 	}
13207961SNatalie.Li@Sun.COM 
13217961SNatalie.Li@Sun.COM 	return (NERR_Success);
13227961SNatalie.Li@Sun.COM }
13237961SNatalie.Li@Sun.COM 
13247961SNatalie.Li@Sun.COM /*
13257961SNatalie.Li@Sun.COM  * Read the specified share information from sharemgr and return
13267961SNatalie.Li@Sun.COM  * it in the given smb_share_t structure.
13277961SNatalie.Li@Sun.COM  *
13287961SNatalie.Li@Sun.COM  * Shares read from sharemgr are marked as permanent/persistent.
13297961SNatalie.Li@Sun.COM  */
13307961SNatalie.Li@Sun.COM static uint32_t
13317961SNatalie.Li@Sun.COM smb_shr_sa_get(sa_share_t share, sa_resource_t resource, smb_share_t *si)
13327348SJose.Borrego@Sun.COM {
13337348SJose.Borrego@Sun.COM 	sa_property_t prop;
13347348SJose.Borrego@Sun.COM 	sa_optionset_t opts;
13357348SJose.Borrego@Sun.COM 	char *val = NULL;
13367348SJose.Borrego@Sun.COM 	char *path;
13377348SJose.Borrego@Sun.COM 	char *rname;
13387348SJose.Borrego@Sun.COM 
13397348SJose.Borrego@Sun.COM 	if ((path = sa_get_share_attr(share, "path")) == NULL)
13407348SJose.Borrego@Sun.COM 		return (NERR_InternalError);
13417348SJose.Borrego@Sun.COM 
13427348SJose.Borrego@Sun.COM 	if ((rname = sa_get_resource_attr(resource, "name")) == NULL) {
13437348SJose.Borrego@Sun.COM 		sa_free_attr_string(path);
13447348SJose.Borrego@Sun.COM 		return (NERR_InternalError);
13457348SJose.Borrego@Sun.COM 	}
13467348SJose.Borrego@Sun.COM 
13477348SJose.Borrego@Sun.COM 	bzero(si, sizeof (smb_share_t));
13487348SJose.Borrego@Sun.COM 	si->shr_flags = SMB_SHRF_PERM;
13497348SJose.Borrego@Sun.COM 
13507348SJose.Borrego@Sun.COM 	(void) strlcpy(si->shr_path, path, sizeof (si->shr_path));
13517348SJose.Borrego@Sun.COM 	(void) strlcpy(si->shr_name, rname, sizeof (si->shr_name));
13527348SJose.Borrego@Sun.COM 	sa_free_attr_string(path);
13537348SJose.Borrego@Sun.COM 	sa_free_attr_string(rname);
13547348SJose.Borrego@Sun.COM 
13557348SJose.Borrego@Sun.COM 	val = sa_get_resource_description(resource);
13567348SJose.Borrego@Sun.COM 	if (val == NULL)
13577348SJose.Borrego@Sun.COM 		val = sa_get_share_description(share);
13587348SJose.Borrego@Sun.COM 
13597348SJose.Borrego@Sun.COM 	if (val != NULL) {
13607348SJose.Borrego@Sun.COM 		(void) strlcpy(si->shr_cmnt, val, sizeof (si->shr_cmnt));
13617348SJose.Borrego@Sun.COM 		sa_free_share_description(val);
13627348SJose.Borrego@Sun.COM 	}
13637348SJose.Borrego@Sun.COM 
13647348SJose.Borrego@Sun.COM 	opts = sa_get_derived_optionset(resource, SMB_PROTOCOL_NAME, 1);
13657348SJose.Borrego@Sun.COM 	if (opts == NULL)
13667348SJose.Borrego@Sun.COM 		return (NERR_Success);
13677348SJose.Borrego@Sun.COM 
13688334SJose.Borrego@Sun.COM 	prop = (sa_property_t)sa_get_property(opts, SHOPT_AD_CONTAINER);
13697348SJose.Borrego@Sun.COM 	if (prop != NULL) {
13707348SJose.Borrego@Sun.COM 		if ((val = sa_get_property_attr(prop, "value")) != NULL) {
13717348SJose.Borrego@Sun.COM 			(void) strlcpy(si->shr_container, val,
13727348SJose.Borrego@Sun.COM 			    sizeof (si->shr_container));
13737348SJose.Borrego@Sun.COM 			free(val);
13747348SJose.Borrego@Sun.COM 		}
13757348SJose.Borrego@Sun.COM 	}
13767348SJose.Borrego@Sun.COM 
1377*9231SAfshin.Ardakani@Sun.COM 	prop = (sa_property_t)sa_get_property(opts, SHOPT_CATIA);
1378*9231SAfshin.Ardakani@Sun.COM 	if (prop != NULL) {
1379*9231SAfshin.Ardakani@Sun.COM 		if ((val = sa_get_property_attr(prop, "value")) != NULL) {
1380*9231SAfshin.Ardakani@Sun.COM 			smb_shr_sa_catia_option(val, si);
1381*9231SAfshin.Ardakani@Sun.COM 			free(val);
1382*9231SAfshin.Ardakani@Sun.COM 		}
1383*9231SAfshin.Ardakani@Sun.COM 	}
1384*9231SAfshin.Ardakani@Sun.COM 
13858334SJose.Borrego@Sun.COM 	prop = (sa_property_t)sa_get_property(opts, SHOPT_CSC);
13868334SJose.Borrego@Sun.COM 	if (prop != NULL) {
13878334SJose.Borrego@Sun.COM 		if ((val = sa_get_property_attr(prop, "value")) != NULL) {
13888334SJose.Borrego@Sun.COM 			smb_shr_sa_csc_option(val, si);
13898334SJose.Borrego@Sun.COM 			free(val);
13908334SJose.Borrego@Sun.COM 		}
13918334SJose.Borrego@Sun.COM 	}
13928334SJose.Borrego@Sun.COM 
13937961SNatalie.Li@Sun.COM 	prop = (sa_property_t)sa_get_property(opts, SHOPT_NONE);
13947961SNatalie.Li@Sun.COM 	if (prop != NULL) {
13957961SNatalie.Li@Sun.COM 		if ((val = sa_get_property_attr(prop, "value")) != NULL) {
13967961SNatalie.Li@Sun.COM 			(void) strlcpy(si->shr_access_none, val,
13977961SNatalie.Li@Sun.COM 			    sizeof (si->shr_access_none));
13987961SNatalie.Li@Sun.COM 			free(val);
13997961SNatalie.Li@Sun.COM 			si->shr_flags |= SMB_SHRF_ACC_NONE;
14007961SNatalie.Li@Sun.COM 		}
14017348SJose.Borrego@Sun.COM 	}
14027348SJose.Borrego@Sun.COM 
14037961SNatalie.Li@Sun.COM 	prop = (sa_property_t)sa_get_property(opts, SHOPT_RO);
14047961SNatalie.Li@Sun.COM 	if (prop != NULL) {
14057961SNatalie.Li@Sun.COM 		if ((val = sa_get_property_attr(prop, "value")) != NULL) {
14067961SNatalie.Li@Sun.COM 			(void) strlcpy(si->shr_access_ro, val,
14077961SNatalie.Li@Sun.COM 			    sizeof (si->shr_access_ro));
14087961SNatalie.Li@Sun.COM 			free(val);
14097961SNatalie.Li@Sun.COM 			si->shr_flags |= SMB_SHRF_ACC_RO;
14107961SNatalie.Li@Sun.COM 		}
14117348SJose.Borrego@Sun.COM 	}
14127348SJose.Borrego@Sun.COM 
14137961SNatalie.Li@Sun.COM 	prop = (sa_property_t)sa_get_property(opts, SHOPT_RW);
14147961SNatalie.Li@Sun.COM 	if (prop != NULL) {
14157961SNatalie.Li@Sun.COM 		if ((val = sa_get_property_attr(prop, "value")) != NULL) {
14167961SNatalie.Li@Sun.COM 			(void) strlcpy(si->shr_access_rw, val,
14177961SNatalie.Li@Sun.COM 			    sizeof (si->shr_access_rw));
14187961SNatalie.Li@Sun.COM 			free(val);
14197961SNatalie.Li@Sun.COM 			si->shr_flags |= SMB_SHRF_ACC_RW;
14207961SNatalie.Li@Sun.COM 		}
14217961SNatalie.Li@Sun.COM 	}
14227961SNatalie.Li@Sun.COM 
14237961SNatalie.Li@Sun.COM 	sa_free_derived_optionset(opts);
14247961SNatalie.Li@Sun.COM 	return (NERR_Success);
14257348SJose.Borrego@Sun.COM }
14267348SJose.Borrego@Sun.COM 
14277348SJose.Borrego@Sun.COM /*
14288334SJose.Borrego@Sun.COM  * Map a client-side caching (CSC) option to the appropriate share
14298334SJose.Borrego@Sun.COM  * flag.  Only one option is allowed; an error will be logged if
14308334SJose.Borrego@Sun.COM  * multiple options have been specified.  We don't need to do anything
14318334SJose.Borrego@Sun.COM  * about multiple values here because the SRVSVC will not recognize
14328334SJose.Borrego@Sun.COM  * a value containing multiple flags and will return the default value.
14338334SJose.Borrego@Sun.COM  *
14348334SJose.Borrego@Sun.COM  * If the option value is not recognized, it will be ignored: invalid
14358334SJose.Borrego@Sun.COM  * values will typically be caught and rejected by sharemgr.
14368334SJose.Borrego@Sun.COM  */
14378474SJose.Borrego@Sun.COM void
14388334SJose.Borrego@Sun.COM smb_shr_sa_csc_option(const char *value, smb_share_t *si)
14398334SJose.Borrego@Sun.COM {
14408334SJose.Borrego@Sun.COM 	struct {
14418334SJose.Borrego@Sun.COM 		char *value;
14428334SJose.Borrego@Sun.COM 		uint32_t flag;
14438334SJose.Borrego@Sun.COM 	} cscopt[] = {
14448334SJose.Borrego@Sun.COM 		{ "disabled",	SMB_SHRF_CSC_DISABLED },
14458334SJose.Borrego@Sun.COM 		{ "manual",	SMB_SHRF_CSC_MANUAL },
14468334SJose.Borrego@Sun.COM 		{ "auto",	SMB_SHRF_CSC_AUTO },
14478334SJose.Borrego@Sun.COM 		{ "vdo",	SMB_SHRF_CSC_VDO }
14488334SJose.Borrego@Sun.COM 	};
14498334SJose.Borrego@Sun.COM 
14508334SJose.Borrego@Sun.COM 	int i;
14518334SJose.Borrego@Sun.COM 
14528334SJose.Borrego@Sun.COM 	for (i = 0; i < (sizeof (cscopt) / sizeof (cscopt[0])); ++i) {
14538334SJose.Borrego@Sun.COM 		if (strcasecmp(value, cscopt[i].value) == 0) {
14548334SJose.Borrego@Sun.COM 			si->shr_flags |= cscopt[i].flag;
14558334SJose.Borrego@Sun.COM 			break;
14568334SJose.Borrego@Sun.COM 		}
14578334SJose.Borrego@Sun.COM 	}
14588334SJose.Borrego@Sun.COM 
14598334SJose.Borrego@Sun.COM 	switch (si->shr_flags & SMB_SHRF_CSC_MASK) {
14608334SJose.Borrego@Sun.COM 	case 0:
14618334SJose.Borrego@Sun.COM 	case SMB_SHRF_CSC_DISABLED:
14628334SJose.Borrego@Sun.COM 	case SMB_SHRF_CSC_MANUAL:
14638334SJose.Borrego@Sun.COM 	case SMB_SHRF_CSC_AUTO:
14648334SJose.Borrego@Sun.COM 	case SMB_SHRF_CSC_VDO:
14658334SJose.Borrego@Sun.COM 		break;
14668334SJose.Borrego@Sun.COM 
14678334SJose.Borrego@Sun.COM 	default:
14688474SJose.Borrego@Sun.COM 		syslog(LOG_INFO, "csc option conflict: 0x%08x",
14698474SJose.Borrego@Sun.COM 		    si->shr_flags & SMB_SHRF_CSC_MASK);
14708334SJose.Borrego@Sun.COM 		break;
14718334SJose.Borrego@Sun.COM 	}
14728334SJose.Borrego@Sun.COM }
14738334SJose.Borrego@Sun.COM 
14748334SJose.Borrego@Sun.COM /*
1475*9231SAfshin.Ardakani@Sun.COM  * set SMB_SHRF_CATIA in accordance with catia property value
1476*9231SAfshin.Ardakani@Sun.COM  */
1477*9231SAfshin.Ardakani@Sun.COM void
1478*9231SAfshin.Ardakani@Sun.COM smb_shr_sa_catia_option(const char *value, smb_share_t *si)
1479*9231SAfshin.Ardakani@Sun.COM {
1480*9231SAfshin.Ardakani@Sun.COM 	if ((strcasecmp(value, "true") == 0) || (strcmp(value, "1") == 0)) {
1481*9231SAfshin.Ardakani@Sun.COM 		si->shr_flags |= SMB_SHRF_CATIA;
1482*9231SAfshin.Ardakani@Sun.COM 	} else {
1483*9231SAfshin.Ardakani@Sun.COM 		si->shr_flags &= ~SMB_SHRF_CATIA;
1484*9231SAfshin.Ardakani@Sun.COM 	}
1485*9231SAfshin.Ardakani@Sun.COM }
1486*9231SAfshin.Ardakani@Sun.COM 
1487*9231SAfshin.Ardakani@Sun.COM /*
14888334SJose.Borrego@Sun.COM  * looks up sharemgr for the given share (resource) and loads
14898334SJose.Borrego@Sun.COM  * the definition into cache if lookup is successful
14908334SJose.Borrego@Sun.COM  */
14918334SJose.Borrego@Sun.COM static uint32_t
14928334SJose.Borrego@Sun.COM smb_shr_sa_loadbyname(char *sharename)
14938334SJose.Borrego@Sun.COM {
14948334SJose.Borrego@Sun.COM 	sa_handle_t handle;
14958334SJose.Borrego@Sun.COM 	sa_share_t share;
14968334SJose.Borrego@Sun.COM 	sa_resource_t resource;
14978334SJose.Borrego@Sun.COM 	uint32_t status;
14988334SJose.Borrego@Sun.COM 
14998474SJose.Borrego@Sun.COM 	if ((handle = smb_shr_sa_enter()) == NULL)
15008334SJose.Borrego@Sun.COM 		return (NERR_InternalError);
15018334SJose.Borrego@Sun.COM 
15028334SJose.Borrego@Sun.COM 	resource = sa_find_resource(handle, sharename);
15038334SJose.Borrego@Sun.COM 	if (resource == NULL) {
15048474SJose.Borrego@Sun.COM 		smb_shr_sa_exit();
15058334SJose.Borrego@Sun.COM 		return (NERR_NetNameNotFound);
15068334SJose.Borrego@Sun.COM 	}
15078334SJose.Borrego@Sun.COM 
15088334SJose.Borrego@Sun.COM 	share = sa_get_resource_parent(resource);
15098334SJose.Borrego@Sun.COM 	if (share == NULL) {
15108474SJose.Borrego@Sun.COM 		smb_shr_sa_exit();
15118334SJose.Borrego@Sun.COM 		return (NERR_InternalError);
15128334SJose.Borrego@Sun.COM 	}
15138334SJose.Borrego@Sun.COM 
15148334SJose.Borrego@Sun.COM 	status = smb_shr_sa_load(share, resource);
15158334SJose.Borrego@Sun.COM 
15168474SJose.Borrego@Sun.COM 	smb_shr_sa_exit();
15178334SJose.Borrego@Sun.COM 	return (status);
15188334SJose.Borrego@Sun.COM }
15198334SJose.Borrego@Sun.COM 
15208334SJose.Borrego@Sun.COM /*
15217348SJose.Borrego@Sun.COM  * ============================================
15227348SJose.Borrego@Sun.COM  * Share publishing functions
15237961SNatalie.Li@Sun.COM  *
15247961SNatalie.Li@Sun.COM  * All the functions are private
15257348SJose.Borrego@Sun.COM  * ============================================
15267348SJose.Borrego@Sun.COM  */
15277348SJose.Borrego@Sun.COM 
15287961SNatalie.Li@Sun.COM static void
15297961SNatalie.Li@Sun.COM smb_shr_publish(const char *sharename, const char *container)
15307961SNatalie.Li@Sun.COM {
15317961SNatalie.Li@Sun.COM 	smb_shr_publisher_queue(sharename, container, SMB_SHR_PUBLISH);
15327961SNatalie.Li@Sun.COM }
15337961SNatalie.Li@Sun.COM 
15347961SNatalie.Li@Sun.COM static void
15357961SNatalie.Li@Sun.COM smb_shr_unpublish(const char *sharename, const char *container)
15367961SNatalie.Li@Sun.COM {
15377961SNatalie.Li@Sun.COM 	smb_shr_publisher_queue(sharename, container, SMB_SHR_UNPUBLISH);
15387961SNatalie.Li@Sun.COM }
15397961SNatalie.Li@Sun.COM 
15407348SJose.Borrego@Sun.COM /*
15417961SNatalie.Li@Sun.COM  * In domain mode, put a share on the publisher queue.
15427961SNatalie.Li@Sun.COM  * This is a no-op if the smb service is in Workgroup mode.
15437348SJose.Borrego@Sun.COM  */
15447348SJose.Borrego@Sun.COM static void
15457961SNatalie.Li@Sun.COM smb_shr_publisher_queue(const char *sharename, const char *container, char op)
15467348SJose.Borrego@Sun.COM {
15477348SJose.Borrego@Sun.COM 	smb_shr_pitem_t *item = NULL;
15487348SJose.Borrego@Sun.COM 
15497348SJose.Borrego@Sun.COM 	if (container == NULL || *container == '\0')
15507348SJose.Borrego@Sun.COM 		return;
15517348SJose.Borrego@Sun.COM 
15527961SNatalie.Li@Sun.COM 	if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN)
15537961SNatalie.Li@Sun.COM 		return;
15547961SNatalie.Li@Sun.COM 
15557348SJose.Borrego@Sun.COM 	(void) mutex_lock(&ad_queue.spq_mtx);
15567348SJose.Borrego@Sun.COM 	switch (ad_queue.spq_state) {
15577348SJose.Borrego@Sun.COM 	case SMB_SHR_PQS_READY:
15587348SJose.Borrego@Sun.COM 	case SMB_SHR_PQS_PUBLISHING:
15597348SJose.Borrego@Sun.COM 		break;
15607348SJose.Borrego@Sun.COM 	default:
15617348SJose.Borrego@Sun.COM 		(void) mutex_unlock(&ad_queue.spq_mtx);
15627348SJose.Borrego@Sun.COM 		return;
15637348SJose.Borrego@Sun.COM 	}
15647348SJose.Borrego@Sun.COM 	(void) mutex_unlock(&ad_queue.spq_mtx);
15657348SJose.Borrego@Sun.COM 
15667961SNatalie.Li@Sun.COM 	if ((item = malloc(sizeof (smb_shr_pitem_t))) == NULL)
15677348SJose.Borrego@Sun.COM 		return;
15687348SJose.Borrego@Sun.COM 
15697348SJose.Borrego@Sun.COM 	item->spi_op = op;
15707348SJose.Borrego@Sun.COM 	(void) strlcpy(item->spi_name, sharename, sizeof (item->spi_name));
15717348SJose.Borrego@Sun.COM 	(void) strlcpy(item->spi_container, container,
15727348SJose.Borrego@Sun.COM 	    sizeof (item->spi_container));
15737348SJose.Borrego@Sun.COM 
15747348SJose.Borrego@Sun.COM 	(void) mutex_lock(&ad_queue.spq_mtx);
15757348SJose.Borrego@Sun.COM 	list_insert_tail(&ad_queue.spq_list, item);
15767348SJose.Borrego@Sun.COM 	(void) cond_signal(&ad_queue.spq_cv);
15777348SJose.Borrego@Sun.COM 	(void) mutex_unlock(&ad_queue.spq_mtx);
15787348SJose.Borrego@Sun.COM }
15797348SJose.Borrego@Sun.COM 
15807961SNatalie.Li@Sun.COM /*
15817961SNatalie.Li@Sun.COM  * Publishing won't be activated if the smb service is running in
15827961SNatalie.Li@Sun.COM  * Workgroup mode.
15837961SNatalie.Li@Sun.COM  */
15847348SJose.Borrego@Sun.COM static int
15857348SJose.Borrego@Sun.COM smb_shr_publisher_start(void)
15867348SJose.Borrego@Sun.COM {
15877961SNatalie.Li@Sun.COM 	pthread_t publish_thr;
15887348SJose.Borrego@Sun.COM 	pthread_attr_t tattr;
15897348SJose.Borrego@Sun.COM 	int rc;
15907348SJose.Borrego@Sun.COM 
15917961SNatalie.Li@Sun.COM 	if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN)
15927961SNatalie.Li@Sun.COM 		return (0);
15937961SNatalie.Li@Sun.COM 
15947348SJose.Borrego@Sun.COM 	(void) mutex_lock(&ad_queue.spq_mtx);
15957348SJose.Borrego@Sun.COM 	if (ad_queue.spq_state != SMB_SHR_PQS_NOQUEUE) {
15967348SJose.Borrego@Sun.COM 		(void) mutex_unlock(&ad_queue.spq_mtx);
15977348SJose.Borrego@Sun.COM 		errno = EINVAL;
15987348SJose.Borrego@Sun.COM 		return (-1);
15997348SJose.Borrego@Sun.COM 	}
16007348SJose.Borrego@Sun.COM 
16017348SJose.Borrego@Sun.COM 	list_create(&ad_queue.spq_list, sizeof (smb_shr_pitem_t),
16027348SJose.Borrego@Sun.COM 	    offsetof(smb_shr_pitem_t, spi_lnd));
16037348SJose.Borrego@Sun.COM 	ad_queue.spq_state = SMB_SHR_PQS_READY;
16047348SJose.Borrego@Sun.COM 	(void) mutex_unlock(&ad_queue.spq_mtx);
16057348SJose.Borrego@Sun.COM 
16067348SJose.Borrego@Sun.COM 	(void) pthread_attr_init(&tattr);
16077348SJose.Borrego@Sun.COM 	(void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
16087961SNatalie.Li@Sun.COM 	rc = pthread_create(&publish_thr, &tattr, smb_shr_publisher, 0);
16097348SJose.Borrego@Sun.COM 	(void) pthread_attr_destroy(&tattr);
16107348SJose.Borrego@Sun.COM 
16117348SJose.Borrego@Sun.COM 	return (rc);
16127348SJose.Borrego@Sun.COM }
16137348SJose.Borrego@Sun.COM 
16147348SJose.Borrego@Sun.COM static void
16157348SJose.Borrego@Sun.COM smb_shr_publisher_stop(void)
16167348SJose.Borrego@Sun.COM {
16177961SNatalie.Li@Sun.COM 	if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN)
16187961SNatalie.Li@Sun.COM 		return;
16197961SNatalie.Li@Sun.COM 
16207348SJose.Borrego@Sun.COM 	(void) mutex_lock(&ad_queue.spq_mtx);
16217348SJose.Borrego@Sun.COM 	switch (ad_queue.spq_state) {
16227348SJose.Borrego@Sun.COM 	case SMB_SHR_PQS_READY:
16237348SJose.Borrego@Sun.COM 	case SMB_SHR_PQS_PUBLISHING:
16247348SJose.Borrego@Sun.COM 		ad_queue.spq_state = SMB_SHR_PQS_STOPPING;
16257348SJose.Borrego@Sun.COM 		(void) cond_signal(&ad_queue.spq_cv);
16267348SJose.Borrego@Sun.COM 		break;
16277348SJose.Borrego@Sun.COM 	default:
16287348SJose.Borrego@Sun.COM 		break;
16297348SJose.Borrego@Sun.COM 	}
16307348SJose.Borrego@Sun.COM 	(void) mutex_unlock(&ad_queue.spq_mtx);
16317348SJose.Borrego@Sun.COM }
16327348SJose.Borrego@Sun.COM 
16337348SJose.Borrego@Sun.COM /*
16347961SNatalie.Li@Sun.COM  * This is the publisher daemon thread.  While running, the thread waits
16357961SNatalie.Li@Sun.COM  * on a conditional variable until notified that a share needs to be
16367961SNatalie.Li@Sun.COM  * [un]published or that the thread should be terminated.
16377961SNatalie.Li@Sun.COM  *
16387961SNatalie.Li@Sun.COM  * Entries may remain in the outgoing queue if the Active Directory
16397961SNatalie.Li@Sun.COM  * service is inaccessible, in which case the thread wakes up every 60
16407961SNatalie.Li@Sun.COM  * seconds to retry.
16417348SJose.Borrego@Sun.COM  */
16427348SJose.Borrego@Sun.COM /*ARGSUSED*/
16437348SJose.Borrego@Sun.COM static void *
16447348SJose.Borrego@Sun.COM smb_shr_publisher(void *arg)
16457348SJose.Borrego@Sun.COM {
16467348SJose.Borrego@Sun.COM 	smb_ads_handle_t *ah;
16477348SJose.Borrego@Sun.COM 	smb_shr_pitem_t *shr;
16487348SJose.Borrego@Sun.COM 	list_t publist;
16497961SNatalie.Li@Sun.COM 	timestruc_t pubretry;
16507348SJose.Borrego@Sun.COM 	char hostname[MAXHOSTNAMELEN];
16517348SJose.Borrego@Sun.COM 
16527348SJose.Borrego@Sun.COM 	(void) mutex_lock(&ad_queue.spq_mtx);
16537961SNatalie.Li@Sun.COM 	if (ad_queue.spq_state != SMB_SHR_PQS_READY) {
16547348SJose.Borrego@Sun.COM 		(void) mutex_unlock(&ad_queue.spq_mtx);
16557348SJose.Borrego@Sun.COM 		return (NULL);
16567348SJose.Borrego@Sun.COM 	}
16577961SNatalie.Li@Sun.COM 	ad_queue.spq_state = SMB_SHR_PQS_PUBLISHING;
16587348SJose.Borrego@Sun.COM 	(void) mutex_unlock(&ad_queue.spq_mtx);
16597348SJose.Borrego@Sun.COM 
16607348SJose.Borrego@Sun.COM 	(void) smb_gethostname(hostname, MAXHOSTNAMELEN, 0);
16617961SNatalie.Li@Sun.COM 
16627348SJose.Borrego@Sun.COM 	list_create(&publist, sizeof (smb_shr_pitem_t),
16637348SJose.Borrego@Sun.COM 	    offsetof(smb_shr_pitem_t, spi_lnd));
16647348SJose.Borrego@Sun.COM 
16657348SJose.Borrego@Sun.COM 	for (;;) {
16667348SJose.Borrego@Sun.COM 		(void) mutex_lock(&ad_queue.spq_mtx);
16677961SNatalie.Li@Sun.COM 
16687961SNatalie.Li@Sun.COM 		while (list_is_empty(&ad_queue.spq_list) &&
16697961SNatalie.Li@Sun.COM 		    (ad_queue.spq_state == SMB_SHR_PQS_PUBLISHING)) {
16707961SNatalie.Li@Sun.COM 			if (list_is_empty(&publist)) {
16717961SNatalie.Li@Sun.COM 				(void) cond_wait(&ad_queue.spq_cv,
16727961SNatalie.Li@Sun.COM 				    &ad_queue.spq_mtx);
16737961SNatalie.Li@Sun.COM 			} else {
16747961SNatalie.Li@Sun.COM 				pubretry.tv_sec = 60;
16757961SNatalie.Li@Sun.COM 				pubretry.tv_nsec = 0;
16767961SNatalie.Li@Sun.COM 				(void) cond_reltimedwait(&ad_queue.spq_cv,
16777961SNatalie.Li@Sun.COM 				    &ad_queue.spq_mtx, &pubretry);
16787961SNatalie.Li@Sun.COM 				break;
16797961SNatalie.Li@Sun.COM 			}
16807961SNatalie.Li@Sun.COM 		}
16817348SJose.Borrego@Sun.COM 
16827348SJose.Borrego@Sun.COM 		if (ad_queue.spq_state != SMB_SHR_PQS_PUBLISHING) {
16837348SJose.Borrego@Sun.COM 			(void) mutex_unlock(&ad_queue.spq_mtx);
16847348SJose.Borrego@Sun.COM 			break;
16857348SJose.Borrego@Sun.COM 		}
16867348SJose.Borrego@Sun.COM 
16877348SJose.Borrego@Sun.COM 		/*
16887961SNatalie.Li@Sun.COM 		 * Transfer queued items to the local list so that
16897961SNatalie.Li@Sun.COM 		 * the mutex can be released.
16907348SJose.Borrego@Sun.COM 		 */
16917348SJose.Borrego@Sun.COM 		while ((shr = list_head(&ad_queue.spq_list)) != NULL) {
16927348SJose.Borrego@Sun.COM 			list_remove(&ad_queue.spq_list, shr);
16937348SJose.Borrego@Sun.COM 			list_insert_tail(&publist, shr);
16947348SJose.Borrego@Sun.COM 		}
16957961SNatalie.Li@Sun.COM 
16967348SJose.Borrego@Sun.COM 		(void) mutex_unlock(&ad_queue.spq_mtx);
16977348SJose.Borrego@Sun.COM 
16987961SNatalie.Li@Sun.COM 		if ((ah = smb_ads_open()) != NULL) {
16997961SNatalie.Li@Sun.COM 			smb_shr_publisher_send(ah, &publist, hostname);
17007961SNatalie.Li@Sun.COM 			smb_ads_close(ah);
17017961SNatalie.Li@Sun.COM 		}
17027348SJose.Borrego@Sun.COM 	}
17037348SJose.Borrego@Sun.COM 
17047348SJose.Borrego@Sun.COM 	(void) mutex_lock(&ad_queue.spq_mtx);
17057961SNatalie.Li@Sun.COM 	smb_shr_publisher_flush(&ad_queue.spq_list);
17067348SJose.Borrego@Sun.COM 	list_destroy(&ad_queue.spq_list);
17077348SJose.Borrego@Sun.COM 	ad_queue.spq_state = SMB_SHR_PQS_NOQUEUE;
17087348SJose.Borrego@Sun.COM 	(void) mutex_unlock(&ad_queue.spq_mtx);
17097348SJose.Borrego@Sun.COM 
17107961SNatalie.Li@Sun.COM 	smb_shr_publisher_flush(&publist);
17117348SJose.Borrego@Sun.COM 	list_destroy(&publist);
17127348SJose.Borrego@Sun.COM 	return (NULL);
17137348SJose.Borrego@Sun.COM }
17147348SJose.Borrego@Sun.COM 
17157348SJose.Borrego@Sun.COM /*
17167961SNatalie.Li@Sun.COM  * Remove items from the specified queue and [un]publish them.
17177348SJose.Borrego@Sun.COM  */
17187348SJose.Borrego@Sun.COM static void
17197348SJose.Borrego@Sun.COM smb_shr_publisher_send(smb_ads_handle_t *ah, list_t *publist, const char *host)
17207348SJose.Borrego@Sun.COM {
17217348SJose.Borrego@Sun.COM 	smb_shr_pitem_t *shr;
17227348SJose.Borrego@Sun.COM 
17237348SJose.Borrego@Sun.COM 	while ((shr = list_head(publist)) != NULL) {
17247961SNatalie.Li@Sun.COM 		(void) mutex_lock(&ad_queue.spq_mtx);
17257961SNatalie.Li@Sun.COM 		if (ad_queue.spq_state != SMB_SHR_PQS_PUBLISHING) {
17267348SJose.Borrego@Sun.COM 			(void) mutex_unlock(&ad_queue.spq_mtx);
17277961SNatalie.Li@Sun.COM 			return;
17287961SNatalie.Li@Sun.COM 		}
17297961SNatalie.Li@Sun.COM 		(void) mutex_unlock(&ad_queue.spq_mtx);
17307348SJose.Borrego@Sun.COM 
17317961SNatalie.Li@Sun.COM 		list_remove(publist, shr);
17327961SNatalie.Li@Sun.COM 
17337961SNatalie.Li@Sun.COM 		if (shr->spi_op == SMB_SHR_PUBLISH)
17347961SNatalie.Li@Sun.COM 			(void) smb_ads_publish_share(ah, shr->spi_name,
17357961SNatalie.Li@Sun.COM 			    NULL, shr->spi_container, host);
17367961SNatalie.Li@Sun.COM 		else
17377961SNatalie.Li@Sun.COM 			(void) smb_ads_remove_share(ah, shr->spi_name,
17387961SNatalie.Li@Sun.COM 			    NULL, shr->spi_container, host);
17397961SNatalie.Li@Sun.COM 
17407348SJose.Borrego@Sun.COM 		free(shr);
17417348SJose.Borrego@Sun.COM 	}
17427348SJose.Borrego@Sun.COM }
17437961SNatalie.Li@Sun.COM 
17447961SNatalie.Li@Sun.COM /*
17457961SNatalie.Li@Sun.COM  * Flush all remaining items from the specified list/queue.
17467961SNatalie.Li@Sun.COM  */
17477961SNatalie.Li@Sun.COM static void
17487961SNatalie.Li@Sun.COM smb_shr_publisher_flush(list_t *lst)
17497961SNatalie.Li@Sun.COM {
17507961SNatalie.Li@Sun.COM 	smb_shr_pitem_t *shr;
17517961SNatalie.Li@Sun.COM 
17527961SNatalie.Li@Sun.COM 	while ((shr = list_head(lst)) != NULL) {
17537961SNatalie.Li@Sun.COM 		list_remove(lst, shr);
17547961SNatalie.Li@Sun.COM 		free(shr);
17557961SNatalie.Li@Sun.COM 	}
17567961SNatalie.Li@Sun.COM }
17578845Samw@Sun.COM 
17588845Samw@Sun.COM /*
17598871Samw@Sun.COM  * If the share path refers to a ZFS file system, add the
17608845Samw@Sun.COM  * .zfs/shares/<share> object.
17618845Samw@Sun.COM  */
17628845Samw@Sun.COM 
17638845Samw@Sun.COM static void
17648845Samw@Sun.COM smb_shr_zfs_add(smb_share_t *si)
17658845Samw@Sun.COM {
17668871Samw@Sun.COM 	libzfs_handle_t *libhd;
17678871Samw@Sun.COM 	zfs_handle_t *zfshd;
17688871Samw@Sun.COM 	int ret;
17698845Samw@Sun.COM 	char dataset[MAXPATHLEN];
17708845Samw@Sun.COM 
17718871Samw@Sun.COM 	if (smb_getdataset(si->shr_path, dataset, MAXPATHLEN) != 0)
17728871Samw@Sun.COM 		return;
17738871Samw@Sun.COM 
17748871Samw@Sun.COM 	if ((libhd = libzfs_init()) == NULL)
17758871Samw@Sun.COM 		return;
17768871Samw@Sun.COM 
17778871Samw@Sun.COM 	if ((zfshd = zfs_open(libhd, dataset, ZFS_TYPE_FILESYSTEM)) == NULL) {
17788871Samw@Sun.COM 		libzfs_fini(libhd);
17798871Samw@Sun.COM 		return;
17808845Samw@Sun.COM 	}
17818871Samw@Sun.COM 
17828871Samw@Sun.COM 	errno = 0;
17838871Samw@Sun.COM 	ret = zfs_smb_acl_add(libhd, dataset, si->shr_path, si->shr_name);
17848871Samw@Sun.COM 	if (ret != 0 && errno != EAGAIN && errno != EEXIST)
17858871Samw@Sun.COM 		syslog(LOG_INFO, "share: failed to add ACL object: %s: %s\n",
17868871Samw@Sun.COM 		    si->shr_name, strerror(errno));
17878871Samw@Sun.COM 
17888871Samw@Sun.COM 	zfs_close(zfshd);
17898871Samw@Sun.COM 	libzfs_fini(libhd);
17908845Samw@Sun.COM }
17918845Samw@Sun.COM 
17928845Samw@Sun.COM /*
17938871Samw@Sun.COM  * If the share path refers to a ZFS file system, remove the
17948845Samw@Sun.COM  * .zfs/shares/<share> object.
17958845Samw@Sun.COM  */
17968845Samw@Sun.COM 
17978845Samw@Sun.COM static void
17988845Samw@Sun.COM smb_shr_zfs_remove(smb_share_t *si)
17998845Samw@Sun.COM {
18008871Samw@Sun.COM 	libzfs_handle_t *libhd;
18018871Samw@Sun.COM 	zfs_handle_t *zfshd;
18028871Samw@Sun.COM 	int ret;
18038845Samw@Sun.COM 	char dataset[MAXPATHLEN];
18048845Samw@Sun.COM 
18058871Samw@Sun.COM 	if (smb_getdataset(si->shr_path, dataset, MAXPATHLEN) != 0)
18068871Samw@Sun.COM 		return;
18078871Samw@Sun.COM 
18088871Samw@Sun.COM 	if ((libhd = libzfs_init()) == NULL)
18098871Samw@Sun.COM 		return;
18108871Samw@Sun.COM 
18118871Samw@Sun.COM 	if ((zfshd = zfs_open(libhd, dataset, ZFS_TYPE_FILESYSTEM)) == NULL) {
18128871Samw@Sun.COM 		libzfs_fini(libhd);
18138871Samw@Sun.COM 		return;
18148845Samw@Sun.COM 	}
18158871Samw@Sun.COM 
18168871Samw@Sun.COM 	errno = 0;
18178871Samw@Sun.COM 	ret = zfs_smb_acl_remove(libhd, dataset, si->shr_path, si->shr_name);
18188871Samw@Sun.COM 	if (ret != 0 && errno != EAGAIN)
18198871Samw@Sun.COM 		syslog(LOG_INFO, "share: failed to remove ACL object: %s: %s\n",
18208871Samw@Sun.COM 		    si->shr_name, strerror(errno));
18218871Samw@Sun.COM 
18228871Samw@Sun.COM 	zfs_close(zfshd);
18238871Samw@Sun.COM 	libzfs_fini(libhd);
18248845Samw@Sun.COM }
18258845Samw@Sun.COM 
18268845Samw@Sun.COM /*
18278871Samw@Sun.COM  * If the share path refers to a ZFS file system, rename the
18288845Samw@Sun.COM  * .zfs/shares/<share> object.
18298845Samw@Sun.COM  */
18308845Samw@Sun.COM 
18318845Samw@Sun.COM static void
18328845Samw@Sun.COM smb_shr_zfs_rename(smb_share_t *from, smb_share_t *to)
18338845Samw@Sun.COM {
18348871Samw@Sun.COM 	libzfs_handle_t *libhd;
18358871Samw@Sun.COM 	zfs_handle_t *zfshd;
18368871Samw@Sun.COM 	int ret;
18378845Samw@Sun.COM 	char dataset[MAXPATHLEN];
18388845Samw@Sun.COM 
18398871Samw@Sun.COM 	if (smb_getdataset(from->shr_path, dataset, MAXPATHLEN) != 0)
18408871Samw@Sun.COM 		return;
18418871Samw@Sun.COM 
18428871Samw@Sun.COM 	if ((libhd = libzfs_init()) == NULL)
18438871Samw@Sun.COM 		return;
18448871Samw@Sun.COM 
18458871Samw@Sun.COM 	if ((zfshd = zfs_open(libhd, dataset, ZFS_TYPE_FILESYSTEM)) == NULL) {
18468871Samw@Sun.COM 		libzfs_fini(libhd);
18478871Samw@Sun.COM 		return;
18488845Samw@Sun.COM 	}
18498871Samw@Sun.COM 
18508871Samw@Sun.COM 	errno = 0;
18518871Samw@Sun.COM 	ret = zfs_smb_acl_rename(libhd, dataset, from->shr_path,
18528871Samw@Sun.COM 	    from->shr_name, to->shr_name);
18538871Samw@Sun.COM 	if (ret != 0 && errno != EAGAIN)
18548871Samw@Sun.COM 		syslog(LOG_INFO, "share: failed to rename ACL object: %s: %s\n",
18558871Samw@Sun.COM 		    from->shr_name, strerror(errno));
18568871Samw@Sun.COM 
18578871Samw@Sun.COM 	zfs_close(zfshd);
18588871Samw@Sun.COM 	libzfs_fini(libhd);
18598845Samw@Sun.COM }
1860