xref: /onnv-gate/usr/src/lib/smbsrv/libmlsvc/common/smb_share.c (revision 7348:73b61202d5d6)
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 /*
227052Samw  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
237052Samw  * Use is subject to license terms.
247052Samw  */
257052Samw 
26*7348SJose.Borrego@Sun.COM #pragma ident	"@(#)smb_share.c	1.7	08/08/07 SMI"
277052Samw 
287052Samw /*
297052Samw  * Lan Manager (SMB/CIFS) share interface implementation. This interface
307052Samw  * returns Win32 error codes, usually network error values (lmerr.h).
317052Samw  */
327052Samw 
337052Samw #include <errno.h>
347052Samw #include <synch.h>
357052Samw #include <stdio.h>
367052Samw #include <stdlib.h>
377052Samw #include <strings.h>
387052Samw #include <syslog.h>
397052Samw #include <thread.h>
407052Samw #include <fcntl.h>
417052Samw #include <unistd.h>
427052Samw #include <netdb.h>
437052Samw #include <synch.h>
447052Samw #include <pthread.h>
45*7348SJose.Borrego@Sun.COM #include <ctype.h>
46*7348SJose.Borrego@Sun.COM #include <assert.h>
477052Samw #include <sys/mnttab.h>
487052Samw #include <sys/stat.h>
497052Samw #include <sys/types.h>
507052Samw 
517052Samw #include <smbsrv/libsmb.h>
527052Samw #include <smbsrv/libsmbns.h>
537052Samw 
547052Samw #include <libshare.h>
557052Samw 
567052Samw #include <smbsrv/lm.h>
577052Samw #include <smbsrv/smb_share.h>
587052Samw #include <smbsrv/cifs.h>
597052Samw 
607052Samw #include <smbsrv/ctype.h>
617052Samw #include <smbsrv/smb_vops.h>
62*7348SJose.Borrego@Sun.COM #include <smbsrv/nterror.h>
637052Samw 
64*7348SJose.Borrego@Sun.COM /*
65*7348SJose.Borrego@Sun.COM  * Cache functions and vars
66*7348SJose.Borrego@Sun.COM  */
677052Samw #define	SMB_SHARE_HTAB_SZ	1024
687052Samw 
697052Samw static HT_HANDLE *smb_shr_handle = NULL;
707052Samw static rwlock_t smb_shr_lock;
71*7348SJose.Borrego@Sun.COM static pthread_t smb_shr_populate_thr;
727052Samw 
737052Samw static uint32_t smb_shr_cache_create(void);
74*7348SJose.Borrego@Sun.COM static void smb_shr_cache_destroy(void);
757052Samw static void *smb_shr_cache_populate(void *);
76*7348SJose.Borrego@Sun.COM static uint32_t smb_shr_cache_addent(smb_share_t *);
77*7348SJose.Borrego@Sun.COM static void smb_shr_cache_delent(char *);
78*7348SJose.Borrego@Sun.COM static uint32_t smb_shr_cache_chgent(smb_share_t *);
79*7348SJose.Borrego@Sun.COM static void smb_shr_cache_freent(HT_ITEM *);
80*7348SJose.Borrego@Sun.COM static uint32_t smb_shr_cache_loadent(sa_share_t, sa_resource_t);
81*7348SJose.Borrego@Sun.COM static void smb_shr_cache_loadgrp(sa_group_t);
827052Samw 
83*7348SJose.Borrego@Sun.COM static void smb_shr_set_ahcnt(char *, int);
84*7348SJose.Borrego@Sun.COM static void smb_shr_set_oemname(smb_share_t *);
85*7348SJose.Borrego@Sun.COM static uint32_t smb_shr_create_autohome(smb_share_t *);
86*7348SJose.Borrego@Sun.COM static uint32_t smb_shr_create_ipc(void);
877052Samw 
88*7348SJose.Borrego@Sun.COM /*
89*7348SJose.Borrego@Sun.COM  * sharemgr functions
90*7348SJose.Borrego@Sun.COM  */
91*7348SJose.Borrego@Sun.COM static uint32_t smb_shr_sa_delent(smb_share_t *);
92*7348SJose.Borrego@Sun.COM static uint32_t smb_shr_sa_addent(smb_share_t *);
93*7348SJose.Borrego@Sun.COM static uint32_t smb_shr_sa_getent(sa_share_t, sa_resource_t, smb_share_t *);
94*7348SJose.Borrego@Sun.COM static sa_group_t smb_shr_sa_getdefgrp(sa_handle_t);
957052Samw 
967052Samw /*
97*7348SJose.Borrego@Sun.COM  * share publishing
98*7348SJose.Borrego@Sun.COM  */
99*7348SJose.Borrego@Sun.COM #define	SMB_SHR_PUBLISH		0
100*7348SJose.Borrego@Sun.COM #define	SMB_SHR_UNPUBLISH	1
101*7348SJose.Borrego@Sun.COM 
102*7348SJose.Borrego@Sun.COM typedef struct smb_shr_pitem {
103*7348SJose.Borrego@Sun.COM 	list_node_t	spi_lnd;
104*7348SJose.Borrego@Sun.COM 	char		spi_name[MAXNAMELEN];
105*7348SJose.Borrego@Sun.COM 	char		spi_container[MAXPATHLEN];
106*7348SJose.Borrego@Sun.COM 	char		spi_op;
107*7348SJose.Borrego@Sun.COM } smb_shr_pitem_t;
108*7348SJose.Borrego@Sun.COM 
109*7348SJose.Borrego@Sun.COM /*
110*7348SJose.Borrego@Sun.COM  * publish queue states
111*7348SJose.Borrego@Sun.COM  */
112*7348SJose.Borrego@Sun.COM #define	SMB_SHR_PQS_NOQUEUE	0
113*7348SJose.Borrego@Sun.COM #define	SMB_SHR_PQS_READY	1	/* the queue is ready */
114*7348SJose.Borrego@Sun.COM #define	SMB_SHR_PQS_PUBLISHING	2	/* publisher thread is running */
115*7348SJose.Borrego@Sun.COM #define	SMB_SHR_PQS_STOPPING	3
116*7348SJose.Borrego@Sun.COM 
117*7348SJose.Borrego@Sun.COM /*
118*7348SJose.Borrego@Sun.COM  * share publishing queue
119*7348SJose.Borrego@Sun.COM  */
120*7348SJose.Borrego@Sun.COM typedef struct smb_shr_pqueue {
121*7348SJose.Borrego@Sun.COM 	int		spq_cnt;
122*7348SJose.Borrego@Sun.COM 	list_t		spq_list;
123*7348SJose.Borrego@Sun.COM 	mutex_t		spq_mtx;
124*7348SJose.Borrego@Sun.COM 	cond_t		spq_cv;
125*7348SJose.Borrego@Sun.COM 	uint32_t	spq_state;
126*7348SJose.Borrego@Sun.COM } smb_shr_pqueue_t;
127*7348SJose.Borrego@Sun.COM 
128*7348SJose.Borrego@Sun.COM static smb_shr_pqueue_t ad_queue;
129*7348SJose.Borrego@Sun.COM static pthread_t smb_shr_publish_thr;
130*7348SJose.Borrego@Sun.COM 
131*7348SJose.Borrego@Sun.COM static int smb_shr_publisher_start(void);
132*7348SJose.Borrego@Sun.COM static void smb_shr_publisher_stop(void);
133*7348SJose.Borrego@Sun.COM static void smb_shr_publisher_send(smb_ads_handle_t *, list_t *, const char *);
134*7348SJose.Borrego@Sun.COM static void *smb_shr_publisher(void *);
135*7348SJose.Borrego@Sun.COM static void smb_shr_publish(const char *, const char *, char);
136*7348SJose.Borrego@Sun.COM 
137*7348SJose.Borrego@Sun.COM 
138*7348SJose.Borrego@Sun.COM /*
139*7348SJose.Borrego@Sun.COM  * smb_shr_start
140*7348SJose.Borrego@Sun.COM  *
141*7348SJose.Borrego@Sun.COM  * Starts the publisher thread and another thread which
142*7348SJose.Borrego@Sun.COM  * populates the share cache by share information stored
143*7348SJose.Borrego@Sun.COM  * by sharemgr
1447052Samw  */
1457052Samw int
1467052Samw smb_shr_start(void)
1477052Samw {
148*7348SJose.Borrego@Sun.COM 	pthread_attr_t tattr;
1497052Samw 	int rc;
1507052Samw 
151*7348SJose.Borrego@Sun.COM 	if ((rc = smb_shr_publisher_start()) != 0)
152*7348SJose.Borrego@Sun.COM 		return (rc);
1537052Samw 
154*7348SJose.Borrego@Sun.COM 	(void) pthread_attr_init(&tattr);
155*7348SJose.Borrego@Sun.COM 	(void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
156*7348SJose.Borrego@Sun.COM 	rc = pthread_create(&smb_shr_populate_thr, &tattr,
1577052Samw 	    smb_shr_cache_populate, 0);
158*7348SJose.Borrego@Sun.COM 	(void) pthread_attr_destroy(&tattr);
1597052Samw 
1607052Samw 	return (rc);
1617052Samw }
1627052Samw 
1637052Samw void
1647052Samw smb_shr_stop(void)
1657052Samw {
166*7348SJose.Borrego@Sun.COM 	smb_shr_cache_destroy();
167*7348SJose.Borrego@Sun.COM 	smb_shr_publisher_stop();
1687052Samw }
1697052Samw 
1707052Samw /*
1717052Samw  * smb_shr_count
1727052Samw  *
173*7348SJose.Borrego@Sun.COM  * Return the total number of shares
1747052Samw  */
1757052Samw int
1767052Samw smb_shr_count(void)
1777052Samw {
1787052Samw 	int n_shares;
1797052Samw 
180*7348SJose.Borrego@Sun.COM 	(void) rw_rdlock(&smb_shr_lock);
1817052Samw 	n_shares = ht_get_total_items(smb_shr_handle);
182*7348SJose.Borrego@Sun.COM 	(void) rw_unlock(&smb_shr_lock);
1837052Samw 
1847052Samw 	return (n_shares);
1857052Samw }
1867052Samw 
1877052Samw /*
1887052Samw  * smb_shr_iterinit
1897052Samw  *
190*7348SJose.Borrego@Sun.COM  * Initialize given iterator for traversing hash table.
1917052Samw  */
1927052Samw void
193*7348SJose.Borrego@Sun.COM smb_shr_iterinit(smb_shriter_t *shi)
1947052Samw {
1957052Samw 	bzero(shi, sizeof (smb_shriter_t));
196*7348SJose.Borrego@Sun.COM 	shi->si_first = B_TRUE;
1977052Samw }
1987052Samw 
1997052Samw /*
2007052Samw  * smb_shr_iterate
2017052Samw  *
2027052Samw  * Iterate on the shares in the hash table. The iterator must be initialized
2037052Samw  * before the first iteration. On subsequent calls, the iterator must be
2047052Samw  * passed unchanged.
2057052Samw  *
2067052Samw  * Returns NULL on failure or when all shares are visited, otherwise
2077052Samw  * returns information of visited share.
2087052Samw  */
2097052Samw smb_share_t *
2107052Samw smb_shr_iterate(smb_shriter_t *shi)
2117052Samw {
2127052Samw 	HT_ITEM *item;
213*7348SJose.Borrego@Sun.COM 	smb_share_t *share = NULL;
2147052Samw 
2157052Samw 	if (smb_shr_handle == NULL || shi == NULL)
2167052Samw 		return (NULL);
2177052Samw 
218*7348SJose.Borrego@Sun.COM 	(void) rw_rdlock(&smb_shr_lock);
219*7348SJose.Borrego@Sun.COM 	if (shi->si_first) {
220*7348SJose.Borrego@Sun.COM 		item = ht_findfirst(smb_shr_handle, &shi->si_hashiter);
221*7348SJose.Borrego@Sun.COM 		shi->si_first = B_FALSE;
222*7348SJose.Borrego@Sun.COM 	} else {
223*7348SJose.Borrego@Sun.COM 		item = ht_findnext(&shi->si_hashiter);
2247052Samw 	}
2257052Samw 
226*7348SJose.Borrego@Sun.COM 	if (item && item->hi_data) {
227*7348SJose.Borrego@Sun.COM 		share = &shi->si_share;
228*7348SJose.Borrego@Sun.COM 		bcopy(item->hi_data, share, sizeof (smb_share_t));
229*7348SJose.Borrego@Sun.COM 	}
230*7348SJose.Borrego@Sun.COM 	(void) rw_unlock(&smb_shr_lock);
2317052Samw 
232*7348SJose.Borrego@Sun.COM 	return (share);
2337052Samw }
2347052Samw 
2357052Samw /*
236*7348SJose.Borrego@Sun.COM  * smb_shr_create
2377052Samw  *
238*7348SJose.Borrego@Sun.COM  * Adds the given to cache and if 'store' is B_TRUE it's also
239*7348SJose.Borrego@Sun.COM  * added to sharemgr
2407052Samw  */
2417052Samw uint32_t
242*7348SJose.Borrego@Sun.COM smb_shr_create(smb_share_t *si, boolean_t store)
2437052Samw {
2447052Samw 	uint32_t status = NERR_Success;
245*7348SJose.Borrego@Sun.COM 	int rc;
2467052Samw 
247*7348SJose.Borrego@Sun.COM 	assert(si != NULL);
2487052Samw 
249*7348SJose.Borrego@Sun.COM 	if (!smb_shr_chkname(si->shr_name))
250*7348SJose.Borrego@Sun.COM 		return (ERROR_INVALID_NAME);
2517052Samw 
252*7348SJose.Borrego@Sun.COM 	if (si->shr_flags & SMB_SHRF_AUTOHOME)
253*7348SJose.Borrego@Sun.COM 		return (smb_shr_create_autohome(si));
2547052Samw 
255*7348SJose.Borrego@Sun.COM 	if (smb_shr_exists(si->shr_name))
256*7348SJose.Borrego@Sun.COM 		return (NERR_DuplicateShare);
2577052Samw 
258*7348SJose.Borrego@Sun.COM 	if ((status = smb_shr_cache_addent(si)) != NERR_Success)
2597052Samw 		return (status);
2607052Samw 
261*7348SJose.Borrego@Sun.COM 	if (store && (si->shr_flags & SMB_SHRF_PERM)) {
262*7348SJose.Borrego@Sun.COM 		if ((status = smb_shr_sa_addent(si)) != NERR_Success) {
263*7348SJose.Borrego@Sun.COM 			(void) smb_shr_cache_delent(si->shr_name);
2647052Samw 			return (status);
2657052Samw 		}
2667052Samw 	}
2677052Samw 
268*7348SJose.Borrego@Sun.COM 	rc = smb_dwncall_share(SMB_SHROP_ADD, si->shr_path, si->shr_name);
269*7348SJose.Borrego@Sun.COM 
270*7348SJose.Borrego@Sun.COM 	if (rc == 0) {
271*7348SJose.Borrego@Sun.COM 		smb_shr_publish(si->shr_name, si->shr_container,
272*7348SJose.Borrego@Sun.COM 		    SMB_SHR_PUBLISH);
273*7348SJose.Borrego@Sun.COM 		return (status);
2747052Samw 	}
2757052Samw 
276*7348SJose.Borrego@Sun.COM 	smb_shr_cache_delent(si->shr_name);
277*7348SJose.Borrego@Sun.COM 	if (store && (si->shr_flags & SMB_SHRF_PERM))
278*7348SJose.Borrego@Sun.COM 		(void) smb_shr_sa_delent(si);
2797052Samw 
2807052Samw 	/*
281*7348SJose.Borrego@Sun.COM 	 * rc == ENOENT means the shared directory doesn't exist
2827052Samw 	 */
283*7348SJose.Borrego@Sun.COM 	return ((rc == ENOENT) ? NERR_UnknownDevDir : NERR_InternalError);
2847052Samw }
2857052Samw 
2867052Samw /*
287*7348SJose.Borrego@Sun.COM  * smb_shr_delete
2887052Samw  *
289*7348SJose.Borrego@Sun.COM  * Removes the specified share.
2907052Samw  */
291*7348SJose.Borrego@Sun.COM uint32_t
292*7348SJose.Borrego@Sun.COM smb_shr_delete(char *sharename, boolean_t store)
2937052Samw {
294*7348SJose.Borrego@Sun.COM 	smb_share_t si;
295*7348SJose.Borrego@Sun.COM 	uint32_t status = NERR_Success;
296*7348SJose.Borrego@Sun.COM 
297*7348SJose.Borrego@Sun.COM 	assert(sharename != NULL);
298*7348SJose.Borrego@Sun.COM 
299*7348SJose.Borrego@Sun.COM 	if ((status = smb_shr_get(sharename, &si)) != NERR_Success)
300*7348SJose.Borrego@Sun.COM 		return (status);
3017052Samw 
302*7348SJose.Borrego@Sun.COM 	if (si.shr_type & STYPE_IPC)
303*7348SJose.Borrego@Sun.COM 		return (ERROR_ACCESS_DENIED);
304*7348SJose.Borrego@Sun.COM 
305*7348SJose.Borrego@Sun.COM 	if (si.shr_flags & SMB_SHRF_AUTOHOME) {
306*7348SJose.Borrego@Sun.COM 		si.shr_refcnt--;
307*7348SJose.Borrego@Sun.COM 		if (si.shr_refcnt > 0) {
308*7348SJose.Borrego@Sun.COM 			smb_shr_set_ahcnt(si.shr_name, si.shr_refcnt);
309*7348SJose.Borrego@Sun.COM 			return (status);
310*7348SJose.Borrego@Sun.COM 		}
3117052Samw 	}
3127052Samw 
313*7348SJose.Borrego@Sun.COM 	if (store && (si.shr_flags & SMB_SHRF_PERM)) {
314*7348SJose.Borrego@Sun.COM 		if (smb_shr_sa_delent(&si) != NERR_Success)
315*7348SJose.Borrego@Sun.COM 			return (NERR_InternalError);
3167052Samw 	}
317*7348SJose.Borrego@Sun.COM 
318*7348SJose.Borrego@Sun.COM 	smb_shr_cache_delent(si.shr_name);
319*7348SJose.Borrego@Sun.COM 	smb_shr_publish(si.shr_name, si.shr_container, SMB_SHR_UNPUBLISH);
320*7348SJose.Borrego@Sun.COM 	(void) smb_dwncall_share(SMB_SHROP_DELETE, si.shr_path, si.shr_name);
321*7348SJose.Borrego@Sun.COM 
3227052Samw 	return (NERR_Success);
3237052Samw }
3247052Samw 
3257052Samw /*
326*7348SJose.Borrego@Sun.COM  * smb_shr_rename
3277052Samw  *
3287052Samw  * Rename a share. Check that the current name exists and the new name
3297052Samw  * doesn't exist. The rename is performed by deleting the current share
3307052Samw  * definition and creating a new share with the new name.
3317052Samw  */
3327052Samw uint32_t
333*7348SJose.Borrego@Sun.COM smb_shr_rename(char *from_name, char *to_name)
3347052Samw {
3357052Samw 	smb_share_t si;
336*7348SJose.Borrego@Sun.COM 	uint32_t status;
337*7348SJose.Borrego@Sun.COM 
338*7348SJose.Borrego@Sun.COM 	assert((from_name != NULL) && (to_name != NULL));
3397052Samw 
340*7348SJose.Borrego@Sun.COM 	if (!smb_shr_chkname(from_name) || !smb_shr_chkname(to_name))
341*7348SJose.Borrego@Sun.COM 		return (ERROR_INVALID_NAME);
3427052Samw 
343*7348SJose.Borrego@Sun.COM 	if (!smb_shr_exists(from_name))
3447052Samw 		return (NERR_NetNameNotFound);
3457052Samw 
3467052Samw 	if (smb_shr_exists(to_name))
3477052Samw 		return (NERR_DuplicateShare);
3487052Samw 
349*7348SJose.Borrego@Sun.COM 	if ((status = smb_shr_get(from_name, &si)) != NERR_Success)
350*7348SJose.Borrego@Sun.COM 		return (status);
351*7348SJose.Borrego@Sun.COM 
352*7348SJose.Borrego@Sun.COM 	if (si.shr_type & STYPE_IPC)
353*7348SJose.Borrego@Sun.COM 		return (ERROR_ACCESS_DENIED);
354*7348SJose.Borrego@Sun.COM 
355*7348SJose.Borrego@Sun.COM 	(void) strlcpy(si.shr_name, to_name, sizeof (si.shr_name));
356*7348SJose.Borrego@Sun.COM 	if ((status = smb_shr_cache_addent(&si)) != NERR_Success)
357*7348SJose.Borrego@Sun.COM 		return (status);
358*7348SJose.Borrego@Sun.COM 
359*7348SJose.Borrego@Sun.COM 	smb_shr_cache_delent(from_name);
360*7348SJose.Borrego@Sun.COM 	smb_shr_publish(from_name, si.shr_container, SMB_SHR_UNPUBLISH);
361*7348SJose.Borrego@Sun.COM 	smb_shr_publish(to_name, si.shr_container, SMB_SHR_PUBLISH);
362*7348SJose.Borrego@Sun.COM 
363*7348SJose.Borrego@Sun.COM 	return (NERR_Success);
364*7348SJose.Borrego@Sun.COM }
365*7348SJose.Borrego@Sun.COM 
366*7348SJose.Borrego@Sun.COM /*
367*7348SJose.Borrego@Sun.COM  * smb_shr_get
368*7348SJose.Borrego@Sun.COM  *
369*7348SJose.Borrego@Sun.COM  * Load the information for the specified share into the supplied share
370*7348SJose.Borrego@Sun.COM  * info structure.
371*7348SJose.Borrego@Sun.COM  */
372*7348SJose.Borrego@Sun.COM uint32_t
373*7348SJose.Borrego@Sun.COM smb_shr_get(char *sharename, smb_share_t *si)
374*7348SJose.Borrego@Sun.COM {
375*7348SJose.Borrego@Sun.COM 	HT_ITEM *item;
376*7348SJose.Borrego@Sun.COM 
377*7348SJose.Borrego@Sun.COM 	(void) utf8_strlwr(sharename);
378*7348SJose.Borrego@Sun.COM 
379*7348SJose.Borrego@Sun.COM 	(void) rw_rdlock(&smb_shr_lock);
380*7348SJose.Borrego@Sun.COM 	item = ht_find_item(smb_shr_handle, sharename);
381*7348SJose.Borrego@Sun.COM 	if (item == NULL || item->hi_data == NULL) {
382*7348SJose.Borrego@Sun.COM 		(void) rw_unlock(&smb_shr_lock);
383*7348SJose.Borrego@Sun.COM 		return (NERR_NetNameNotFound);
384*7348SJose.Borrego@Sun.COM 	}
385*7348SJose.Borrego@Sun.COM 
386*7348SJose.Borrego@Sun.COM 	bcopy(item->hi_data, si, sizeof (smb_share_t));
387*7348SJose.Borrego@Sun.COM 	(void) rw_unlock(&smb_shr_lock);
388*7348SJose.Borrego@Sun.COM 
389*7348SJose.Borrego@Sun.COM 	return (NERR_Success);
390*7348SJose.Borrego@Sun.COM }
391*7348SJose.Borrego@Sun.COM 
392*7348SJose.Borrego@Sun.COM /*
393*7348SJose.Borrego@Sun.COM  * smb_shr_modify
394*7348SJose.Borrego@Sun.COM  *
395*7348SJose.Borrego@Sun.COM  * Modifies an existing share. Properties that can be modified are:
396*7348SJose.Borrego@Sun.COM  *
397*7348SJose.Borrego@Sun.COM  *   o comment
398*7348SJose.Borrego@Sun.COM  *   o AD container
399*7348SJose.Borrego@Sun.COM  */
400*7348SJose.Borrego@Sun.COM uint32_t
401*7348SJose.Borrego@Sun.COM smb_shr_modify(char *sharename, const char *cmnt,
402*7348SJose.Borrego@Sun.COM     const char *ad_container, boolean_t store)
403*7348SJose.Borrego@Sun.COM {
404*7348SJose.Borrego@Sun.COM 	smb_share_t si;
405*7348SJose.Borrego@Sun.COM 	uint32_t status;
406*7348SJose.Borrego@Sun.COM 	boolean_t cmnt_changed = B_FALSE;
407*7348SJose.Borrego@Sun.COM 	boolean_t adc_changed = B_FALSE;
408*7348SJose.Borrego@Sun.COM 	char shr_container[MAXPATHLEN];
409*7348SJose.Borrego@Sun.COM 
410*7348SJose.Borrego@Sun.COM 	assert(sharename != NULL);
411*7348SJose.Borrego@Sun.COM 
412*7348SJose.Borrego@Sun.COM 	if ((cmnt == NULL) && (ad_container == NULL))
413*7348SJose.Borrego@Sun.COM 		/* no changes */
414*7348SJose.Borrego@Sun.COM 		return (NERR_Success);
4157052Samw 
416*7348SJose.Borrego@Sun.COM 	if ((status = smb_shr_get(sharename, &si)) != NERR_Success)
417*7348SJose.Borrego@Sun.COM 		return (status);
418*7348SJose.Borrego@Sun.COM 
419*7348SJose.Borrego@Sun.COM 	if (si.shr_type & STYPE_IPC)
420*7348SJose.Borrego@Sun.COM 		return (ERROR_ACCESS_DENIED);
421*7348SJose.Borrego@Sun.COM 
422*7348SJose.Borrego@Sun.COM 	if (cmnt) {
423*7348SJose.Borrego@Sun.COM 		cmnt_changed = (strcmp(cmnt, si.shr_cmnt) != 0);
424*7348SJose.Borrego@Sun.COM 		if (cmnt_changed)
425*7348SJose.Borrego@Sun.COM 			(void) strlcpy(si.shr_cmnt, cmnt, sizeof (si.shr_cmnt));
426*7348SJose.Borrego@Sun.COM 	}
427*7348SJose.Borrego@Sun.COM 
428*7348SJose.Borrego@Sun.COM 	if (ad_container) {
429*7348SJose.Borrego@Sun.COM 		adc_changed = (strcmp(ad_container, si.shr_container) != 0);
430*7348SJose.Borrego@Sun.COM 		if (adc_changed) {
431*7348SJose.Borrego@Sun.COM 			/* save current container needed for unpublishing */
432*7348SJose.Borrego@Sun.COM 			(void) strlcpy(shr_container, si.shr_container,
433*7348SJose.Borrego@Sun.COM 			    sizeof (shr_container));
434*7348SJose.Borrego@Sun.COM 			(void) strlcpy(si.shr_container, ad_container,
435*7348SJose.Borrego@Sun.COM 			    sizeof (si.shr_container));
436*7348SJose.Borrego@Sun.COM 		}
437*7348SJose.Borrego@Sun.COM 	}
438*7348SJose.Borrego@Sun.COM 
439*7348SJose.Borrego@Sun.COM 	if (!cmnt_changed && !adc_changed)
440*7348SJose.Borrego@Sun.COM 		/* no changes */
441*7348SJose.Borrego@Sun.COM 		return (NERR_Success);
442*7348SJose.Borrego@Sun.COM 
443*7348SJose.Borrego@Sun.COM 	if (store && (si.shr_flags & SMB_SHRF_PERM)) {
444*7348SJose.Borrego@Sun.COM 		if (smb_shr_sa_addent(&si) != NERR_Success)
445*7348SJose.Borrego@Sun.COM 			return (NERR_InternalError);
446*7348SJose.Borrego@Sun.COM 	}
447*7348SJose.Borrego@Sun.COM 
448*7348SJose.Borrego@Sun.COM 	(void) smb_shr_cache_chgent(&si);
4497052Samw 
450*7348SJose.Borrego@Sun.COM 	if (adc_changed) {
451*7348SJose.Borrego@Sun.COM 		smb_shr_publish(si.shr_name, shr_container,
452*7348SJose.Borrego@Sun.COM 		    SMB_SHR_UNPUBLISH);
453*7348SJose.Borrego@Sun.COM 		smb_shr_publish(si.shr_name, si.shr_container,
454*7348SJose.Borrego@Sun.COM 		    SMB_SHR_PUBLISH);
455*7348SJose.Borrego@Sun.COM 	}
456*7348SJose.Borrego@Sun.COM 
457*7348SJose.Borrego@Sun.COM 	return (NERR_Success);
4587052Samw }
4597052Samw 
460*7348SJose.Borrego@Sun.COM void
461*7348SJose.Borrego@Sun.COM smb_shr_list(int offset, smb_shrlist_t *list)
462*7348SJose.Borrego@Sun.COM {
463*7348SJose.Borrego@Sun.COM 	smb_shriter_t iterator;
464*7348SJose.Borrego@Sun.COM 	smb_share_t *si;
465*7348SJose.Borrego@Sun.COM 	int n = 0;
466*7348SJose.Borrego@Sun.COM 
467*7348SJose.Borrego@Sun.COM 	bzero(list, sizeof (smb_shrlist_t));
468*7348SJose.Borrego@Sun.COM 	smb_shr_iterinit(&iterator);
469*7348SJose.Borrego@Sun.COM 
470*7348SJose.Borrego@Sun.COM 	while ((si = smb_shr_iterate(&iterator)) != NULL) {
471*7348SJose.Borrego@Sun.COM 		if (--offset > 0)
472*7348SJose.Borrego@Sun.COM 			continue;
473*7348SJose.Borrego@Sun.COM 
474*7348SJose.Borrego@Sun.COM 		if ((si->shr_flags & SMB_SHRF_TRANS) &&
475*7348SJose.Borrego@Sun.COM 		    ((si->shr_type & STYPE_IPC) == 0)) {
476*7348SJose.Borrego@Sun.COM 			bcopy(si, &list->sl_shares[n], sizeof (smb_share_t));
477*7348SJose.Borrego@Sun.COM 			if (++n == LMSHARES_PER_REQUEST)
478*7348SJose.Borrego@Sun.COM 				break;
479*7348SJose.Borrego@Sun.COM 		}
480*7348SJose.Borrego@Sun.COM 	}
481*7348SJose.Borrego@Sun.COM 
482*7348SJose.Borrego@Sun.COM 	list->sl_cnt = n;
483*7348SJose.Borrego@Sun.COM }
484*7348SJose.Borrego@Sun.COM 
485*7348SJose.Borrego@Sun.COM 
4867052Samw /*
4877052Samw  * smb_shr_exists
4887052Samw  *
489*7348SJose.Borrego@Sun.COM  * Returns B_TRUE if the share exists. Otherwise returns B_FALSE
4907052Samw  */
491*7348SJose.Borrego@Sun.COM boolean_t
492*7348SJose.Borrego@Sun.COM smb_shr_exists(char *sharename)
4937052Samw {
494*7348SJose.Borrego@Sun.COM 	boolean_t exists;
495*7348SJose.Borrego@Sun.COM 
496*7348SJose.Borrego@Sun.COM 	if (sharename == NULL || *sharename == '\0')
497*7348SJose.Borrego@Sun.COM 		return (B_FALSE);
4987052Samw 
499*7348SJose.Borrego@Sun.COM 	(void) utf8_strlwr(sharename);
500*7348SJose.Borrego@Sun.COM 
501*7348SJose.Borrego@Sun.COM 	(void) rw_rdlock(&smb_shr_lock);
502*7348SJose.Borrego@Sun.COM 	exists = (ht_find_item(smb_shr_handle, sharename) != NULL);
503*7348SJose.Borrego@Sun.COM 	(void) rw_unlock(&smb_shr_lock);
504*7348SJose.Borrego@Sun.COM 
505*7348SJose.Borrego@Sun.COM 	return (exists);
5067052Samw }
5077052Samw 
5087052Samw /*
5097052Samw  * smb_shr_is_special
5107052Samw  *
511*7348SJose.Borrego@Sun.COM  * Special share reserved for interprocess communication (IPC$) or
512*7348SJose.Borrego@Sun.COM  * remote administration of the server (ADMIN$). Can also refer to
513*7348SJose.Borrego@Sun.COM  * administrative shares such as C$, D$, E$, and so forth.
5147052Samw  */
5157052Samw int
516*7348SJose.Borrego@Sun.COM smb_shr_is_special(char *sharename)
5177052Samw {
5187052Samw 	int len;
5197052Samw 
520*7348SJose.Borrego@Sun.COM 	if (sharename == NULL)
5217052Samw 		return (0);
5227052Samw 
523*7348SJose.Borrego@Sun.COM 	if ((len = strlen(sharename)) == 0)
5247052Samw 		return (0);
5257052Samw 
526*7348SJose.Borrego@Sun.COM 	if (sharename[len - 1] == '$')
5277052Samw 		return (STYPE_SPECIAL);
528*7348SJose.Borrego@Sun.COM 
529*7348SJose.Borrego@Sun.COM 	return (0);
5307052Samw }
5317052Samw 
5327052Samw /*
5337052Samw  * smb_shr_is_restricted
5347052Samw  *
5357052Samw  * Check whether or not there is a restriction on a share. Restricted
5367052Samw  * shares are generally STYPE_SPECIAL, for example, IPC$. All the
537*7348SJose.Borrego@Sun.COM  * administration share names are restricted: C$, D$ etc. Returns B_TRUE
538*7348SJose.Borrego@Sun.COM  * if the share is restricted. Otherwise B_FALSE is returned to indicate
5397052Samw  * that there are no restrictions.
5407052Samw  */
541*7348SJose.Borrego@Sun.COM boolean_t
542*7348SJose.Borrego@Sun.COM smb_shr_is_restricted(char *sharename)
5437052Samw {
5447052Samw 	static char *restricted[] = {
5457052Samw 		"IPC$"
5467052Samw 	};
5477052Samw 
5487052Samw 	int i;
5497052Samw 
550*7348SJose.Borrego@Sun.COM 	if (sharename == NULL)
551*7348SJose.Borrego@Sun.COM 		return (B_FALSE);
552*7348SJose.Borrego@Sun.COM 
5537052Samw 	for (i = 0; i < sizeof (restricted)/sizeof (restricted[0]); i++) {
554*7348SJose.Borrego@Sun.COM 		if (utf8_strcasecmp(restricted[i], sharename) == 0)
555*7348SJose.Borrego@Sun.COM 			return (B_TRUE);
5567052Samw 	}
5577052Samw 
558*7348SJose.Borrego@Sun.COM 	return (smb_shr_is_admin(sharename));
5597052Samw }
5607052Samw 
5617052Samw /*
5627052Samw  * smb_shr_is_admin
5637052Samw  *
5647052Samw  * Check whether or not access to the share should be restricted to
5657052Samw  * administrators. This is a bit of a hack because what we're doing
5667052Samw  * is checking for the default admin shares: C$, D$ etc.. There are
5677052Samw  * other shares that have restrictions: see smb_shr_is_restricted().
5687052Samw  *
569*7348SJose.Borrego@Sun.COM  * Returns B_TRUE if the shares is an admin share. Otherwise B_FALSE
570*7348SJose.Borrego@Sun.COM  * is returned to indicate that there are no restrictions.
5717052Samw  */
572*7348SJose.Borrego@Sun.COM boolean_t
573*7348SJose.Borrego@Sun.COM smb_shr_is_admin(char *sharename)
5747052Samw {
575*7348SJose.Borrego@Sun.COM 	if (sharename == NULL)
576*7348SJose.Borrego@Sun.COM 		return (B_FALSE);
5777052Samw 
578*7348SJose.Borrego@Sun.COM 	if (strlen(sharename) == 2 &&
579*7348SJose.Borrego@Sun.COM 	    mts_isalpha(sharename[0]) && sharename[1] == '$') {
580*7348SJose.Borrego@Sun.COM 		return (B_TRUE);
5817052Samw 	}
5827052Samw 
583*7348SJose.Borrego@Sun.COM 	return (B_FALSE);
5847052Samw }
5857052Samw 
5867052Samw /*
587*7348SJose.Borrego@Sun.COM  * smb_shr_chkname
5887052Samw  *
5897052Samw  * Check if any invalid char is present in share name. According to
5907052Samw  * MSDN article #236388: "Err Msg: The Share Name Contains Invalid
5917052Samw  * Characters", the list of invalid character is:
5927052Samw  *
5937052Samw  * " / \ [ ] : | < > + ; , ? * =
5947052Samw  *
5957052Samw  * Also rejects if control characters are embedded.
5967052Samw  */
597*7348SJose.Borrego@Sun.COM boolean_t
598*7348SJose.Borrego@Sun.COM smb_shr_chkname(char *sharename)
5997052Samw {
6007052Samw 	char *invalid = "\"/\\[]:|<>+;,?*=";
6017052Samw 	char *cp;
6027052Samw 
603*7348SJose.Borrego@Sun.COM 	if (sharename == NULL)
604*7348SJose.Borrego@Sun.COM 		return (B_FALSE);
6057052Samw 
606*7348SJose.Borrego@Sun.COM 	if (strpbrk(sharename, invalid))
607*7348SJose.Borrego@Sun.COM 		return (B_FALSE);
6087052Samw 
609*7348SJose.Borrego@Sun.COM 	for (cp = sharename; *cp != '\0'; cp++) {
610*7348SJose.Borrego@Sun.COM 		if (iscntrl(*cp))
611*7348SJose.Borrego@Sun.COM 			return (B_FALSE);
6127052Samw 	}
6137052Samw 
614*7348SJose.Borrego@Sun.COM 	return (B_TRUE);
6157052Samw }
6167052Samw 
6177052Samw /*
6187052Samw  * smb_shr_get_realpath
6197052Samw  *
6207052Samw  * Derive the real path of a share from the path provided by a
6217052Samw  * Windows client application during the share addition.
6227052Samw  *
6237052Samw  * For instance, the real path of C:\ is /cvol and the
6247052Samw  * real path of F:\home is /vol1/home.
6257052Samw  *
6267052Samw  * clipath  - path provided by the Windows client is in the
6277052Samw  *            format of <drive letter>:\<dir>
6287052Samw  * realpath - path that will be stored as the directory field of
6297052Samw  *            the smb_share_t structure of the share.
6307052Samw  * maxlen   - maximum length fo the realpath buffer
6317052Samw  *
6327052Samw  * Return LAN Manager network error code.
6337052Samw  */
6347052Samw /*ARGSUSED*/
6357052Samw uint32_t
6367052Samw smb_shr_get_realpath(const char *clipath, char *realpath, int maxlen)
6377052Samw {
6387052Samw 	/* XXX do this translation */
6397052Samw 	return (NERR_Success);
6407052Samw }
6417052Samw 
6427052Samw /*
643*7348SJose.Borrego@Sun.COM  * ============================================
644*7348SJose.Borrego@Sun.COM  * Cache management functions
645*7348SJose.Borrego@Sun.COM  * ============================================
646*7348SJose.Borrego@Sun.COM  */
647*7348SJose.Borrego@Sun.COM 
648*7348SJose.Borrego@Sun.COM /*
649*7348SJose.Borrego@Sun.COM  * smb_shr_cache_create
650*7348SJose.Borrego@Sun.COM  *
651*7348SJose.Borrego@Sun.COM  * Create the share hash table.
652*7348SJose.Borrego@Sun.COM  */
653*7348SJose.Borrego@Sun.COM static uint32_t
654*7348SJose.Borrego@Sun.COM smb_shr_cache_create(void)
655*7348SJose.Borrego@Sun.COM {
656*7348SJose.Borrego@Sun.COM 	if (smb_shr_handle == NULL) {
657*7348SJose.Borrego@Sun.COM 		(void) rwlock_init(&smb_shr_lock, USYNC_THREAD, 0);
658*7348SJose.Borrego@Sun.COM 		(void) rw_wrlock(&smb_shr_lock);
659*7348SJose.Borrego@Sun.COM 
660*7348SJose.Borrego@Sun.COM 		smb_shr_handle = ht_create_table(SMB_SHARE_HTAB_SZ,
661*7348SJose.Borrego@Sun.COM 		    MAXNAMELEN, 0);
662*7348SJose.Borrego@Sun.COM 		if (smb_shr_handle == NULL) {
663*7348SJose.Borrego@Sun.COM 			(void) rw_unlock(&smb_shr_lock);
664*7348SJose.Borrego@Sun.COM 			return (NERR_InternalError);
665*7348SJose.Borrego@Sun.COM 		}
666*7348SJose.Borrego@Sun.COM 
667*7348SJose.Borrego@Sun.COM 		(void) ht_register_callback(smb_shr_handle,
668*7348SJose.Borrego@Sun.COM 		    smb_shr_cache_freent);
669*7348SJose.Borrego@Sun.COM 		(void) rw_unlock(&smb_shr_lock);
670*7348SJose.Borrego@Sun.COM 	}
671*7348SJose.Borrego@Sun.COM 
672*7348SJose.Borrego@Sun.COM 	return (NERR_Success);
673*7348SJose.Borrego@Sun.COM }
674*7348SJose.Borrego@Sun.COM 
675*7348SJose.Borrego@Sun.COM /*
676*7348SJose.Borrego@Sun.COM  * smb_shr_cache_destroy
677*7348SJose.Borrego@Sun.COM  *
678*7348SJose.Borrego@Sun.COM  * Destroys the share hash table.
679*7348SJose.Borrego@Sun.COM  */
680*7348SJose.Borrego@Sun.COM static void
681*7348SJose.Borrego@Sun.COM smb_shr_cache_destroy(void)
682*7348SJose.Borrego@Sun.COM {
683*7348SJose.Borrego@Sun.COM 	if (smb_shr_handle) {
684*7348SJose.Borrego@Sun.COM 		(void) rw_wrlock(&smb_shr_lock);
685*7348SJose.Borrego@Sun.COM 		ht_destroy_table(smb_shr_handle);
686*7348SJose.Borrego@Sun.COM 		(void) rw_unlock(&smb_shr_lock);
687*7348SJose.Borrego@Sun.COM 		(void) rwlock_destroy(&smb_shr_lock);
688*7348SJose.Borrego@Sun.COM 		smb_shr_handle = NULL;
689*7348SJose.Borrego@Sun.COM 	}
690*7348SJose.Borrego@Sun.COM }
691*7348SJose.Borrego@Sun.COM 
692*7348SJose.Borrego@Sun.COM /*
693*7348SJose.Borrego@Sun.COM  * smb_shr_cache_populate
694*7348SJose.Borrego@Sun.COM  *
695*7348SJose.Borrego@Sun.COM  * Load shares from sharemgr
696*7348SJose.Borrego@Sun.COM  */
697*7348SJose.Borrego@Sun.COM /*ARGSUSED*/
698*7348SJose.Borrego@Sun.COM static void *
699*7348SJose.Borrego@Sun.COM smb_shr_cache_populate(void *args)
700*7348SJose.Borrego@Sun.COM {
701*7348SJose.Borrego@Sun.COM 	sa_handle_t handle;
702*7348SJose.Borrego@Sun.COM 	sa_group_t group, subgroup;
703*7348SJose.Borrego@Sun.COM 	char *gstate;
704*7348SJose.Borrego@Sun.COM 	boolean_t gdisabled;
705*7348SJose.Borrego@Sun.COM 
706*7348SJose.Borrego@Sun.COM 	if (smb_shr_cache_create() != NERR_Success) {
707*7348SJose.Borrego@Sun.COM 		syslog(LOG_ERR, "share: failed creating the cache");
708*7348SJose.Borrego@Sun.COM 		return (NULL);
709*7348SJose.Borrego@Sun.COM 	}
710*7348SJose.Borrego@Sun.COM 
711*7348SJose.Borrego@Sun.COM 	if (smb_shr_create_ipc() != NERR_Success) {
712*7348SJose.Borrego@Sun.COM 		syslog(LOG_ERR, "share: failed creating IPC$");
713*7348SJose.Borrego@Sun.COM 		return (NULL);
714*7348SJose.Borrego@Sun.COM 	}
715*7348SJose.Borrego@Sun.COM 
716*7348SJose.Borrego@Sun.COM 	if ((handle = sa_init(SA_INIT_SHARE_API)) == NULL) {
717*7348SJose.Borrego@Sun.COM 		syslog(LOG_ERR, "share: failed connecting to backend");
718*7348SJose.Borrego@Sun.COM 		return (NULL);
719*7348SJose.Borrego@Sun.COM 	}
720*7348SJose.Borrego@Sun.COM 
721*7348SJose.Borrego@Sun.COM 	for (group = sa_get_group(handle, NULL);
722*7348SJose.Borrego@Sun.COM 	    group != NULL; group = sa_get_next_group(group)) {
723*7348SJose.Borrego@Sun.COM 		gstate = sa_get_group_attr(group, "state");
724*7348SJose.Borrego@Sun.COM 		if (gstate == NULL)
725*7348SJose.Borrego@Sun.COM 			continue;
726*7348SJose.Borrego@Sun.COM 
727*7348SJose.Borrego@Sun.COM 		gdisabled = (strcasecmp(gstate, "disabled") == 0);
728*7348SJose.Borrego@Sun.COM 		sa_free_attr_string(gstate);
729*7348SJose.Borrego@Sun.COM 		if (gdisabled)
730*7348SJose.Borrego@Sun.COM 			continue;
731*7348SJose.Borrego@Sun.COM 
732*7348SJose.Borrego@Sun.COM 		smb_shr_cache_loadgrp(group);
733*7348SJose.Borrego@Sun.COM 		for (subgroup = sa_get_sub_group(group);
734*7348SJose.Borrego@Sun.COM 		    subgroup != NULL;
735*7348SJose.Borrego@Sun.COM 		    subgroup = sa_get_next_group(subgroup)) {
736*7348SJose.Borrego@Sun.COM 			smb_shr_cache_loadgrp(subgroup);
737*7348SJose.Borrego@Sun.COM 		}
738*7348SJose.Borrego@Sun.COM 
739*7348SJose.Borrego@Sun.COM 	}
740*7348SJose.Borrego@Sun.COM 
741*7348SJose.Borrego@Sun.COM 	sa_fini(handle);
742*7348SJose.Borrego@Sun.COM 	return (NULL);
743*7348SJose.Borrego@Sun.COM }
744*7348SJose.Borrego@Sun.COM 
745*7348SJose.Borrego@Sun.COM static uint32_t
746*7348SJose.Borrego@Sun.COM smb_shr_cache_addent(smb_share_t *si)
747*7348SJose.Borrego@Sun.COM {
748*7348SJose.Borrego@Sun.COM 	smb_share_t *cache_ent;
749*7348SJose.Borrego@Sun.COM 	uint32_t status = NERR_Success;
750*7348SJose.Borrego@Sun.COM 
751*7348SJose.Borrego@Sun.COM 	/*
752*7348SJose.Borrego@Sun.COM 	 * allocate memory for the entry that needs to be cached.
753*7348SJose.Borrego@Sun.COM 	 */
754*7348SJose.Borrego@Sun.COM 	if ((cache_ent = malloc(sizeof (smb_share_t))) == NULL)
755*7348SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
756*7348SJose.Borrego@Sun.COM 
757*7348SJose.Borrego@Sun.COM 	bcopy(si, cache_ent, sizeof (smb_share_t));
758*7348SJose.Borrego@Sun.COM 
759*7348SJose.Borrego@Sun.COM 	(void) utf8_strlwr(cache_ent->shr_name);
760*7348SJose.Borrego@Sun.COM 	smb_shr_set_oemname(cache_ent);
761*7348SJose.Borrego@Sun.COM 	if ((si->shr_type & STYPE_IPC) == 0)
762*7348SJose.Borrego@Sun.COM 		cache_ent->shr_type = STYPE_DISKTREE;
763*7348SJose.Borrego@Sun.COM 	cache_ent->shr_type |= smb_shr_is_special(cache_ent->shr_name);
764*7348SJose.Borrego@Sun.COM 
765*7348SJose.Borrego@Sun.COM 	(void) rw_wrlock(&smb_shr_lock);
766*7348SJose.Borrego@Sun.COM 	if (ht_add_item(smb_shr_handle, cache_ent->shr_name, cache_ent)
767*7348SJose.Borrego@Sun.COM 	    == NULL) {
768*7348SJose.Borrego@Sun.COM 		syslog(LOG_DEBUG, "share: failed adding %s to cache",
769*7348SJose.Borrego@Sun.COM 		    cache_ent->shr_name);
770*7348SJose.Borrego@Sun.COM 		free(cache_ent);
771*7348SJose.Borrego@Sun.COM 		status = NERR_InternalError;
772*7348SJose.Borrego@Sun.COM 	}
773*7348SJose.Borrego@Sun.COM 	(void) rw_unlock(&smb_shr_lock);
774*7348SJose.Borrego@Sun.COM 
775*7348SJose.Borrego@Sun.COM 	return (status);
776*7348SJose.Borrego@Sun.COM }
777*7348SJose.Borrego@Sun.COM 
778*7348SJose.Borrego@Sun.COM static void
779*7348SJose.Borrego@Sun.COM smb_shr_cache_delent(char *sharename)
780*7348SJose.Borrego@Sun.COM {
781*7348SJose.Borrego@Sun.COM 	(void) utf8_strlwr(sharename);
782*7348SJose.Borrego@Sun.COM 	(void) rw_wrlock(&smb_shr_lock);
783*7348SJose.Borrego@Sun.COM 	(void) ht_remove_item(smb_shr_handle, sharename);
784*7348SJose.Borrego@Sun.COM 	(void) rw_unlock(&smb_shr_lock);
785*7348SJose.Borrego@Sun.COM }
786*7348SJose.Borrego@Sun.COM 
787*7348SJose.Borrego@Sun.COM static uint32_t
788*7348SJose.Borrego@Sun.COM smb_shr_cache_chgent(smb_share_t *si)
789*7348SJose.Borrego@Sun.COM {
790*7348SJose.Borrego@Sun.COM 	smb_share_t *cache_ent;
791*7348SJose.Borrego@Sun.COM 	uint32_t status = NERR_Success;
792*7348SJose.Borrego@Sun.COM 
793*7348SJose.Borrego@Sun.COM 	/*
794*7348SJose.Borrego@Sun.COM 	 * allocate memory for the entry that needs to be cached.
795*7348SJose.Borrego@Sun.COM 	 */
796*7348SJose.Borrego@Sun.COM 	if ((cache_ent = malloc(sizeof (smb_share_t))) == NULL)
797*7348SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
798*7348SJose.Borrego@Sun.COM 
799*7348SJose.Borrego@Sun.COM 	bcopy(si, cache_ent, sizeof (smb_share_t));
800*7348SJose.Borrego@Sun.COM 	(void) utf8_strlwr(cache_ent->shr_name);
801*7348SJose.Borrego@Sun.COM 
802*7348SJose.Borrego@Sun.COM 	(void) rw_wrlock(&smb_shr_lock);
803*7348SJose.Borrego@Sun.COM 	if (ht_replace_item(smb_shr_handle, cache_ent->shr_name, cache_ent)
804*7348SJose.Borrego@Sun.COM 	    == NULL) {
805*7348SJose.Borrego@Sun.COM 		syslog(LOG_DEBUG, "share: failed modifying %s",
806*7348SJose.Borrego@Sun.COM 		    cache_ent->shr_name);
807*7348SJose.Borrego@Sun.COM 		free(cache_ent);
808*7348SJose.Borrego@Sun.COM 		status = NERR_InternalError;
809*7348SJose.Borrego@Sun.COM 	}
810*7348SJose.Borrego@Sun.COM 	(void) rw_unlock(&smb_shr_lock);
811*7348SJose.Borrego@Sun.COM 
812*7348SJose.Borrego@Sun.COM 	return (status);
813*7348SJose.Borrego@Sun.COM }
814*7348SJose.Borrego@Sun.COM 
815*7348SJose.Borrego@Sun.COM static uint32_t
816*7348SJose.Borrego@Sun.COM smb_shr_create_autohome(smb_share_t *si)
817*7348SJose.Borrego@Sun.COM {
818*7348SJose.Borrego@Sun.COM 	uint32_t status = NERR_Success;
819*7348SJose.Borrego@Sun.COM 	int rc;
820*7348SJose.Borrego@Sun.COM 
821*7348SJose.Borrego@Sun.COM 	if (si->shr_refcnt == 0) {
822*7348SJose.Borrego@Sun.COM 		if ((status = smb_shr_cache_addent(si)) != NERR_Success)
823*7348SJose.Borrego@Sun.COM 			return (status);
824*7348SJose.Borrego@Sun.COM 
825*7348SJose.Borrego@Sun.COM 		rc = smb_dwncall_share(SMB_SHROP_ADD, si->shr_path,
826*7348SJose.Borrego@Sun.COM 		    si->shr_name);
827*7348SJose.Borrego@Sun.COM 
828*7348SJose.Borrego@Sun.COM 		if (rc != 0) {
829*7348SJose.Borrego@Sun.COM 			smb_shr_cache_delent(si->shr_name);
830*7348SJose.Borrego@Sun.COM 			return ((rc == ENOENT)
831*7348SJose.Borrego@Sun.COM 			    ? NERR_UnknownDevDir : NERR_InternalError);
832*7348SJose.Borrego@Sun.COM 		}
833*7348SJose.Borrego@Sun.COM 
834*7348SJose.Borrego@Sun.COM 		smb_shr_publish(si->shr_name, si->shr_container,
835*7348SJose.Borrego@Sun.COM 		    SMB_SHR_PUBLISH);
836*7348SJose.Borrego@Sun.COM 	}
837*7348SJose.Borrego@Sun.COM 
838*7348SJose.Borrego@Sun.COM 	si->shr_refcnt++;
839*7348SJose.Borrego@Sun.COM 	smb_shr_set_ahcnt(si->shr_name, si->shr_refcnt);
840*7348SJose.Borrego@Sun.COM 	return (status);
841*7348SJose.Borrego@Sun.COM }
842*7348SJose.Borrego@Sun.COM 
843*7348SJose.Borrego@Sun.COM static uint32_t
844*7348SJose.Borrego@Sun.COM smb_shr_create_ipc(void)
845*7348SJose.Borrego@Sun.COM {
846*7348SJose.Borrego@Sun.COM 	smb_share_t ipc;
847*7348SJose.Borrego@Sun.COM 
848*7348SJose.Borrego@Sun.COM 	bzero(&ipc, sizeof (smb_share_t));
849*7348SJose.Borrego@Sun.COM 	(void) strcpy(ipc.shr_name, "IPC$");
850*7348SJose.Borrego@Sun.COM 	(void) strcpy(ipc.shr_cmnt, "Remote IPC");
851*7348SJose.Borrego@Sun.COM 	ipc.shr_flags = SMB_SHRF_TRANS;
852*7348SJose.Borrego@Sun.COM 	ipc.shr_type = STYPE_IPC;
853*7348SJose.Borrego@Sun.COM 	return (smb_shr_cache_addent(&ipc));
854*7348SJose.Borrego@Sun.COM }
855*7348SJose.Borrego@Sun.COM 
856*7348SJose.Borrego@Sun.COM /*
857*7348SJose.Borrego@Sun.COM  * loads the given resource
858*7348SJose.Borrego@Sun.COM  */
859*7348SJose.Borrego@Sun.COM static uint32_t
860*7348SJose.Borrego@Sun.COM smb_shr_cache_loadent(sa_share_t share, sa_resource_t resource)
861*7348SJose.Borrego@Sun.COM {
862*7348SJose.Borrego@Sun.COM 	smb_share_t si;
863*7348SJose.Borrego@Sun.COM 	uint32_t status;
864*7348SJose.Borrego@Sun.COM 
865*7348SJose.Borrego@Sun.COM 	if ((status = smb_shr_sa_getent(share, resource, &si)) != NERR_Success)
866*7348SJose.Borrego@Sun.COM 		return (status);
867*7348SJose.Borrego@Sun.COM 
868*7348SJose.Borrego@Sun.COM 	if ((status = smb_shr_cache_addent(&si)) == NERR_Success)
869*7348SJose.Borrego@Sun.COM 		smb_shr_publish(si.shr_name, si.shr_container, SMB_SHR_PUBLISH);
870*7348SJose.Borrego@Sun.COM 
871*7348SJose.Borrego@Sun.COM 	if (status != NERR_Success) {
872*7348SJose.Borrego@Sun.COM 		syslog(LOG_ERR, "share: failed loading %s (%d)", si.shr_name,
873*7348SJose.Borrego@Sun.COM 		    status);
874*7348SJose.Borrego@Sun.COM 	}
875*7348SJose.Borrego@Sun.COM 
876*7348SJose.Borrego@Sun.COM 	return (status);
877*7348SJose.Borrego@Sun.COM }
878*7348SJose.Borrego@Sun.COM 
879*7348SJose.Borrego@Sun.COM /*
880*7348SJose.Borrego@Sun.COM  * smb_shr_cache_loadgrp
881*7348SJose.Borrego@Sun.COM  *
882*7348SJose.Borrego@Sun.COM  * Helper function for smb_shr_cache_populate.
883*7348SJose.Borrego@Sun.COM  * It attempts to load the shares contained in the given group.
884*7348SJose.Borrego@Sun.COM  * It will check to see if "smb" protocol is enabled or
885*7348SJose.Borrego@Sun.COM  * not on the given group. This is needed in the ZFS case where
886*7348SJose.Borrego@Sun.COM  * the top level ZFS group won't have "smb" protocol
887*7348SJose.Borrego@Sun.COM  * enabled but the sub-groups will.
888*7348SJose.Borrego@Sun.COM  */
889*7348SJose.Borrego@Sun.COM static void
890*7348SJose.Borrego@Sun.COM smb_shr_cache_loadgrp(sa_group_t group)
891*7348SJose.Borrego@Sun.COM {
892*7348SJose.Borrego@Sun.COM 	sa_share_t share;
893*7348SJose.Borrego@Sun.COM 	sa_resource_t resource;
894*7348SJose.Borrego@Sun.COM 
895*7348SJose.Borrego@Sun.COM 	/* Don't bother if "smb" isn't set on the group */
896*7348SJose.Borrego@Sun.COM 	if (sa_get_optionset(group, SMB_PROTOCOL_NAME) == NULL)
897*7348SJose.Borrego@Sun.COM 		return;
898*7348SJose.Borrego@Sun.COM 
899*7348SJose.Borrego@Sun.COM 	for (share = sa_get_share(group, NULL);
900*7348SJose.Borrego@Sun.COM 	    share != NULL; share = sa_get_next_share(share)) {
901*7348SJose.Borrego@Sun.COM 		for (resource = sa_get_share_resource(share, NULL);
902*7348SJose.Borrego@Sun.COM 		    resource != NULL;
903*7348SJose.Borrego@Sun.COM 		    resource = sa_get_next_resource(resource)) {
904*7348SJose.Borrego@Sun.COM 			(void) smb_shr_cache_loadent(share, resource);
905*7348SJose.Borrego@Sun.COM 		}
906*7348SJose.Borrego@Sun.COM 	}
907*7348SJose.Borrego@Sun.COM }
908*7348SJose.Borrego@Sun.COM 
909*7348SJose.Borrego@Sun.COM /*
910*7348SJose.Borrego@Sun.COM  * smb_shr_cache_freent
911*7348SJose.Borrego@Sun.COM  *
912*7348SJose.Borrego@Sun.COM  * Call back to free given cache entry
913*7348SJose.Borrego@Sun.COM  */
914*7348SJose.Borrego@Sun.COM static void
915*7348SJose.Borrego@Sun.COM smb_shr_cache_freent(HT_ITEM *item)
916*7348SJose.Borrego@Sun.COM {
917*7348SJose.Borrego@Sun.COM 	if (item && item->hi_data)
918*7348SJose.Borrego@Sun.COM 		free(item->hi_data);
919*7348SJose.Borrego@Sun.COM }
920*7348SJose.Borrego@Sun.COM 
921*7348SJose.Borrego@Sun.COM /*
922*7348SJose.Borrego@Sun.COM  * smb_shr_set_ahcnt
923*7348SJose.Borrego@Sun.COM  *
924*7348SJose.Borrego@Sun.COM  * sets the autohome reference count for the given share
925*7348SJose.Borrego@Sun.COM  */
926*7348SJose.Borrego@Sun.COM static void
927*7348SJose.Borrego@Sun.COM smb_shr_set_ahcnt(char *sharename, int refcnt)
928*7348SJose.Borrego@Sun.COM {
929*7348SJose.Borrego@Sun.COM 	smb_share_t *si;
930*7348SJose.Borrego@Sun.COM 	HT_ITEM *item;
931*7348SJose.Borrego@Sun.COM 
932*7348SJose.Borrego@Sun.COM 	(void) rw_wrlock(&smb_shr_lock);
933*7348SJose.Borrego@Sun.COM 	item = ht_find_item(smb_shr_handle, sharename);
934*7348SJose.Borrego@Sun.COM 	if (item == NULL || item->hi_data == NULL) {
935*7348SJose.Borrego@Sun.COM 		(void) rw_unlock(&smb_shr_lock);
936*7348SJose.Borrego@Sun.COM 		return;
937*7348SJose.Borrego@Sun.COM 	}
938*7348SJose.Borrego@Sun.COM 
939*7348SJose.Borrego@Sun.COM 	si = (smb_share_t *)item->hi_data;
940*7348SJose.Borrego@Sun.COM 	si->shr_refcnt = refcnt;
941*7348SJose.Borrego@Sun.COM 	(void) rw_unlock(&smb_shr_lock);
942*7348SJose.Borrego@Sun.COM }
943*7348SJose.Borrego@Sun.COM 
944*7348SJose.Borrego@Sun.COM /*
9457052Samw  * smb_shr_set_oemname
9467052Samw  *
9477052Samw  * Generates the OEM name of the given share. If it's
9487052Samw  * shorter than 13 chars it'll be saved in si->shr_oemname.
9497052Samw  * Otherwise si->shr_oemname will be empty and SMB_SHRF_LONGNAME
9507052Samw  * will be set in si->shr_flags.
9517052Samw  */
9527052Samw static void
9537052Samw smb_shr_set_oemname(smb_share_t *si)
9547052Samw {
9557052Samw 	unsigned int cpid = oem_get_smb_cpid();
9567052Samw 	mts_wchar_t *unibuf;
9577052Samw 	char *oem_name;
9587052Samw 	int length;
9597052Samw 
9607052Samw 	length = strlen(si->shr_name) + 1;
9617052Samw 
9627052Samw 	oem_name = malloc(length);
9637052Samw 	unibuf = malloc(length * sizeof (mts_wchar_t));
9647052Samw 	if ((oem_name == NULL) || (unibuf == NULL)) {
9657052Samw 		free(oem_name);
9667052Samw 		free(unibuf);
9677052Samw 		return;
9687052Samw 	}
9697052Samw 
9707052Samw 	(void) mts_mbstowcs(unibuf, si->shr_name, length);
9717052Samw 
9727052Samw 	if (unicodestooems(oem_name, unibuf, length, cpid) == 0)
9737052Samw 		(void) strcpy(oem_name, si->shr_name);
9747052Samw 
9757052Samw 	free(unibuf);
9767052Samw 
9777052Samw 	if (strlen(oem_name) + 1 > SMB_SHARE_OEMNAME_MAX) {
9787052Samw 		si->shr_flags |= SMB_SHRF_LONGNAME;
9797052Samw 		*si->shr_oemname = '\0';
9807052Samw 	} else {
9817052Samw 		si->shr_flags &= ~SMB_SHRF_LONGNAME;
9827052Samw 		(void) strlcpy(si->shr_oemname, oem_name,
9837052Samw 		    SMB_SHARE_OEMNAME_MAX);
9847052Samw 	}
9857052Samw 
9867052Samw 	free(oem_name);
9877052Samw }
988*7348SJose.Borrego@Sun.COM 
989*7348SJose.Borrego@Sun.COM /*
990*7348SJose.Borrego@Sun.COM  * ============================================
991*7348SJose.Borrego@Sun.COM  * Interfaces to sharemgr
992*7348SJose.Borrego@Sun.COM  * ============================================
993*7348SJose.Borrego@Sun.COM  */
994*7348SJose.Borrego@Sun.COM 
995*7348SJose.Borrego@Sun.COM /*
996*7348SJose.Borrego@Sun.COM  * Stores the given share in sharemgr
997*7348SJose.Borrego@Sun.COM  */
998*7348SJose.Borrego@Sun.COM static uint32_t
999*7348SJose.Borrego@Sun.COM smb_shr_sa_addent(smb_share_t *si)
1000*7348SJose.Borrego@Sun.COM {
1001*7348SJose.Borrego@Sun.COM 	sa_handle_t handle;
1002*7348SJose.Borrego@Sun.COM 	sa_share_t share;
1003*7348SJose.Borrego@Sun.COM 	sa_group_t group;
1004*7348SJose.Borrego@Sun.COM 	sa_resource_t resource;
1005*7348SJose.Borrego@Sun.COM 	boolean_t share_created = B_FALSE;
1006*7348SJose.Borrego@Sun.COM 	int err;
1007*7348SJose.Borrego@Sun.COM 
1008*7348SJose.Borrego@Sun.COM 	if ((handle = sa_init(SA_INIT_SHARE_API)) == NULL)
1009*7348SJose.Borrego@Sun.COM 		return (NERR_InternalError);
1010*7348SJose.Borrego@Sun.COM 
1011*7348SJose.Borrego@Sun.COM 	share = sa_find_share(handle, si->shr_path);
1012*7348SJose.Borrego@Sun.COM 	if (share == NULL) {
1013*7348SJose.Borrego@Sun.COM 		group = smb_shr_sa_getdefgrp(handle);
1014*7348SJose.Borrego@Sun.COM 		if (group == NULL) {
1015*7348SJose.Borrego@Sun.COM 			sa_fini(handle);
1016*7348SJose.Borrego@Sun.COM 			return (NERR_InternalError);
1017*7348SJose.Borrego@Sun.COM 		}
1018*7348SJose.Borrego@Sun.COM 
1019*7348SJose.Borrego@Sun.COM 		share = sa_add_share(group, si->shr_path, SA_SHARE_PERMANENT,
1020*7348SJose.Borrego@Sun.COM 		    &err);
1021*7348SJose.Borrego@Sun.COM 		if (share == NULL) {
1022*7348SJose.Borrego@Sun.COM 			sa_fini(handle);
1023*7348SJose.Borrego@Sun.COM 			return (NERR_InternalError);
1024*7348SJose.Borrego@Sun.COM 		}
1025*7348SJose.Borrego@Sun.COM 		share_created = B_TRUE;
1026*7348SJose.Borrego@Sun.COM 	}
1027*7348SJose.Borrego@Sun.COM 
1028*7348SJose.Borrego@Sun.COM 	resource = sa_get_share_resource(share, si->shr_name);
1029*7348SJose.Borrego@Sun.COM 	if (resource == NULL) {
1030*7348SJose.Borrego@Sun.COM 		resource = sa_add_resource(share, si->shr_name,
1031*7348SJose.Borrego@Sun.COM 		    SA_SHARE_PERMANENT, &err);
1032*7348SJose.Borrego@Sun.COM 		if (resource == NULL)
1033*7348SJose.Borrego@Sun.COM 			goto failure;
1034*7348SJose.Borrego@Sun.COM 	}
1035*7348SJose.Borrego@Sun.COM 
1036*7348SJose.Borrego@Sun.COM 	if (sa_set_resource_attr(resource, "description", si->shr_cmnt)
1037*7348SJose.Borrego@Sun.COM 	    != SA_OK) {
1038*7348SJose.Borrego@Sun.COM 		goto failure;
1039*7348SJose.Borrego@Sun.COM 	}
1040*7348SJose.Borrego@Sun.COM 
1041*7348SJose.Borrego@Sun.COM 	if (sa_set_resource_attr(resource, SMB_SHROPT_AD_CONTAINER,
1042*7348SJose.Borrego@Sun.COM 	    si->shr_container) != SA_OK) {
1043*7348SJose.Borrego@Sun.COM 		goto failure;
1044*7348SJose.Borrego@Sun.COM 	}
1045*7348SJose.Borrego@Sun.COM 
1046*7348SJose.Borrego@Sun.COM 	sa_fini(handle);
1047*7348SJose.Borrego@Sun.COM 	return (NERR_Success);
1048*7348SJose.Borrego@Sun.COM 
1049*7348SJose.Borrego@Sun.COM failure:
1050*7348SJose.Borrego@Sun.COM 	if (share_created && (share != NULL))
1051*7348SJose.Borrego@Sun.COM 		(void) sa_remove_share(share);
1052*7348SJose.Borrego@Sun.COM 
1053*7348SJose.Borrego@Sun.COM 	if (resource != NULL)
1054*7348SJose.Borrego@Sun.COM 		(void) sa_remove_resource(resource);
1055*7348SJose.Borrego@Sun.COM 
1056*7348SJose.Borrego@Sun.COM 	sa_fini(handle);
1057*7348SJose.Borrego@Sun.COM 	return (NERR_InternalError);
1058*7348SJose.Borrego@Sun.COM }
1059*7348SJose.Borrego@Sun.COM 
1060*7348SJose.Borrego@Sun.COM static uint32_t
1061*7348SJose.Borrego@Sun.COM smb_shr_sa_getent(sa_share_t share, sa_resource_t resource, smb_share_t *si)
1062*7348SJose.Borrego@Sun.COM {
1063*7348SJose.Borrego@Sun.COM 	sa_property_t prop;
1064*7348SJose.Borrego@Sun.COM 	sa_optionset_t opts;
1065*7348SJose.Borrego@Sun.COM 	char *val = NULL;
1066*7348SJose.Borrego@Sun.COM 	char *path;
1067*7348SJose.Borrego@Sun.COM 	char *rname;
1068*7348SJose.Borrego@Sun.COM 
1069*7348SJose.Borrego@Sun.COM 	if ((path = sa_get_share_attr(share, "path")) == NULL)
1070*7348SJose.Borrego@Sun.COM 		return (NERR_InternalError);
1071*7348SJose.Borrego@Sun.COM 
1072*7348SJose.Borrego@Sun.COM 	if ((rname = sa_get_resource_attr(resource, "name")) == NULL) {
1073*7348SJose.Borrego@Sun.COM 		sa_free_attr_string(path);
1074*7348SJose.Borrego@Sun.COM 		return (NERR_InternalError);
1075*7348SJose.Borrego@Sun.COM 	}
1076*7348SJose.Borrego@Sun.COM 
1077*7348SJose.Borrego@Sun.COM 	bzero(si, sizeof (smb_share_t));
1078*7348SJose.Borrego@Sun.COM 	/* Share is read from SMF so it should be permanent */
1079*7348SJose.Borrego@Sun.COM 	si->shr_flags = SMB_SHRF_PERM;
1080*7348SJose.Borrego@Sun.COM 
1081*7348SJose.Borrego@Sun.COM 	(void) strlcpy(si->shr_path, path, sizeof (si->shr_path));
1082*7348SJose.Borrego@Sun.COM 	(void) strlcpy(si->shr_name, rname, sizeof (si->shr_name));
1083*7348SJose.Borrego@Sun.COM 
1084*7348SJose.Borrego@Sun.COM 	sa_free_attr_string(path);
1085*7348SJose.Borrego@Sun.COM 	sa_free_attr_string(rname);
1086*7348SJose.Borrego@Sun.COM 
1087*7348SJose.Borrego@Sun.COM 	val = sa_get_resource_description(resource);
1088*7348SJose.Borrego@Sun.COM 	if (val == NULL)
1089*7348SJose.Borrego@Sun.COM 		val = sa_get_share_description(share);
1090*7348SJose.Borrego@Sun.COM 
1091*7348SJose.Borrego@Sun.COM 	if (val != NULL) {
1092*7348SJose.Borrego@Sun.COM 		(void) strlcpy(si->shr_cmnt, val, sizeof (si->shr_cmnt));
1093*7348SJose.Borrego@Sun.COM 		sa_free_share_description(val);
1094*7348SJose.Borrego@Sun.COM 	}
1095*7348SJose.Borrego@Sun.COM 
1096*7348SJose.Borrego@Sun.COM 	opts = sa_get_derived_optionset(resource, SMB_PROTOCOL_NAME, 1);
1097*7348SJose.Borrego@Sun.COM 	if (opts == NULL)
1098*7348SJose.Borrego@Sun.COM 		return (NERR_Success);
1099*7348SJose.Borrego@Sun.COM 
1100*7348SJose.Borrego@Sun.COM 	prop = (sa_property_t)sa_get_property(opts, SMB_SHROPT_AD_CONTAINER);
1101*7348SJose.Borrego@Sun.COM 	if (prop != NULL) {
1102*7348SJose.Borrego@Sun.COM 		if ((val = sa_get_property_attr(prop, "value")) != NULL) {
1103*7348SJose.Borrego@Sun.COM 			(void) strlcpy(si->shr_container, val,
1104*7348SJose.Borrego@Sun.COM 			    sizeof (si->shr_container));
1105*7348SJose.Borrego@Sun.COM 			free(val);
1106*7348SJose.Borrego@Sun.COM 		}
1107*7348SJose.Borrego@Sun.COM 	}
1108*7348SJose.Borrego@Sun.COM 	sa_free_derived_optionset(opts);
1109*7348SJose.Borrego@Sun.COM 
1110*7348SJose.Borrego@Sun.COM 	return (NERR_Success);
1111*7348SJose.Borrego@Sun.COM }
1112*7348SJose.Borrego@Sun.COM 
1113*7348SJose.Borrego@Sun.COM /*
1114*7348SJose.Borrego@Sun.COM  * Removes the share from sharemgr
1115*7348SJose.Borrego@Sun.COM  */
1116*7348SJose.Borrego@Sun.COM static uint32_t
1117*7348SJose.Borrego@Sun.COM smb_shr_sa_delent(smb_share_t *si)
1118*7348SJose.Borrego@Sun.COM {
1119*7348SJose.Borrego@Sun.COM 	sa_handle_t handle;
1120*7348SJose.Borrego@Sun.COM 	sa_share_t share;
1121*7348SJose.Borrego@Sun.COM 	sa_resource_t resource;
1122*7348SJose.Borrego@Sun.COM 
1123*7348SJose.Borrego@Sun.COM 	if ((handle = sa_init(SA_INIT_SHARE_API)) == NULL)
1124*7348SJose.Borrego@Sun.COM 		return (NERR_InternalError);
1125*7348SJose.Borrego@Sun.COM 
1126*7348SJose.Borrego@Sun.COM 	if ((share = sa_find_share(handle, si->shr_path)) == NULL) {
1127*7348SJose.Borrego@Sun.COM 		sa_fini(handle);
1128*7348SJose.Borrego@Sun.COM 		return (NERR_InternalError);
1129*7348SJose.Borrego@Sun.COM 	}
1130*7348SJose.Borrego@Sun.COM 
1131*7348SJose.Borrego@Sun.COM 	if ((resource = sa_get_share_resource(share, si->shr_name)) == NULL) {
1132*7348SJose.Borrego@Sun.COM 		sa_fini(handle);
1133*7348SJose.Borrego@Sun.COM 		return (NERR_InternalError);
1134*7348SJose.Borrego@Sun.COM 	}
1135*7348SJose.Borrego@Sun.COM 
1136*7348SJose.Borrego@Sun.COM 	if (sa_remove_resource(resource) != SA_OK) {
1137*7348SJose.Borrego@Sun.COM 		sa_fini(handle);
1138*7348SJose.Borrego@Sun.COM 		return (NERR_InternalError);
1139*7348SJose.Borrego@Sun.COM 	}
1140*7348SJose.Borrego@Sun.COM 
1141*7348SJose.Borrego@Sun.COM 	sa_fini(handle);
1142*7348SJose.Borrego@Sun.COM 	return (NERR_Success);
1143*7348SJose.Borrego@Sun.COM }
1144*7348SJose.Borrego@Sun.COM 
1145*7348SJose.Borrego@Sun.COM /*
1146*7348SJose.Borrego@Sun.COM  * smb_shr_sa_getdefgrp
1147*7348SJose.Borrego@Sun.COM  *
1148*7348SJose.Borrego@Sun.COM  * If default group for CIFS shares (i.e. "smb") exists
1149*7348SJose.Borrego@Sun.COM  * then it will return the group handle, otherwise it will
1150*7348SJose.Borrego@Sun.COM  * create the group and return the handle.
1151*7348SJose.Borrego@Sun.COM  *
1152*7348SJose.Borrego@Sun.COM  * All the shares created by CIFS clients (this is only possible
1153*7348SJose.Borrego@Sun.COM  * via RPC) will be added to "smb" groups.
1154*7348SJose.Borrego@Sun.COM  */
1155*7348SJose.Borrego@Sun.COM static sa_group_t
1156*7348SJose.Borrego@Sun.COM smb_shr_sa_getdefgrp(sa_handle_t handle)
1157*7348SJose.Borrego@Sun.COM {
1158*7348SJose.Borrego@Sun.COM 	sa_group_t group = NULL;
1159*7348SJose.Borrego@Sun.COM 	int err;
1160*7348SJose.Borrego@Sun.COM 
1161*7348SJose.Borrego@Sun.COM 	group = sa_get_group(handle, SMB_DEFAULT_SHARE_GROUP);
1162*7348SJose.Borrego@Sun.COM 	if (group != NULL)
1163*7348SJose.Borrego@Sun.COM 		return (group);
1164*7348SJose.Borrego@Sun.COM 
1165*7348SJose.Borrego@Sun.COM 	group = sa_create_group(handle, SMB_DEFAULT_SHARE_GROUP, &err);
1166*7348SJose.Borrego@Sun.COM 	if (group == NULL)
1167*7348SJose.Borrego@Sun.COM 		return (NULL);
1168*7348SJose.Borrego@Sun.COM 
1169*7348SJose.Borrego@Sun.COM 	if (sa_create_optionset(group, SMB_DEFAULT_SHARE_GROUP) == NULL) {
1170*7348SJose.Borrego@Sun.COM 		(void) sa_remove_group(group);
1171*7348SJose.Borrego@Sun.COM 		group = NULL;
1172*7348SJose.Borrego@Sun.COM 	}
1173*7348SJose.Borrego@Sun.COM 
1174*7348SJose.Borrego@Sun.COM 	return (group);
1175*7348SJose.Borrego@Sun.COM }
1176*7348SJose.Borrego@Sun.COM 
1177*7348SJose.Borrego@Sun.COM /*
1178*7348SJose.Borrego@Sun.COM  * ============================================
1179*7348SJose.Borrego@Sun.COM  * Share publishing functions
1180*7348SJose.Borrego@Sun.COM  * ============================================
1181*7348SJose.Borrego@Sun.COM  */
1182*7348SJose.Borrego@Sun.COM 
1183*7348SJose.Borrego@Sun.COM /*
1184*7348SJose.Borrego@Sun.COM  * Put the share on publish queue.
1185*7348SJose.Borrego@Sun.COM  */
1186*7348SJose.Borrego@Sun.COM static void
1187*7348SJose.Borrego@Sun.COM smb_shr_publish(const char *sharename, const char *container, char op)
1188*7348SJose.Borrego@Sun.COM {
1189*7348SJose.Borrego@Sun.COM 	smb_shr_pitem_t *item = NULL;
1190*7348SJose.Borrego@Sun.COM 
1191*7348SJose.Borrego@Sun.COM 	if (container == NULL || *container == '\0')
1192*7348SJose.Borrego@Sun.COM 		return;
1193*7348SJose.Borrego@Sun.COM 
1194*7348SJose.Borrego@Sun.COM 	(void) mutex_lock(&ad_queue.spq_mtx);
1195*7348SJose.Borrego@Sun.COM 	switch (ad_queue.spq_state) {
1196*7348SJose.Borrego@Sun.COM 	case SMB_SHR_PQS_READY:
1197*7348SJose.Borrego@Sun.COM 	case SMB_SHR_PQS_PUBLISHING:
1198*7348SJose.Borrego@Sun.COM 		break;
1199*7348SJose.Borrego@Sun.COM 	default:
1200*7348SJose.Borrego@Sun.COM 		(void) mutex_unlock(&ad_queue.spq_mtx);
1201*7348SJose.Borrego@Sun.COM 		return;
1202*7348SJose.Borrego@Sun.COM 	}
1203*7348SJose.Borrego@Sun.COM 	(void) mutex_unlock(&ad_queue.spq_mtx);
1204*7348SJose.Borrego@Sun.COM 
1205*7348SJose.Borrego@Sun.COM 	if ((item = malloc(sizeof (smb_shr_pitem_t))) == NULL) {
1206*7348SJose.Borrego@Sun.COM 		syslog(LOG_DEBUG, "failed allocating share publish item");
1207*7348SJose.Borrego@Sun.COM 		return;
1208*7348SJose.Borrego@Sun.COM 	}
1209*7348SJose.Borrego@Sun.COM 
1210*7348SJose.Borrego@Sun.COM 	item->spi_op = op;
1211*7348SJose.Borrego@Sun.COM 	(void) strlcpy(item->spi_name, sharename, sizeof (item->spi_name));
1212*7348SJose.Borrego@Sun.COM 	(void) strlcpy(item->spi_container, container,
1213*7348SJose.Borrego@Sun.COM 	    sizeof (item->spi_container));
1214*7348SJose.Borrego@Sun.COM 
1215*7348SJose.Borrego@Sun.COM 	(void) mutex_lock(&ad_queue.spq_mtx);
1216*7348SJose.Borrego@Sun.COM 	list_insert_tail(&ad_queue.spq_list, item);
1217*7348SJose.Borrego@Sun.COM 	ad_queue.spq_cnt++;
1218*7348SJose.Borrego@Sun.COM 	(void) cond_signal(&ad_queue.spq_cv);
1219*7348SJose.Borrego@Sun.COM 	(void) mutex_unlock(&ad_queue.spq_mtx);
1220*7348SJose.Borrego@Sun.COM }
1221*7348SJose.Borrego@Sun.COM 
1222*7348SJose.Borrego@Sun.COM static int
1223*7348SJose.Borrego@Sun.COM smb_shr_publisher_start(void)
1224*7348SJose.Borrego@Sun.COM {
1225*7348SJose.Borrego@Sun.COM 	pthread_attr_t tattr;
1226*7348SJose.Borrego@Sun.COM 	int rc;
1227*7348SJose.Borrego@Sun.COM 
1228*7348SJose.Borrego@Sun.COM 	(void) mutex_lock(&ad_queue.spq_mtx);
1229*7348SJose.Borrego@Sun.COM 	if (ad_queue.spq_state != SMB_SHR_PQS_NOQUEUE) {
1230*7348SJose.Borrego@Sun.COM 		(void) mutex_unlock(&ad_queue.spq_mtx);
1231*7348SJose.Borrego@Sun.COM 		errno = EINVAL;
1232*7348SJose.Borrego@Sun.COM 		return (-1);
1233*7348SJose.Borrego@Sun.COM 	}
1234*7348SJose.Borrego@Sun.COM 
1235*7348SJose.Borrego@Sun.COM 	list_create(&ad_queue.spq_list, sizeof (smb_shr_pitem_t),
1236*7348SJose.Borrego@Sun.COM 	    offsetof(smb_shr_pitem_t, spi_lnd));
1237*7348SJose.Borrego@Sun.COM 	ad_queue.spq_state = SMB_SHR_PQS_READY;
1238*7348SJose.Borrego@Sun.COM 	(void) mutex_unlock(&ad_queue.spq_mtx);
1239*7348SJose.Borrego@Sun.COM 
1240*7348SJose.Borrego@Sun.COM 	(void) pthread_attr_init(&tattr);
1241*7348SJose.Borrego@Sun.COM 	(void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
1242*7348SJose.Borrego@Sun.COM 	rc = pthread_create(&smb_shr_publish_thr, &tattr,
1243*7348SJose.Borrego@Sun.COM 	    smb_shr_publisher, 0);
1244*7348SJose.Borrego@Sun.COM 	(void) pthread_attr_destroy(&tattr);
1245*7348SJose.Borrego@Sun.COM 
1246*7348SJose.Borrego@Sun.COM 	return (rc);
1247*7348SJose.Borrego@Sun.COM }
1248*7348SJose.Borrego@Sun.COM 
1249*7348SJose.Borrego@Sun.COM static void
1250*7348SJose.Borrego@Sun.COM smb_shr_publisher_stop(void)
1251*7348SJose.Borrego@Sun.COM {
1252*7348SJose.Borrego@Sun.COM 	(void) mutex_lock(&ad_queue.spq_mtx);
1253*7348SJose.Borrego@Sun.COM 	switch (ad_queue.spq_state) {
1254*7348SJose.Borrego@Sun.COM 	case SMB_SHR_PQS_READY:
1255*7348SJose.Borrego@Sun.COM 	case SMB_SHR_PQS_PUBLISHING:
1256*7348SJose.Borrego@Sun.COM 		ad_queue.spq_state = SMB_SHR_PQS_STOPPING;
1257*7348SJose.Borrego@Sun.COM 		(void) cond_signal(&ad_queue.spq_cv);
1258*7348SJose.Borrego@Sun.COM 		break;
1259*7348SJose.Borrego@Sun.COM 	default:
1260*7348SJose.Borrego@Sun.COM 		break;
1261*7348SJose.Borrego@Sun.COM 	}
1262*7348SJose.Borrego@Sun.COM 	(void) mutex_unlock(&ad_queue.spq_mtx);
1263*7348SJose.Borrego@Sun.COM }
1264*7348SJose.Borrego@Sun.COM 
1265*7348SJose.Borrego@Sun.COM /*
1266*7348SJose.Borrego@Sun.COM  * This functions waits to be signaled and once running
1267*7348SJose.Borrego@Sun.COM  * will publish/unpublish any items in the ad_queue
1268*7348SJose.Borrego@Sun.COM  */
1269*7348SJose.Borrego@Sun.COM /*ARGSUSED*/
1270*7348SJose.Borrego@Sun.COM static void *
1271*7348SJose.Borrego@Sun.COM smb_shr_publisher(void *arg)
1272*7348SJose.Borrego@Sun.COM {
1273*7348SJose.Borrego@Sun.COM 	smb_ads_handle_t *ah;
1274*7348SJose.Borrego@Sun.COM 	smb_shr_pitem_t *shr;
1275*7348SJose.Borrego@Sun.COM 	list_t publist;
1276*7348SJose.Borrego@Sun.COM 	char hostname[MAXHOSTNAMELEN];
1277*7348SJose.Borrego@Sun.COM 
1278*7348SJose.Borrego@Sun.COM 	(void) mutex_lock(&ad_queue.spq_mtx);
1279*7348SJose.Borrego@Sun.COM 	if (ad_queue.spq_state == SMB_SHR_PQS_READY) {
1280*7348SJose.Borrego@Sun.COM 		ad_queue.spq_state = SMB_SHR_PQS_PUBLISHING;
1281*7348SJose.Borrego@Sun.COM 	} else {
1282*7348SJose.Borrego@Sun.COM 		(void) mutex_unlock(&ad_queue.spq_mtx);
1283*7348SJose.Borrego@Sun.COM 		return (NULL);
1284*7348SJose.Borrego@Sun.COM 	}
1285*7348SJose.Borrego@Sun.COM 	(void) mutex_unlock(&ad_queue.spq_mtx);
1286*7348SJose.Borrego@Sun.COM 
1287*7348SJose.Borrego@Sun.COM 	(void) smb_gethostname(hostname, MAXHOSTNAMELEN, 0);
1288*7348SJose.Borrego@Sun.COM 	list_create(&publist, sizeof (smb_shr_pitem_t),
1289*7348SJose.Borrego@Sun.COM 	    offsetof(smb_shr_pitem_t, spi_lnd));
1290*7348SJose.Borrego@Sun.COM 
1291*7348SJose.Borrego@Sun.COM 	for (;;) {
1292*7348SJose.Borrego@Sun.COM 		(void) mutex_lock(&ad_queue.spq_mtx);
1293*7348SJose.Borrego@Sun.COM 		while ((ad_queue.spq_cnt == 0) &&
1294*7348SJose.Borrego@Sun.COM 		    (ad_queue.spq_state == SMB_SHR_PQS_PUBLISHING))
1295*7348SJose.Borrego@Sun.COM 			(void) cond_wait(&ad_queue.spq_cv, &ad_queue.spq_mtx);
1296*7348SJose.Borrego@Sun.COM 
1297*7348SJose.Borrego@Sun.COM 		if (ad_queue.spq_state != SMB_SHR_PQS_PUBLISHING) {
1298*7348SJose.Borrego@Sun.COM 			(void) mutex_unlock(&ad_queue.spq_mtx);
1299*7348SJose.Borrego@Sun.COM 			break;
1300*7348SJose.Borrego@Sun.COM 		}
1301*7348SJose.Borrego@Sun.COM 
1302*7348SJose.Borrego@Sun.COM 		if ((ah = smb_ads_open()) == NULL) {
1303*7348SJose.Borrego@Sun.COM 			(void) mutex_unlock(&ad_queue.spq_mtx);
1304*7348SJose.Borrego@Sun.COM 			continue;
1305*7348SJose.Borrego@Sun.COM 		}
1306*7348SJose.Borrego@Sun.COM 
1307*7348SJose.Borrego@Sun.COM 		/*
1308*7348SJose.Borrego@Sun.COM 		 * Transfer queued items to the local list so the mutex
1309*7348SJose.Borrego@Sun.COM 		 * can be quickly released
1310*7348SJose.Borrego@Sun.COM 		 */
1311*7348SJose.Borrego@Sun.COM 		while ((shr = list_head(&ad_queue.spq_list)) != NULL) {
1312*7348SJose.Borrego@Sun.COM 			list_remove(&ad_queue.spq_list, shr);
1313*7348SJose.Borrego@Sun.COM 			ad_queue.spq_cnt--;
1314*7348SJose.Borrego@Sun.COM 			list_insert_tail(&publist, shr);
1315*7348SJose.Borrego@Sun.COM 		}
1316*7348SJose.Borrego@Sun.COM 		(void) mutex_unlock(&ad_queue.spq_mtx);
1317*7348SJose.Borrego@Sun.COM 
1318*7348SJose.Borrego@Sun.COM 		smb_shr_publisher_send(ah, &publist, hostname);
1319*7348SJose.Borrego@Sun.COM 		smb_ads_close(ah);
1320*7348SJose.Borrego@Sun.COM 	}
1321*7348SJose.Borrego@Sun.COM 
1322*7348SJose.Borrego@Sun.COM 	/* Remove any leftover items from publishing queue */
1323*7348SJose.Borrego@Sun.COM 	(void) mutex_lock(&ad_queue.spq_mtx);
1324*7348SJose.Borrego@Sun.COM 	while ((shr = list_head(&ad_queue.spq_list)) != NULL) {
1325*7348SJose.Borrego@Sun.COM 		list_remove(&ad_queue.spq_list, shr);
1326*7348SJose.Borrego@Sun.COM 		free(shr);
1327*7348SJose.Borrego@Sun.COM 	}
1328*7348SJose.Borrego@Sun.COM 	ad_queue.spq_cnt = 0;
1329*7348SJose.Borrego@Sun.COM 	list_destroy(&ad_queue.spq_list);
1330*7348SJose.Borrego@Sun.COM 	ad_queue.spq_state = SMB_SHR_PQS_NOQUEUE;
1331*7348SJose.Borrego@Sun.COM 	(void) mutex_unlock(&ad_queue.spq_mtx);
1332*7348SJose.Borrego@Sun.COM 
1333*7348SJose.Borrego@Sun.COM 	list_destroy(&publist);
1334*7348SJose.Borrego@Sun.COM 	return (NULL);
1335*7348SJose.Borrego@Sun.COM }
1336*7348SJose.Borrego@Sun.COM 
1337*7348SJose.Borrego@Sun.COM /*
1338*7348SJose.Borrego@Sun.COM  * Takes item from the given list and [un]publish them one by one.
1339*7348SJose.Borrego@Sun.COM  * In each iteration it checks the status of the publisher thread
1340*7348SJose.Borrego@Sun.COM  * and if it's been stopped then it continues to just empty the list
1341*7348SJose.Borrego@Sun.COM  */
1342*7348SJose.Borrego@Sun.COM static void
1343*7348SJose.Borrego@Sun.COM smb_shr_publisher_send(smb_ads_handle_t *ah, list_t *publist, const char *host)
1344*7348SJose.Borrego@Sun.COM {
1345*7348SJose.Borrego@Sun.COM 	smb_shr_pitem_t *shr;
1346*7348SJose.Borrego@Sun.COM 	boolean_t publish = B_TRUE;
1347*7348SJose.Borrego@Sun.COM 
1348*7348SJose.Borrego@Sun.COM 	while ((shr = list_head(publist)) != NULL) {
1349*7348SJose.Borrego@Sun.COM 		list_remove(publist, shr);
1350*7348SJose.Borrego@Sun.COM 		if (publish) {
1351*7348SJose.Borrego@Sun.COM 			(void) mutex_unlock(&ad_queue.spq_mtx);
1352*7348SJose.Borrego@Sun.COM 			if (ad_queue.spq_state != SMB_SHR_PQS_PUBLISHING)
1353*7348SJose.Borrego@Sun.COM 				publish = B_FALSE;
1354*7348SJose.Borrego@Sun.COM 			(void) mutex_unlock(&ad_queue.spq_mtx);
1355*7348SJose.Borrego@Sun.COM 
1356*7348SJose.Borrego@Sun.COM 			if (shr->spi_op == SMB_SHR_PUBLISH)
1357*7348SJose.Borrego@Sun.COM 				(void) smb_ads_publish_share(ah, shr->spi_name,
1358*7348SJose.Borrego@Sun.COM 				    NULL, shr->spi_container, host);
1359*7348SJose.Borrego@Sun.COM 			else
1360*7348SJose.Borrego@Sun.COM 				(void) smb_ads_remove_share(ah, shr->spi_name,
1361*7348SJose.Borrego@Sun.COM 				    NULL, shr->spi_container, host);
1362*7348SJose.Borrego@Sun.COM 		}
1363*7348SJose.Borrego@Sun.COM 		free(shr);
1364*7348SJose.Borrego@Sun.COM 	}
1365*7348SJose.Borrego@Sun.COM }
1366