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 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> 397052Samw 407052Samw #include <smbsrv/libsmb.h> 417052Samw #include <smbsrv/libsmbns.h> 427588Samw@Sun.COM #include <smbsrv/libmlsvc.h> 437052Samw 447052Samw #include <smbsrv/lm.h> 457052Samw #include <smbsrv/smb_share.h> 467052Samw #include <smbsrv/cifs.h> 477961SNatalie.Li@Sun.COM #include <smbsrv/nterror.h> 487052Samw 497961SNatalie.Li@Sun.COM #define SMB_SHR_ERROR_THRESHOLD 3 507052Samw 51*8334SJose.Borrego@Sun.COM #define SMB_SHR_CSC_BUFSZ 64 52*8334SJose.Borrego@Sun.COM 537348SJose.Borrego@Sun.COM /* 547348SJose.Borrego@Sun.COM * Cache functions and vars 557348SJose.Borrego@Sun.COM */ 567961SNatalie.Li@Sun.COM #define SMB_SHR_HTAB_SZ 1024 577052Samw 587961SNatalie.Li@Sun.COM /* 597961SNatalie.Li@Sun.COM * Cache handle 607961SNatalie.Li@Sun.COM * 617961SNatalie.Li@Sun.COM * Shares cache is a hash table. 627961SNatalie.Li@Sun.COM * 637961SNatalie.Li@Sun.COM * sc_cache pointer to hash table handle 647961SNatalie.Li@Sun.COM * sc_cache_lck synchronize cache read/write accesses 657961SNatalie.Li@Sun.COM * sc_state cache state machine values 667961SNatalie.Li@Sun.COM * sc_nops number of inflight/pending cache operations 677961SNatalie.Li@Sun.COM * sc_mtx protects handle fields 687961SNatalie.Li@Sun.COM */ 697961SNatalie.Li@Sun.COM typedef struct smb_shr_cache { 707961SNatalie.Li@Sun.COM HT_HANDLE *sc_cache; 717961SNatalie.Li@Sun.COM rwlock_t sc_cache_lck; 727961SNatalie.Li@Sun.COM mutex_t sc_mtx; 737961SNatalie.Li@Sun.COM cond_t sc_cv; 747961SNatalie.Li@Sun.COM uint32_t sc_state; 757961SNatalie.Li@Sun.COM uint32_t sc_nops; 767961SNatalie.Li@Sun.COM } smb_shr_cache_t; 777961SNatalie.Li@Sun.COM 787961SNatalie.Li@Sun.COM /* 797961SNatalie.Li@Sun.COM * Cache states 807961SNatalie.Li@Sun.COM */ 817961SNatalie.Li@Sun.COM #define SMB_SHR_CACHE_STATE_NONE 0 827961SNatalie.Li@Sun.COM #define SMB_SHR_CACHE_STATE_CREATED 1 837961SNatalie.Li@Sun.COM #define SMB_SHR_CACHE_STATE_DESTROYING 2 847961SNatalie.Li@Sun.COM 857961SNatalie.Li@Sun.COM /* 867961SNatalie.Li@Sun.COM * Cache lock modes 877961SNatalie.Li@Sun.COM */ 887961SNatalie.Li@Sun.COM #define SMB_SHR_CACHE_RDLOCK 0 897961SNatalie.Li@Sun.COM #define SMB_SHR_CACHE_WRLOCK 1 907961SNatalie.Li@Sun.COM 917961SNatalie.Li@Sun.COM static smb_shr_cache_t smb_shr_cache; 927052Samw 937052Samw static uint32_t smb_shr_cache_create(void); 947348SJose.Borrego@Sun.COM static void smb_shr_cache_destroy(void); 957961SNatalie.Li@Sun.COM static uint32_t smb_shr_cache_lock(int); 967961SNatalie.Li@Sun.COM static void smb_shr_cache_unlock(void); 977961SNatalie.Li@Sun.COM static int smb_shr_cache_count(void); 987961SNatalie.Li@Sun.COM static smb_share_t *smb_shr_cache_iterate(smb_shriter_t *); 997961SNatalie.Li@Sun.COM 1007961SNatalie.Li@Sun.COM static smb_share_t *smb_shr_cache_findent(char *); 1017348SJose.Borrego@Sun.COM static uint32_t smb_shr_cache_addent(smb_share_t *); 1027348SJose.Borrego@Sun.COM static void smb_shr_cache_delent(char *); 1037348SJose.Borrego@Sun.COM static void smb_shr_cache_freent(HT_ITEM *); 1047052Samw 1057348SJose.Borrego@Sun.COM /* 1067348SJose.Borrego@Sun.COM * sharemgr functions 1077348SJose.Borrego@Sun.COM */ 1087961SNatalie.Li@Sun.COM static void *smb_shr_sa_loadall(void *); 1097961SNatalie.Li@Sun.COM static void smb_shr_sa_loadgrp(sa_group_t); 1107961SNatalie.Li@Sun.COM static uint32_t smb_shr_sa_load(sa_share_t, sa_resource_t); 111*8334SJose.Borrego@Sun.COM static uint32_t smb_shr_sa_loadbyname(char *); 1127961SNatalie.Li@Sun.COM static uint32_t smb_shr_sa_get(sa_share_t, sa_resource_t, smb_share_t *); 113*8334SJose.Borrego@Sun.COM static void smb_shr_sa_csc_option(const char *, smb_share_t *); 1147052Samw 1157052Samw /* 1167348SJose.Borrego@Sun.COM * share publishing 1177348SJose.Borrego@Sun.COM */ 1187348SJose.Borrego@Sun.COM #define SMB_SHR_PUBLISH 0 1197348SJose.Borrego@Sun.COM #define SMB_SHR_UNPUBLISH 1 1207348SJose.Borrego@Sun.COM 1217348SJose.Borrego@Sun.COM typedef struct smb_shr_pitem { 1227348SJose.Borrego@Sun.COM list_node_t spi_lnd; 1237348SJose.Borrego@Sun.COM char spi_name[MAXNAMELEN]; 1247348SJose.Borrego@Sun.COM char spi_container[MAXPATHLEN]; 1257348SJose.Borrego@Sun.COM char spi_op; 1267348SJose.Borrego@Sun.COM } smb_shr_pitem_t; 1277348SJose.Borrego@Sun.COM 1287348SJose.Borrego@Sun.COM /* 1297348SJose.Borrego@Sun.COM * publish queue states 1307348SJose.Borrego@Sun.COM */ 1317348SJose.Borrego@Sun.COM #define SMB_SHR_PQS_NOQUEUE 0 1327348SJose.Borrego@Sun.COM #define SMB_SHR_PQS_READY 1 /* the queue is ready */ 1337348SJose.Borrego@Sun.COM #define SMB_SHR_PQS_PUBLISHING 2 /* publisher thread is running */ 1347348SJose.Borrego@Sun.COM #define SMB_SHR_PQS_STOPPING 3 1357348SJose.Borrego@Sun.COM 1367348SJose.Borrego@Sun.COM /* 1377348SJose.Borrego@Sun.COM * share publishing queue 1387348SJose.Borrego@Sun.COM */ 1397348SJose.Borrego@Sun.COM typedef struct smb_shr_pqueue { 1407348SJose.Borrego@Sun.COM list_t spq_list; 1417348SJose.Borrego@Sun.COM mutex_t spq_mtx; 1427348SJose.Borrego@Sun.COM cond_t spq_cv; 1437348SJose.Borrego@Sun.COM uint32_t spq_state; 1447348SJose.Borrego@Sun.COM } smb_shr_pqueue_t; 1457348SJose.Borrego@Sun.COM 1467348SJose.Borrego@Sun.COM static smb_shr_pqueue_t ad_queue; 1477348SJose.Borrego@Sun.COM 1487348SJose.Borrego@Sun.COM static int smb_shr_publisher_start(void); 1497348SJose.Borrego@Sun.COM static void smb_shr_publisher_stop(void); 1507348SJose.Borrego@Sun.COM static void smb_shr_publisher_send(smb_ads_handle_t *, list_t *, const char *); 1517961SNatalie.Li@Sun.COM static void smb_shr_publisher_queue(const char *, const char *, char); 1527348SJose.Borrego@Sun.COM static void *smb_shr_publisher(void *); 1537961SNatalie.Li@Sun.COM static void smb_shr_publisher_flush(list_t *); 1547961SNatalie.Li@Sun.COM static void smb_shr_publish(const char *, const char *); 1557961SNatalie.Li@Sun.COM static void smb_shr_unpublish(const char *, const char *); 1567348SJose.Borrego@Sun.COM 1577348SJose.Borrego@Sun.COM /* 1587961SNatalie.Li@Sun.COM * Utility/helper functions 1597961SNatalie.Li@Sun.COM */ 160*8334SJose.Borrego@Sun.COM static uint32_t smb_shr_lookup(char *, smb_share_t *); 1617961SNatalie.Li@Sun.COM static uint32_t smb_shr_addipc(void); 1627961SNatalie.Li@Sun.COM static void smb_shr_set_oemname(smb_share_t *); 1637961SNatalie.Li@Sun.COM 1647961SNatalie.Li@Sun.COM /* 165*8334SJose.Borrego@Sun.COM * Creates and initializes the cache and starts the publisher 166*8334SJose.Borrego@Sun.COM * thread. 1677052Samw */ 1687052Samw int 1697052Samw smb_shr_start(void) 1707052Samw { 1717961SNatalie.Li@Sun.COM if (smb_shr_cache_create() != NERR_Success) 1727961SNatalie.Li@Sun.COM return (ENOMEM); 1737961SNatalie.Li@Sun.COM 1747961SNatalie.Li@Sun.COM if (smb_shr_addipc() != NERR_Success) 1757961SNatalie.Li@Sun.COM return (ENOMEM); 1767961SNatalie.Li@Sun.COM 177*8334SJose.Borrego@Sun.COM return (smb_shr_publisher_start()); 178*8334SJose.Borrego@Sun.COM } 179*8334SJose.Borrego@Sun.COM 180*8334SJose.Borrego@Sun.COM void 181*8334SJose.Borrego@Sun.COM smb_shr_stop(void) 182*8334SJose.Borrego@Sun.COM { 183*8334SJose.Borrego@Sun.COM smb_shr_cache_destroy(); 184*8334SJose.Borrego@Sun.COM smb_shr_publisher_stop(); 185*8334SJose.Borrego@Sun.COM } 186*8334SJose.Borrego@Sun.COM 187*8334SJose.Borrego@Sun.COM /* 188*8334SJose.Borrego@Sun.COM * Launches a thread to populate the share cache by share information 189*8334SJose.Borrego@Sun.COM * stored in sharemgr 190*8334SJose.Borrego@Sun.COM */ 191*8334SJose.Borrego@Sun.COM int 192*8334SJose.Borrego@Sun.COM smb_shr_load(void) 193*8334SJose.Borrego@Sun.COM { 194*8334SJose.Borrego@Sun.COM pthread_t load_thr; 195*8334SJose.Borrego@Sun.COM pthread_attr_t tattr; 196*8334SJose.Borrego@Sun.COM int rc; 197*8334SJose.Borrego@Sun.COM 1987348SJose.Borrego@Sun.COM (void) pthread_attr_init(&tattr); 1997348SJose.Borrego@Sun.COM (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); 2007961SNatalie.Li@Sun.COM rc = pthread_create(&load_thr, &tattr, smb_shr_sa_loadall, 0); 2017348SJose.Borrego@Sun.COM (void) pthread_attr_destroy(&tattr); 2027052Samw 2037052Samw return (rc); 2047052Samw } 2057052Samw 2067052Samw /* 2077348SJose.Borrego@Sun.COM * Return the total number of shares 2087052Samw */ 2097052Samw int 2107052Samw smb_shr_count(void) 2117052Samw { 2127961SNatalie.Li@Sun.COM int n_shares = 0; 2137052Samw 2147961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) { 2157961SNatalie.Li@Sun.COM n_shares = smb_shr_cache_count(); 2167961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 2177961SNatalie.Li@Sun.COM } 2187052Samw 2197052Samw return (n_shares); 2207052Samw } 2217052Samw 2227052Samw /* 2237052Samw * smb_shr_iterinit 2247052Samw * 2257348SJose.Borrego@Sun.COM * Initialize given iterator for traversing hash table. 2267052Samw */ 2277052Samw void 2287348SJose.Borrego@Sun.COM smb_shr_iterinit(smb_shriter_t *shi) 2297052Samw { 2307052Samw bzero(shi, sizeof (smb_shriter_t)); 2317348SJose.Borrego@Sun.COM shi->si_first = B_TRUE; 2327052Samw } 2337052Samw 2347052Samw /* 2357052Samw * smb_shr_iterate 2367052Samw * 2377052Samw * Iterate on the shares in the hash table. The iterator must be initialized 2387052Samw * before the first iteration. On subsequent calls, the iterator must be 2397052Samw * passed unchanged. 2407052Samw * 2417052Samw * Returns NULL on failure or when all shares are visited, otherwise 2427052Samw * returns information of visited share. 2437052Samw */ 2447052Samw smb_share_t * 2457052Samw smb_shr_iterate(smb_shriter_t *shi) 2467052Samw { 2477348SJose.Borrego@Sun.COM smb_share_t *share = NULL; 2487961SNatalie.Li@Sun.COM smb_share_t *cached_si; 2497052Samw 2507961SNatalie.Li@Sun.COM if (shi == NULL) 2517052Samw return (NULL); 2527052Samw 2537961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) { 2547961SNatalie.Li@Sun.COM if ((cached_si = smb_shr_cache_iterate(shi)) != NULL) { 2557961SNatalie.Li@Sun.COM share = &shi->si_share; 2567961SNatalie.Li@Sun.COM bcopy(cached_si, share, sizeof (smb_share_t)); 2577961SNatalie.Li@Sun.COM } 2587961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 2597052Samw } 2607052Samw 2617348SJose.Borrego@Sun.COM return (share); 2627052Samw } 2637052Samw 2647052Samw /* 2657961SNatalie.Li@Sun.COM * Adds the given share to cache, publishes the share in ADS 2667961SNatalie.Li@Sun.COM * if it has an AD container, calls kernel to take a hold on 2677961SNatalie.Li@Sun.COM * the shared file system. If it can't take a hold on the 2687961SNatalie.Li@Sun.COM * shared file system, it's either because shared directory 2697961SNatalie.Li@Sun.COM * does not exist or some other error has occurred, in any 2707961SNatalie.Li@Sun.COM * case the share is removed from the cache. 2717052Samw * 2727961SNatalie.Li@Sun.COM * If the specified share is an autohome share which already 2737961SNatalie.Li@Sun.COM * exists in the cache, just increments the reference count. 2747052Samw */ 2757052Samw uint32_t 2767961SNatalie.Li@Sun.COM smb_shr_add(smb_share_t *si) 2777052Samw { 2787961SNatalie.Li@Sun.COM smb_share_t *cached_si; 2797961SNatalie.Li@Sun.COM uint32_t status; 2807348SJose.Borrego@Sun.COM int rc; 2817052Samw 2827348SJose.Borrego@Sun.COM assert(si != NULL); 2837052Samw 2847348SJose.Borrego@Sun.COM if (!smb_shr_chkname(si->shr_name)) 2857348SJose.Borrego@Sun.COM return (ERROR_INVALID_NAME); 2867052Samw 2877961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success) 2887961SNatalie.Li@Sun.COM return (NERR_InternalError); 2897052Samw 2907961SNatalie.Li@Sun.COM cached_si = smb_shr_cache_findent(si->shr_name); 2917961SNatalie.Li@Sun.COM if (cached_si) { 2927961SNatalie.Li@Sun.COM if (si->shr_flags & SMB_SHRF_AUTOHOME) { 2937961SNatalie.Li@Sun.COM cached_si->shr_refcnt++; 2947961SNatalie.Li@Sun.COM status = NERR_Success; 2957961SNatalie.Li@Sun.COM } else { 2967961SNatalie.Li@Sun.COM status = NERR_DuplicateShare; 2977961SNatalie.Li@Sun.COM } 2987961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 2997052Samw return (status); 3007052Samw } 3017052Samw 3027961SNatalie.Li@Sun.COM if ((status = smb_shr_cache_addent(si)) != NERR_Success) { 3037961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 3047961SNatalie.Li@Sun.COM return (status); 3057961SNatalie.Li@Sun.COM } 3067961SNatalie.Li@Sun.COM 3077961SNatalie.Li@Sun.COM /* don't hold the lock across door call */ 3087961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 3097961SNatalie.Li@Sun.COM 3107961SNatalie.Li@Sun.COM /* call kernel to take a hold on the shared file system */ 3117588Samw@Sun.COM rc = mlsvc_set_share(SMB_SHROP_ADD, si->shr_path, si->shr_name); 3127348SJose.Borrego@Sun.COM 3137348SJose.Borrego@Sun.COM if (rc == 0) { 3147961SNatalie.Li@Sun.COM smb_shr_publish(si->shr_name, si->shr_container); 3157961SNatalie.Li@Sun.COM return (NERR_Success); 3167052Samw } 3177052Samw 3187961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) == NERR_Success) { 3197961SNatalie.Li@Sun.COM smb_shr_cache_delent(si->shr_name); 3207961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 3217961SNatalie.Li@Sun.COM } 3227052Samw 3237052Samw /* 3247348SJose.Borrego@Sun.COM * rc == ENOENT means the shared directory doesn't exist 3257052Samw */ 3267348SJose.Borrego@Sun.COM return ((rc == ENOENT) ? NERR_UnknownDevDir : NERR_InternalError); 3277052Samw } 3287052Samw 3297052Samw /* 3307961SNatalie.Li@Sun.COM * Removes the specified share from cache, removes it from AD 3317961SNatalie.Li@Sun.COM * if it has an AD container, and calls the kernel to release 3327961SNatalie.Li@Sun.COM * the hold on the shared file system. 3337052Samw * 3347961SNatalie.Li@Sun.COM * If this is an autohome share then decrement the reference 3357961SNatalie.Li@Sun.COM * count. If it reaches 0 then it proceeds with removing steps. 3367052Samw */ 3377348SJose.Borrego@Sun.COM uint32_t 3387961SNatalie.Li@Sun.COM smb_shr_remove(char *sharename) 3397052Samw { 3407961SNatalie.Li@Sun.COM smb_share_t *si; 3417961SNatalie.Li@Sun.COM char path[MAXPATHLEN]; 3427961SNatalie.Li@Sun.COM char container[MAXPATHLEN]; 3437348SJose.Borrego@Sun.COM 3447348SJose.Borrego@Sun.COM assert(sharename != NULL); 3457348SJose.Borrego@Sun.COM 3467961SNatalie.Li@Sun.COM if (!smb_shr_chkname(sharename)) 3477961SNatalie.Li@Sun.COM return (ERROR_INVALID_NAME); 3487052Samw 3497961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success) 3507961SNatalie.Li@Sun.COM return (NERR_InternalError); 3517961SNatalie.Li@Sun.COM 3527961SNatalie.Li@Sun.COM if ((si = smb_shr_cache_findent(sharename)) == NULL) { 3537961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 3547961SNatalie.Li@Sun.COM return (NERR_NetNameNotFound); 3557961SNatalie.Li@Sun.COM } 3567348SJose.Borrego@Sun.COM 3577961SNatalie.Li@Sun.COM if (si->shr_type & STYPE_IPC) { 3587961SNatalie.Li@Sun.COM /* IPC$ share cannot be removed */ 3597961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 3607961SNatalie.Li@Sun.COM return (ERROR_ACCESS_DENIED); 3617961SNatalie.Li@Sun.COM } 3627961SNatalie.Li@Sun.COM 3637961SNatalie.Li@Sun.COM if (si->shr_flags & SMB_SHRF_AUTOHOME) { 3647961SNatalie.Li@Sun.COM if ((--si->shr_refcnt) > 0) { 3657961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 3667961SNatalie.Li@Sun.COM return (NERR_Success); 3677348SJose.Borrego@Sun.COM } 3687052Samw } 3697052Samw 3707961SNatalie.Li@Sun.COM (void) strlcpy(path, si->shr_path, sizeof (path)); 3717961SNatalie.Li@Sun.COM (void) strlcpy(container, si->shr_container, sizeof (container)); 3727961SNatalie.Li@Sun.COM smb_shr_cache_delent(sharename); 3737961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 3747348SJose.Borrego@Sun.COM 3757961SNatalie.Li@Sun.COM smb_shr_unpublish(sharename, container); 3767961SNatalie.Li@Sun.COM 3777961SNatalie.Li@Sun.COM /* call kernel to release the hold on the shared file system */ 3787961SNatalie.Li@Sun.COM (void) mlsvc_set_share(SMB_SHROP_DELETE, path, sharename); 3797348SJose.Borrego@Sun.COM 3807052Samw return (NERR_Success); 3817052Samw } 3827052Samw 3837052Samw /* 3847052Samw * Rename a share. Check that the current name exists and the new name 3857052Samw * doesn't exist. The rename is performed by deleting the current share 3867052Samw * definition and creating a new share with the new name. 3877052Samw */ 3887052Samw uint32_t 3897348SJose.Borrego@Sun.COM smb_shr_rename(char *from_name, char *to_name) 3907052Samw { 3917961SNatalie.Li@Sun.COM smb_share_t *from_si; 3927961SNatalie.Li@Sun.COM smb_share_t to_si; 3937348SJose.Borrego@Sun.COM uint32_t status; 3947348SJose.Borrego@Sun.COM 3957348SJose.Borrego@Sun.COM assert((from_name != NULL) && (to_name != NULL)); 3967052Samw 3977348SJose.Borrego@Sun.COM if (!smb_shr_chkname(from_name) || !smb_shr_chkname(to_name)) 3987348SJose.Borrego@Sun.COM return (ERROR_INVALID_NAME); 3997052Samw 4007961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success) 4017961SNatalie.Li@Sun.COM return (NERR_InternalError); 4027961SNatalie.Li@Sun.COM 4037961SNatalie.Li@Sun.COM if ((from_si = smb_shr_cache_findent(from_name)) == NULL) { 4047961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 4057052Samw return (NERR_NetNameNotFound); 4067961SNatalie.Li@Sun.COM } 4077052Samw 4087961SNatalie.Li@Sun.COM if (from_si->shr_type & STYPE_IPC) { 4097961SNatalie.Li@Sun.COM /* IPC$ share cannot be renamed */ 4107961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 4117961SNatalie.Li@Sun.COM return (ERROR_ACCESS_DENIED); 4127961SNatalie.Li@Sun.COM } 4137961SNatalie.Li@Sun.COM 4147961SNatalie.Li@Sun.COM if (smb_shr_cache_findent(to_name) != NULL) { 4157961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 4167052Samw return (NERR_DuplicateShare); 4177961SNatalie.Li@Sun.COM } 4187052Samw 4197961SNatalie.Li@Sun.COM bcopy(from_si, &to_si, sizeof (smb_share_t)); 4207961SNatalie.Li@Sun.COM (void) strlcpy(to_si.shr_name, to_name, sizeof (to_si.shr_name)); 4217961SNatalie.Li@Sun.COM 4227961SNatalie.Li@Sun.COM if ((status = smb_shr_cache_addent(&to_si)) != NERR_Success) { 4237961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 4247348SJose.Borrego@Sun.COM return (status); 4257961SNatalie.Li@Sun.COM } 4267348SJose.Borrego@Sun.COM 4277348SJose.Borrego@Sun.COM smb_shr_cache_delent(from_name); 4287961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 4297961SNatalie.Li@Sun.COM 4307961SNatalie.Li@Sun.COM smb_shr_unpublish(from_name, to_si.shr_container); 4317961SNatalie.Li@Sun.COM smb_shr_publish(to_name, to_si.shr_container); 4327348SJose.Borrego@Sun.COM 4337348SJose.Borrego@Sun.COM return (NERR_Success); 4347348SJose.Borrego@Sun.COM } 4357348SJose.Borrego@Sun.COM 4367348SJose.Borrego@Sun.COM /* 4377348SJose.Borrego@Sun.COM * Load the information for the specified share into the supplied share 4387348SJose.Borrego@Sun.COM * info structure. 439*8334SJose.Borrego@Sun.COM * 440*8334SJose.Borrego@Sun.COM * First looks up the cache to see if the specified share exists, if there 441*8334SJose.Borrego@Sun.COM * is a miss then it looks up sharemgr. 4427348SJose.Borrego@Sun.COM */ 4437348SJose.Borrego@Sun.COM uint32_t 4447348SJose.Borrego@Sun.COM smb_shr_get(char *sharename, smb_share_t *si) 4457348SJose.Borrego@Sun.COM { 446*8334SJose.Borrego@Sun.COM uint32_t status; 4477348SJose.Borrego@Sun.COM 4487961SNatalie.Li@Sun.COM if (sharename == NULL || *sharename == '\0') 4497961SNatalie.Li@Sun.COM return (NERR_NetNameNotFound); 4507348SJose.Borrego@Sun.COM 451*8334SJose.Borrego@Sun.COM if ((status = smb_shr_lookup(sharename, si)) == NERR_Success) 452*8334SJose.Borrego@Sun.COM return (status); 4537961SNatalie.Li@Sun.COM 454*8334SJose.Borrego@Sun.COM if ((status = smb_shr_sa_loadbyname(sharename)) == NERR_Success) 455*8334SJose.Borrego@Sun.COM status = smb_shr_lookup(sharename, si); 4567348SJose.Borrego@Sun.COM 4577961SNatalie.Li@Sun.COM return (status); 4587348SJose.Borrego@Sun.COM } 4597348SJose.Borrego@Sun.COM 4607348SJose.Borrego@Sun.COM /* 4617348SJose.Borrego@Sun.COM * Modifies an existing share. Properties that can be modified are: 4627348SJose.Borrego@Sun.COM * 4637348SJose.Borrego@Sun.COM * o comment 4647348SJose.Borrego@Sun.COM * o AD container 4657961SNatalie.Li@Sun.COM * o host access 4667348SJose.Borrego@Sun.COM */ 4677348SJose.Borrego@Sun.COM uint32_t 4687961SNatalie.Li@Sun.COM smb_shr_modify(smb_share_t *new_si) 4697348SJose.Borrego@Sun.COM { 4707961SNatalie.Li@Sun.COM smb_share_t *si; 4717348SJose.Borrego@Sun.COM boolean_t adc_changed = B_FALSE; 4727961SNatalie.Li@Sun.COM char old_container[MAXPATHLEN]; 473*8334SJose.Borrego@Sun.COM uint32_t cscopt; 4747961SNatalie.Li@Sun.COM uint32_t access; 4757348SJose.Borrego@Sun.COM 4767961SNatalie.Li@Sun.COM assert(new_si != NULL); 4777348SJose.Borrego@Sun.COM 4787961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success) 4797961SNatalie.Li@Sun.COM return (NERR_InternalError); 4807348SJose.Borrego@Sun.COM 4817961SNatalie.Li@Sun.COM if ((si = smb_shr_cache_findent(new_si->shr_name)) == NULL) { 4827961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 4837961SNatalie.Li@Sun.COM return (NERR_NetNameNotFound); 4847961SNatalie.Li@Sun.COM } 4857348SJose.Borrego@Sun.COM 4867961SNatalie.Li@Sun.COM if (si->shr_type & STYPE_IPC) { 4877961SNatalie.Li@Sun.COM /* IPC$ share cannot be modified */ 4887961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 4897961SNatalie.Li@Sun.COM return (ERROR_ACCESS_DENIED); 4907348SJose.Borrego@Sun.COM } 4917348SJose.Borrego@Sun.COM 4927961SNatalie.Li@Sun.COM if (strcmp(new_si->shr_cmnt, si->shr_cmnt) != 0) 4937961SNatalie.Li@Sun.COM (void) strlcpy(si->shr_cmnt, new_si->shr_cmnt, 4947961SNatalie.Li@Sun.COM sizeof (si->shr_cmnt)); 4957961SNatalie.Li@Sun.COM 4967961SNatalie.Li@Sun.COM adc_changed = (strcmp(new_si->shr_container, si->shr_container) != 0); 4977961SNatalie.Li@Sun.COM if (adc_changed) { 4987961SNatalie.Li@Sun.COM /* save current container - needed for unpublishing */ 4997961SNatalie.Li@Sun.COM (void) strlcpy(old_container, si->shr_container, 5007961SNatalie.Li@Sun.COM sizeof (old_container)); 5017961SNatalie.Li@Sun.COM (void) strlcpy(si->shr_container, new_si->shr_container, 5027961SNatalie.Li@Sun.COM sizeof (si->shr_container)); 5037348SJose.Borrego@Sun.COM } 5047348SJose.Borrego@Sun.COM 505*8334SJose.Borrego@Sun.COM cscopt = (new_si->shr_flags & SMB_SHRF_CSC_MASK); 506*8334SJose.Borrego@Sun.COM si->shr_flags &= ~SMB_SHRF_CSC_MASK; 507*8334SJose.Borrego@Sun.COM si->shr_flags |= cscopt; 508*8334SJose.Borrego@Sun.COM 5097961SNatalie.Li@Sun.COM access = (new_si->shr_flags & SMB_SHRF_ACC_ALL); 5107961SNatalie.Li@Sun.COM si->shr_flags |= access; 5117961SNatalie.Li@Sun.COM 5127961SNatalie.Li@Sun.COM if (access & SMB_SHRF_ACC_NONE) 5137961SNatalie.Li@Sun.COM (void) strlcpy(si->shr_access_none, new_si->shr_access_none, 5147961SNatalie.Li@Sun.COM sizeof (si->shr_access_none)); 5157348SJose.Borrego@Sun.COM 5167961SNatalie.Li@Sun.COM if (access & SMB_SHRF_ACC_RO) 5177961SNatalie.Li@Sun.COM (void) strlcpy(si->shr_access_ro, new_si->shr_access_ro, 5187961SNatalie.Li@Sun.COM sizeof (si->shr_access_ro)); 5197348SJose.Borrego@Sun.COM 5207961SNatalie.Li@Sun.COM if (access & SMB_SHRF_ACC_RW) 5217961SNatalie.Li@Sun.COM (void) strlcpy(si->shr_access_rw, new_si->shr_access_rw, 5227961SNatalie.Li@Sun.COM sizeof (si->shr_access_rw)); 5237961SNatalie.Li@Sun.COM 5247961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 5257052Samw 5267348SJose.Borrego@Sun.COM if (adc_changed) { 5277961SNatalie.Li@Sun.COM smb_shr_unpublish(new_si->shr_name, old_container); 5287961SNatalie.Li@Sun.COM smb_shr_publish(new_si->shr_name, new_si->shr_container); 5297348SJose.Borrego@Sun.COM } 5307348SJose.Borrego@Sun.COM 5317348SJose.Borrego@Sun.COM return (NERR_Success); 5327052Samw } 5337052Samw 5347052Samw /* 5357052Samw * smb_shr_exists 5367052Samw * 5377348SJose.Borrego@Sun.COM * Returns B_TRUE if the share exists. Otherwise returns B_FALSE 5387052Samw */ 5397348SJose.Borrego@Sun.COM boolean_t 5407348SJose.Borrego@Sun.COM smb_shr_exists(char *sharename) 5417052Samw { 5427961SNatalie.Li@Sun.COM boolean_t exists = B_FALSE; 5437348SJose.Borrego@Sun.COM 5447348SJose.Borrego@Sun.COM if (sharename == NULL || *sharename == '\0') 5457348SJose.Borrego@Sun.COM return (B_FALSE); 5467052Samw 5477961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) { 5487961SNatalie.Li@Sun.COM exists = (smb_shr_cache_findent(sharename) != NULL); 5497961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 5507961SNatalie.Li@Sun.COM } 5517348SJose.Borrego@Sun.COM 5527348SJose.Borrego@Sun.COM return (exists); 5537052Samw } 5547052Samw 5557052Samw /* 5567961SNatalie.Li@Sun.COM * If the shared directory does not begin with a /, one will be 5577961SNatalie.Li@Sun.COM * inserted as a prefix. If ipaddr is not zero, then also return 5587961SNatalie.Li@Sun.COM * information about access based on the host level access lists, if 5597961SNatalie.Li@Sun.COM * present. Also return access check if there is an IP address and 5607961SNatalie.Li@Sun.COM * shr_accflags. 5617961SNatalie.Li@Sun.COM * 5627961SNatalie.Li@Sun.COM * The value of smb_chk_hostaccess is checked for an access match. 5637961SNatalie.Li@Sun.COM * -1 is wildcard match 5647961SNatalie.Li@Sun.COM * 0 is no match 5657961SNatalie.Li@Sun.COM * 1 is match 5667961SNatalie.Li@Sun.COM * 5677961SNatalie.Li@Sun.COM * Precedence is none is checked first followed by ro then rw if 5687961SNatalie.Li@Sun.COM * needed. If x is wildcard (< 0) then check to see if the other 5697961SNatalie.Li@Sun.COM * values are a match. If a match, that wins. 5707961SNatalie.Li@Sun.COM */ 5717961SNatalie.Li@Sun.COM void 5727961SNatalie.Li@Sun.COM smb_shr_hostaccess(smb_share_t *si, ipaddr_t ipaddr) 5737961SNatalie.Li@Sun.COM { 5747961SNatalie.Li@Sun.COM int acc = SMB_SHRF_ACC_OPEN; 5757961SNatalie.Li@Sun.COM 5767961SNatalie.Li@Sun.COM /* 5777961SNatalie.Li@Sun.COM * Check to see if there area any share level access 5787961SNatalie.Li@Sun.COM * restrictions. 5797961SNatalie.Li@Sun.COM */ 5807961SNatalie.Li@Sun.COM if (ipaddr != 0 && (si->shr_flags & SMB_SHRF_ACC_ALL) != 0) { 5817961SNatalie.Li@Sun.COM int none = SMB_SHRF_ACC_OPEN; 5827961SNatalie.Li@Sun.COM int rw = SMB_SHRF_ACC_OPEN; 5837961SNatalie.Li@Sun.COM int ro = SMB_SHRF_ACC_OPEN; 5847961SNatalie.Li@Sun.COM 5857961SNatalie.Li@Sun.COM if (si->shr_flags & SMB_SHRF_ACC_NONE) 5867961SNatalie.Li@Sun.COM none = smb_chk_hostaccess(ipaddr, si->shr_access_none); 5877961SNatalie.Li@Sun.COM if (si->shr_flags & SMB_SHRF_ACC_RW) 5887961SNatalie.Li@Sun.COM rw = smb_chk_hostaccess(ipaddr, si->shr_access_rw); 5897961SNatalie.Li@Sun.COM if (si->shr_flags & SMB_SHRF_ACC_RO) 5907961SNatalie.Li@Sun.COM ro = smb_chk_hostaccess(ipaddr, si->shr_access_ro); 5917961SNatalie.Li@Sun.COM 5927961SNatalie.Li@Sun.COM /* make first pass to get basic value */ 5937961SNatalie.Li@Sun.COM if (none != 0) 5947961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_NONE; 5957961SNatalie.Li@Sun.COM else if (ro != 0) 5967961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RO; 5977961SNatalie.Li@Sun.COM else if (rw != 0) 5987961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RW; 5997961SNatalie.Li@Sun.COM 6007961SNatalie.Li@Sun.COM /* make second pass to handle '*' case */ 6017961SNatalie.Li@Sun.COM if (none < 0) { 6027961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_NONE; 6037961SNatalie.Li@Sun.COM if (ro > 0) 6047961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RO; 6057961SNatalie.Li@Sun.COM else if (rw > 0) 6067961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RW; 6077961SNatalie.Li@Sun.COM } else if (ro < 0) { 6087961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RO; 6097961SNatalie.Li@Sun.COM if (none > 0) 6107961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_NONE; 6117961SNatalie.Li@Sun.COM else if (rw > 0) 6127961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RW; 6137961SNatalie.Li@Sun.COM } else if (rw < 0) { 6147961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RW; 6157961SNatalie.Li@Sun.COM if (none > 0) 6167961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_NONE; 6177961SNatalie.Li@Sun.COM else if (ro > 0) 6187961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RO; 6197961SNatalie.Li@Sun.COM } 6207961SNatalie.Li@Sun.COM } 6217961SNatalie.Li@Sun.COM si->shr_access_value = acc; /* return access here */ 6227961SNatalie.Li@Sun.COM } 6237961SNatalie.Li@Sun.COM 6247961SNatalie.Li@Sun.COM /* 6257052Samw * smb_shr_is_special 6267052Samw * 6277348SJose.Borrego@Sun.COM * Special share reserved for interprocess communication (IPC$) or 6287348SJose.Borrego@Sun.COM * remote administration of the server (ADMIN$). Can also refer to 6297348SJose.Borrego@Sun.COM * administrative shares such as C$, D$, E$, and so forth. 6307052Samw */ 6317052Samw int 6327348SJose.Borrego@Sun.COM smb_shr_is_special(char *sharename) 6337052Samw { 6347052Samw int len; 6357052Samw 6367348SJose.Borrego@Sun.COM if (sharename == NULL) 6377052Samw return (0); 6387052Samw 6397348SJose.Borrego@Sun.COM if ((len = strlen(sharename)) == 0) 6407052Samw return (0); 6417052Samw 6427348SJose.Borrego@Sun.COM if (sharename[len - 1] == '$') 6437052Samw return (STYPE_SPECIAL); 6447348SJose.Borrego@Sun.COM 6457348SJose.Borrego@Sun.COM return (0); 6467052Samw } 6477052Samw 6487052Samw /* 6497052Samw * smb_shr_is_restricted 6507052Samw * 6517052Samw * Check whether or not there is a restriction on a share. Restricted 6527052Samw * shares are generally STYPE_SPECIAL, for example, IPC$. All the 6537348SJose.Borrego@Sun.COM * administration share names are restricted: C$, D$ etc. Returns B_TRUE 6547348SJose.Borrego@Sun.COM * if the share is restricted. Otherwise B_FALSE is returned to indicate 6557052Samw * that there are no restrictions. 6567052Samw */ 6577348SJose.Borrego@Sun.COM boolean_t 6587348SJose.Borrego@Sun.COM smb_shr_is_restricted(char *sharename) 6597052Samw { 6607052Samw static char *restricted[] = { 6617052Samw "IPC$" 6627052Samw }; 6637052Samw 6647052Samw int i; 6657052Samw 6667348SJose.Borrego@Sun.COM if (sharename == NULL) 6677348SJose.Borrego@Sun.COM return (B_FALSE); 6687348SJose.Borrego@Sun.COM 6697052Samw for (i = 0; i < sizeof (restricted)/sizeof (restricted[0]); i++) { 6707348SJose.Borrego@Sun.COM if (utf8_strcasecmp(restricted[i], sharename) == 0) 6717348SJose.Borrego@Sun.COM return (B_TRUE); 6727052Samw } 6737052Samw 6747348SJose.Borrego@Sun.COM return (smb_shr_is_admin(sharename)); 6757052Samw } 6767052Samw 6777052Samw /* 6787052Samw * smb_shr_is_admin 6797052Samw * 6807052Samw * Check whether or not access to the share should be restricted to 6817052Samw * administrators. This is a bit of a hack because what we're doing 6827052Samw * is checking for the default admin shares: C$, D$ etc.. There are 6837052Samw * other shares that have restrictions: see smb_shr_is_restricted(). 6847052Samw * 6857348SJose.Borrego@Sun.COM * Returns B_TRUE if the shares is an admin share. Otherwise B_FALSE 6867348SJose.Borrego@Sun.COM * is returned to indicate that there are no restrictions. 6877052Samw */ 6887348SJose.Borrego@Sun.COM boolean_t 6897348SJose.Borrego@Sun.COM smb_shr_is_admin(char *sharename) 6907052Samw { 6917348SJose.Borrego@Sun.COM if (sharename == NULL) 6927348SJose.Borrego@Sun.COM return (B_FALSE); 6937052Samw 6947348SJose.Borrego@Sun.COM if (strlen(sharename) == 2 && 6957348SJose.Borrego@Sun.COM mts_isalpha(sharename[0]) && sharename[1] == '$') { 6967348SJose.Borrego@Sun.COM return (B_TRUE); 6977052Samw } 6987052Samw 6997348SJose.Borrego@Sun.COM return (B_FALSE); 7007052Samw } 7017052Samw 7027052Samw /* 7037348SJose.Borrego@Sun.COM * smb_shr_chkname 7047052Samw * 7057961SNatalie.Li@Sun.COM * Check for invalid characters in a share name. The list of invalid 7067961SNatalie.Li@Sun.COM * characters includes control characters and the following: 7077052Samw * 7087052Samw * " / \ [ ] : | < > + ; , ? * = 7097052Samw */ 7107348SJose.Borrego@Sun.COM boolean_t 7117348SJose.Borrego@Sun.COM smb_shr_chkname(char *sharename) 7127052Samw { 7137052Samw char *invalid = "\"/\\[]:|<>+;,?*="; 7147052Samw char *cp; 7157052Samw 7167348SJose.Borrego@Sun.COM if (sharename == NULL) 7177348SJose.Borrego@Sun.COM return (B_FALSE); 7187052Samw 7197348SJose.Borrego@Sun.COM if (strpbrk(sharename, invalid)) 7207348SJose.Borrego@Sun.COM return (B_FALSE); 7217052Samw 7227348SJose.Borrego@Sun.COM for (cp = sharename; *cp != '\0'; cp++) { 7237348SJose.Borrego@Sun.COM if (iscntrl(*cp)) 7247348SJose.Borrego@Sun.COM return (B_FALSE); 7257052Samw } 7267052Samw 7277348SJose.Borrego@Sun.COM return (B_TRUE); 7287052Samw } 7297052Samw 7307052Samw /* 7317052Samw * smb_shr_get_realpath 7327052Samw * 7337961SNatalie.Li@Sun.COM * Derive the real path for a share from the path provided by a client. 7347961SNatalie.Li@Sun.COM * For instance, the real path of C:\ may be /cvol or the real path of 7357961SNatalie.Li@Sun.COM * F:\home may be /vol1/home. 7367052Samw * 7377961SNatalie.Li@Sun.COM * clntpath - path provided by the Windows client is in the 7387052Samw * format of <drive letter>:\<dir> 7397052Samw * realpath - path that will be stored as the directory field of 7407052Samw * the smb_share_t structure of the share. 7417961SNatalie.Li@Sun.COM * maxlen - maximum length of the realpath buffer 7427052Samw * 7437052Samw * Return LAN Manager network error code. 7447052Samw */ 7457052Samw uint32_t 7467961SNatalie.Li@Sun.COM smb_shr_get_realpath(const char *clntpath, char *realpath, int maxlen) 7477052Samw { 7487961SNatalie.Li@Sun.COM const char *p; 7497961SNatalie.Li@Sun.COM int len; 7507348SJose.Borrego@Sun.COM 7517961SNatalie.Li@Sun.COM if ((p = strchr(clntpath, ':')) != NULL) 7527961SNatalie.Li@Sun.COM ++p; 7537961SNatalie.Li@Sun.COM else 7547961SNatalie.Li@Sun.COM p = clntpath; 7557348SJose.Borrego@Sun.COM 7567961SNatalie.Li@Sun.COM (void) strlcpy(realpath, p, maxlen); 7577961SNatalie.Li@Sun.COM (void) strcanon(realpath, "/\\"); 7587961SNatalie.Li@Sun.COM (void) strsubst(realpath, '\\', '/'); 7597348SJose.Borrego@Sun.COM 7607961SNatalie.Li@Sun.COM len = strlen(realpath); 7617961SNatalie.Li@Sun.COM if ((len > 1) && (realpath[len - 1] == '/')) 7627961SNatalie.Li@Sun.COM realpath[len - 1] = '\0'; 7637348SJose.Borrego@Sun.COM 7647348SJose.Borrego@Sun.COM return (NERR_Success); 7657348SJose.Borrego@Sun.COM } 7667348SJose.Borrego@Sun.COM 7677961SNatalie.Li@Sun.COM void 7687961SNatalie.Li@Sun.COM smb_shr_list(int offset, smb_shrlist_t *list) 7697348SJose.Borrego@Sun.COM { 7707961SNatalie.Li@Sun.COM smb_shriter_t iterator; 7717961SNatalie.Li@Sun.COM smb_share_t *si; 7727961SNatalie.Li@Sun.COM int n = 0; 7737961SNatalie.Li@Sun.COM 7747961SNatalie.Li@Sun.COM bzero(list, sizeof (smb_shrlist_t)); 7757961SNatalie.Li@Sun.COM smb_shr_iterinit(&iterator); 7767961SNatalie.Li@Sun.COM 7777961SNatalie.Li@Sun.COM while ((si = smb_shr_iterate(&iterator)) != NULL) { 7787961SNatalie.Li@Sun.COM if (--offset > 0) 7797961SNatalie.Li@Sun.COM continue; 7807961SNatalie.Li@Sun.COM 7817961SNatalie.Li@Sun.COM if ((si->shr_flags & SMB_SHRF_TRANS) && 7827961SNatalie.Li@Sun.COM ((si->shr_type & STYPE_IPC) == 0)) { 7837961SNatalie.Li@Sun.COM bcopy(si, &list->sl_shares[n], sizeof (smb_share_t)); 7847961SNatalie.Li@Sun.COM if (++n == LMSHARES_PER_REQUEST) 7857961SNatalie.Li@Sun.COM break; 7867961SNatalie.Li@Sun.COM } 7877348SJose.Borrego@Sun.COM } 7887961SNatalie.Li@Sun.COM 7897961SNatalie.Li@Sun.COM list->sl_cnt = n; 7907348SJose.Borrego@Sun.COM } 7917348SJose.Borrego@Sun.COM 7927348SJose.Borrego@Sun.COM /* 7937961SNatalie.Li@Sun.COM * ============================================ 7947961SNatalie.Li@Sun.COM * Private helper/utility functions 7957961SNatalie.Li@Sun.COM * ============================================ 7967348SJose.Borrego@Sun.COM */ 7977348SJose.Borrego@Sun.COM 7987961SNatalie.Li@Sun.COM /* 799*8334SJose.Borrego@Sun.COM * Looks up the given share in the cache and return 800*8334SJose.Borrego@Sun.COM * the info in 'si' 801*8334SJose.Borrego@Sun.COM */ 802*8334SJose.Borrego@Sun.COM static uint32_t 803*8334SJose.Borrego@Sun.COM smb_shr_lookup(char *sharename, smb_share_t *si) 804*8334SJose.Borrego@Sun.COM { 805*8334SJose.Borrego@Sun.COM smb_share_t *cached_si; 806*8334SJose.Borrego@Sun.COM uint32_t status = NERR_NetNameNotFound; 807*8334SJose.Borrego@Sun.COM 808*8334SJose.Borrego@Sun.COM if (sharename == NULL || *sharename == '\0') 809*8334SJose.Borrego@Sun.COM return (NERR_NetNameNotFound); 810*8334SJose.Borrego@Sun.COM 811*8334SJose.Borrego@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) { 812*8334SJose.Borrego@Sun.COM cached_si = smb_shr_cache_findent(sharename); 813*8334SJose.Borrego@Sun.COM if (cached_si != NULL) { 814*8334SJose.Borrego@Sun.COM bcopy(cached_si, si, sizeof (smb_share_t)); 815*8334SJose.Borrego@Sun.COM status = NERR_Success; 816*8334SJose.Borrego@Sun.COM } 817*8334SJose.Borrego@Sun.COM 818*8334SJose.Borrego@Sun.COM smb_shr_cache_unlock(); 819*8334SJose.Borrego@Sun.COM } 820*8334SJose.Borrego@Sun.COM 821*8334SJose.Borrego@Sun.COM return (status); 822*8334SJose.Borrego@Sun.COM } 823*8334SJose.Borrego@Sun.COM 824*8334SJose.Borrego@Sun.COM /* 8257961SNatalie.Li@Sun.COM * Add IPC$ to the cache upon startup. 8267961SNatalie.Li@Sun.COM */ 8277348SJose.Borrego@Sun.COM static uint32_t 8287961SNatalie.Li@Sun.COM smb_shr_addipc(void) 8297348SJose.Borrego@Sun.COM { 8307348SJose.Borrego@Sun.COM smb_share_t ipc; 8317961SNatalie.Li@Sun.COM uint32_t status = NERR_InternalError; 8327348SJose.Borrego@Sun.COM 8337348SJose.Borrego@Sun.COM bzero(&ipc, sizeof (smb_share_t)); 8347348SJose.Borrego@Sun.COM (void) strcpy(ipc.shr_name, "IPC$"); 8357348SJose.Borrego@Sun.COM (void) strcpy(ipc.shr_cmnt, "Remote IPC"); 8367348SJose.Borrego@Sun.COM ipc.shr_flags = SMB_SHRF_TRANS; 8377348SJose.Borrego@Sun.COM ipc.shr_type = STYPE_IPC; 8387348SJose.Borrego@Sun.COM 8397961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) == NERR_Success) { 8407961SNatalie.Li@Sun.COM status = smb_shr_cache_addent(&ipc); 8417961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 8427348SJose.Borrego@Sun.COM } 8437348SJose.Borrego@Sun.COM 8447348SJose.Borrego@Sun.COM return (status); 8457348SJose.Borrego@Sun.COM } 8467348SJose.Borrego@Sun.COM 8477348SJose.Borrego@Sun.COM /* 8487052Samw * smb_shr_set_oemname 8497052Samw * 8507961SNatalie.Li@Sun.COM * Generate the OEM name for the specified share. If the name is 8517961SNatalie.Li@Sun.COM * shorter than 13 bytes the oemname will be saved in si->shr_oemname. 8527961SNatalie.Li@Sun.COM * Otherwise si->shr_oemname will be empty and SMB_SHRF_LONGNAME will 8537961SNatalie.Li@Sun.COM * be set in si->shr_flags. 8547052Samw */ 8557052Samw static void 8567052Samw smb_shr_set_oemname(smb_share_t *si) 8577052Samw { 8587052Samw unsigned int cpid = oem_get_smb_cpid(); 8597052Samw mts_wchar_t *unibuf; 8607052Samw char *oem_name; 8617052Samw int length; 8627052Samw 8637052Samw length = strlen(si->shr_name) + 1; 8647052Samw 8657052Samw oem_name = malloc(length); 8667052Samw unibuf = malloc(length * sizeof (mts_wchar_t)); 8677052Samw if ((oem_name == NULL) || (unibuf == NULL)) { 8687052Samw free(oem_name); 8697052Samw free(unibuf); 8707052Samw return; 8717052Samw } 8727052Samw 8737052Samw (void) mts_mbstowcs(unibuf, si->shr_name, length); 8747052Samw 8757052Samw if (unicodestooems(oem_name, unibuf, length, cpid) == 0) 8767052Samw (void) strcpy(oem_name, si->shr_name); 8777052Samw 8787052Samw free(unibuf); 8797052Samw 8807052Samw if (strlen(oem_name) + 1 > SMB_SHARE_OEMNAME_MAX) { 8817052Samw si->shr_flags |= SMB_SHRF_LONGNAME; 8827052Samw *si->shr_oemname = '\0'; 8837052Samw } else { 8847052Samw si->shr_flags &= ~SMB_SHRF_LONGNAME; 8857052Samw (void) strlcpy(si->shr_oemname, oem_name, 8867052Samw SMB_SHARE_OEMNAME_MAX); 8877052Samw } 8887052Samw 8897052Samw free(oem_name); 8907052Samw } 8917348SJose.Borrego@Sun.COM 8927348SJose.Borrego@Sun.COM /* 8937348SJose.Borrego@Sun.COM * ============================================ 8947961SNatalie.Li@Sun.COM * Cache management functions 8957961SNatalie.Li@Sun.COM * 8967961SNatalie.Li@Sun.COM * All cache functions are private 8977348SJose.Borrego@Sun.COM * ============================================ 8987348SJose.Borrego@Sun.COM */ 8997348SJose.Borrego@Sun.COM 9007348SJose.Borrego@Sun.COM /* 9017961SNatalie.Li@Sun.COM * Create the share cache (hash table). 9027348SJose.Borrego@Sun.COM */ 9037348SJose.Borrego@Sun.COM static uint32_t 9047961SNatalie.Li@Sun.COM smb_shr_cache_create(void) 9057348SJose.Borrego@Sun.COM { 9067961SNatalie.Li@Sun.COM uint32_t status = NERR_Success; 9077348SJose.Borrego@Sun.COM 9087961SNatalie.Li@Sun.COM (void) mutex_lock(&smb_shr_cache.sc_mtx); 9097961SNatalie.Li@Sun.COM switch (smb_shr_cache.sc_state) { 9107961SNatalie.Li@Sun.COM case SMB_SHR_CACHE_STATE_NONE: 9117961SNatalie.Li@Sun.COM smb_shr_cache.sc_cache = ht_create_table(SMB_SHR_HTAB_SZ, 9127961SNatalie.Li@Sun.COM MAXNAMELEN, 0); 9137961SNatalie.Li@Sun.COM if (smb_shr_cache.sc_cache == NULL) { 9147961SNatalie.Li@Sun.COM status = NERR_InternalError; 9157961SNatalie.Li@Sun.COM break; 9167348SJose.Borrego@Sun.COM } 9177348SJose.Borrego@Sun.COM 9187961SNatalie.Li@Sun.COM (void) ht_register_callback(smb_shr_cache.sc_cache, 9197961SNatalie.Li@Sun.COM smb_shr_cache_freent); 9207961SNatalie.Li@Sun.COM smb_shr_cache.sc_nops = 0; 9217961SNatalie.Li@Sun.COM smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_CREATED; 9227961SNatalie.Li@Sun.COM break; 9237961SNatalie.Li@Sun.COM 9247961SNatalie.Li@Sun.COM default: 9257961SNatalie.Li@Sun.COM assert(0); 9267961SNatalie.Li@Sun.COM status = NERR_InternalError; 9277961SNatalie.Li@Sun.COM break; 9287961SNatalie.Li@Sun.COM } 9297961SNatalie.Li@Sun.COM (void) mutex_unlock(&smb_shr_cache.sc_mtx); 9307961SNatalie.Li@Sun.COM 9317961SNatalie.Li@Sun.COM return (status); 9327961SNatalie.Li@Sun.COM } 9337961SNatalie.Li@Sun.COM 9347961SNatalie.Li@Sun.COM /* 9357961SNatalie.Li@Sun.COM * Destroy the share cache (hash table). 9367961SNatalie.Li@Sun.COM * Wait for inflight/pending operations to finish or abort before 9377961SNatalie.Li@Sun.COM * destroying the cache. 9387961SNatalie.Li@Sun.COM */ 9397961SNatalie.Li@Sun.COM static void 9407961SNatalie.Li@Sun.COM smb_shr_cache_destroy(void) 9417961SNatalie.Li@Sun.COM { 9427961SNatalie.Li@Sun.COM (void) mutex_lock(&smb_shr_cache.sc_mtx); 9437961SNatalie.Li@Sun.COM if (smb_shr_cache.sc_state == SMB_SHR_CACHE_STATE_CREATED) { 9447961SNatalie.Li@Sun.COM smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_DESTROYING; 9457961SNatalie.Li@Sun.COM while (smb_shr_cache.sc_nops > 0) 9467961SNatalie.Li@Sun.COM (void) cond_wait(&smb_shr_cache.sc_cv, 9477961SNatalie.Li@Sun.COM &smb_shr_cache.sc_mtx); 9487961SNatalie.Li@Sun.COM 9497961SNatalie.Li@Sun.COM smb_shr_cache.sc_cache = NULL; 9507961SNatalie.Li@Sun.COM smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_NONE; 9517961SNatalie.Li@Sun.COM } 9527961SNatalie.Li@Sun.COM (void) mutex_unlock(&smb_shr_cache.sc_mtx); 9537961SNatalie.Li@Sun.COM } 9547961SNatalie.Li@Sun.COM 9557961SNatalie.Li@Sun.COM /* 9567961SNatalie.Li@Sun.COM * If the cache is in "created" state, lock the cache for read 9577961SNatalie.Li@Sun.COM * or read/write based on the specified mode. 9587961SNatalie.Li@Sun.COM * 9597961SNatalie.Li@Sun.COM * Whenever a lock is granted, the number of inflight cache 9607961SNatalie.Li@Sun.COM * operations is incremented. 9617961SNatalie.Li@Sun.COM */ 9627961SNatalie.Li@Sun.COM static uint32_t 9637961SNatalie.Li@Sun.COM smb_shr_cache_lock(int mode) 9647961SNatalie.Li@Sun.COM { 9657961SNatalie.Li@Sun.COM (void) mutex_lock(&smb_shr_cache.sc_mtx); 966*8334SJose.Borrego@Sun.COM if (smb_shr_cache.sc_state != SMB_SHR_CACHE_STATE_CREATED) { 9677961SNatalie.Li@Sun.COM (void) mutex_unlock(&smb_shr_cache.sc_mtx); 9687961SNatalie.Li@Sun.COM return (NERR_InternalError); 9697961SNatalie.Li@Sun.COM } 970*8334SJose.Borrego@Sun.COM smb_shr_cache.sc_nops++; 9717961SNatalie.Li@Sun.COM (void) mutex_unlock(&smb_shr_cache.sc_mtx); 9727961SNatalie.Li@Sun.COM 9737961SNatalie.Li@Sun.COM /* 9747961SNatalie.Li@Sun.COM * Lock has to be taken outside the mutex otherwise 9757961SNatalie.Li@Sun.COM * there could be a deadlock 9767961SNatalie.Li@Sun.COM */ 9777961SNatalie.Li@Sun.COM if (mode == SMB_SHR_CACHE_RDLOCK) 9787961SNatalie.Li@Sun.COM (void) rw_rdlock(&smb_shr_cache.sc_cache_lck); 9797961SNatalie.Li@Sun.COM else 9807961SNatalie.Li@Sun.COM (void) rw_wrlock(&smb_shr_cache.sc_cache_lck); 9817961SNatalie.Li@Sun.COM 9827961SNatalie.Li@Sun.COM return (NERR_Success); 9837961SNatalie.Li@Sun.COM } 9847961SNatalie.Li@Sun.COM 9857961SNatalie.Li@Sun.COM /* 9867961SNatalie.Li@Sun.COM * Decrement the number of inflight operations and then unlock. 9877961SNatalie.Li@Sun.COM */ 9887961SNatalie.Li@Sun.COM static void 9897961SNatalie.Li@Sun.COM smb_shr_cache_unlock(void) 9907961SNatalie.Li@Sun.COM { 9917961SNatalie.Li@Sun.COM (void) mutex_lock(&smb_shr_cache.sc_mtx); 9927961SNatalie.Li@Sun.COM assert(smb_shr_cache.sc_nops > 0); 9937961SNatalie.Li@Sun.COM smb_shr_cache.sc_nops--; 9947961SNatalie.Li@Sun.COM (void) cond_broadcast(&smb_shr_cache.sc_cv); 9957961SNatalie.Li@Sun.COM (void) mutex_unlock(&smb_shr_cache.sc_mtx); 9967961SNatalie.Li@Sun.COM 9977961SNatalie.Li@Sun.COM (void) rw_unlock(&smb_shr_cache.sc_cache_lck); 9987961SNatalie.Li@Sun.COM } 9997961SNatalie.Li@Sun.COM 10007961SNatalie.Li@Sun.COM /* 10017961SNatalie.Li@Sun.COM * Return the total number of shares 10027961SNatalie.Li@Sun.COM */ 10037961SNatalie.Li@Sun.COM static int 10047961SNatalie.Li@Sun.COM smb_shr_cache_count(void) 10057961SNatalie.Li@Sun.COM { 10067961SNatalie.Li@Sun.COM return (ht_get_total_items(smb_shr_cache.sc_cache)); 10077961SNatalie.Li@Sun.COM } 10087961SNatalie.Li@Sun.COM 10097961SNatalie.Li@Sun.COM /* 10107961SNatalie.Li@Sun.COM * looks up the given share name in the cache and if it 10117961SNatalie.Li@Sun.COM * finds a match returns a pointer to the cached entry. 10127961SNatalie.Li@Sun.COM * Note that since a pointer is returned this function 10137961SNatalie.Li@Sun.COM * MUST be protected by smb_shr_cache_lock/unlock pair 10147961SNatalie.Li@Sun.COM */ 10157961SNatalie.Li@Sun.COM static smb_share_t * 10167961SNatalie.Li@Sun.COM smb_shr_cache_findent(char *sharename) 10177961SNatalie.Li@Sun.COM { 10187961SNatalie.Li@Sun.COM HT_ITEM *item; 10197961SNatalie.Li@Sun.COM 10207961SNatalie.Li@Sun.COM (void) utf8_strlwr(sharename); 10217961SNatalie.Li@Sun.COM item = ht_find_item(smb_shr_cache.sc_cache, sharename); 10227961SNatalie.Li@Sun.COM if (item && item->hi_data) 10237961SNatalie.Li@Sun.COM return ((smb_share_t *)item->hi_data); 10247961SNatalie.Li@Sun.COM 10257961SNatalie.Li@Sun.COM return (NULL); 10267961SNatalie.Li@Sun.COM } 10277961SNatalie.Li@Sun.COM 10287961SNatalie.Li@Sun.COM /* 10297961SNatalie.Li@Sun.COM * Return a pointer to the first/next entry in 10307961SNatalie.Li@Sun.COM * the cache based on the given iterator. 10317961SNatalie.Li@Sun.COM * 10327961SNatalie.Li@Sun.COM * Calls to this function MUST be protected by 10337961SNatalie.Li@Sun.COM * smb_shr_cache_lock/unlock. 10347961SNatalie.Li@Sun.COM */ 10357961SNatalie.Li@Sun.COM static smb_share_t * 10367961SNatalie.Li@Sun.COM smb_shr_cache_iterate(smb_shriter_t *shi) 10377961SNatalie.Li@Sun.COM { 10387961SNatalie.Li@Sun.COM HT_ITEM *item; 10397961SNatalie.Li@Sun.COM 10407961SNatalie.Li@Sun.COM if (shi->si_first) { 10417961SNatalie.Li@Sun.COM item = ht_findfirst(smb_shr_cache.sc_cache, &shi->si_hashiter); 10427961SNatalie.Li@Sun.COM shi->si_first = B_FALSE; 10437961SNatalie.Li@Sun.COM } else { 10447961SNatalie.Li@Sun.COM item = ht_findnext(&shi->si_hashiter); 10457348SJose.Borrego@Sun.COM } 10467348SJose.Borrego@Sun.COM 10477961SNatalie.Li@Sun.COM if (item && item->hi_data) 10487961SNatalie.Li@Sun.COM return ((smb_share_t *)item->hi_data); 10497961SNatalie.Li@Sun.COM 10507961SNatalie.Li@Sun.COM return (NULL); 10517961SNatalie.Li@Sun.COM } 10527961SNatalie.Li@Sun.COM 10537961SNatalie.Li@Sun.COM /* 10547961SNatalie.Li@Sun.COM * Add the specified share to the cache. Memory needs to be allocated 10557961SNatalie.Li@Sun.COM * for the cache entry and the passed information is copied to the 10567961SNatalie.Li@Sun.COM * allocated space. 10577961SNatalie.Li@Sun.COM */ 10587961SNatalie.Li@Sun.COM static uint32_t 10597961SNatalie.Li@Sun.COM smb_shr_cache_addent(smb_share_t *si) 10607961SNatalie.Li@Sun.COM { 10617961SNatalie.Li@Sun.COM smb_share_t *cache_ent; 10627961SNatalie.Li@Sun.COM uint32_t status = NERR_Success; 10637961SNatalie.Li@Sun.COM 10647961SNatalie.Li@Sun.COM if ((cache_ent = malloc(sizeof (smb_share_t))) == NULL) 10657961SNatalie.Li@Sun.COM return (ERROR_NOT_ENOUGH_MEMORY); 10667961SNatalie.Li@Sun.COM 10677961SNatalie.Li@Sun.COM bcopy(si, cache_ent, sizeof (smb_share_t)); 10687961SNatalie.Li@Sun.COM 10697961SNatalie.Li@Sun.COM (void) utf8_strlwr(cache_ent->shr_name); 10707961SNatalie.Li@Sun.COM smb_shr_set_oemname(cache_ent); 10717961SNatalie.Li@Sun.COM 10727961SNatalie.Li@Sun.COM if ((si->shr_type & STYPE_IPC) == 0) 10737961SNatalie.Li@Sun.COM cache_ent->shr_type = STYPE_DISKTREE; 10747961SNatalie.Li@Sun.COM cache_ent->shr_type |= smb_shr_is_special(cache_ent->shr_name); 10757961SNatalie.Li@Sun.COM 10767961SNatalie.Li@Sun.COM if (smb_shr_is_admin(cache_ent->shr_name)) 10777961SNatalie.Li@Sun.COM cache_ent->shr_flags |= SMB_SHRF_ADMIN; 10787961SNatalie.Li@Sun.COM 10797961SNatalie.Li@Sun.COM if (si->shr_flags & SMB_SHRF_AUTOHOME) 10807961SNatalie.Li@Sun.COM cache_ent->shr_refcnt = 1; 10817961SNatalie.Li@Sun.COM 10827961SNatalie.Li@Sun.COM if (ht_add_item(smb_shr_cache.sc_cache, cache_ent->shr_name, cache_ent) 10837961SNatalie.Li@Sun.COM == NULL) { 10847961SNatalie.Li@Sun.COM syslog(LOG_DEBUG, "share: %s: cache update failed", 10857961SNatalie.Li@Sun.COM cache_ent->shr_name); 10867961SNatalie.Li@Sun.COM free(cache_ent); 10877961SNatalie.Li@Sun.COM status = NERR_InternalError; 10887348SJose.Borrego@Sun.COM } 10897348SJose.Borrego@Sun.COM 10907961SNatalie.Li@Sun.COM return (status); 10917961SNatalie.Li@Sun.COM } 10927961SNatalie.Li@Sun.COM 10937961SNatalie.Li@Sun.COM /* 10947961SNatalie.Li@Sun.COM * Delete the specified share from the cache. 10957961SNatalie.Li@Sun.COM */ 10967961SNatalie.Li@Sun.COM static void 10977961SNatalie.Li@Sun.COM smb_shr_cache_delent(char *sharename) 10987961SNatalie.Li@Sun.COM { 10997961SNatalie.Li@Sun.COM (void) utf8_strlwr(sharename); 11007961SNatalie.Li@Sun.COM (void) ht_remove_item(smb_shr_cache.sc_cache, sharename); 11017961SNatalie.Li@Sun.COM } 11027961SNatalie.Li@Sun.COM 11037961SNatalie.Li@Sun.COM /* 11047961SNatalie.Li@Sun.COM * Call back to free the given cache entry. 11057961SNatalie.Li@Sun.COM */ 11067961SNatalie.Li@Sun.COM static void 11077961SNatalie.Li@Sun.COM smb_shr_cache_freent(HT_ITEM *item) 11087961SNatalie.Li@Sun.COM { 11097961SNatalie.Li@Sun.COM if (item && item->hi_data) 11107961SNatalie.Li@Sun.COM free(item->hi_data); 11117961SNatalie.Li@Sun.COM } 11127961SNatalie.Li@Sun.COM 11137961SNatalie.Li@Sun.COM /* 11147961SNatalie.Li@Sun.COM * ============================================ 11157961SNatalie.Li@Sun.COM * Interfaces to sharemgr 11167961SNatalie.Li@Sun.COM * 11177961SNatalie.Li@Sun.COM * All functions in this section are private 11187961SNatalie.Li@Sun.COM * ============================================ 11197961SNatalie.Li@Sun.COM */ 11207961SNatalie.Li@Sun.COM 11217961SNatalie.Li@Sun.COM /* 11227961SNatalie.Li@Sun.COM * Load shares from sharemgr 11237961SNatalie.Li@Sun.COM */ 11247961SNatalie.Li@Sun.COM /*ARGSUSED*/ 11257961SNatalie.Li@Sun.COM static void * 11267961SNatalie.Li@Sun.COM smb_shr_sa_loadall(void *args) 11277961SNatalie.Li@Sun.COM { 11287961SNatalie.Li@Sun.COM sa_handle_t handle; 11297961SNatalie.Li@Sun.COM sa_group_t group, subgroup; 11307961SNatalie.Li@Sun.COM char *gstate; 11317961SNatalie.Li@Sun.COM boolean_t gdisabled; 11327961SNatalie.Li@Sun.COM 11337961SNatalie.Li@Sun.COM if ((handle = sa_init(SA_INIT_SHARE_API)) == NULL) { 11347961SNatalie.Li@Sun.COM syslog(LOG_ERR, "share: failed to get libshare API handle"); 11357961SNatalie.Li@Sun.COM return (NULL); 11367348SJose.Borrego@Sun.COM } 11377348SJose.Borrego@Sun.COM 11387961SNatalie.Li@Sun.COM for (group = sa_get_group(handle, NULL); 11397961SNatalie.Li@Sun.COM group != NULL; group = sa_get_next_group(group)) { 11407961SNatalie.Li@Sun.COM gstate = sa_get_group_attr(group, "state"); 11417961SNatalie.Li@Sun.COM if (gstate == NULL) 11427961SNatalie.Li@Sun.COM continue; 11437961SNatalie.Li@Sun.COM 11447961SNatalie.Li@Sun.COM gdisabled = (strcasecmp(gstate, "disabled") == 0); 11457961SNatalie.Li@Sun.COM sa_free_attr_string(gstate); 11467961SNatalie.Li@Sun.COM if (gdisabled) 11477961SNatalie.Li@Sun.COM continue; 11487961SNatalie.Li@Sun.COM 11497961SNatalie.Li@Sun.COM smb_shr_sa_loadgrp(group); 11507961SNatalie.Li@Sun.COM 11517961SNatalie.Li@Sun.COM for (subgroup = sa_get_sub_group(group); 11527961SNatalie.Li@Sun.COM subgroup != NULL; 11537961SNatalie.Li@Sun.COM subgroup = sa_get_next_group(subgroup)) { 11547961SNatalie.Li@Sun.COM smb_shr_sa_loadgrp(subgroup); 11557961SNatalie.Li@Sun.COM } 11567961SNatalie.Li@Sun.COM 11577348SJose.Borrego@Sun.COM } 11587348SJose.Borrego@Sun.COM 11597348SJose.Borrego@Sun.COM sa_fini(handle); 11607961SNatalie.Li@Sun.COM return (NULL); 11617348SJose.Borrego@Sun.COM } 11627348SJose.Borrego@Sun.COM 11637961SNatalie.Li@Sun.COM /* 11647961SNatalie.Li@Sun.COM * Load the shares contained in the specified group. 11657961SNatalie.Li@Sun.COM * 11667961SNatalie.Li@Sun.COM * Don't process groups on which the smb protocol is disabled. 11677961SNatalie.Li@Sun.COM * The top level ZFS group won't have the smb protocol enabled 11687961SNatalie.Li@Sun.COM * but sub-groups will. 11697961SNatalie.Li@Sun.COM * 11707961SNatalie.Li@Sun.COM * We will tolerate a limited number of errors and then give 11717961SNatalie.Li@Sun.COM * up on the current group. A typical error might be that the 11727961SNatalie.Li@Sun.COM * shared directory no longer exists. 11737961SNatalie.Li@Sun.COM */ 11747961SNatalie.Li@Sun.COM static void 11757961SNatalie.Li@Sun.COM smb_shr_sa_loadgrp(sa_group_t group) 11767961SNatalie.Li@Sun.COM { 11777961SNatalie.Li@Sun.COM sa_share_t share; 11787961SNatalie.Li@Sun.COM sa_resource_t resource; 11797961SNatalie.Li@Sun.COM int error_count = 0; 11807961SNatalie.Li@Sun.COM 11817961SNatalie.Li@Sun.COM if (sa_get_optionset(group, SMB_PROTOCOL_NAME) == NULL) 11827961SNatalie.Li@Sun.COM return; 11837961SNatalie.Li@Sun.COM 11847961SNatalie.Li@Sun.COM for (share = sa_get_share(group, NULL); 11857961SNatalie.Li@Sun.COM share != NULL; 11867961SNatalie.Li@Sun.COM share = sa_get_next_share(share)) { 11877961SNatalie.Li@Sun.COM for (resource = sa_get_share_resource(share, NULL); 11887961SNatalie.Li@Sun.COM resource != NULL; 11897961SNatalie.Li@Sun.COM resource = sa_get_next_resource(resource)) { 11907961SNatalie.Li@Sun.COM if (smb_shr_sa_load(share, resource)) 11917961SNatalie.Li@Sun.COM ++error_count; 11927961SNatalie.Li@Sun.COM 11937961SNatalie.Li@Sun.COM if (error_count > SMB_SHR_ERROR_THRESHOLD) 11947961SNatalie.Li@Sun.COM break; 11957961SNatalie.Li@Sun.COM } 11967961SNatalie.Li@Sun.COM 11977961SNatalie.Li@Sun.COM if (error_count > SMB_SHR_ERROR_THRESHOLD) 11987961SNatalie.Li@Sun.COM break; 11997961SNatalie.Li@Sun.COM } 12007961SNatalie.Li@Sun.COM } 12017961SNatalie.Li@Sun.COM 12027961SNatalie.Li@Sun.COM /* 12037961SNatalie.Li@Sun.COM * Load a share definition from sharemgr and add it to the cache. 1204*8334SJose.Borrego@Sun.COM * If the share is already in the cache then it doesn't do anything. 1205*8334SJose.Borrego@Sun.COM * 1206*8334SJose.Borrego@Sun.COM * This function does not report duplicate shares as error since 1207*8334SJose.Borrego@Sun.COM * a share might have been added by smb_shr_get() while load is 1208*8334SJose.Borrego@Sun.COM * in progress. 12097961SNatalie.Li@Sun.COM */ 12107348SJose.Borrego@Sun.COM static uint32_t 12117961SNatalie.Li@Sun.COM smb_shr_sa_load(sa_share_t share, sa_resource_t resource) 12127961SNatalie.Li@Sun.COM { 12137961SNatalie.Li@Sun.COM smb_share_t si; 1214*8334SJose.Borrego@Sun.COM char *sharename; 12157961SNatalie.Li@Sun.COM uint32_t status; 1216*8334SJose.Borrego@Sun.COM boolean_t loaded; 1217*8334SJose.Borrego@Sun.COM 1218*8334SJose.Borrego@Sun.COM if ((sharename = sa_get_resource_attr(resource, "name")) == NULL) 1219*8334SJose.Borrego@Sun.COM return (NERR_InternalError); 1220*8334SJose.Borrego@Sun.COM 1221*8334SJose.Borrego@Sun.COM loaded = smb_shr_exists(sharename); 1222*8334SJose.Borrego@Sun.COM sa_free_attr_string(sharename); 1223*8334SJose.Borrego@Sun.COM 1224*8334SJose.Borrego@Sun.COM if (loaded) 1225*8334SJose.Borrego@Sun.COM return (NERR_Success); 12267961SNatalie.Li@Sun.COM 12277961SNatalie.Li@Sun.COM if ((status = smb_shr_sa_get(share, resource, &si)) != NERR_Success) { 12287961SNatalie.Li@Sun.COM syslog(LOG_DEBUG, "share: failed to load %s (%d)", 12297961SNatalie.Li@Sun.COM si.shr_name, status); 12307961SNatalie.Li@Sun.COM return (status); 12317961SNatalie.Li@Sun.COM } 12327961SNatalie.Li@Sun.COM 1233*8334SJose.Borrego@Sun.COM status = smb_shr_add(&si); 1234*8334SJose.Borrego@Sun.COM if ((status != NERR_Success) && (status != NERR_DuplicateShare)) { 12357961SNatalie.Li@Sun.COM syslog(LOG_DEBUG, "share: failed to cache %s (%d)", 12367961SNatalie.Li@Sun.COM si.shr_name, status); 12377961SNatalie.Li@Sun.COM return (status); 12387961SNatalie.Li@Sun.COM } 12397961SNatalie.Li@Sun.COM 12407961SNatalie.Li@Sun.COM return (NERR_Success); 12417961SNatalie.Li@Sun.COM } 12427961SNatalie.Li@Sun.COM 12437961SNatalie.Li@Sun.COM /* 12447961SNatalie.Li@Sun.COM * Read the specified share information from sharemgr and return 12457961SNatalie.Li@Sun.COM * it in the given smb_share_t structure. 12467961SNatalie.Li@Sun.COM * 12477961SNatalie.Li@Sun.COM * Shares read from sharemgr are marked as permanent/persistent. 12487961SNatalie.Li@Sun.COM */ 12497961SNatalie.Li@Sun.COM static uint32_t 12507961SNatalie.Li@Sun.COM smb_shr_sa_get(sa_share_t share, sa_resource_t resource, smb_share_t *si) 12517348SJose.Borrego@Sun.COM { 12527348SJose.Borrego@Sun.COM sa_property_t prop; 12537348SJose.Borrego@Sun.COM sa_optionset_t opts; 12547348SJose.Borrego@Sun.COM char *val = NULL; 12557348SJose.Borrego@Sun.COM char *path; 12567348SJose.Borrego@Sun.COM char *rname; 12577348SJose.Borrego@Sun.COM 12587348SJose.Borrego@Sun.COM if ((path = sa_get_share_attr(share, "path")) == NULL) 12597348SJose.Borrego@Sun.COM return (NERR_InternalError); 12607348SJose.Borrego@Sun.COM 12617348SJose.Borrego@Sun.COM if ((rname = sa_get_resource_attr(resource, "name")) == NULL) { 12627348SJose.Borrego@Sun.COM sa_free_attr_string(path); 12637348SJose.Borrego@Sun.COM return (NERR_InternalError); 12647348SJose.Borrego@Sun.COM } 12657348SJose.Borrego@Sun.COM 12667348SJose.Borrego@Sun.COM bzero(si, sizeof (smb_share_t)); 12677348SJose.Borrego@Sun.COM si->shr_flags = SMB_SHRF_PERM; 12687348SJose.Borrego@Sun.COM 12697348SJose.Borrego@Sun.COM (void) strlcpy(si->shr_path, path, sizeof (si->shr_path)); 12707348SJose.Borrego@Sun.COM (void) strlcpy(si->shr_name, rname, sizeof (si->shr_name)); 12717348SJose.Borrego@Sun.COM 12727348SJose.Borrego@Sun.COM sa_free_attr_string(path); 12737348SJose.Borrego@Sun.COM sa_free_attr_string(rname); 12747348SJose.Borrego@Sun.COM 12757348SJose.Borrego@Sun.COM val = sa_get_resource_description(resource); 12767348SJose.Borrego@Sun.COM if (val == NULL) 12777348SJose.Borrego@Sun.COM val = sa_get_share_description(share); 12787348SJose.Borrego@Sun.COM 12797348SJose.Borrego@Sun.COM if (val != NULL) { 12807348SJose.Borrego@Sun.COM (void) strlcpy(si->shr_cmnt, val, sizeof (si->shr_cmnt)); 12817348SJose.Borrego@Sun.COM sa_free_share_description(val); 12827348SJose.Borrego@Sun.COM } 12837348SJose.Borrego@Sun.COM 12847348SJose.Borrego@Sun.COM opts = sa_get_derived_optionset(resource, SMB_PROTOCOL_NAME, 1); 12857348SJose.Borrego@Sun.COM if (opts == NULL) 12867348SJose.Borrego@Sun.COM return (NERR_Success); 12877348SJose.Borrego@Sun.COM 1288*8334SJose.Borrego@Sun.COM prop = (sa_property_t)sa_get_property(opts, SHOPT_AD_CONTAINER); 12897348SJose.Borrego@Sun.COM if (prop != NULL) { 12907348SJose.Borrego@Sun.COM if ((val = sa_get_property_attr(prop, "value")) != NULL) { 12917348SJose.Borrego@Sun.COM (void) strlcpy(si->shr_container, val, 12927348SJose.Borrego@Sun.COM sizeof (si->shr_container)); 12937348SJose.Borrego@Sun.COM free(val); 12947348SJose.Borrego@Sun.COM } 12957348SJose.Borrego@Sun.COM } 12967348SJose.Borrego@Sun.COM 1297*8334SJose.Borrego@Sun.COM prop = (sa_property_t)sa_get_property(opts, SHOPT_CSC); 1298*8334SJose.Borrego@Sun.COM if (prop != NULL) { 1299*8334SJose.Borrego@Sun.COM if ((val = sa_get_property_attr(prop, "value")) != NULL) { 1300*8334SJose.Borrego@Sun.COM smb_shr_sa_csc_option(val, si); 1301*8334SJose.Borrego@Sun.COM free(val); 1302*8334SJose.Borrego@Sun.COM } 1303*8334SJose.Borrego@Sun.COM } 1304*8334SJose.Borrego@Sun.COM 13057961SNatalie.Li@Sun.COM prop = (sa_property_t)sa_get_property(opts, SHOPT_NONE); 13067961SNatalie.Li@Sun.COM if (prop != NULL) { 13077961SNatalie.Li@Sun.COM if ((val = sa_get_property_attr(prop, "value")) != NULL) { 13087961SNatalie.Li@Sun.COM (void) strlcpy(si->shr_access_none, val, 13097961SNatalie.Li@Sun.COM sizeof (si->shr_access_none)); 13107961SNatalie.Li@Sun.COM free(val); 13117961SNatalie.Li@Sun.COM si->shr_flags |= SMB_SHRF_ACC_NONE; 13127961SNatalie.Li@Sun.COM } 13137348SJose.Borrego@Sun.COM } 13147348SJose.Borrego@Sun.COM 13157961SNatalie.Li@Sun.COM prop = (sa_property_t)sa_get_property(opts, SHOPT_RO); 13167961SNatalie.Li@Sun.COM if (prop != NULL) { 13177961SNatalie.Li@Sun.COM if ((val = sa_get_property_attr(prop, "value")) != NULL) { 13187961SNatalie.Li@Sun.COM (void) strlcpy(si->shr_access_ro, val, 13197961SNatalie.Li@Sun.COM sizeof (si->shr_access_ro)); 13207961SNatalie.Li@Sun.COM free(val); 13217961SNatalie.Li@Sun.COM si->shr_flags |= SMB_SHRF_ACC_RO; 13227961SNatalie.Li@Sun.COM } 13237348SJose.Borrego@Sun.COM } 13247348SJose.Borrego@Sun.COM 13257961SNatalie.Li@Sun.COM prop = (sa_property_t)sa_get_property(opts, SHOPT_RW); 13267961SNatalie.Li@Sun.COM if (prop != NULL) { 13277961SNatalie.Li@Sun.COM if ((val = sa_get_property_attr(prop, "value")) != NULL) { 13287961SNatalie.Li@Sun.COM (void) strlcpy(si->shr_access_rw, val, 13297961SNatalie.Li@Sun.COM sizeof (si->shr_access_rw)); 13307961SNatalie.Li@Sun.COM free(val); 13317961SNatalie.Li@Sun.COM si->shr_flags |= SMB_SHRF_ACC_RW; 13327961SNatalie.Li@Sun.COM } 13337961SNatalie.Li@Sun.COM } 13347961SNatalie.Li@Sun.COM 13357961SNatalie.Li@Sun.COM sa_free_derived_optionset(opts); 13367961SNatalie.Li@Sun.COM return (NERR_Success); 13377348SJose.Borrego@Sun.COM } 13387348SJose.Borrego@Sun.COM 13397348SJose.Borrego@Sun.COM /* 1340*8334SJose.Borrego@Sun.COM * Map a client-side caching (CSC) option to the appropriate share 1341*8334SJose.Borrego@Sun.COM * flag. Only one option is allowed; an error will be logged if 1342*8334SJose.Borrego@Sun.COM * multiple options have been specified. We don't need to do anything 1343*8334SJose.Borrego@Sun.COM * about multiple values here because the SRVSVC will not recognize 1344*8334SJose.Borrego@Sun.COM * a value containing multiple flags and will return the default value. 1345*8334SJose.Borrego@Sun.COM * 1346*8334SJose.Borrego@Sun.COM * If the option value is not recognized, it will be ignored: invalid 1347*8334SJose.Borrego@Sun.COM * values will typically be caught and rejected by sharemgr. 1348*8334SJose.Borrego@Sun.COM */ 1349*8334SJose.Borrego@Sun.COM static void 1350*8334SJose.Borrego@Sun.COM smb_shr_sa_csc_option(const char *value, smb_share_t *si) 1351*8334SJose.Borrego@Sun.COM { 1352*8334SJose.Borrego@Sun.COM struct { 1353*8334SJose.Borrego@Sun.COM char *value; 1354*8334SJose.Borrego@Sun.COM uint32_t flag; 1355*8334SJose.Borrego@Sun.COM } cscopt[] = { 1356*8334SJose.Borrego@Sun.COM { "disabled", SMB_SHRF_CSC_DISABLED }, 1357*8334SJose.Borrego@Sun.COM { "manual", SMB_SHRF_CSC_MANUAL }, 1358*8334SJose.Borrego@Sun.COM { "auto", SMB_SHRF_CSC_AUTO }, 1359*8334SJose.Borrego@Sun.COM { "vdo", SMB_SHRF_CSC_VDO } 1360*8334SJose.Borrego@Sun.COM }; 1361*8334SJose.Borrego@Sun.COM 1362*8334SJose.Borrego@Sun.COM char buf[SMB_SHR_CSC_BUFSZ]; 1363*8334SJose.Borrego@Sun.COM smb_ctxbuf_t ctx; 1364*8334SJose.Borrego@Sun.COM int i; 1365*8334SJose.Borrego@Sun.COM 1366*8334SJose.Borrego@Sun.COM for (i = 0; i < (sizeof (cscopt) / sizeof (cscopt[0])); ++i) { 1367*8334SJose.Borrego@Sun.COM if (strcasecmp(value, cscopt[i].value) == 0) { 1368*8334SJose.Borrego@Sun.COM si->shr_flags |= cscopt[i].flag; 1369*8334SJose.Borrego@Sun.COM break; 1370*8334SJose.Borrego@Sun.COM } 1371*8334SJose.Borrego@Sun.COM } 1372*8334SJose.Borrego@Sun.COM 1373*8334SJose.Borrego@Sun.COM switch (si->shr_flags & SMB_SHRF_CSC_MASK) { 1374*8334SJose.Borrego@Sun.COM case 0: 1375*8334SJose.Borrego@Sun.COM case SMB_SHRF_CSC_DISABLED: 1376*8334SJose.Borrego@Sun.COM case SMB_SHRF_CSC_MANUAL: 1377*8334SJose.Borrego@Sun.COM case SMB_SHRF_CSC_AUTO: 1378*8334SJose.Borrego@Sun.COM case SMB_SHRF_CSC_VDO: 1379*8334SJose.Borrego@Sun.COM break; 1380*8334SJose.Borrego@Sun.COM 1381*8334SJose.Borrego@Sun.COM default: 1382*8334SJose.Borrego@Sun.COM (void) smb_ctxbuf_init(&ctx, (uint8_t *)buf, SMB_SHR_CSC_BUFSZ); 1383*8334SJose.Borrego@Sun.COM 1384*8334SJose.Borrego@Sun.COM for (i = 0; i < (sizeof (cscopt) / sizeof (cscopt[0])); ++i) { 1385*8334SJose.Borrego@Sun.COM if (si->shr_flags & cscopt[i].flag) 1386*8334SJose.Borrego@Sun.COM (void) smb_ctxbuf_printf(&ctx, " %s", 1387*8334SJose.Borrego@Sun.COM cscopt[i].value); 1388*8334SJose.Borrego@Sun.COM } 1389*8334SJose.Borrego@Sun.COM 1390*8334SJose.Borrego@Sun.COM syslog(LOG_ERR, "csc option conflict:%s", buf); 1391*8334SJose.Borrego@Sun.COM break; 1392*8334SJose.Borrego@Sun.COM } 1393*8334SJose.Borrego@Sun.COM } 1394*8334SJose.Borrego@Sun.COM 1395*8334SJose.Borrego@Sun.COM /* 1396*8334SJose.Borrego@Sun.COM * looks up sharemgr for the given share (resource) and loads 1397*8334SJose.Borrego@Sun.COM * the definition into cache if lookup is successful 1398*8334SJose.Borrego@Sun.COM */ 1399*8334SJose.Borrego@Sun.COM static uint32_t 1400*8334SJose.Borrego@Sun.COM smb_shr_sa_loadbyname(char *sharename) 1401*8334SJose.Borrego@Sun.COM { 1402*8334SJose.Borrego@Sun.COM sa_handle_t handle; 1403*8334SJose.Borrego@Sun.COM sa_share_t share; 1404*8334SJose.Borrego@Sun.COM sa_resource_t resource; 1405*8334SJose.Borrego@Sun.COM uint32_t status; 1406*8334SJose.Borrego@Sun.COM 1407*8334SJose.Borrego@Sun.COM if ((handle = sa_init(SA_INIT_SHARE_API)) == NULL) 1408*8334SJose.Borrego@Sun.COM return (NERR_InternalError); 1409*8334SJose.Borrego@Sun.COM 1410*8334SJose.Borrego@Sun.COM resource = sa_find_resource(handle, sharename); 1411*8334SJose.Borrego@Sun.COM if (resource == NULL) { 1412*8334SJose.Borrego@Sun.COM sa_fini(handle); 1413*8334SJose.Borrego@Sun.COM return (NERR_NetNameNotFound); 1414*8334SJose.Borrego@Sun.COM } 1415*8334SJose.Borrego@Sun.COM 1416*8334SJose.Borrego@Sun.COM share = sa_get_resource_parent(resource); 1417*8334SJose.Borrego@Sun.COM if (share == NULL) { 1418*8334SJose.Borrego@Sun.COM sa_fini(handle); 1419*8334SJose.Borrego@Sun.COM return (NERR_InternalError); 1420*8334SJose.Borrego@Sun.COM } 1421*8334SJose.Borrego@Sun.COM 1422*8334SJose.Borrego@Sun.COM status = smb_shr_sa_load(share, resource); 1423*8334SJose.Borrego@Sun.COM 1424*8334SJose.Borrego@Sun.COM sa_fini(handle); 1425*8334SJose.Borrego@Sun.COM return (status); 1426*8334SJose.Borrego@Sun.COM } 1427*8334SJose.Borrego@Sun.COM 1428*8334SJose.Borrego@Sun.COM /* 14297348SJose.Borrego@Sun.COM * ============================================ 14307348SJose.Borrego@Sun.COM * Share publishing functions 14317961SNatalie.Li@Sun.COM * 14327961SNatalie.Li@Sun.COM * All the functions are private 14337348SJose.Borrego@Sun.COM * ============================================ 14347348SJose.Borrego@Sun.COM */ 14357348SJose.Borrego@Sun.COM 14367961SNatalie.Li@Sun.COM static void 14377961SNatalie.Li@Sun.COM smb_shr_publish(const char *sharename, const char *container) 14387961SNatalie.Li@Sun.COM { 14397961SNatalie.Li@Sun.COM smb_shr_publisher_queue(sharename, container, SMB_SHR_PUBLISH); 14407961SNatalie.Li@Sun.COM } 14417961SNatalie.Li@Sun.COM 14427961SNatalie.Li@Sun.COM static void 14437961SNatalie.Li@Sun.COM smb_shr_unpublish(const char *sharename, const char *container) 14447961SNatalie.Li@Sun.COM { 14457961SNatalie.Li@Sun.COM smb_shr_publisher_queue(sharename, container, SMB_SHR_UNPUBLISH); 14467961SNatalie.Li@Sun.COM } 14477961SNatalie.Li@Sun.COM 14487348SJose.Borrego@Sun.COM /* 14497961SNatalie.Li@Sun.COM * In domain mode, put a share on the publisher queue. 14507961SNatalie.Li@Sun.COM * This is a no-op if the smb service is in Workgroup mode. 14517348SJose.Borrego@Sun.COM */ 14527348SJose.Borrego@Sun.COM static void 14537961SNatalie.Li@Sun.COM smb_shr_publisher_queue(const char *sharename, const char *container, char op) 14547348SJose.Borrego@Sun.COM { 14557348SJose.Borrego@Sun.COM smb_shr_pitem_t *item = NULL; 14567348SJose.Borrego@Sun.COM 14577348SJose.Borrego@Sun.COM if (container == NULL || *container == '\0') 14587348SJose.Borrego@Sun.COM return; 14597348SJose.Borrego@Sun.COM 14607961SNatalie.Li@Sun.COM if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN) 14617961SNatalie.Li@Sun.COM return; 14627961SNatalie.Li@Sun.COM 14637348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 14647348SJose.Borrego@Sun.COM switch (ad_queue.spq_state) { 14657348SJose.Borrego@Sun.COM case SMB_SHR_PQS_READY: 14667348SJose.Borrego@Sun.COM case SMB_SHR_PQS_PUBLISHING: 14677348SJose.Borrego@Sun.COM break; 14687348SJose.Borrego@Sun.COM default: 14697348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 14707348SJose.Borrego@Sun.COM return; 14717348SJose.Borrego@Sun.COM } 14727348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 14737348SJose.Borrego@Sun.COM 14747961SNatalie.Li@Sun.COM if ((item = malloc(sizeof (smb_shr_pitem_t))) == NULL) 14757348SJose.Borrego@Sun.COM return; 14767348SJose.Borrego@Sun.COM 14777348SJose.Borrego@Sun.COM item->spi_op = op; 14787348SJose.Borrego@Sun.COM (void) strlcpy(item->spi_name, sharename, sizeof (item->spi_name)); 14797348SJose.Borrego@Sun.COM (void) strlcpy(item->spi_container, container, 14807348SJose.Borrego@Sun.COM sizeof (item->spi_container)); 14817348SJose.Borrego@Sun.COM 14827348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 14837348SJose.Borrego@Sun.COM list_insert_tail(&ad_queue.spq_list, item); 14847348SJose.Borrego@Sun.COM (void) cond_signal(&ad_queue.spq_cv); 14857348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 14867348SJose.Borrego@Sun.COM } 14877348SJose.Borrego@Sun.COM 14887961SNatalie.Li@Sun.COM /* 14897961SNatalie.Li@Sun.COM * Publishing won't be activated if the smb service is running in 14907961SNatalie.Li@Sun.COM * Workgroup mode. 14917961SNatalie.Li@Sun.COM */ 14927348SJose.Borrego@Sun.COM static int 14937348SJose.Borrego@Sun.COM smb_shr_publisher_start(void) 14947348SJose.Borrego@Sun.COM { 14957961SNatalie.Li@Sun.COM pthread_t publish_thr; 14967348SJose.Borrego@Sun.COM pthread_attr_t tattr; 14977348SJose.Borrego@Sun.COM int rc; 14987348SJose.Borrego@Sun.COM 14997961SNatalie.Li@Sun.COM if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN) 15007961SNatalie.Li@Sun.COM return (0); 15017961SNatalie.Li@Sun.COM 15027348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 15037348SJose.Borrego@Sun.COM if (ad_queue.spq_state != SMB_SHR_PQS_NOQUEUE) { 15047348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 15057348SJose.Borrego@Sun.COM errno = EINVAL; 15067348SJose.Borrego@Sun.COM return (-1); 15077348SJose.Borrego@Sun.COM } 15087348SJose.Borrego@Sun.COM 15097348SJose.Borrego@Sun.COM list_create(&ad_queue.spq_list, sizeof (smb_shr_pitem_t), 15107348SJose.Borrego@Sun.COM offsetof(smb_shr_pitem_t, spi_lnd)); 15117348SJose.Borrego@Sun.COM ad_queue.spq_state = SMB_SHR_PQS_READY; 15127348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 15137348SJose.Borrego@Sun.COM 15147348SJose.Borrego@Sun.COM (void) pthread_attr_init(&tattr); 15157348SJose.Borrego@Sun.COM (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); 15167961SNatalie.Li@Sun.COM rc = pthread_create(&publish_thr, &tattr, smb_shr_publisher, 0); 15177348SJose.Borrego@Sun.COM (void) pthread_attr_destroy(&tattr); 15187348SJose.Borrego@Sun.COM 15197348SJose.Borrego@Sun.COM return (rc); 15207348SJose.Borrego@Sun.COM } 15217348SJose.Borrego@Sun.COM 15227348SJose.Borrego@Sun.COM static void 15237348SJose.Borrego@Sun.COM smb_shr_publisher_stop(void) 15247348SJose.Borrego@Sun.COM { 15257961SNatalie.Li@Sun.COM if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN) 15267961SNatalie.Li@Sun.COM return; 15277961SNatalie.Li@Sun.COM 15287348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 15297348SJose.Borrego@Sun.COM switch (ad_queue.spq_state) { 15307348SJose.Borrego@Sun.COM case SMB_SHR_PQS_READY: 15317348SJose.Borrego@Sun.COM case SMB_SHR_PQS_PUBLISHING: 15327348SJose.Borrego@Sun.COM ad_queue.spq_state = SMB_SHR_PQS_STOPPING; 15337348SJose.Borrego@Sun.COM (void) cond_signal(&ad_queue.spq_cv); 15347348SJose.Borrego@Sun.COM break; 15357348SJose.Borrego@Sun.COM default: 15367348SJose.Borrego@Sun.COM break; 15377348SJose.Borrego@Sun.COM } 15387348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 15397348SJose.Borrego@Sun.COM } 15407348SJose.Borrego@Sun.COM 15417348SJose.Borrego@Sun.COM /* 15427961SNatalie.Li@Sun.COM * This is the publisher daemon thread. While running, the thread waits 15437961SNatalie.Li@Sun.COM * on a conditional variable until notified that a share needs to be 15447961SNatalie.Li@Sun.COM * [un]published or that the thread should be terminated. 15457961SNatalie.Li@Sun.COM * 15467961SNatalie.Li@Sun.COM * Entries may remain in the outgoing queue if the Active Directory 15477961SNatalie.Li@Sun.COM * service is inaccessible, in which case the thread wakes up every 60 15487961SNatalie.Li@Sun.COM * seconds to retry. 15497348SJose.Borrego@Sun.COM */ 15507348SJose.Borrego@Sun.COM /*ARGSUSED*/ 15517348SJose.Borrego@Sun.COM static void * 15527348SJose.Borrego@Sun.COM smb_shr_publisher(void *arg) 15537348SJose.Borrego@Sun.COM { 15547348SJose.Borrego@Sun.COM smb_ads_handle_t *ah; 15557348SJose.Borrego@Sun.COM smb_shr_pitem_t *shr; 15567348SJose.Borrego@Sun.COM list_t publist; 15577961SNatalie.Li@Sun.COM timestruc_t pubretry; 15587348SJose.Borrego@Sun.COM char hostname[MAXHOSTNAMELEN]; 15597348SJose.Borrego@Sun.COM 15607348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 15617961SNatalie.Li@Sun.COM if (ad_queue.spq_state != SMB_SHR_PQS_READY) { 15627348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 15637348SJose.Borrego@Sun.COM return (NULL); 15647348SJose.Borrego@Sun.COM } 15657961SNatalie.Li@Sun.COM ad_queue.spq_state = SMB_SHR_PQS_PUBLISHING; 15667348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 15677348SJose.Borrego@Sun.COM 15687348SJose.Borrego@Sun.COM (void) smb_gethostname(hostname, MAXHOSTNAMELEN, 0); 15697961SNatalie.Li@Sun.COM 15707348SJose.Borrego@Sun.COM list_create(&publist, sizeof (smb_shr_pitem_t), 15717348SJose.Borrego@Sun.COM offsetof(smb_shr_pitem_t, spi_lnd)); 15727348SJose.Borrego@Sun.COM 15737348SJose.Borrego@Sun.COM for (;;) { 15747348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 15757961SNatalie.Li@Sun.COM 15767961SNatalie.Li@Sun.COM while (list_is_empty(&ad_queue.spq_list) && 15777961SNatalie.Li@Sun.COM (ad_queue.spq_state == SMB_SHR_PQS_PUBLISHING)) { 15787961SNatalie.Li@Sun.COM if (list_is_empty(&publist)) { 15797961SNatalie.Li@Sun.COM (void) cond_wait(&ad_queue.spq_cv, 15807961SNatalie.Li@Sun.COM &ad_queue.spq_mtx); 15817961SNatalie.Li@Sun.COM } else { 15827961SNatalie.Li@Sun.COM pubretry.tv_sec = 60; 15837961SNatalie.Li@Sun.COM pubretry.tv_nsec = 0; 15847961SNatalie.Li@Sun.COM (void) cond_reltimedwait(&ad_queue.spq_cv, 15857961SNatalie.Li@Sun.COM &ad_queue.spq_mtx, &pubretry); 15867961SNatalie.Li@Sun.COM break; 15877961SNatalie.Li@Sun.COM } 15887961SNatalie.Li@Sun.COM } 15897348SJose.Borrego@Sun.COM 15907348SJose.Borrego@Sun.COM if (ad_queue.spq_state != SMB_SHR_PQS_PUBLISHING) { 15917348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 15927348SJose.Borrego@Sun.COM break; 15937348SJose.Borrego@Sun.COM } 15947348SJose.Borrego@Sun.COM 15957348SJose.Borrego@Sun.COM /* 15967961SNatalie.Li@Sun.COM * Transfer queued items to the local list so that 15977961SNatalie.Li@Sun.COM * the mutex can be released. 15987348SJose.Borrego@Sun.COM */ 15997348SJose.Borrego@Sun.COM while ((shr = list_head(&ad_queue.spq_list)) != NULL) { 16007348SJose.Borrego@Sun.COM list_remove(&ad_queue.spq_list, shr); 16017348SJose.Borrego@Sun.COM list_insert_tail(&publist, shr); 16027348SJose.Borrego@Sun.COM } 16037961SNatalie.Li@Sun.COM 16047348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 16057348SJose.Borrego@Sun.COM 16067961SNatalie.Li@Sun.COM if ((ah = smb_ads_open()) != NULL) { 16077961SNatalie.Li@Sun.COM smb_shr_publisher_send(ah, &publist, hostname); 16087961SNatalie.Li@Sun.COM smb_ads_close(ah); 16097961SNatalie.Li@Sun.COM } 16107348SJose.Borrego@Sun.COM } 16117348SJose.Borrego@Sun.COM 16127348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 16137961SNatalie.Li@Sun.COM smb_shr_publisher_flush(&ad_queue.spq_list); 16147348SJose.Borrego@Sun.COM list_destroy(&ad_queue.spq_list); 16157348SJose.Borrego@Sun.COM ad_queue.spq_state = SMB_SHR_PQS_NOQUEUE; 16167348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 16177348SJose.Borrego@Sun.COM 16187961SNatalie.Li@Sun.COM smb_shr_publisher_flush(&publist); 16197348SJose.Borrego@Sun.COM list_destroy(&publist); 16207348SJose.Borrego@Sun.COM return (NULL); 16217348SJose.Borrego@Sun.COM } 16227348SJose.Borrego@Sun.COM 16237348SJose.Borrego@Sun.COM /* 16247961SNatalie.Li@Sun.COM * Remove items from the specified queue and [un]publish them. 16257348SJose.Borrego@Sun.COM */ 16267348SJose.Borrego@Sun.COM static void 16277348SJose.Borrego@Sun.COM smb_shr_publisher_send(smb_ads_handle_t *ah, list_t *publist, const char *host) 16287348SJose.Borrego@Sun.COM { 16297348SJose.Borrego@Sun.COM smb_shr_pitem_t *shr; 16307348SJose.Borrego@Sun.COM 16317348SJose.Borrego@Sun.COM while ((shr = list_head(publist)) != NULL) { 16327961SNatalie.Li@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 16337961SNatalie.Li@Sun.COM if (ad_queue.spq_state != SMB_SHR_PQS_PUBLISHING) { 16347348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 16357961SNatalie.Li@Sun.COM return; 16367961SNatalie.Li@Sun.COM } 16377961SNatalie.Li@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 16387348SJose.Borrego@Sun.COM 16397961SNatalie.Li@Sun.COM list_remove(publist, shr); 16407961SNatalie.Li@Sun.COM 16417961SNatalie.Li@Sun.COM if (shr->spi_op == SMB_SHR_PUBLISH) 16427961SNatalie.Li@Sun.COM (void) smb_ads_publish_share(ah, shr->spi_name, 16437961SNatalie.Li@Sun.COM NULL, shr->spi_container, host); 16447961SNatalie.Li@Sun.COM else 16457961SNatalie.Li@Sun.COM (void) smb_ads_remove_share(ah, shr->spi_name, 16467961SNatalie.Li@Sun.COM NULL, shr->spi_container, host); 16477961SNatalie.Li@Sun.COM 16487348SJose.Borrego@Sun.COM free(shr); 16497348SJose.Borrego@Sun.COM } 16507348SJose.Borrego@Sun.COM } 16517961SNatalie.Li@Sun.COM 16527961SNatalie.Li@Sun.COM /* 16537961SNatalie.Li@Sun.COM * Flush all remaining items from the specified list/queue. 16547961SNatalie.Li@Sun.COM */ 16557961SNatalie.Li@Sun.COM static void 16567961SNatalie.Li@Sun.COM smb_shr_publisher_flush(list_t *lst) 16577961SNatalie.Li@Sun.COM { 16587961SNatalie.Li@Sun.COM smb_shr_pitem_t *shr; 16597961SNatalie.Li@Sun.COM 16607961SNatalie.Li@Sun.COM while ((shr = list_head(lst)) != NULL) { 16617961SNatalie.Li@Sun.COM list_remove(lst, shr); 16627961SNatalie.Li@Sun.COM free(shr); 16637961SNatalie.Li@Sun.COM } 16647961SNatalie.Li@Sun.COM } 1665