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 /* 27*7961SNatalie.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> 38*7961SNatalie.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> 47*7961SNatalie.Li@Sun.COM #include <smbsrv/nterror.h> 487052Samw 49*7961SNatalie.Li@Sun.COM #define SMB_SHR_ERROR_THRESHOLD 3 507052Samw 517348SJose.Borrego@Sun.COM /* 527348SJose.Borrego@Sun.COM * Cache functions and vars 537348SJose.Borrego@Sun.COM */ 54*7961SNatalie.Li@Sun.COM #define SMB_SHR_HTAB_SZ 1024 557052Samw 56*7961SNatalie.Li@Sun.COM /* 57*7961SNatalie.Li@Sun.COM * Cache handle 58*7961SNatalie.Li@Sun.COM * 59*7961SNatalie.Li@Sun.COM * Shares cache is a hash table. 60*7961SNatalie.Li@Sun.COM * 61*7961SNatalie.Li@Sun.COM * sc_cache pointer to hash table handle 62*7961SNatalie.Li@Sun.COM * sc_cache_lck synchronize cache read/write accesses 63*7961SNatalie.Li@Sun.COM * sc_state cache state machine values 64*7961SNatalie.Li@Sun.COM * sc_nops number of inflight/pending cache operations 65*7961SNatalie.Li@Sun.COM * sc_mtx protects handle fields 66*7961SNatalie.Li@Sun.COM */ 67*7961SNatalie.Li@Sun.COM typedef struct smb_shr_cache { 68*7961SNatalie.Li@Sun.COM HT_HANDLE *sc_cache; 69*7961SNatalie.Li@Sun.COM rwlock_t sc_cache_lck; 70*7961SNatalie.Li@Sun.COM mutex_t sc_mtx; 71*7961SNatalie.Li@Sun.COM cond_t sc_cv; 72*7961SNatalie.Li@Sun.COM uint32_t sc_state; 73*7961SNatalie.Li@Sun.COM uint32_t sc_nops; 74*7961SNatalie.Li@Sun.COM } smb_shr_cache_t; 75*7961SNatalie.Li@Sun.COM 76*7961SNatalie.Li@Sun.COM /* 77*7961SNatalie.Li@Sun.COM * Cache states 78*7961SNatalie.Li@Sun.COM */ 79*7961SNatalie.Li@Sun.COM #define SMB_SHR_CACHE_STATE_NONE 0 80*7961SNatalie.Li@Sun.COM #define SMB_SHR_CACHE_STATE_CREATED 1 81*7961SNatalie.Li@Sun.COM #define SMB_SHR_CACHE_STATE_DESTROYING 2 82*7961SNatalie.Li@Sun.COM 83*7961SNatalie.Li@Sun.COM /* 84*7961SNatalie.Li@Sun.COM * Cache lock modes 85*7961SNatalie.Li@Sun.COM */ 86*7961SNatalie.Li@Sun.COM #define SMB_SHR_CACHE_RDLOCK 0 87*7961SNatalie.Li@Sun.COM #define SMB_SHR_CACHE_WRLOCK 1 88*7961SNatalie.Li@Sun.COM 89*7961SNatalie.Li@Sun.COM static smb_shr_cache_t smb_shr_cache; 907052Samw 917052Samw static uint32_t smb_shr_cache_create(void); 927348SJose.Borrego@Sun.COM static void smb_shr_cache_destroy(void); 93*7961SNatalie.Li@Sun.COM static uint32_t smb_shr_cache_lock(int); 94*7961SNatalie.Li@Sun.COM static void smb_shr_cache_unlock(void); 95*7961SNatalie.Li@Sun.COM static int smb_shr_cache_count(void); 96*7961SNatalie.Li@Sun.COM static smb_share_t *smb_shr_cache_iterate(smb_shriter_t *); 97*7961SNatalie.Li@Sun.COM 98*7961SNatalie.Li@Sun.COM static smb_share_t *smb_shr_cache_findent(char *); 997348SJose.Borrego@Sun.COM static uint32_t smb_shr_cache_addent(smb_share_t *); 1007348SJose.Borrego@Sun.COM static void smb_shr_cache_delent(char *); 1017348SJose.Borrego@Sun.COM static void smb_shr_cache_freent(HT_ITEM *); 1027052Samw 1037348SJose.Borrego@Sun.COM /* 1047348SJose.Borrego@Sun.COM * sharemgr functions 1057348SJose.Borrego@Sun.COM */ 106*7961SNatalie.Li@Sun.COM static void *smb_shr_sa_loadall(void *); 107*7961SNatalie.Li@Sun.COM static void smb_shr_sa_loadgrp(sa_group_t); 108*7961SNatalie.Li@Sun.COM static uint32_t smb_shr_sa_load(sa_share_t, sa_resource_t); 109*7961SNatalie.Li@Sun.COM static uint32_t smb_shr_sa_get(sa_share_t, sa_resource_t, smb_share_t *); 1107052Samw 1117052Samw /* 1127348SJose.Borrego@Sun.COM * share publishing 1137348SJose.Borrego@Sun.COM */ 1147348SJose.Borrego@Sun.COM #define SMB_SHR_PUBLISH 0 1157348SJose.Borrego@Sun.COM #define SMB_SHR_UNPUBLISH 1 1167348SJose.Borrego@Sun.COM 1177348SJose.Borrego@Sun.COM typedef struct smb_shr_pitem { 1187348SJose.Borrego@Sun.COM list_node_t spi_lnd; 1197348SJose.Borrego@Sun.COM char spi_name[MAXNAMELEN]; 1207348SJose.Borrego@Sun.COM char spi_container[MAXPATHLEN]; 1217348SJose.Borrego@Sun.COM char spi_op; 1227348SJose.Borrego@Sun.COM } smb_shr_pitem_t; 1237348SJose.Borrego@Sun.COM 1247348SJose.Borrego@Sun.COM /* 1257348SJose.Borrego@Sun.COM * publish queue states 1267348SJose.Borrego@Sun.COM */ 1277348SJose.Borrego@Sun.COM #define SMB_SHR_PQS_NOQUEUE 0 1287348SJose.Borrego@Sun.COM #define SMB_SHR_PQS_READY 1 /* the queue is ready */ 1297348SJose.Borrego@Sun.COM #define SMB_SHR_PQS_PUBLISHING 2 /* publisher thread is running */ 1307348SJose.Borrego@Sun.COM #define SMB_SHR_PQS_STOPPING 3 1317348SJose.Borrego@Sun.COM 1327348SJose.Borrego@Sun.COM /* 1337348SJose.Borrego@Sun.COM * share publishing queue 1347348SJose.Borrego@Sun.COM */ 1357348SJose.Borrego@Sun.COM typedef struct smb_shr_pqueue { 1367348SJose.Borrego@Sun.COM list_t spq_list; 1377348SJose.Borrego@Sun.COM mutex_t spq_mtx; 1387348SJose.Borrego@Sun.COM cond_t spq_cv; 1397348SJose.Borrego@Sun.COM uint32_t spq_state; 1407348SJose.Borrego@Sun.COM } smb_shr_pqueue_t; 1417348SJose.Borrego@Sun.COM 1427348SJose.Borrego@Sun.COM static smb_shr_pqueue_t ad_queue; 1437348SJose.Borrego@Sun.COM 1447348SJose.Borrego@Sun.COM static int smb_shr_publisher_start(void); 1457348SJose.Borrego@Sun.COM static void smb_shr_publisher_stop(void); 1467348SJose.Borrego@Sun.COM static void smb_shr_publisher_send(smb_ads_handle_t *, list_t *, const char *); 147*7961SNatalie.Li@Sun.COM static void smb_shr_publisher_queue(const char *, const char *, char); 1487348SJose.Borrego@Sun.COM static void *smb_shr_publisher(void *); 149*7961SNatalie.Li@Sun.COM static void smb_shr_publisher_flush(list_t *); 150*7961SNatalie.Li@Sun.COM static void smb_shr_publish(const char *, const char *); 151*7961SNatalie.Li@Sun.COM static void smb_shr_unpublish(const char *, const char *); 1527348SJose.Borrego@Sun.COM 1537348SJose.Borrego@Sun.COM /* 154*7961SNatalie.Li@Sun.COM * Utility/helper functions 155*7961SNatalie.Li@Sun.COM */ 156*7961SNatalie.Li@Sun.COM static uint32_t smb_shr_addipc(void); 157*7961SNatalie.Li@Sun.COM static void smb_shr_set_oemname(smb_share_t *); 158*7961SNatalie.Li@Sun.COM 159*7961SNatalie.Li@Sun.COM /* 1607348SJose.Borrego@Sun.COM * Starts the publisher thread and another thread which 1617348SJose.Borrego@Sun.COM * populates the share cache by share information stored 1627348SJose.Borrego@Sun.COM * by sharemgr 1637052Samw */ 1647052Samw int 1657052Samw smb_shr_start(void) 1667052Samw { 167*7961SNatalie.Li@Sun.COM pthread_t load_thr; 1687348SJose.Borrego@Sun.COM pthread_attr_t tattr; 1697052Samw int rc; 1707052Samw 1717348SJose.Borrego@Sun.COM if ((rc = smb_shr_publisher_start()) != 0) 1727348SJose.Borrego@Sun.COM return (rc); 1737052Samw 174*7961SNatalie.Li@Sun.COM if (smb_shr_cache_create() != NERR_Success) 175*7961SNatalie.Li@Sun.COM return (ENOMEM); 176*7961SNatalie.Li@Sun.COM 177*7961SNatalie.Li@Sun.COM if (smb_shr_addipc() != NERR_Success) 178*7961SNatalie.Li@Sun.COM return (ENOMEM); 179*7961SNatalie.Li@Sun.COM 1807348SJose.Borrego@Sun.COM (void) pthread_attr_init(&tattr); 1817348SJose.Borrego@Sun.COM (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); 182*7961SNatalie.Li@Sun.COM rc = pthread_create(&load_thr, &tattr, smb_shr_sa_loadall, 0); 1837348SJose.Borrego@Sun.COM (void) pthread_attr_destroy(&tattr); 1847052Samw 1857052Samw return (rc); 1867052Samw } 1877052Samw 1887052Samw void 1897052Samw smb_shr_stop(void) 1907052Samw { 1917348SJose.Borrego@Sun.COM smb_shr_cache_destroy(); 1927348SJose.Borrego@Sun.COM smb_shr_publisher_stop(); 1937052Samw } 1947052Samw 1957052Samw /* 1967348SJose.Borrego@Sun.COM * Return the total number of shares 1977052Samw */ 1987052Samw int 1997052Samw smb_shr_count(void) 2007052Samw { 201*7961SNatalie.Li@Sun.COM int n_shares = 0; 2027052Samw 203*7961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) { 204*7961SNatalie.Li@Sun.COM n_shares = smb_shr_cache_count(); 205*7961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 206*7961SNatalie.Li@Sun.COM } 2077052Samw 2087052Samw return (n_shares); 2097052Samw } 2107052Samw 2117052Samw /* 2127052Samw * smb_shr_iterinit 2137052Samw * 2147348SJose.Borrego@Sun.COM * Initialize given iterator for traversing hash table. 2157052Samw */ 2167052Samw void 2177348SJose.Borrego@Sun.COM smb_shr_iterinit(smb_shriter_t *shi) 2187052Samw { 2197052Samw bzero(shi, sizeof (smb_shriter_t)); 2207348SJose.Borrego@Sun.COM shi->si_first = B_TRUE; 2217052Samw } 2227052Samw 2237052Samw /* 2247052Samw * smb_shr_iterate 2257052Samw * 2267052Samw * Iterate on the shares in the hash table. The iterator must be initialized 2277052Samw * before the first iteration. On subsequent calls, the iterator must be 2287052Samw * passed unchanged. 2297052Samw * 2307052Samw * Returns NULL on failure or when all shares are visited, otherwise 2317052Samw * returns information of visited share. 2327052Samw */ 2337052Samw smb_share_t * 2347052Samw smb_shr_iterate(smb_shriter_t *shi) 2357052Samw { 2367348SJose.Borrego@Sun.COM smb_share_t *share = NULL; 237*7961SNatalie.Li@Sun.COM smb_share_t *cached_si; 2387052Samw 239*7961SNatalie.Li@Sun.COM if (shi == NULL) 2407052Samw return (NULL); 2417052Samw 242*7961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) { 243*7961SNatalie.Li@Sun.COM if ((cached_si = smb_shr_cache_iterate(shi)) != NULL) { 244*7961SNatalie.Li@Sun.COM share = &shi->si_share; 245*7961SNatalie.Li@Sun.COM bcopy(cached_si, share, sizeof (smb_share_t)); 246*7961SNatalie.Li@Sun.COM } 247*7961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 2487052Samw } 2497052Samw 2507348SJose.Borrego@Sun.COM return (share); 2517052Samw } 2527052Samw 2537052Samw /* 254*7961SNatalie.Li@Sun.COM * Adds the given share to cache, publishes the share in ADS 255*7961SNatalie.Li@Sun.COM * if it has an AD container, calls kernel to take a hold on 256*7961SNatalie.Li@Sun.COM * the shared file system. If it can't take a hold on the 257*7961SNatalie.Li@Sun.COM * shared file system, it's either because shared directory 258*7961SNatalie.Li@Sun.COM * does not exist or some other error has occurred, in any 259*7961SNatalie.Li@Sun.COM * case the share is removed from the cache. 2607052Samw * 261*7961SNatalie.Li@Sun.COM * If the specified share is an autohome share which already 262*7961SNatalie.Li@Sun.COM * exists in the cache, just increments the reference count. 2637052Samw */ 2647052Samw uint32_t 265*7961SNatalie.Li@Sun.COM smb_shr_add(smb_share_t *si) 2667052Samw { 267*7961SNatalie.Li@Sun.COM smb_share_t *cached_si; 268*7961SNatalie.Li@Sun.COM uint32_t status; 2697348SJose.Borrego@Sun.COM int rc; 2707052Samw 2717348SJose.Borrego@Sun.COM assert(si != NULL); 2727052Samw 2737348SJose.Borrego@Sun.COM if (!smb_shr_chkname(si->shr_name)) 2747348SJose.Borrego@Sun.COM return (ERROR_INVALID_NAME); 2757052Samw 276*7961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success) 277*7961SNatalie.Li@Sun.COM return (NERR_InternalError); 2787052Samw 279*7961SNatalie.Li@Sun.COM cached_si = smb_shr_cache_findent(si->shr_name); 280*7961SNatalie.Li@Sun.COM if (cached_si) { 281*7961SNatalie.Li@Sun.COM if (si->shr_flags & SMB_SHRF_AUTOHOME) { 282*7961SNatalie.Li@Sun.COM cached_si->shr_refcnt++; 283*7961SNatalie.Li@Sun.COM status = NERR_Success; 284*7961SNatalie.Li@Sun.COM } else { 285*7961SNatalie.Li@Sun.COM status = NERR_DuplicateShare; 286*7961SNatalie.Li@Sun.COM } 287*7961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 2887052Samw return (status); 2897052Samw } 2907052Samw 291*7961SNatalie.Li@Sun.COM if ((status = smb_shr_cache_addent(si)) != NERR_Success) { 292*7961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 293*7961SNatalie.Li@Sun.COM return (status); 294*7961SNatalie.Li@Sun.COM } 295*7961SNatalie.Li@Sun.COM 296*7961SNatalie.Li@Sun.COM /* don't hold the lock across door call */ 297*7961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 298*7961SNatalie.Li@Sun.COM 299*7961SNatalie.Li@Sun.COM /* call kernel to take a hold on the shared file system */ 3007588Samw@Sun.COM rc = mlsvc_set_share(SMB_SHROP_ADD, si->shr_path, si->shr_name); 3017348SJose.Borrego@Sun.COM 3027348SJose.Borrego@Sun.COM if (rc == 0) { 303*7961SNatalie.Li@Sun.COM smb_shr_publish(si->shr_name, si->shr_container); 304*7961SNatalie.Li@Sun.COM return (NERR_Success); 3057052Samw } 3067052Samw 307*7961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) == NERR_Success) { 308*7961SNatalie.Li@Sun.COM smb_shr_cache_delent(si->shr_name); 309*7961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 310*7961SNatalie.Li@Sun.COM } 3117052Samw 3127052Samw /* 3137348SJose.Borrego@Sun.COM * rc == ENOENT means the shared directory doesn't exist 3147052Samw */ 3157348SJose.Borrego@Sun.COM return ((rc == ENOENT) ? NERR_UnknownDevDir : NERR_InternalError); 3167052Samw } 3177052Samw 3187052Samw /* 319*7961SNatalie.Li@Sun.COM * Removes the specified share from cache, removes it from AD 320*7961SNatalie.Li@Sun.COM * if it has an AD container, and calls the kernel to release 321*7961SNatalie.Li@Sun.COM * the hold on the shared file system. 3227052Samw * 323*7961SNatalie.Li@Sun.COM * If this is an autohome share then decrement the reference 324*7961SNatalie.Li@Sun.COM * count. If it reaches 0 then it proceeds with removing steps. 3257052Samw */ 3267348SJose.Borrego@Sun.COM uint32_t 327*7961SNatalie.Li@Sun.COM smb_shr_remove(char *sharename) 3287052Samw { 329*7961SNatalie.Li@Sun.COM smb_share_t *si; 330*7961SNatalie.Li@Sun.COM char path[MAXPATHLEN]; 331*7961SNatalie.Li@Sun.COM char container[MAXPATHLEN]; 3327348SJose.Borrego@Sun.COM 3337348SJose.Borrego@Sun.COM assert(sharename != NULL); 3347348SJose.Borrego@Sun.COM 335*7961SNatalie.Li@Sun.COM if (!smb_shr_chkname(sharename)) 336*7961SNatalie.Li@Sun.COM return (ERROR_INVALID_NAME); 3377052Samw 338*7961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success) 339*7961SNatalie.Li@Sun.COM return (NERR_InternalError); 340*7961SNatalie.Li@Sun.COM 341*7961SNatalie.Li@Sun.COM if ((si = smb_shr_cache_findent(sharename)) == NULL) { 342*7961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 343*7961SNatalie.Li@Sun.COM return (NERR_NetNameNotFound); 344*7961SNatalie.Li@Sun.COM } 3457348SJose.Borrego@Sun.COM 346*7961SNatalie.Li@Sun.COM if (si->shr_type & STYPE_IPC) { 347*7961SNatalie.Li@Sun.COM /* IPC$ share cannot be removed */ 348*7961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 349*7961SNatalie.Li@Sun.COM return (ERROR_ACCESS_DENIED); 350*7961SNatalie.Li@Sun.COM } 351*7961SNatalie.Li@Sun.COM 352*7961SNatalie.Li@Sun.COM if (si->shr_flags & SMB_SHRF_AUTOHOME) { 353*7961SNatalie.Li@Sun.COM if ((--si->shr_refcnt) > 0) { 354*7961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 355*7961SNatalie.Li@Sun.COM return (NERR_Success); 3567348SJose.Borrego@Sun.COM } 3577052Samw } 3587052Samw 359*7961SNatalie.Li@Sun.COM (void) strlcpy(path, si->shr_path, sizeof (path)); 360*7961SNatalie.Li@Sun.COM (void) strlcpy(container, si->shr_container, sizeof (container)); 361*7961SNatalie.Li@Sun.COM smb_shr_cache_delent(sharename); 362*7961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 3637348SJose.Borrego@Sun.COM 364*7961SNatalie.Li@Sun.COM smb_shr_unpublish(sharename, container); 365*7961SNatalie.Li@Sun.COM 366*7961SNatalie.Li@Sun.COM /* call kernel to release the hold on the shared file system */ 367*7961SNatalie.Li@Sun.COM (void) mlsvc_set_share(SMB_SHROP_DELETE, path, sharename); 3687348SJose.Borrego@Sun.COM 3697052Samw return (NERR_Success); 3707052Samw } 3717052Samw 3727052Samw /* 3737052Samw * Rename a share. Check that the current name exists and the new name 3747052Samw * doesn't exist. The rename is performed by deleting the current share 3757052Samw * definition and creating a new share with the new name. 3767052Samw */ 3777052Samw uint32_t 3787348SJose.Borrego@Sun.COM smb_shr_rename(char *from_name, char *to_name) 3797052Samw { 380*7961SNatalie.Li@Sun.COM smb_share_t *from_si; 381*7961SNatalie.Li@Sun.COM smb_share_t to_si; 3827348SJose.Borrego@Sun.COM uint32_t status; 3837348SJose.Borrego@Sun.COM 3847348SJose.Borrego@Sun.COM assert((from_name != NULL) && (to_name != NULL)); 3857052Samw 3867348SJose.Borrego@Sun.COM if (!smb_shr_chkname(from_name) || !smb_shr_chkname(to_name)) 3877348SJose.Borrego@Sun.COM return (ERROR_INVALID_NAME); 3887052Samw 389*7961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success) 390*7961SNatalie.Li@Sun.COM return (NERR_InternalError); 391*7961SNatalie.Li@Sun.COM 392*7961SNatalie.Li@Sun.COM if ((from_si = smb_shr_cache_findent(from_name)) == NULL) { 393*7961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 3947052Samw return (NERR_NetNameNotFound); 395*7961SNatalie.Li@Sun.COM } 3967052Samw 397*7961SNatalie.Li@Sun.COM if (from_si->shr_type & STYPE_IPC) { 398*7961SNatalie.Li@Sun.COM /* IPC$ share cannot be renamed */ 399*7961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 400*7961SNatalie.Li@Sun.COM return (ERROR_ACCESS_DENIED); 401*7961SNatalie.Li@Sun.COM } 402*7961SNatalie.Li@Sun.COM 403*7961SNatalie.Li@Sun.COM if (smb_shr_cache_findent(to_name) != NULL) { 404*7961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 4057052Samw return (NERR_DuplicateShare); 406*7961SNatalie.Li@Sun.COM } 4077052Samw 408*7961SNatalie.Li@Sun.COM bcopy(from_si, &to_si, sizeof (smb_share_t)); 409*7961SNatalie.Li@Sun.COM (void) strlcpy(to_si.shr_name, to_name, sizeof (to_si.shr_name)); 410*7961SNatalie.Li@Sun.COM 411*7961SNatalie.Li@Sun.COM if ((status = smb_shr_cache_addent(&to_si)) != NERR_Success) { 412*7961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 4137348SJose.Borrego@Sun.COM return (status); 414*7961SNatalie.Li@Sun.COM } 4157348SJose.Borrego@Sun.COM 4167348SJose.Borrego@Sun.COM smb_shr_cache_delent(from_name); 417*7961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 418*7961SNatalie.Li@Sun.COM 419*7961SNatalie.Li@Sun.COM smb_shr_unpublish(from_name, to_si.shr_container); 420*7961SNatalie.Li@Sun.COM smb_shr_publish(to_name, to_si.shr_container); 4217348SJose.Borrego@Sun.COM 4227348SJose.Borrego@Sun.COM return (NERR_Success); 4237348SJose.Borrego@Sun.COM } 4247348SJose.Borrego@Sun.COM 4257348SJose.Borrego@Sun.COM /* 4267348SJose.Borrego@Sun.COM * Load the information for the specified share into the supplied share 4277348SJose.Borrego@Sun.COM * info structure. 4287348SJose.Borrego@Sun.COM */ 4297348SJose.Borrego@Sun.COM uint32_t 4307348SJose.Borrego@Sun.COM smb_shr_get(char *sharename, smb_share_t *si) 4317348SJose.Borrego@Sun.COM { 432*7961SNatalie.Li@Sun.COM smb_share_t *cached_si; 433*7961SNatalie.Li@Sun.COM uint32_t status = NERR_NetNameNotFound; 4347348SJose.Borrego@Sun.COM 435*7961SNatalie.Li@Sun.COM if (sharename == NULL || *sharename == '\0') 436*7961SNatalie.Li@Sun.COM return (NERR_NetNameNotFound); 4377348SJose.Borrego@Sun.COM 438*7961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) { 439*7961SNatalie.Li@Sun.COM cached_si = smb_shr_cache_findent(sharename); 440*7961SNatalie.Li@Sun.COM if (cached_si != NULL) { 441*7961SNatalie.Li@Sun.COM bcopy(cached_si, si, sizeof (smb_share_t)); 442*7961SNatalie.Li@Sun.COM status = NERR_Success; 443*7961SNatalie.Li@Sun.COM } 444*7961SNatalie.Li@Sun.COM 445*7961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 4467348SJose.Borrego@Sun.COM } 4477348SJose.Borrego@Sun.COM 448*7961SNatalie.Li@Sun.COM return (status); 4497348SJose.Borrego@Sun.COM } 4507348SJose.Borrego@Sun.COM 4517348SJose.Borrego@Sun.COM /* 4527348SJose.Borrego@Sun.COM * Modifies an existing share. Properties that can be modified are: 4537348SJose.Borrego@Sun.COM * 4547348SJose.Borrego@Sun.COM * o comment 4557348SJose.Borrego@Sun.COM * o AD container 456*7961SNatalie.Li@Sun.COM * o host access 4577348SJose.Borrego@Sun.COM */ 4587348SJose.Borrego@Sun.COM uint32_t 459*7961SNatalie.Li@Sun.COM smb_shr_modify(smb_share_t *new_si) 4607348SJose.Borrego@Sun.COM { 461*7961SNatalie.Li@Sun.COM smb_share_t *si; 4627348SJose.Borrego@Sun.COM boolean_t adc_changed = B_FALSE; 463*7961SNatalie.Li@Sun.COM char old_container[MAXPATHLEN]; 464*7961SNatalie.Li@Sun.COM uint32_t access; 4657348SJose.Borrego@Sun.COM 466*7961SNatalie.Li@Sun.COM assert(new_si != NULL); 4677348SJose.Borrego@Sun.COM 468*7961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success) 469*7961SNatalie.Li@Sun.COM return (NERR_InternalError); 4707348SJose.Borrego@Sun.COM 471*7961SNatalie.Li@Sun.COM if ((si = smb_shr_cache_findent(new_si->shr_name)) == NULL) { 472*7961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 473*7961SNatalie.Li@Sun.COM return (NERR_NetNameNotFound); 474*7961SNatalie.Li@Sun.COM } 4757348SJose.Borrego@Sun.COM 476*7961SNatalie.Li@Sun.COM if (si->shr_type & STYPE_IPC) { 477*7961SNatalie.Li@Sun.COM /* IPC$ share cannot be modified */ 478*7961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 479*7961SNatalie.Li@Sun.COM return (ERROR_ACCESS_DENIED); 4807348SJose.Borrego@Sun.COM } 4817348SJose.Borrego@Sun.COM 482*7961SNatalie.Li@Sun.COM if (strcmp(new_si->shr_cmnt, si->shr_cmnt) != 0) 483*7961SNatalie.Li@Sun.COM (void) strlcpy(si->shr_cmnt, new_si->shr_cmnt, 484*7961SNatalie.Li@Sun.COM sizeof (si->shr_cmnt)); 485*7961SNatalie.Li@Sun.COM 486*7961SNatalie.Li@Sun.COM adc_changed = (strcmp(new_si->shr_container, si->shr_container) != 0); 487*7961SNatalie.Li@Sun.COM if (adc_changed) { 488*7961SNatalie.Li@Sun.COM /* save current container - needed for unpublishing */ 489*7961SNatalie.Li@Sun.COM (void) strlcpy(old_container, si->shr_container, 490*7961SNatalie.Li@Sun.COM sizeof (old_container)); 491*7961SNatalie.Li@Sun.COM (void) strlcpy(si->shr_container, new_si->shr_container, 492*7961SNatalie.Li@Sun.COM sizeof (si->shr_container)); 4937348SJose.Borrego@Sun.COM } 4947348SJose.Borrego@Sun.COM 495*7961SNatalie.Li@Sun.COM access = (new_si->shr_flags & SMB_SHRF_ACC_ALL); 496*7961SNatalie.Li@Sun.COM si->shr_flags |= access; 497*7961SNatalie.Li@Sun.COM 498*7961SNatalie.Li@Sun.COM if (access & SMB_SHRF_ACC_NONE) 499*7961SNatalie.Li@Sun.COM (void) strlcpy(si->shr_access_none, new_si->shr_access_none, 500*7961SNatalie.Li@Sun.COM sizeof (si->shr_access_none)); 5017348SJose.Borrego@Sun.COM 502*7961SNatalie.Li@Sun.COM if (access & SMB_SHRF_ACC_RO) 503*7961SNatalie.Li@Sun.COM (void) strlcpy(si->shr_access_ro, new_si->shr_access_ro, 504*7961SNatalie.Li@Sun.COM sizeof (si->shr_access_ro)); 5057348SJose.Borrego@Sun.COM 506*7961SNatalie.Li@Sun.COM if (access & SMB_SHRF_ACC_RW) 507*7961SNatalie.Li@Sun.COM (void) strlcpy(si->shr_access_rw, new_si->shr_access_rw, 508*7961SNatalie.Li@Sun.COM sizeof (si->shr_access_rw)); 509*7961SNatalie.Li@Sun.COM 510*7961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 5117052Samw 5127348SJose.Borrego@Sun.COM if (adc_changed) { 513*7961SNatalie.Li@Sun.COM smb_shr_unpublish(new_si->shr_name, old_container); 514*7961SNatalie.Li@Sun.COM smb_shr_publish(new_si->shr_name, new_si->shr_container); 5157348SJose.Borrego@Sun.COM } 5167348SJose.Borrego@Sun.COM 5177348SJose.Borrego@Sun.COM return (NERR_Success); 5187052Samw } 5197052Samw 5207052Samw /* 5217052Samw * smb_shr_exists 5227052Samw * 5237348SJose.Borrego@Sun.COM * Returns B_TRUE if the share exists. Otherwise returns B_FALSE 5247052Samw */ 5257348SJose.Borrego@Sun.COM boolean_t 5267348SJose.Borrego@Sun.COM smb_shr_exists(char *sharename) 5277052Samw { 528*7961SNatalie.Li@Sun.COM boolean_t exists = B_FALSE; 5297348SJose.Borrego@Sun.COM 5307348SJose.Borrego@Sun.COM if (sharename == NULL || *sharename == '\0') 5317348SJose.Borrego@Sun.COM return (B_FALSE); 5327052Samw 533*7961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) { 534*7961SNatalie.Li@Sun.COM exists = (smb_shr_cache_findent(sharename) != NULL); 535*7961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 536*7961SNatalie.Li@Sun.COM } 5377348SJose.Borrego@Sun.COM 5387348SJose.Borrego@Sun.COM return (exists); 5397052Samw } 5407052Samw 5417052Samw /* 542*7961SNatalie.Li@Sun.COM * If the shared directory does not begin with a /, one will be 543*7961SNatalie.Li@Sun.COM * inserted as a prefix. If ipaddr is not zero, then also return 544*7961SNatalie.Li@Sun.COM * information about access based on the host level access lists, if 545*7961SNatalie.Li@Sun.COM * present. Also return access check if there is an IP address and 546*7961SNatalie.Li@Sun.COM * shr_accflags. 547*7961SNatalie.Li@Sun.COM * 548*7961SNatalie.Li@Sun.COM * The value of smb_chk_hostaccess is checked for an access match. 549*7961SNatalie.Li@Sun.COM * -1 is wildcard match 550*7961SNatalie.Li@Sun.COM * 0 is no match 551*7961SNatalie.Li@Sun.COM * 1 is match 552*7961SNatalie.Li@Sun.COM * 553*7961SNatalie.Li@Sun.COM * Precedence is none is checked first followed by ro then rw if 554*7961SNatalie.Li@Sun.COM * needed. If x is wildcard (< 0) then check to see if the other 555*7961SNatalie.Li@Sun.COM * values are a match. If a match, that wins. 556*7961SNatalie.Li@Sun.COM */ 557*7961SNatalie.Li@Sun.COM void 558*7961SNatalie.Li@Sun.COM smb_shr_hostaccess(smb_share_t *si, ipaddr_t ipaddr) 559*7961SNatalie.Li@Sun.COM { 560*7961SNatalie.Li@Sun.COM int acc = SMB_SHRF_ACC_OPEN; 561*7961SNatalie.Li@Sun.COM 562*7961SNatalie.Li@Sun.COM /* 563*7961SNatalie.Li@Sun.COM * Check to see if there area any share level access 564*7961SNatalie.Li@Sun.COM * restrictions. 565*7961SNatalie.Li@Sun.COM */ 566*7961SNatalie.Li@Sun.COM if (ipaddr != 0 && (si->shr_flags & SMB_SHRF_ACC_ALL) != 0) { 567*7961SNatalie.Li@Sun.COM int none = SMB_SHRF_ACC_OPEN; 568*7961SNatalie.Li@Sun.COM int rw = SMB_SHRF_ACC_OPEN; 569*7961SNatalie.Li@Sun.COM int ro = SMB_SHRF_ACC_OPEN; 570*7961SNatalie.Li@Sun.COM 571*7961SNatalie.Li@Sun.COM if (si->shr_flags & SMB_SHRF_ACC_NONE) 572*7961SNatalie.Li@Sun.COM none = smb_chk_hostaccess(ipaddr, si->shr_access_none); 573*7961SNatalie.Li@Sun.COM if (si->shr_flags & SMB_SHRF_ACC_RW) 574*7961SNatalie.Li@Sun.COM rw = smb_chk_hostaccess(ipaddr, si->shr_access_rw); 575*7961SNatalie.Li@Sun.COM if (si->shr_flags & SMB_SHRF_ACC_RO) 576*7961SNatalie.Li@Sun.COM ro = smb_chk_hostaccess(ipaddr, si->shr_access_ro); 577*7961SNatalie.Li@Sun.COM 578*7961SNatalie.Li@Sun.COM /* make first pass to get basic value */ 579*7961SNatalie.Li@Sun.COM if (none != 0) 580*7961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_NONE; 581*7961SNatalie.Li@Sun.COM else if (ro != 0) 582*7961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RO; 583*7961SNatalie.Li@Sun.COM else if (rw != 0) 584*7961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RW; 585*7961SNatalie.Li@Sun.COM 586*7961SNatalie.Li@Sun.COM /* make second pass to handle '*' case */ 587*7961SNatalie.Li@Sun.COM if (none < 0) { 588*7961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_NONE; 589*7961SNatalie.Li@Sun.COM if (ro > 0) 590*7961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RO; 591*7961SNatalie.Li@Sun.COM else if (rw > 0) 592*7961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RW; 593*7961SNatalie.Li@Sun.COM } else if (ro < 0) { 594*7961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RO; 595*7961SNatalie.Li@Sun.COM if (none > 0) 596*7961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_NONE; 597*7961SNatalie.Li@Sun.COM else if (rw > 0) 598*7961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RW; 599*7961SNatalie.Li@Sun.COM } else if (rw < 0) { 600*7961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RW; 601*7961SNatalie.Li@Sun.COM if (none > 0) 602*7961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_NONE; 603*7961SNatalie.Li@Sun.COM else if (ro > 0) 604*7961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RO; 605*7961SNatalie.Li@Sun.COM } 606*7961SNatalie.Li@Sun.COM } 607*7961SNatalie.Li@Sun.COM si->shr_access_value = acc; /* return access here */ 608*7961SNatalie.Li@Sun.COM } 609*7961SNatalie.Li@Sun.COM 610*7961SNatalie.Li@Sun.COM /* 6117052Samw * smb_shr_is_special 6127052Samw * 6137348SJose.Borrego@Sun.COM * Special share reserved for interprocess communication (IPC$) or 6147348SJose.Borrego@Sun.COM * remote administration of the server (ADMIN$). Can also refer to 6157348SJose.Borrego@Sun.COM * administrative shares such as C$, D$, E$, and so forth. 6167052Samw */ 6177052Samw int 6187348SJose.Borrego@Sun.COM smb_shr_is_special(char *sharename) 6197052Samw { 6207052Samw int len; 6217052Samw 6227348SJose.Borrego@Sun.COM if (sharename == NULL) 6237052Samw return (0); 6247052Samw 6257348SJose.Borrego@Sun.COM if ((len = strlen(sharename)) == 0) 6267052Samw return (0); 6277052Samw 6287348SJose.Borrego@Sun.COM if (sharename[len - 1] == '$') 6297052Samw return (STYPE_SPECIAL); 6307348SJose.Borrego@Sun.COM 6317348SJose.Borrego@Sun.COM return (0); 6327052Samw } 6337052Samw 6347052Samw /* 6357052Samw * smb_shr_is_restricted 6367052Samw * 6377052Samw * Check whether or not there is a restriction on a share. Restricted 6387052Samw * shares are generally STYPE_SPECIAL, for example, IPC$. All the 6397348SJose.Borrego@Sun.COM * administration share names are restricted: C$, D$ etc. Returns B_TRUE 6407348SJose.Borrego@Sun.COM * if the share is restricted. Otherwise B_FALSE is returned to indicate 6417052Samw * that there are no restrictions. 6427052Samw */ 6437348SJose.Borrego@Sun.COM boolean_t 6447348SJose.Borrego@Sun.COM smb_shr_is_restricted(char *sharename) 6457052Samw { 6467052Samw static char *restricted[] = { 6477052Samw "IPC$" 6487052Samw }; 6497052Samw 6507052Samw int i; 6517052Samw 6527348SJose.Borrego@Sun.COM if (sharename == NULL) 6537348SJose.Borrego@Sun.COM return (B_FALSE); 6547348SJose.Borrego@Sun.COM 6557052Samw for (i = 0; i < sizeof (restricted)/sizeof (restricted[0]); i++) { 6567348SJose.Borrego@Sun.COM if (utf8_strcasecmp(restricted[i], sharename) == 0) 6577348SJose.Borrego@Sun.COM return (B_TRUE); 6587052Samw } 6597052Samw 6607348SJose.Borrego@Sun.COM return (smb_shr_is_admin(sharename)); 6617052Samw } 6627052Samw 6637052Samw /* 6647052Samw * smb_shr_is_admin 6657052Samw * 6667052Samw * Check whether or not access to the share should be restricted to 6677052Samw * administrators. This is a bit of a hack because what we're doing 6687052Samw * is checking for the default admin shares: C$, D$ etc.. There are 6697052Samw * other shares that have restrictions: see smb_shr_is_restricted(). 6707052Samw * 6717348SJose.Borrego@Sun.COM * Returns B_TRUE if the shares is an admin share. Otherwise B_FALSE 6727348SJose.Borrego@Sun.COM * is returned to indicate that there are no restrictions. 6737052Samw */ 6747348SJose.Borrego@Sun.COM boolean_t 6757348SJose.Borrego@Sun.COM smb_shr_is_admin(char *sharename) 6767052Samw { 6777348SJose.Borrego@Sun.COM if (sharename == NULL) 6787348SJose.Borrego@Sun.COM return (B_FALSE); 6797052Samw 6807348SJose.Borrego@Sun.COM if (strlen(sharename) == 2 && 6817348SJose.Borrego@Sun.COM mts_isalpha(sharename[0]) && sharename[1] == '$') { 6827348SJose.Borrego@Sun.COM return (B_TRUE); 6837052Samw } 6847052Samw 6857348SJose.Borrego@Sun.COM return (B_FALSE); 6867052Samw } 6877052Samw 6887052Samw /* 6897348SJose.Borrego@Sun.COM * smb_shr_chkname 6907052Samw * 691*7961SNatalie.Li@Sun.COM * Check for invalid characters in a share name. The list of invalid 692*7961SNatalie.Li@Sun.COM * characters includes control characters and the following: 6937052Samw * 6947052Samw * " / \ [ ] : | < > + ; , ? * = 6957052Samw */ 6967348SJose.Borrego@Sun.COM boolean_t 6977348SJose.Borrego@Sun.COM smb_shr_chkname(char *sharename) 6987052Samw { 6997052Samw char *invalid = "\"/\\[]:|<>+;,?*="; 7007052Samw char *cp; 7017052Samw 7027348SJose.Borrego@Sun.COM if (sharename == NULL) 7037348SJose.Borrego@Sun.COM return (B_FALSE); 7047052Samw 7057348SJose.Borrego@Sun.COM if (strpbrk(sharename, invalid)) 7067348SJose.Borrego@Sun.COM return (B_FALSE); 7077052Samw 7087348SJose.Borrego@Sun.COM for (cp = sharename; *cp != '\0'; cp++) { 7097348SJose.Borrego@Sun.COM if (iscntrl(*cp)) 7107348SJose.Borrego@Sun.COM return (B_FALSE); 7117052Samw } 7127052Samw 7137348SJose.Borrego@Sun.COM return (B_TRUE); 7147052Samw } 7157052Samw 7167052Samw /* 7177052Samw * smb_shr_get_realpath 7187052Samw * 719*7961SNatalie.Li@Sun.COM * Derive the real path for a share from the path provided by a client. 720*7961SNatalie.Li@Sun.COM * For instance, the real path of C:\ may be /cvol or the real path of 721*7961SNatalie.Li@Sun.COM * F:\home may be /vol1/home. 7227052Samw * 723*7961SNatalie.Li@Sun.COM * clntpath - path provided by the Windows client is in the 7247052Samw * format of <drive letter>:\<dir> 7257052Samw * realpath - path that will be stored as the directory field of 7267052Samw * the smb_share_t structure of the share. 727*7961SNatalie.Li@Sun.COM * maxlen - maximum length of the realpath buffer 7287052Samw * 7297052Samw * Return LAN Manager network error code. 7307052Samw */ 7317052Samw uint32_t 732*7961SNatalie.Li@Sun.COM smb_shr_get_realpath(const char *clntpath, char *realpath, int maxlen) 7337052Samw { 734*7961SNatalie.Li@Sun.COM const char *p; 735*7961SNatalie.Li@Sun.COM int len; 7367348SJose.Borrego@Sun.COM 737*7961SNatalie.Li@Sun.COM if ((p = strchr(clntpath, ':')) != NULL) 738*7961SNatalie.Li@Sun.COM ++p; 739*7961SNatalie.Li@Sun.COM else 740*7961SNatalie.Li@Sun.COM p = clntpath; 7417348SJose.Borrego@Sun.COM 742*7961SNatalie.Li@Sun.COM (void) strlcpy(realpath, p, maxlen); 743*7961SNatalie.Li@Sun.COM (void) strcanon(realpath, "/\\"); 744*7961SNatalie.Li@Sun.COM (void) strsubst(realpath, '\\', '/'); 7457348SJose.Borrego@Sun.COM 746*7961SNatalie.Li@Sun.COM len = strlen(realpath); 747*7961SNatalie.Li@Sun.COM if ((len > 1) && (realpath[len - 1] == '/')) 748*7961SNatalie.Li@Sun.COM realpath[len - 1] = '\0'; 7497348SJose.Borrego@Sun.COM 7507348SJose.Borrego@Sun.COM return (NERR_Success); 7517348SJose.Borrego@Sun.COM } 7527348SJose.Borrego@Sun.COM 753*7961SNatalie.Li@Sun.COM void 754*7961SNatalie.Li@Sun.COM smb_shr_list(int offset, smb_shrlist_t *list) 7557348SJose.Borrego@Sun.COM { 756*7961SNatalie.Li@Sun.COM smb_shriter_t iterator; 757*7961SNatalie.Li@Sun.COM smb_share_t *si; 758*7961SNatalie.Li@Sun.COM int n = 0; 759*7961SNatalie.Li@Sun.COM 760*7961SNatalie.Li@Sun.COM bzero(list, sizeof (smb_shrlist_t)); 761*7961SNatalie.Li@Sun.COM smb_shr_iterinit(&iterator); 762*7961SNatalie.Li@Sun.COM 763*7961SNatalie.Li@Sun.COM while ((si = smb_shr_iterate(&iterator)) != NULL) { 764*7961SNatalie.Li@Sun.COM if (--offset > 0) 765*7961SNatalie.Li@Sun.COM continue; 766*7961SNatalie.Li@Sun.COM 767*7961SNatalie.Li@Sun.COM if ((si->shr_flags & SMB_SHRF_TRANS) && 768*7961SNatalie.Li@Sun.COM ((si->shr_type & STYPE_IPC) == 0)) { 769*7961SNatalie.Li@Sun.COM bcopy(si, &list->sl_shares[n], sizeof (smb_share_t)); 770*7961SNatalie.Li@Sun.COM if (++n == LMSHARES_PER_REQUEST) 771*7961SNatalie.Li@Sun.COM break; 772*7961SNatalie.Li@Sun.COM } 7737348SJose.Borrego@Sun.COM } 774*7961SNatalie.Li@Sun.COM 775*7961SNatalie.Li@Sun.COM list->sl_cnt = n; 7767348SJose.Borrego@Sun.COM } 7777348SJose.Borrego@Sun.COM 7787348SJose.Borrego@Sun.COM /* 779*7961SNatalie.Li@Sun.COM * ============================================ 780*7961SNatalie.Li@Sun.COM * Private helper/utility functions 781*7961SNatalie.Li@Sun.COM * ============================================ 7827348SJose.Borrego@Sun.COM */ 7837348SJose.Borrego@Sun.COM 784*7961SNatalie.Li@Sun.COM /* 785*7961SNatalie.Li@Sun.COM * Add IPC$ to the cache upon startup. 786*7961SNatalie.Li@Sun.COM */ 7877348SJose.Borrego@Sun.COM static uint32_t 788*7961SNatalie.Li@Sun.COM smb_shr_addipc(void) 7897348SJose.Borrego@Sun.COM { 7907348SJose.Borrego@Sun.COM smb_share_t ipc; 791*7961SNatalie.Li@Sun.COM uint32_t status = NERR_InternalError; 7927348SJose.Borrego@Sun.COM 7937348SJose.Borrego@Sun.COM bzero(&ipc, sizeof (smb_share_t)); 7947348SJose.Borrego@Sun.COM (void) strcpy(ipc.shr_name, "IPC$"); 7957348SJose.Borrego@Sun.COM (void) strcpy(ipc.shr_cmnt, "Remote IPC"); 7967348SJose.Borrego@Sun.COM ipc.shr_flags = SMB_SHRF_TRANS; 7977348SJose.Borrego@Sun.COM ipc.shr_type = STYPE_IPC; 7987348SJose.Borrego@Sun.COM 799*7961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) == NERR_Success) { 800*7961SNatalie.Li@Sun.COM status = smb_shr_cache_addent(&ipc); 801*7961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 8027348SJose.Borrego@Sun.COM } 8037348SJose.Borrego@Sun.COM 8047348SJose.Borrego@Sun.COM return (status); 8057348SJose.Borrego@Sun.COM } 8067348SJose.Borrego@Sun.COM 8077348SJose.Borrego@Sun.COM /* 8087052Samw * smb_shr_set_oemname 8097052Samw * 810*7961SNatalie.Li@Sun.COM * Generate the OEM name for the specified share. If the name is 811*7961SNatalie.Li@Sun.COM * shorter than 13 bytes the oemname will be saved in si->shr_oemname. 812*7961SNatalie.Li@Sun.COM * Otherwise si->shr_oemname will be empty and SMB_SHRF_LONGNAME will 813*7961SNatalie.Li@Sun.COM * be set in si->shr_flags. 8147052Samw */ 8157052Samw static void 8167052Samw smb_shr_set_oemname(smb_share_t *si) 8177052Samw { 8187052Samw unsigned int cpid = oem_get_smb_cpid(); 8197052Samw mts_wchar_t *unibuf; 8207052Samw char *oem_name; 8217052Samw int length; 8227052Samw 8237052Samw length = strlen(si->shr_name) + 1; 8247052Samw 8257052Samw oem_name = malloc(length); 8267052Samw unibuf = malloc(length * sizeof (mts_wchar_t)); 8277052Samw if ((oem_name == NULL) || (unibuf == NULL)) { 8287052Samw free(oem_name); 8297052Samw free(unibuf); 8307052Samw return; 8317052Samw } 8327052Samw 8337052Samw (void) mts_mbstowcs(unibuf, si->shr_name, length); 8347052Samw 8357052Samw if (unicodestooems(oem_name, unibuf, length, cpid) == 0) 8367052Samw (void) strcpy(oem_name, si->shr_name); 8377052Samw 8387052Samw free(unibuf); 8397052Samw 8407052Samw if (strlen(oem_name) + 1 > SMB_SHARE_OEMNAME_MAX) { 8417052Samw si->shr_flags |= SMB_SHRF_LONGNAME; 8427052Samw *si->shr_oemname = '\0'; 8437052Samw } else { 8447052Samw si->shr_flags &= ~SMB_SHRF_LONGNAME; 8457052Samw (void) strlcpy(si->shr_oemname, oem_name, 8467052Samw SMB_SHARE_OEMNAME_MAX); 8477052Samw } 8487052Samw 8497052Samw free(oem_name); 8507052Samw } 8517348SJose.Borrego@Sun.COM 8527348SJose.Borrego@Sun.COM /* 8537348SJose.Borrego@Sun.COM * ============================================ 854*7961SNatalie.Li@Sun.COM * Cache management functions 855*7961SNatalie.Li@Sun.COM * 856*7961SNatalie.Li@Sun.COM * All cache functions are private 8577348SJose.Borrego@Sun.COM * ============================================ 8587348SJose.Borrego@Sun.COM */ 8597348SJose.Borrego@Sun.COM 8607348SJose.Borrego@Sun.COM /* 861*7961SNatalie.Li@Sun.COM * Create the share cache (hash table). 8627348SJose.Borrego@Sun.COM */ 8637348SJose.Borrego@Sun.COM static uint32_t 864*7961SNatalie.Li@Sun.COM smb_shr_cache_create(void) 8657348SJose.Borrego@Sun.COM { 866*7961SNatalie.Li@Sun.COM uint32_t status = NERR_Success; 8677348SJose.Borrego@Sun.COM 868*7961SNatalie.Li@Sun.COM (void) mutex_lock(&smb_shr_cache.sc_mtx); 869*7961SNatalie.Li@Sun.COM switch (smb_shr_cache.sc_state) { 870*7961SNatalie.Li@Sun.COM case SMB_SHR_CACHE_STATE_NONE: 871*7961SNatalie.Li@Sun.COM smb_shr_cache.sc_cache = ht_create_table(SMB_SHR_HTAB_SZ, 872*7961SNatalie.Li@Sun.COM MAXNAMELEN, 0); 873*7961SNatalie.Li@Sun.COM if (smb_shr_cache.sc_cache == NULL) { 874*7961SNatalie.Li@Sun.COM status = NERR_InternalError; 875*7961SNatalie.Li@Sun.COM break; 8767348SJose.Borrego@Sun.COM } 8777348SJose.Borrego@Sun.COM 878*7961SNatalie.Li@Sun.COM (void) ht_register_callback(smb_shr_cache.sc_cache, 879*7961SNatalie.Li@Sun.COM smb_shr_cache_freent); 880*7961SNatalie.Li@Sun.COM smb_shr_cache.sc_nops = 0; 881*7961SNatalie.Li@Sun.COM smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_CREATED; 882*7961SNatalie.Li@Sun.COM break; 883*7961SNatalie.Li@Sun.COM 884*7961SNatalie.Li@Sun.COM default: 885*7961SNatalie.Li@Sun.COM assert(0); 886*7961SNatalie.Li@Sun.COM status = NERR_InternalError; 887*7961SNatalie.Li@Sun.COM break; 888*7961SNatalie.Li@Sun.COM } 889*7961SNatalie.Li@Sun.COM (void) mutex_unlock(&smb_shr_cache.sc_mtx); 890*7961SNatalie.Li@Sun.COM 891*7961SNatalie.Li@Sun.COM return (status); 892*7961SNatalie.Li@Sun.COM } 893*7961SNatalie.Li@Sun.COM 894*7961SNatalie.Li@Sun.COM /* 895*7961SNatalie.Li@Sun.COM * Destroy the share cache (hash table). 896*7961SNatalie.Li@Sun.COM * Wait for inflight/pending operations to finish or abort before 897*7961SNatalie.Li@Sun.COM * destroying the cache. 898*7961SNatalie.Li@Sun.COM */ 899*7961SNatalie.Li@Sun.COM static void 900*7961SNatalie.Li@Sun.COM smb_shr_cache_destroy(void) 901*7961SNatalie.Li@Sun.COM { 902*7961SNatalie.Li@Sun.COM (void) mutex_lock(&smb_shr_cache.sc_mtx); 903*7961SNatalie.Li@Sun.COM if (smb_shr_cache.sc_state == SMB_SHR_CACHE_STATE_CREATED) { 904*7961SNatalie.Li@Sun.COM smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_DESTROYING; 905*7961SNatalie.Li@Sun.COM while (smb_shr_cache.sc_nops > 0) 906*7961SNatalie.Li@Sun.COM (void) cond_wait(&smb_shr_cache.sc_cv, 907*7961SNatalie.Li@Sun.COM &smb_shr_cache.sc_mtx); 908*7961SNatalie.Li@Sun.COM 909*7961SNatalie.Li@Sun.COM smb_shr_cache.sc_cache = NULL; 910*7961SNatalie.Li@Sun.COM smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_NONE; 911*7961SNatalie.Li@Sun.COM } 912*7961SNatalie.Li@Sun.COM (void) mutex_unlock(&smb_shr_cache.sc_mtx); 913*7961SNatalie.Li@Sun.COM } 914*7961SNatalie.Li@Sun.COM 915*7961SNatalie.Li@Sun.COM /* 916*7961SNatalie.Li@Sun.COM * If the cache is in "created" state, lock the cache for read 917*7961SNatalie.Li@Sun.COM * or read/write based on the specified mode. 918*7961SNatalie.Li@Sun.COM * 919*7961SNatalie.Li@Sun.COM * Whenever a lock is granted, the number of inflight cache 920*7961SNatalie.Li@Sun.COM * operations is incremented. 921*7961SNatalie.Li@Sun.COM */ 922*7961SNatalie.Li@Sun.COM static uint32_t 923*7961SNatalie.Li@Sun.COM smb_shr_cache_lock(int mode) 924*7961SNatalie.Li@Sun.COM { 925*7961SNatalie.Li@Sun.COM (void) mutex_lock(&smb_shr_cache.sc_mtx); 926*7961SNatalie.Li@Sun.COM switch (smb_shr_cache.sc_state) { 927*7961SNatalie.Li@Sun.COM case SMB_SHR_CACHE_STATE_CREATED: 928*7961SNatalie.Li@Sun.COM smb_shr_cache.sc_nops++; 929*7961SNatalie.Li@Sun.COM break; 930*7961SNatalie.Li@Sun.COM 931*7961SNatalie.Li@Sun.COM case SMB_SHR_CACHE_STATE_DESTROYING: 932*7961SNatalie.Li@Sun.COM (void) mutex_unlock(&smb_shr_cache.sc_mtx); 933*7961SNatalie.Li@Sun.COM return (NERR_InternalError); 934*7961SNatalie.Li@Sun.COM 935*7961SNatalie.Li@Sun.COM case SMB_SHR_CACHE_STATE_NONE: 936*7961SNatalie.Li@Sun.COM default: 937*7961SNatalie.Li@Sun.COM assert(0); 938*7961SNatalie.Li@Sun.COM (void) mutex_unlock(&smb_shr_cache.sc_mtx); 939*7961SNatalie.Li@Sun.COM return (NERR_InternalError); 940*7961SNatalie.Li@Sun.COM 941*7961SNatalie.Li@Sun.COM } 942*7961SNatalie.Li@Sun.COM (void) mutex_unlock(&smb_shr_cache.sc_mtx); 943*7961SNatalie.Li@Sun.COM 944*7961SNatalie.Li@Sun.COM /* 945*7961SNatalie.Li@Sun.COM * Lock has to be taken outside the mutex otherwise 946*7961SNatalie.Li@Sun.COM * there could be a deadlock 947*7961SNatalie.Li@Sun.COM */ 948*7961SNatalie.Li@Sun.COM if (mode == SMB_SHR_CACHE_RDLOCK) 949*7961SNatalie.Li@Sun.COM (void) rw_rdlock(&smb_shr_cache.sc_cache_lck); 950*7961SNatalie.Li@Sun.COM else 951*7961SNatalie.Li@Sun.COM (void) rw_wrlock(&smb_shr_cache.sc_cache_lck); 952*7961SNatalie.Li@Sun.COM 953*7961SNatalie.Li@Sun.COM return (NERR_Success); 954*7961SNatalie.Li@Sun.COM } 955*7961SNatalie.Li@Sun.COM 956*7961SNatalie.Li@Sun.COM /* 957*7961SNatalie.Li@Sun.COM * Decrement the number of inflight operations and then unlock. 958*7961SNatalie.Li@Sun.COM */ 959*7961SNatalie.Li@Sun.COM static void 960*7961SNatalie.Li@Sun.COM smb_shr_cache_unlock(void) 961*7961SNatalie.Li@Sun.COM { 962*7961SNatalie.Li@Sun.COM (void) mutex_lock(&smb_shr_cache.sc_mtx); 963*7961SNatalie.Li@Sun.COM assert(smb_shr_cache.sc_nops > 0); 964*7961SNatalie.Li@Sun.COM smb_shr_cache.sc_nops--; 965*7961SNatalie.Li@Sun.COM (void) cond_broadcast(&smb_shr_cache.sc_cv); 966*7961SNatalie.Li@Sun.COM (void) mutex_unlock(&smb_shr_cache.sc_mtx); 967*7961SNatalie.Li@Sun.COM 968*7961SNatalie.Li@Sun.COM (void) rw_unlock(&smb_shr_cache.sc_cache_lck); 969*7961SNatalie.Li@Sun.COM } 970*7961SNatalie.Li@Sun.COM 971*7961SNatalie.Li@Sun.COM /* 972*7961SNatalie.Li@Sun.COM * Return the total number of shares 973*7961SNatalie.Li@Sun.COM */ 974*7961SNatalie.Li@Sun.COM static int 975*7961SNatalie.Li@Sun.COM smb_shr_cache_count(void) 976*7961SNatalie.Li@Sun.COM { 977*7961SNatalie.Li@Sun.COM return (ht_get_total_items(smb_shr_cache.sc_cache)); 978*7961SNatalie.Li@Sun.COM } 979*7961SNatalie.Li@Sun.COM 980*7961SNatalie.Li@Sun.COM /* 981*7961SNatalie.Li@Sun.COM * looks up the given share name in the cache and if it 982*7961SNatalie.Li@Sun.COM * finds a match returns a pointer to the cached entry. 983*7961SNatalie.Li@Sun.COM * Note that since a pointer is returned this function 984*7961SNatalie.Li@Sun.COM * MUST be protected by smb_shr_cache_lock/unlock pair 985*7961SNatalie.Li@Sun.COM */ 986*7961SNatalie.Li@Sun.COM static smb_share_t * 987*7961SNatalie.Li@Sun.COM smb_shr_cache_findent(char *sharename) 988*7961SNatalie.Li@Sun.COM { 989*7961SNatalie.Li@Sun.COM HT_ITEM *item; 990*7961SNatalie.Li@Sun.COM 991*7961SNatalie.Li@Sun.COM (void) utf8_strlwr(sharename); 992*7961SNatalie.Li@Sun.COM item = ht_find_item(smb_shr_cache.sc_cache, sharename); 993*7961SNatalie.Li@Sun.COM if (item && item->hi_data) 994*7961SNatalie.Li@Sun.COM return ((smb_share_t *)item->hi_data); 995*7961SNatalie.Li@Sun.COM 996*7961SNatalie.Li@Sun.COM return (NULL); 997*7961SNatalie.Li@Sun.COM } 998*7961SNatalie.Li@Sun.COM 999*7961SNatalie.Li@Sun.COM /* 1000*7961SNatalie.Li@Sun.COM * Return a pointer to the first/next entry in 1001*7961SNatalie.Li@Sun.COM * the cache based on the given iterator. 1002*7961SNatalie.Li@Sun.COM * 1003*7961SNatalie.Li@Sun.COM * Calls to this function MUST be protected by 1004*7961SNatalie.Li@Sun.COM * smb_shr_cache_lock/unlock. 1005*7961SNatalie.Li@Sun.COM */ 1006*7961SNatalie.Li@Sun.COM static smb_share_t * 1007*7961SNatalie.Li@Sun.COM smb_shr_cache_iterate(smb_shriter_t *shi) 1008*7961SNatalie.Li@Sun.COM { 1009*7961SNatalie.Li@Sun.COM HT_ITEM *item; 1010*7961SNatalie.Li@Sun.COM 1011*7961SNatalie.Li@Sun.COM if (shi->si_first) { 1012*7961SNatalie.Li@Sun.COM item = ht_findfirst(smb_shr_cache.sc_cache, &shi->si_hashiter); 1013*7961SNatalie.Li@Sun.COM shi->si_first = B_FALSE; 1014*7961SNatalie.Li@Sun.COM } else { 1015*7961SNatalie.Li@Sun.COM item = ht_findnext(&shi->si_hashiter); 10167348SJose.Borrego@Sun.COM } 10177348SJose.Borrego@Sun.COM 1018*7961SNatalie.Li@Sun.COM if (item && item->hi_data) 1019*7961SNatalie.Li@Sun.COM return ((smb_share_t *)item->hi_data); 1020*7961SNatalie.Li@Sun.COM 1021*7961SNatalie.Li@Sun.COM return (NULL); 1022*7961SNatalie.Li@Sun.COM } 1023*7961SNatalie.Li@Sun.COM 1024*7961SNatalie.Li@Sun.COM /* 1025*7961SNatalie.Li@Sun.COM * Add the specified share to the cache. Memory needs to be allocated 1026*7961SNatalie.Li@Sun.COM * for the cache entry and the passed information is copied to the 1027*7961SNatalie.Li@Sun.COM * allocated space. 1028*7961SNatalie.Li@Sun.COM */ 1029*7961SNatalie.Li@Sun.COM static uint32_t 1030*7961SNatalie.Li@Sun.COM smb_shr_cache_addent(smb_share_t *si) 1031*7961SNatalie.Li@Sun.COM { 1032*7961SNatalie.Li@Sun.COM smb_share_t *cache_ent; 1033*7961SNatalie.Li@Sun.COM uint32_t status = NERR_Success; 1034*7961SNatalie.Li@Sun.COM 1035*7961SNatalie.Li@Sun.COM if ((cache_ent = malloc(sizeof (smb_share_t))) == NULL) 1036*7961SNatalie.Li@Sun.COM return (ERROR_NOT_ENOUGH_MEMORY); 1037*7961SNatalie.Li@Sun.COM 1038*7961SNatalie.Li@Sun.COM bcopy(si, cache_ent, sizeof (smb_share_t)); 1039*7961SNatalie.Li@Sun.COM 1040*7961SNatalie.Li@Sun.COM (void) utf8_strlwr(cache_ent->shr_name); 1041*7961SNatalie.Li@Sun.COM smb_shr_set_oemname(cache_ent); 1042*7961SNatalie.Li@Sun.COM 1043*7961SNatalie.Li@Sun.COM if ((si->shr_type & STYPE_IPC) == 0) 1044*7961SNatalie.Li@Sun.COM cache_ent->shr_type = STYPE_DISKTREE; 1045*7961SNatalie.Li@Sun.COM cache_ent->shr_type |= smb_shr_is_special(cache_ent->shr_name); 1046*7961SNatalie.Li@Sun.COM 1047*7961SNatalie.Li@Sun.COM if (smb_shr_is_admin(cache_ent->shr_name)) 1048*7961SNatalie.Li@Sun.COM cache_ent->shr_flags |= SMB_SHRF_ADMIN; 1049*7961SNatalie.Li@Sun.COM 1050*7961SNatalie.Li@Sun.COM if (si->shr_flags & SMB_SHRF_AUTOHOME) 1051*7961SNatalie.Li@Sun.COM cache_ent->shr_refcnt = 1; 1052*7961SNatalie.Li@Sun.COM 1053*7961SNatalie.Li@Sun.COM if (ht_add_item(smb_shr_cache.sc_cache, cache_ent->shr_name, cache_ent) 1054*7961SNatalie.Li@Sun.COM == NULL) { 1055*7961SNatalie.Li@Sun.COM syslog(LOG_DEBUG, "share: %s: cache update failed", 1056*7961SNatalie.Li@Sun.COM cache_ent->shr_name); 1057*7961SNatalie.Li@Sun.COM free(cache_ent); 1058*7961SNatalie.Li@Sun.COM status = NERR_InternalError; 10597348SJose.Borrego@Sun.COM } 10607348SJose.Borrego@Sun.COM 1061*7961SNatalie.Li@Sun.COM return (status); 1062*7961SNatalie.Li@Sun.COM } 1063*7961SNatalie.Li@Sun.COM 1064*7961SNatalie.Li@Sun.COM /* 1065*7961SNatalie.Li@Sun.COM * Delete the specified share from the cache. 1066*7961SNatalie.Li@Sun.COM */ 1067*7961SNatalie.Li@Sun.COM static void 1068*7961SNatalie.Li@Sun.COM smb_shr_cache_delent(char *sharename) 1069*7961SNatalie.Li@Sun.COM { 1070*7961SNatalie.Li@Sun.COM (void) utf8_strlwr(sharename); 1071*7961SNatalie.Li@Sun.COM (void) ht_remove_item(smb_shr_cache.sc_cache, sharename); 1072*7961SNatalie.Li@Sun.COM } 1073*7961SNatalie.Li@Sun.COM 1074*7961SNatalie.Li@Sun.COM /* 1075*7961SNatalie.Li@Sun.COM * Call back to free the given cache entry. 1076*7961SNatalie.Li@Sun.COM */ 1077*7961SNatalie.Li@Sun.COM static void 1078*7961SNatalie.Li@Sun.COM smb_shr_cache_freent(HT_ITEM *item) 1079*7961SNatalie.Li@Sun.COM { 1080*7961SNatalie.Li@Sun.COM if (item && item->hi_data) 1081*7961SNatalie.Li@Sun.COM free(item->hi_data); 1082*7961SNatalie.Li@Sun.COM } 1083*7961SNatalie.Li@Sun.COM 1084*7961SNatalie.Li@Sun.COM /* 1085*7961SNatalie.Li@Sun.COM * ============================================ 1086*7961SNatalie.Li@Sun.COM * Interfaces to sharemgr 1087*7961SNatalie.Li@Sun.COM * 1088*7961SNatalie.Li@Sun.COM * All functions in this section are private 1089*7961SNatalie.Li@Sun.COM * ============================================ 1090*7961SNatalie.Li@Sun.COM */ 1091*7961SNatalie.Li@Sun.COM 1092*7961SNatalie.Li@Sun.COM /* 1093*7961SNatalie.Li@Sun.COM * Load shares from sharemgr 1094*7961SNatalie.Li@Sun.COM */ 1095*7961SNatalie.Li@Sun.COM /*ARGSUSED*/ 1096*7961SNatalie.Li@Sun.COM static void * 1097*7961SNatalie.Li@Sun.COM smb_shr_sa_loadall(void *args) 1098*7961SNatalie.Li@Sun.COM { 1099*7961SNatalie.Li@Sun.COM sa_handle_t handle; 1100*7961SNatalie.Li@Sun.COM sa_group_t group, subgroup; 1101*7961SNatalie.Li@Sun.COM char *gstate; 1102*7961SNatalie.Li@Sun.COM boolean_t gdisabled; 1103*7961SNatalie.Li@Sun.COM 1104*7961SNatalie.Li@Sun.COM if ((handle = sa_init(SA_INIT_SHARE_API)) == NULL) { 1105*7961SNatalie.Li@Sun.COM syslog(LOG_ERR, "share: failed to get libshare API handle"); 1106*7961SNatalie.Li@Sun.COM return (NULL); 11077348SJose.Borrego@Sun.COM } 11087348SJose.Borrego@Sun.COM 1109*7961SNatalie.Li@Sun.COM for (group = sa_get_group(handle, NULL); 1110*7961SNatalie.Li@Sun.COM group != NULL; group = sa_get_next_group(group)) { 1111*7961SNatalie.Li@Sun.COM gstate = sa_get_group_attr(group, "state"); 1112*7961SNatalie.Li@Sun.COM if (gstate == NULL) 1113*7961SNatalie.Li@Sun.COM continue; 1114*7961SNatalie.Li@Sun.COM 1115*7961SNatalie.Li@Sun.COM gdisabled = (strcasecmp(gstate, "disabled") == 0); 1116*7961SNatalie.Li@Sun.COM sa_free_attr_string(gstate); 1117*7961SNatalie.Li@Sun.COM if (gdisabled) 1118*7961SNatalie.Li@Sun.COM continue; 1119*7961SNatalie.Li@Sun.COM 1120*7961SNatalie.Li@Sun.COM smb_shr_sa_loadgrp(group); 1121*7961SNatalie.Li@Sun.COM 1122*7961SNatalie.Li@Sun.COM for (subgroup = sa_get_sub_group(group); 1123*7961SNatalie.Li@Sun.COM subgroup != NULL; 1124*7961SNatalie.Li@Sun.COM subgroup = sa_get_next_group(subgroup)) { 1125*7961SNatalie.Li@Sun.COM smb_shr_sa_loadgrp(subgroup); 1126*7961SNatalie.Li@Sun.COM } 1127*7961SNatalie.Li@Sun.COM 11287348SJose.Borrego@Sun.COM } 11297348SJose.Borrego@Sun.COM 11307348SJose.Borrego@Sun.COM sa_fini(handle); 1131*7961SNatalie.Li@Sun.COM return (NULL); 11327348SJose.Borrego@Sun.COM } 11337348SJose.Borrego@Sun.COM 1134*7961SNatalie.Li@Sun.COM /* 1135*7961SNatalie.Li@Sun.COM * Load the shares contained in the specified group. 1136*7961SNatalie.Li@Sun.COM * 1137*7961SNatalie.Li@Sun.COM * Don't process groups on which the smb protocol is disabled. 1138*7961SNatalie.Li@Sun.COM * The top level ZFS group won't have the smb protocol enabled 1139*7961SNatalie.Li@Sun.COM * but sub-groups will. 1140*7961SNatalie.Li@Sun.COM * 1141*7961SNatalie.Li@Sun.COM * We will tolerate a limited number of errors and then give 1142*7961SNatalie.Li@Sun.COM * up on the current group. A typical error might be that the 1143*7961SNatalie.Li@Sun.COM * shared directory no longer exists. 1144*7961SNatalie.Li@Sun.COM */ 1145*7961SNatalie.Li@Sun.COM static void 1146*7961SNatalie.Li@Sun.COM smb_shr_sa_loadgrp(sa_group_t group) 1147*7961SNatalie.Li@Sun.COM { 1148*7961SNatalie.Li@Sun.COM sa_share_t share; 1149*7961SNatalie.Li@Sun.COM sa_resource_t resource; 1150*7961SNatalie.Li@Sun.COM int error_count = 0; 1151*7961SNatalie.Li@Sun.COM 1152*7961SNatalie.Li@Sun.COM if (sa_get_optionset(group, SMB_PROTOCOL_NAME) == NULL) 1153*7961SNatalie.Li@Sun.COM return; 1154*7961SNatalie.Li@Sun.COM 1155*7961SNatalie.Li@Sun.COM for (share = sa_get_share(group, NULL); 1156*7961SNatalie.Li@Sun.COM share != NULL; 1157*7961SNatalie.Li@Sun.COM share = sa_get_next_share(share)) { 1158*7961SNatalie.Li@Sun.COM for (resource = sa_get_share_resource(share, NULL); 1159*7961SNatalie.Li@Sun.COM resource != NULL; 1160*7961SNatalie.Li@Sun.COM resource = sa_get_next_resource(resource)) { 1161*7961SNatalie.Li@Sun.COM if (smb_shr_sa_load(share, resource)) 1162*7961SNatalie.Li@Sun.COM ++error_count; 1163*7961SNatalie.Li@Sun.COM 1164*7961SNatalie.Li@Sun.COM if (error_count > SMB_SHR_ERROR_THRESHOLD) 1165*7961SNatalie.Li@Sun.COM break; 1166*7961SNatalie.Li@Sun.COM } 1167*7961SNatalie.Li@Sun.COM 1168*7961SNatalie.Li@Sun.COM if (error_count > SMB_SHR_ERROR_THRESHOLD) 1169*7961SNatalie.Li@Sun.COM break; 1170*7961SNatalie.Li@Sun.COM } 1171*7961SNatalie.Li@Sun.COM } 1172*7961SNatalie.Li@Sun.COM 1173*7961SNatalie.Li@Sun.COM /* 1174*7961SNatalie.Li@Sun.COM * Load a share definition from sharemgr and add it to the cache. 1175*7961SNatalie.Li@Sun.COM */ 11767348SJose.Borrego@Sun.COM static uint32_t 1177*7961SNatalie.Li@Sun.COM smb_shr_sa_load(sa_share_t share, sa_resource_t resource) 1178*7961SNatalie.Li@Sun.COM { 1179*7961SNatalie.Li@Sun.COM smb_share_t si; 1180*7961SNatalie.Li@Sun.COM uint32_t status; 1181*7961SNatalie.Li@Sun.COM 1182*7961SNatalie.Li@Sun.COM if ((status = smb_shr_sa_get(share, resource, &si)) != NERR_Success) { 1183*7961SNatalie.Li@Sun.COM syslog(LOG_DEBUG, "share: failed to load %s (%d)", 1184*7961SNatalie.Li@Sun.COM si.shr_name, status); 1185*7961SNatalie.Li@Sun.COM return (status); 1186*7961SNatalie.Li@Sun.COM } 1187*7961SNatalie.Li@Sun.COM 1188*7961SNatalie.Li@Sun.COM if ((status = smb_shr_add(&si)) != NERR_Success) { 1189*7961SNatalie.Li@Sun.COM syslog(LOG_DEBUG, "share: failed to cache %s (%d)", 1190*7961SNatalie.Li@Sun.COM si.shr_name, status); 1191*7961SNatalie.Li@Sun.COM return (status); 1192*7961SNatalie.Li@Sun.COM } 1193*7961SNatalie.Li@Sun.COM 1194*7961SNatalie.Li@Sun.COM return (NERR_Success); 1195*7961SNatalie.Li@Sun.COM } 1196*7961SNatalie.Li@Sun.COM 1197*7961SNatalie.Li@Sun.COM /* 1198*7961SNatalie.Li@Sun.COM * Read the specified share information from sharemgr and return 1199*7961SNatalie.Li@Sun.COM * it in the given smb_share_t structure. 1200*7961SNatalie.Li@Sun.COM * 1201*7961SNatalie.Li@Sun.COM * Shares read from sharemgr are marked as permanent/persistent. 1202*7961SNatalie.Li@Sun.COM */ 1203*7961SNatalie.Li@Sun.COM static uint32_t 1204*7961SNatalie.Li@Sun.COM smb_shr_sa_get(sa_share_t share, sa_resource_t resource, smb_share_t *si) 12057348SJose.Borrego@Sun.COM { 12067348SJose.Borrego@Sun.COM sa_property_t prop; 12077348SJose.Borrego@Sun.COM sa_optionset_t opts; 12087348SJose.Borrego@Sun.COM char *val = NULL; 12097348SJose.Borrego@Sun.COM char *path; 12107348SJose.Borrego@Sun.COM char *rname; 12117348SJose.Borrego@Sun.COM 12127348SJose.Borrego@Sun.COM if ((path = sa_get_share_attr(share, "path")) == NULL) 12137348SJose.Borrego@Sun.COM return (NERR_InternalError); 12147348SJose.Borrego@Sun.COM 12157348SJose.Borrego@Sun.COM if ((rname = sa_get_resource_attr(resource, "name")) == NULL) { 12167348SJose.Borrego@Sun.COM sa_free_attr_string(path); 12177348SJose.Borrego@Sun.COM return (NERR_InternalError); 12187348SJose.Borrego@Sun.COM } 12197348SJose.Borrego@Sun.COM 12207348SJose.Borrego@Sun.COM bzero(si, sizeof (smb_share_t)); 12217348SJose.Borrego@Sun.COM si->shr_flags = SMB_SHRF_PERM; 12227348SJose.Borrego@Sun.COM 12237348SJose.Borrego@Sun.COM (void) strlcpy(si->shr_path, path, sizeof (si->shr_path)); 12247348SJose.Borrego@Sun.COM (void) strlcpy(si->shr_name, rname, sizeof (si->shr_name)); 12257348SJose.Borrego@Sun.COM 12267348SJose.Borrego@Sun.COM sa_free_attr_string(path); 12277348SJose.Borrego@Sun.COM sa_free_attr_string(rname); 12287348SJose.Borrego@Sun.COM 12297348SJose.Borrego@Sun.COM val = sa_get_resource_description(resource); 12307348SJose.Borrego@Sun.COM if (val == NULL) 12317348SJose.Borrego@Sun.COM val = sa_get_share_description(share); 12327348SJose.Borrego@Sun.COM 12337348SJose.Borrego@Sun.COM if (val != NULL) { 12347348SJose.Borrego@Sun.COM (void) strlcpy(si->shr_cmnt, val, sizeof (si->shr_cmnt)); 12357348SJose.Borrego@Sun.COM sa_free_share_description(val); 12367348SJose.Borrego@Sun.COM } 12377348SJose.Borrego@Sun.COM 12387348SJose.Borrego@Sun.COM opts = sa_get_derived_optionset(resource, SMB_PROTOCOL_NAME, 1); 12397348SJose.Borrego@Sun.COM if (opts == NULL) 12407348SJose.Borrego@Sun.COM return (NERR_Success); 12417348SJose.Borrego@Sun.COM 12427348SJose.Borrego@Sun.COM prop = (sa_property_t)sa_get_property(opts, SMB_SHROPT_AD_CONTAINER); 12437348SJose.Borrego@Sun.COM if (prop != NULL) { 12447348SJose.Borrego@Sun.COM if ((val = sa_get_property_attr(prop, "value")) != NULL) { 12457348SJose.Borrego@Sun.COM (void) strlcpy(si->shr_container, val, 12467348SJose.Borrego@Sun.COM sizeof (si->shr_container)); 12477348SJose.Borrego@Sun.COM free(val); 12487348SJose.Borrego@Sun.COM } 12497348SJose.Borrego@Sun.COM } 12507348SJose.Borrego@Sun.COM 1251*7961SNatalie.Li@Sun.COM prop = (sa_property_t)sa_get_property(opts, SHOPT_NONE); 1252*7961SNatalie.Li@Sun.COM if (prop != NULL) { 1253*7961SNatalie.Li@Sun.COM if ((val = sa_get_property_attr(prop, "value")) != NULL) { 1254*7961SNatalie.Li@Sun.COM (void) strlcpy(si->shr_access_none, val, 1255*7961SNatalie.Li@Sun.COM sizeof (si->shr_access_none)); 1256*7961SNatalie.Li@Sun.COM free(val); 1257*7961SNatalie.Li@Sun.COM si->shr_flags |= SMB_SHRF_ACC_NONE; 1258*7961SNatalie.Li@Sun.COM } 12597348SJose.Borrego@Sun.COM } 12607348SJose.Borrego@Sun.COM 1261*7961SNatalie.Li@Sun.COM prop = (sa_property_t)sa_get_property(opts, SHOPT_RO); 1262*7961SNatalie.Li@Sun.COM if (prop != NULL) { 1263*7961SNatalie.Li@Sun.COM if ((val = sa_get_property_attr(prop, "value")) != NULL) { 1264*7961SNatalie.Li@Sun.COM (void) strlcpy(si->shr_access_ro, val, 1265*7961SNatalie.Li@Sun.COM sizeof (si->shr_access_ro)); 1266*7961SNatalie.Li@Sun.COM free(val); 1267*7961SNatalie.Li@Sun.COM si->shr_flags |= SMB_SHRF_ACC_RO; 1268*7961SNatalie.Li@Sun.COM } 12697348SJose.Borrego@Sun.COM } 12707348SJose.Borrego@Sun.COM 1271*7961SNatalie.Li@Sun.COM prop = (sa_property_t)sa_get_property(opts, SHOPT_RW); 1272*7961SNatalie.Li@Sun.COM if (prop != NULL) { 1273*7961SNatalie.Li@Sun.COM if ((val = sa_get_property_attr(prop, "value")) != NULL) { 1274*7961SNatalie.Li@Sun.COM (void) strlcpy(si->shr_access_rw, val, 1275*7961SNatalie.Li@Sun.COM sizeof (si->shr_access_rw)); 1276*7961SNatalie.Li@Sun.COM free(val); 1277*7961SNatalie.Li@Sun.COM si->shr_flags |= SMB_SHRF_ACC_RW; 1278*7961SNatalie.Li@Sun.COM } 1279*7961SNatalie.Li@Sun.COM } 1280*7961SNatalie.Li@Sun.COM 1281*7961SNatalie.Li@Sun.COM sa_free_derived_optionset(opts); 1282*7961SNatalie.Li@Sun.COM return (NERR_Success); 12837348SJose.Borrego@Sun.COM } 12847348SJose.Borrego@Sun.COM 12857348SJose.Borrego@Sun.COM /* 12867348SJose.Borrego@Sun.COM * ============================================ 12877348SJose.Borrego@Sun.COM * Share publishing functions 1288*7961SNatalie.Li@Sun.COM * 1289*7961SNatalie.Li@Sun.COM * All the functions are private 12907348SJose.Borrego@Sun.COM * ============================================ 12917348SJose.Borrego@Sun.COM */ 12927348SJose.Borrego@Sun.COM 1293*7961SNatalie.Li@Sun.COM static void 1294*7961SNatalie.Li@Sun.COM smb_shr_publish(const char *sharename, const char *container) 1295*7961SNatalie.Li@Sun.COM { 1296*7961SNatalie.Li@Sun.COM smb_shr_publisher_queue(sharename, container, SMB_SHR_PUBLISH); 1297*7961SNatalie.Li@Sun.COM } 1298*7961SNatalie.Li@Sun.COM 1299*7961SNatalie.Li@Sun.COM static void 1300*7961SNatalie.Li@Sun.COM smb_shr_unpublish(const char *sharename, const char *container) 1301*7961SNatalie.Li@Sun.COM { 1302*7961SNatalie.Li@Sun.COM smb_shr_publisher_queue(sharename, container, SMB_SHR_UNPUBLISH); 1303*7961SNatalie.Li@Sun.COM } 1304*7961SNatalie.Li@Sun.COM 13057348SJose.Borrego@Sun.COM /* 1306*7961SNatalie.Li@Sun.COM * In domain mode, put a share on the publisher queue. 1307*7961SNatalie.Li@Sun.COM * This is a no-op if the smb service is in Workgroup mode. 13087348SJose.Borrego@Sun.COM */ 13097348SJose.Borrego@Sun.COM static void 1310*7961SNatalie.Li@Sun.COM smb_shr_publisher_queue(const char *sharename, const char *container, char op) 13117348SJose.Borrego@Sun.COM { 13127348SJose.Borrego@Sun.COM smb_shr_pitem_t *item = NULL; 13137348SJose.Borrego@Sun.COM 13147348SJose.Borrego@Sun.COM if (container == NULL || *container == '\0') 13157348SJose.Borrego@Sun.COM return; 13167348SJose.Borrego@Sun.COM 1317*7961SNatalie.Li@Sun.COM if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN) 1318*7961SNatalie.Li@Sun.COM return; 1319*7961SNatalie.Li@Sun.COM 13207348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 13217348SJose.Borrego@Sun.COM switch (ad_queue.spq_state) { 13227348SJose.Borrego@Sun.COM case SMB_SHR_PQS_READY: 13237348SJose.Borrego@Sun.COM case SMB_SHR_PQS_PUBLISHING: 13247348SJose.Borrego@Sun.COM break; 13257348SJose.Borrego@Sun.COM default: 13267348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 13277348SJose.Borrego@Sun.COM return; 13287348SJose.Borrego@Sun.COM } 13297348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 13307348SJose.Borrego@Sun.COM 1331*7961SNatalie.Li@Sun.COM if ((item = malloc(sizeof (smb_shr_pitem_t))) == NULL) 13327348SJose.Borrego@Sun.COM return; 13337348SJose.Borrego@Sun.COM 13347348SJose.Borrego@Sun.COM item->spi_op = op; 13357348SJose.Borrego@Sun.COM (void) strlcpy(item->spi_name, sharename, sizeof (item->spi_name)); 13367348SJose.Borrego@Sun.COM (void) strlcpy(item->spi_container, container, 13377348SJose.Borrego@Sun.COM sizeof (item->spi_container)); 13387348SJose.Borrego@Sun.COM 13397348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 13407348SJose.Borrego@Sun.COM list_insert_tail(&ad_queue.spq_list, item); 13417348SJose.Borrego@Sun.COM (void) cond_signal(&ad_queue.spq_cv); 13427348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 13437348SJose.Borrego@Sun.COM } 13447348SJose.Borrego@Sun.COM 1345*7961SNatalie.Li@Sun.COM /* 1346*7961SNatalie.Li@Sun.COM * Publishing won't be activated if the smb service is running in 1347*7961SNatalie.Li@Sun.COM * Workgroup mode. 1348*7961SNatalie.Li@Sun.COM */ 13497348SJose.Borrego@Sun.COM static int 13507348SJose.Borrego@Sun.COM smb_shr_publisher_start(void) 13517348SJose.Borrego@Sun.COM { 1352*7961SNatalie.Li@Sun.COM pthread_t publish_thr; 13537348SJose.Borrego@Sun.COM pthread_attr_t tattr; 13547348SJose.Borrego@Sun.COM int rc; 13557348SJose.Borrego@Sun.COM 1356*7961SNatalie.Li@Sun.COM if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN) 1357*7961SNatalie.Li@Sun.COM return (0); 1358*7961SNatalie.Li@Sun.COM 13597348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 13607348SJose.Borrego@Sun.COM if (ad_queue.spq_state != SMB_SHR_PQS_NOQUEUE) { 13617348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 13627348SJose.Borrego@Sun.COM errno = EINVAL; 13637348SJose.Borrego@Sun.COM return (-1); 13647348SJose.Borrego@Sun.COM } 13657348SJose.Borrego@Sun.COM 13667348SJose.Borrego@Sun.COM list_create(&ad_queue.spq_list, sizeof (smb_shr_pitem_t), 13677348SJose.Borrego@Sun.COM offsetof(smb_shr_pitem_t, spi_lnd)); 13687348SJose.Borrego@Sun.COM ad_queue.spq_state = SMB_SHR_PQS_READY; 13697348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 13707348SJose.Borrego@Sun.COM 13717348SJose.Borrego@Sun.COM (void) pthread_attr_init(&tattr); 13727348SJose.Borrego@Sun.COM (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); 1373*7961SNatalie.Li@Sun.COM rc = pthread_create(&publish_thr, &tattr, smb_shr_publisher, 0); 13747348SJose.Borrego@Sun.COM (void) pthread_attr_destroy(&tattr); 13757348SJose.Borrego@Sun.COM 13767348SJose.Borrego@Sun.COM return (rc); 13777348SJose.Borrego@Sun.COM } 13787348SJose.Borrego@Sun.COM 13797348SJose.Borrego@Sun.COM static void 13807348SJose.Borrego@Sun.COM smb_shr_publisher_stop(void) 13817348SJose.Borrego@Sun.COM { 1382*7961SNatalie.Li@Sun.COM if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN) 1383*7961SNatalie.Li@Sun.COM return; 1384*7961SNatalie.Li@Sun.COM 13857348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 13867348SJose.Borrego@Sun.COM switch (ad_queue.spq_state) { 13877348SJose.Borrego@Sun.COM case SMB_SHR_PQS_READY: 13887348SJose.Borrego@Sun.COM case SMB_SHR_PQS_PUBLISHING: 13897348SJose.Borrego@Sun.COM ad_queue.spq_state = SMB_SHR_PQS_STOPPING; 13907348SJose.Borrego@Sun.COM (void) cond_signal(&ad_queue.spq_cv); 13917348SJose.Borrego@Sun.COM break; 13927348SJose.Borrego@Sun.COM default: 13937348SJose.Borrego@Sun.COM break; 13947348SJose.Borrego@Sun.COM } 13957348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 13967348SJose.Borrego@Sun.COM } 13977348SJose.Borrego@Sun.COM 13987348SJose.Borrego@Sun.COM /* 1399*7961SNatalie.Li@Sun.COM * This is the publisher daemon thread. While running, the thread waits 1400*7961SNatalie.Li@Sun.COM * on a conditional variable until notified that a share needs to be 1401*7961SNatalie.Li@Sun.COM * [un]published or that the thread should be terminated. 1402*7961SNatalie.Li@Sun.COM * 1403*7961SNatalie.Li@Sun.COM * Entries may remain in the outgoing queue if the Active Directory 1404*7961SNatalie.Li@Sun.COM * service is inaccessible, in which case the thread wakes up every 60 1405*7961SNatalie.Li@Sun.COM * seconds to retry. 14067348SJose.Borrego@Sun.COM */ 14077348SJose.Borrego@Sun.COM /*ARGSUSED*/ 14087348SJose.Borrego@Sun.COM static void * 14097348SJose.Borrego@Sun.COM smb_shr_publisher(void *arg) 14107348SJose.Borrego@Sun.COM { 14117348SJose.Borrego@Sun.COM smb_ads_handle_t *ah; 14127348SJose.Borrego@Sun.COM smb_shr_pitem_t *shr; 14137348SJose.Borrego@Sun.COM list_t publist; 1414*7961SNatalie.Li@Sun.COM timestruc_t pubretry; 14157348SJose.Borrego@Sun.COM char hostname[MAXHOSTNAMELEN]; 14167348SJose.Borrego@Sun.COM 14177348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 1418*7961SNatalie.Li@Sun.COM if (ad_queue.spq_state != SMB_SHR_PQS_READY) { 14197348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 14207348SJose.Borrego@Sun.COM return (NULL); 14217348SJose.Borrego@Sun.COM } 1422*7961SNatalie.Li@Sun.COM ad_queue.spq_state = SMB_SHR_PQS_PUBLISHING; 14237348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 14247348SJose.Borrego@Sun.COM 14257348SJose.Borrego@Sun.COM (void) smb_gethostname(hostname, MAXHOSTNAMELEN, 0); 1426*7961SNatalie.Li@Sun.COM 14277348SJose.Borrego@Sun.COM list_create(&publist, sizeof (smb_shr_pitem_t), 14287348SJose.Borrego@Sun.COM offsetof(smb_shr_pitem_t, spi_lnd)); 14297348SJose.Borrego@Sun.COM 14307348SJose.Borrego@Sun.COM for (;;) { 14317348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 1432*7961SNatalie.Li@Sun.COM 1433*7961SNatalie.Li@Sun.COM while (list_is_empty(&ad_queue.spq_list) && 1434*7961SNatalie.Li@Sun.COM (ad_queue.spq_state == SMB_SHR_PQS_PUBLISHING)) { 1435*7961SNatalie.Li@Sun.COM if (list_is_empty(&publist)) { 1436*7961SNatalie.Li@Sun.COM (void) cond_wait(&ad_queue.spq_cv, 1437*7961SNatalie.Li@Sun.COM &ad_queue.spq_mtx); 1438*7961SNatalie.Li@Sun.COM } else { 1439*7961SNatalie.Li@Sun.COM pubretry.tv_sec = 60; 1440*7961SNatalie.Li@Sun.COM pubretry.tv_nsec = 0; 1441*7961SNatalie.Li@Sun.COM (void) cond_reltimedwait(&ad_queue.spq_cv, 1442*7961SNatalie.Li@Sun.COM &ad_queue.spq_mtx, &pubretry); 1443*7961SNatalie.Li@Sun.COM break; 1444*7961SNatalie.Li@Sun.COM } 1445*7961SNatalie.Li@Sun.COM } 14467348SJose.Borrego@Sun.COM 14477348SJose.Borrego@Sun.COM if (ad_queue.spq_state != SMB_SHR_PQS_PUBLISHING) { 14487348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 14497348SJose.Borrego@Sun.COM break; 14507348SJose.Borrego@Sun.COM } 14517348SJose.Borrego@Sun.COM 14527348SJose.Borrego@Sun.COM /* 1453*7961SNatalie.Li@Sun.COM * Transfer queued items to the local list so that 1454*7961SNatalie.Li@Sun.COM * the mutex can be released. 14557348SJose.Borrego@Sun.COM */ 14567348SJose.Borrego@Sun.COM while ((shr = list_head(&ad_queue.spq_list)) != NULL) { 14577348SJose.Borrego@Sun.COM list_remove(&ad_queue.spq_list, shr); 14587348SJose.Borrego@Sun.COM list_insert_tail(&publist, shr); 14597348SJose.Borrego@Sun.COM } 1460*7961SNatalie.Li@Sun.COM 14617348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 14627348SJose.Borrego@Sun.COM 1463*7961SNatalie.Li@Sun.COM if ((ah = smb_ads_open()) != NULL) { 1464*7961SNatalie.Li@Sun.COM smb_shr_publisher_send(ah, &publist, hostname); 1465*7961SNatalie.Li@Sun.COM smb_ads_close(ah); 1466*7961SNatalie.Li@Sun.COM } 14677348SJose.Borrego@Sun.COM } 14687348SJose.Borrego@Sun.COM 14697348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 1470*7961SNatalie.Li@Sun.COM smb_shr_publisher_flush(&ad_queue.spq_list); 14717348SJose.Borrego@Sun.COM list_destroy(&ad_queue.spq_list); 14727348SJose.Borrego@Sun.COM ad_queue.spq_state = SMB_SHR_PQS_NOQUEUE; 14737348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 14747348SJose.Borrego@Sun.COM 1475*7961SNatalie.Li@Sun.COM smb_shr_publisher_flush(&publist); 14767348SJose.Borrego@Sun.COM list_destroy(&publist); 14777348SJose.Borrego@Sun.COM return (NULL); 14787348SJose.Borrego@Sun.COM } 14797348SJose.Borrego@Sun.COM 14807348SJose.Borrego@Sun.COM /* 1481*7961SNatalie.Li@Sun.COM * Remove items from the specified queue and [un]publish them. 14827348SJose.Borrego@Sun.COM */ 14837348SJose.Borrego@Sun.COM static void 14847348SJose.Borrego@Sun.COM smb_shr_publisher_send(smb_ads_handle_t *ah, list_t *publist, const char *host) 14857348SJose.Borrego@Sun.COM { 14867348SJose.Borrego@Sun.COM smb_shr_pitem_t *shr; 14877348SJose.Borrego@Sun.COM 14887348SJose.Borrego@Sun.COM while ((shr = list_head(publist)) != NULL) { 1489*7961SNatalie.Li@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 1490*7961SNatalie.Li@Sun.COM if (ad_queue.spq_state != SMB_SHR_PQS_PUBLISHING) { 14917348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 1492*7961SNatalie.Li@Sun.COM return; 1493*7961SNatalie.Li@Sun.COM } 1494*7961SNatalie.Li@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 14957348SJose.Borrego@Sun.COM 1496*7961SNatalie.Li@Sun.COM list_remove(publist, shr); 1497*7961SNatalie.Li@Sun.COM 1498*7961SNatalie.Li@Sun.COM if (shr->spi_op == SMB_SHR_PUBLISH) 1499*7961SNatalie.Li@Sun.COM (void) smb_ads_publish_share(ah, shr->spi_name, 1500*7961SNatalie.Li@Sun.COM NULL, shr->spi_container, host); 1501*7961SNatalie.Li@Sun.COM else 1502*7961SNatalie.Li@Sun.COM (void) smb_ads_remove_share(ah, shr->spi_name, 1503*7961SNatalie.Li@Sun.COM NULL, shr->spi_container, host); 1504*7961SNatalie.Li@Sun.COM 15057348SJose.Borrego@Sun.COM free(shr); 15067348SJose.Borrego@Sun.COM } 15077348SJose.Borrego@Sun.COM } 1508*7961SNatalie.Li@Sun.COM 1509*7961SNatalie.Li@Sun.COM /* 1510*7961SNatalie.Li@Sun.COM * Flush all remaining items from the specified list/queue. 1511*7961SNatalie.Li@Sun.COM */ 1512*7961SNatalie.Li@Sun.COM static void 1513*7961SNatalie.Li@Sun.COM smb_shr_publisher_flush(list_t *lst) 1514*7961SNatalie.Li@Sun.COM { 1515*7961SNatalie.Li@Sun.COM smb_shr_pitem_t *shr; 1516*7961SNatalie.Li@Sun.COM 1517*7961SNatalie.Li@Sun.COM while ((shr = list_head(lst)) != NULL) { 1518*7961SNatalie.Li@Sun.COM list_remove(lst, shr); 1519*7961SNatalie.Li@Sun.COM free(shr); 1520*7961SNatalie.Li@Sun.COM } 1521*7961SNatalie.Li@Sun.COM } 1522