17052Samw /* 27052Samw * CDDL HEADER START 37052Samw * 47052Samw * The contents of this file are subject to the terms of the 57052Samw * Common Development and Distribution License (the "License"). 67052Samw * You may not use this file except in compliance with the License. 77052Samw * 87052Samw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97052Samw * or http://www.opensolaris.org/os/licensing. 107052Samw * See the License for the specific language governing permissions 117052Samw * and limitations under the License. 127052Samw * 137052Samw * When distributing Covered Code, include this CDDL HEADER in each 147052Samw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157052Samw * If applicable, add the following below this CDDL HEADER, with the 167052Samw * fields enclosed by brackets "[]" replaced with your own identifying 177052Samw * information: Portions Copyright [yyyy] [name of copyright owner] 187052Samw * 197052Samw * CDDL HEADER END 207052Samw */ 217052Samw /* 228474SJose.Borrego@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 237052Samw * Use is subject to license terms. 247052Samw */ 257052Samw 267052Samw /* 277961SNatalie.Li@Sun.COM * SMB/CIFS share cache implementation. 287052Samw */ 297052Samw 307052Samw #include <errno.h> 317052Samw #include <synch.h> 327052Samw #include <stdlib.h> 337052Samw #include <strings.h> 347052Samw #include <syslog.h> 357052Samw #include <thread.h> 367052Samw #include <pthread.h> 377348SJose.Borrego@Sun.COM #include <assert.h> 387961SNatalie.Li@Sun.COM #include <libshare.h> 398845Samw@Sun.COM #include <libzfs.h> 409832Samw@Sun.COM #include <priv_utils.h> 419832Samw@Sun.COM #include <sys/types.h> 429832Samw@Sun.COM #include <sys/wait.h> 439832Samw@Sun.COM #include <unistd.h> 449832Samw@Sun.COM #include <pwd.h> 459832Samw@Sun.COM #include <signal.h> 467052Samw 477052Samw #include <smbsrv/libsmb.h> 487052Samw #include <smbsrv/libsmbns.h> 497588Samw@Sun.COM #include <smbsrv/libmlsvc.h> 507052Samw 517052Samw #include <smbsrv/lm.h> 527052Samw #include <smbsrv/smb_share.h> 537052Samw #include <smbsrv/cifs.h> 547961SNatalie.Li@Sun.COM #include <smbsrv/nterror.h> 55*10504SKeyur.Desai@Sun.COM #include <mlsvc.h> 567052Samw 577961SNatalie.Li@Sun.COM #define SMB_SHR_ERROR_THRESHOLD 3 587052Samw 598334SJose.Borrego@Sun.COM #define SMB_SHR_CSC_BUFSZ 64 608334SJose.Borrego@Sun.COM 619832Samw@Sun.COM static struct { 629832Samw@Sun.COM char *value; 639832Samw@Sun.COM uint32_t flag; 649832Samw@Sun.COM } cscopt[] = { 659832Samw@Sun.COM { "disabled", SMB_SHRF_CSC_DISABLED }, 669832Samw@Sun.COM { "manual", SMB_SHRF_CSC_MANUAL }, 679832Samw@Sun.COM { "auto", SMB_SHRF_CSC_AUTO }, 689832Samw@Sun.COM { "vdo", SMB_SHRF_CSC_VDO } 699832Samw@Sun.COM }; 709832Samw@Sun.COM 717348SJose.Borrego@Sun.COM /* 727348SJose.Borrego@Sun.COM * Cache functions and vars 737348SJose.Borrego@Sun.COM */ 747961SNatalie.Li@Sun.COM #define SMB_SHR_HTAB_SZ 1024 757052Samw 767961SNatalie.Li@Sun.COM /* 777961SNatalie.Li@Sun.COM * Cache handle 787961SNatalie.Li@Sun.COM * 797961SNatalie.Li@Sun.COM * Shares cache is a hash table. 807961SNatalie.Li@Sun.COM * 817961SNatalie.Li@Sun.COM * sc_cache pointer to hash table handle 827961SNatalie.Li@Sun.COM * sc_cache_lck synchronize cache read/write accesses 837961SNatalie.Li@Sun.COM * sc_state cache state machine values 847961SNatalie.Li@Sun.COM * sc_nops number of inflight/pending cache operations 857961SNatalie.Li@Sun.COM * sc_mtx protects handle fields 867961SNatalie.Li@Sun.COM */ 877961SNatalie.Li@Sun.COM typedef struct smb_shr_cache { 887961SNatalie.Li@Sun.COM HT_HANDLE *sc_cache; 897961SNatalie.Li@Sun.COM rwlock_t sc_cache_lck; 907961SNatalie.Li@Sun.COM mutex_t sc_mtx; 917961SNatalie.Li@Sun.COM cond_t sc_cv; 927961SNatalie.Li@Sun.COM uint32_t sc_state; 937961SNatalie.Li@Sun.COM uint32_t sc_nops; 947961SNatalie.Li@Sun.COM } smb_shr_cache_t; 957961SNatalie.Li@Sun.COM 967961SNatalie.Li@Sun.COM /* 977961SNatalie.Li@Sun.COM * Cache states 987961SNatalie.Li@Sun.COM */ 997961SNatalie.Li@Sun.COM #define SMB_SHR_CACHE_STATE_NONE 0 1007961SNatalie.Li@Sun.COM #define SMB_SHR_CACHE_STATE_CREATED 1 1017961SNatalie.Li@Sun.COM #define SMB_SHR_CACHE_STATE_DESTROYING 2 1027961SNatalie.Li@Sun.COM 1037961SNatalie.Li@Sun.COM /* 1047961SNatalie.Li@Sun.COM * Cache lock modes 1057961SNatalie.Li@Sun.COM */ 1067961SNatalie.Li@Sun.COM #define SMB_SHR_CACHE_RDLOCK 0 1077961SNatalie.Li@Sun.COM #define SMB_SHR_CACHE_WRLOCK 1 1087961SNatalie.Li@Sun.COM 1097961SNatalie.Li@Sun.COM static smb_shr_cache_t smb_shr_cache; 1107052Samw 1117052Samw static uint32_t smb_shr_cache_create(void); 1127348SJose.Borrego@Sun.COM static void smb_shr_cache_destroy(void); 1137961SNatalie.Li@Sun.COM static uint32_t smb_shr_cache_lock(int); 1147961SNatalie.Li@Sun.COM static void smb_shr_cache_unlock(void); 1157961SNatalie.Li@Sun.COM static int smb_shr_cache_count(void); 1167961SNatalie.Li@Sun.COM static smb_share_t *smb_shr_cache_iterate(smb_shriter_t *); 1177961SNatalie.Li@Sun.COM 1187961SNatalie.Li@Sun.COM static smb_share_t *smb_shr_cache_findent(char *); 1197348SJose.Borrego@Sun.COM static uint32_t smb_shr_cache_addent(smb_share_t *); 1207348SJose.Borrego@Sun.COM static void smb_shr_cache_delent(char *); 1217348SJose.Borrego@Sun.COM static void smb_shr_cache_freent(HT_ITEM *); 1227052Samw 1237348SJose.Borrego@Sun.COM /* 1247348SJose.Borrego@Sun.COM * sharemgr functions 1257348SJose.Borrego@Sun.COM */ 1267961SNatalie.Li@Sun.COM static void *smb_shr_sa_loadall(void *); 1277961SNatalie.Li@Sun.COM static void smb_shr_sa_loadgrp(sa_group_t); 1287961SNatalie.Li@Sun.COM static uint32_t smb_shr_sa_load(sa_share_t, sa_resource_t); 1298334SJose.Borrego@Sun.COM static uint32_t smb_shr_sa_loadbyname(char *); 1307961SNatalie.Li@Sun.COM static uint32_t smb_shr_sa_get(sa_share_t, sa_resource_t, smb_share_t *); 1317052Samw 1327052Samw /* 1338845Samw@Sun.COM * .ZFS management functions 1348845Samw@Sun.COM */ 1358845Samw@Sun.COM static void smb_shr_zfs_add(smb_share_t *); 1368845Samw@Sun.COM static void smb_shr_zfs_remove(smb_share_t *); 1378845Samw@Sun.COM static void smb_shr_zfs_rename(smb_share_t *, smb_share_t *); 1388845Samw@Sun.COM 1398845Samw@Sun.COM /* 1407348SJose.Borrego@Sun.COM * share publishing 1417348SJose.Borrego@Sun.COM */ 1427348SJose.Borrego@Sun.COM #define SMB_SHR_PUBLISH 0 1437348SJose.Borrego@Sun.COM #define SMB_SHR_UNPUBLISH 1 1447348SJose.Borrego@Sun.COM 1457348SJose.Borrego@Sun.COM typedef struct smb_shr_pitem { 1467348SJose.Borrego@Sun.COM list_node_t spi_lnd; 1477348SJose.Borrego@Sun.COM char spi_name[MAXNAMELEN]; 1487348SJose.Borrego@Sun.COM char spi_container[MAXPATHLEN]; 1497348SJose.Borrego@Sun.COM char spi_op; 1507348SJose.Borrego@Sun.COM } smb_shr_pitem_t; 1517348SJose.Borrego@Sun.COM 1527348SJose.Borrego@Sun.COM /* 1537348SJose.Borrego@Sun.COM * publish queue states 1547348SJose.Borrego@Sun.COM */ 1557348SJose.Borrego@Sun.COM #define SMB_SHR_PQS_NOQUEUE 0 1567348SJose.Borrego@Sun.COM #define SMB_SHR_PQS_READY 1 /* the queue is ready */ 1577348SJose.Borrego@Sun.COM #define SMB_SHR_PQS_PUBLISHING 2 /* publisher thread is running */ 1587348SJose.Borrego@Sun.COM #define SMB_SHR_PQS_STOPPING 3 1597348SJose.Borrego@Sun.COM 1607348SJose.Borrego@Sun.COM /* 1617348SJose.Borrego@Sun.COM * share publishing queue 1627348SJose.Borrego@Sun.COM */ 1637348SJose.Borrego@Sun.COM typedef struct smb_shr_pqueue { 1647348SJose.Borrego@Sun.COM list_t spq_list; 1657348SJose.Borrego@Sun.COM mutex_t spq_mtx; 1667348SJose.Borrego@Sun.COM cond_t spq_cv; 1677348SJose.Borrego@Sun.COM uint32_t spq_state; 1687348SJose.Borrego@Sun.COM } smb_shr_pqueue_t; 1697348SJose.Borrego@Sun.COM 1707348SJose.Borrego@Sun.COM static smb_shr_pqueue_t ad_queue; 1717348SJose.Borrego@Sun.COM 1727348SJose.Borrego@Sun.COM static int smb_shr_publisher_start(void); 1737348SJose.Borrego@Sun.COM static void smb_shr_publisher_stop(void); 1747348SJose.Borrego@Sun.COM static void smb_shr_publisher_send(smb_ads_handle_t *, list_t *, const char *); 1757961SNatalie.Li@Sun.COM static void smb_shr_publisher_queue(const char *, const char *, char); 1767348SJose.Borrego@Sun.COM static void *smb_shr_publisher(void *); 1777961SNatalie.Li@Sun.COM static void smb_shr_publisher_flush(list_t *); 1787961SNatalie.Li@Sun.COM static void smb_shr_publish(const char *, const char *); 1797961SNatalie.Li@Sun.COM static void smb_shr_unpublish(const char *, const char *); 1807348SJose.Borrego@Sun.COM 1817348SJose.Borrego@Sun.COM /* 1827961SNatalie.Li@Sun.COM * Utility/helper functions 1837961SNatalie.Li@Sun.COM */ 1848334SJose.Borrego@Sun.COM static uint32_t smb_shr_lookup(char *, smb_share_t *); 1857961SNatalie.Li@Sun.COM static uint32_t smb_shr_addipc(void); 1867961SNatalie.Li@Sun.COM static void smb_shr_set_oemname(smb_share_t *); 1879832Samw@Sun.COM static int smb_shr_enable_all_privs(void); 1889832Samw@Sun.COM static int smb_shr_expand_subs(char **, smb_share_t *, smb_execsub_info_t *); 1899832Samw@Sun.COM static char **smb_shr_tokenize_cmd(char *); 1909832Samw@Sun.COM static void smb_shr_sig_abnormal_term(int); 1919832Samw@Sun.COM static void smb_shr_sig_child(int); 1929832Samw@Sun.COM static void smb_shr_get_exec_info(void); 1939832Samw@Sun.COM static void smb_shr_set_exec_flags(smb_share_t *); 1949832Samw@Sun.COM static void smb_shr_sa_guest_option(const char *, smb_share_t *); 1957961SNatalie.Li@Sun.COM 1968474SJose.Borrego@Sun.COM 1978474SJose.Borrego@Sun.COM /* 1988474SJose.Borrego@Sun.COM * libshare handle and synchronization 1998474SJose.Borrego@Sun.COM */ 2008474SJose.Borrego@Sun.COM typedef struct smb_sa_handle { 2018474SJose.Borrego@Sun.COM sa_handle_t sa_handle; 2028474SJose.Borrego@Sun.COM mutex_t sa_mtx; 2038474SJose.Borrego@Sun.COM boolean_t sa_in_service; 2048474SJose.Borrego@Sun.COM } smb_sa_handle_t; 2058474SJose.Borrego@Sun.COM 2068474SJose.Borrego@Sun.COM static smb_sa_handle_t smb_sa_handle; 2078474SJose.Borrego@Sun.COM 2089832Samw@Sun.COM static int smb_shr_exec_flags; 2099832Samw@Sun.COM static char smb_shr_exec_map[MAXPATHLEN]; 2109832Samw@Sun.COM static char smb_shr_exec_unmap[MAXPATHLEN]; 2119832Samw@Sun.COM static mutex_t smb_shr_exec_mtx; 2129832Samw@Sun.COM 2137961SNatalie.Li@Sun.COM /* 214*10504SKeyur.Desai@Sun.COM * Semaphore held during temporary, process-wide changes 215*10504SKeyur.Desai@Sun.COM * such as process privileges. It is a seamaphore and 216*10504SKeyur.Desai@Sun.COM * not a mutex so a child of fork can reset it. 217*10504SKeyur.Desai@Sun.COM */ 218*10504SKeyur.Desai@Sun.COM static sema_t smb_proc_sem = DEFAULTSEMA; 219*10504SKeyur.Desai@Sun.COM 220*10504SKeyur.Desai@Sun.COM /* 2218334SJose.Borrego@Sun.COM * Creates and initializes the cache and starts the publisher 2228334SJose.Borrego@Sun.COM * thread. 2237052Samw */ 2247052Samw int 2257052Samw smb_shr_start(void) 2267052Samw { 2278474SJose.Borrego@Sun.COM (void) mutex_lock(&smb_sa_handle.sa_mtx); 2288474SJose.Borrego@Sun.COM smb_sa_handle.sa_in_service = B_TRUE; 2298474SJose.Borrego@Sun.COM (void) mutex_unlock(&smb_sa_handle.sa_mtx); 2308474SJose.Borrego@Sun.COM 2317961SNatalie.Li@Sun.COM if (smb_shr_cache_create() != NERR_Success) 2327961SNatalie.Li@Sun.COM return (ENOMEM); 2337961SNatalie.Li@Sun.COM 2347961SNatalie.Li@Sun.COM if (smb_shr_addipc() != NERR_Success) 2357961SNatalie.Li@Sun.COM return (ENOMEM); 2367961SNatalie.Li@Sun.COM 2378334SJose.Borrego@Sun.COM return (smb_shr_publisher_start()); 2388334SJose.Borrego@Sun.COM } 2398334SJose.Borrego@Sun.COM 2408334SJose.Borrego@Sun.COM void 2418334SJose.Borrego@Sun.COM smb_shr_stop(void) 2428334SJose.Borrego@Sun.COM { 2438334SJose.Borrego@Sun.COM smb_shr_cache_destroy(); 2448334SJose.Borrego@Sun.COM smb_shr_publisher_stop(); 2458474SJose.Borrego@Sun.COM 2468474SJose.Borrego@Sun.COM (void) mutex_lock(&smb_sa_handle.sa_mtx); 2478474SJose.Borrego@Sun.COM smb_sa_handle.sa_in_service = B_FALSE; 2488474SJose.Borrego@Sun.COM 2498474SJose.Borrego@Sun.COM if (smb_sa_handle.sa_handle != NULL) { 2508474SJose.Borrego@Sun.COM sa_fini(smb_sa_handle.sa_handle); 2518474SJose.Borrego@Sun.COM smb_sa_handle.sa_handle = NULL; 2528474SJose.Borrego@Sun.COM } 2538474SJose.Borrego@Sun.COM 2548474SJose.Borrego@Sun.COM (void) mutex_unlock(&smb_sa_handle.sa_mtx); 2558474SJose.Borrego@Sun.COM } 2568474SJose.Borrego@Sun.COM 2578474SJose.Borrego@Sun.COM /* 2588474SJose.Borrego@Sun.COM * Get a handle and exclusive access to the libshare API. 2598474SJose.Borrego@Sun.COM */ 2608474SJose.Borrego@Sun.COM sa_handle_t 2618474SJose.Borrego@Sun.COM smb_shr_sa_enter(void) 2628474SJose.Borrego@Sun.COM { 2638474SJose.Borrego@Sun.COM (void) mutex_lock(&smb_sa_handle.sa_mtx); 2648474SJose.Borrego@Sun.COM if (!smb_sa_handle.sa_in_service) { 2658474SJose.Borrego@Sun.COM (void) mutex_unlock(&smb_sa_handle.sa_mtx); 2668474SJose.Borrego@Sun.COM return (NULL); 2678474SJose.Borrego@Sun.COM } 2688474SJose.Borrego@Sun.COM 2698474SJose.Borrego@Sun.COM if (smb_sa_handle.sa_handle == NULL) { 2708474SJose.Borrego@Sun.COM smb_sa_handle.sa_handle = sa_init(SA_INIT_SHARE_API); 2718474SJose.Borrego@Sun.COM if (smb_sa_handle.sa_handle == NULL) { 2728474SJose.Borrego@Sun.COM syslog(LOG_ERR, "share: failed to get libshare handle"); 2738474SJose.Borrego@Sun.COM (void) mutex_unlock(&smb_sa_handle.sa_mtx); 2748474SJose.Borrego@Sun.COM return (NULL); 2758474SJose.Borrego@Sun.COM } 2768474SJose.Borrego@Sun.COM } 2778474SJose.Borrego@Sun.COM 2788474SJose.Borrego@Sun.COM return (smb_sa_handle.sa_handle); 2798474SJose.Borrego@Sun.COM } 2808474SJose.Borrego@Sun.COM 2818474SJose.Borrego@Sun.COM /* 2828474SJose.Borrego@Sun.COM * Release exclusive access to the libshare API. 2838474SJose.Borrego@Sun.COM */ 2848474SJose.Borrego@Sun.COM void 2858474SJose.Borrego@Sun.COM smb_shr_sa_exit(void) 2868474SJose.Borrego@Sun.COM { 2878474SJose.Borrego@Sun.COM (void) mutex_unlock(&smb_sa_handle.sa_mtx); 2888334SJose.Borrego@Sun.COM } 2898334SJose.Borrego@Sun.COM 2908334SJose.Borrego@Sun.COM /* 2918334SJose.Borrego@Sun.COM * Launches a thread to populate the share cache by share information 2928334SJose.Borrego@Sun.COM * stored in sharemgr 2938334SJose.Borrego@Sun.COM */ 2948334SJose.Borrego@Sun.COM int 2958334SJose.Borrego@Sun.COM smb_shr_load(void) 2968334SJose.Borrego@Sun.COM { 2978334SJose.Borrego@Sun.COM pthread_t load_thr; 2988334SJose.Borrego@Sun.COM pthread_attr_t tattr; 2998334SJose.Borrego@Sun.COM int rc; 3008334SJose.Borrego@Sun.COM 3017348SJose.Borrego@Sun.COM (void) pthread_attr_init(&tattr); 3027348SJose.Borrego@Sun.COM (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); 3037961SNatalie.Li@Sun.COM rc = pthread_create(&load_thr, &tattr, smb_shr_sa_loadall, 0); 3047348SJose.Borrego@Sun.COM (void) pthread_attr_destroy(&tattr); 3057052Samw 3069832Samw@Sun.COM smb_shr_get_exec_info(); 3079832Samw@Sun.COM 3087052Samw return (rc); 3097052Samw } 3107052Samw 3117052Samw /* 3127348SJose.Borrego@Sun.COM * Return the total number of shares 3137052Samw */ 3147052Samw int 3157052Samw smb_shr_count(void) 3167052Samw { 3177961SNatalie.Li@Sun.COM int n_shares = 0; 3187052Samw 3197961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) { 3207961SNatalie.Li@Sun.COM n_shares = smb_shr_cache_count(); 3217961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 3227961SNatalie.Li@Sun.COM } 3237052Samw 3247052Samw return (n_shares); 3257052Samw } 3267052Samw 3277052Samw /* 3287052Samw * smb_shr_iterinit 3297052Samw * 3307348SJose.Borrego@Sun.COM * Initialize given iterator for traversing hash table. 3317052Samw */ 3327052Samw void 3337348SJose.Borrego@Sun.COM smb_shr_iterinit(smb_shriter_t *shi) 3347052Samw { 3357052Samw bzero(shi, sizeof (smb_shriter_t)); 3367348SJose.Borrego@Sun.COM shi->si_first = B_TRUE; 3377052Samw } 3387052Samw 3397052Samw /* 3407052Samw * smb_shr_iterate 3417052Samw * 3427052Samw * Iterate on the shares in the hash table. The iterator must be initialized 3437052Samw * before the first iteration. On subsequent calls, the iterator must be 3447052Samw * passed unchanged. 3457052Samw * 3467052Samw * Returns NULL on failure or when all shares are visited, otherwise 3477052Samw * returns information of visited share. 3487052Samw */ 3497052Samw smb_share_t * 3507052Samw smb_shr_iterate(smb_shriter_t *shi) 3517052Samw { 3527348SJose.Borrego@Sun.COM smb_share_t *share = NULL; 3537961SNatalie.Li@Sun.COM smb_share_t *cached_si; 3547052Samw 3557961SNatalie.Li@Sun.COM if (shi == NULL) 3567052Samw return (NULL); 3577052Samw 3587961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) { 3597961SNatalie.Li@Sun.COM if ((cached_si = smb_shr_cache_iterate(shi)) != NULL) { 3607961SNatalie.Li@Sun.COM share = &shi->si_share; 3617961SNatalie.Li@Sun.COM bcopy(cached_si, share, sizeof (smb_share_t)); 3629832Samw@Sun.COM smb_shr_set_exec_flags(share); 3637961SNatalie.Li@Sun.COM } 3647961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 3657052Samw } 3667052Samw 3677348SJose.Borrego@Sun.COM return (share); 3687052Samw } 3697052Samw 3707052Samw /* 3717961SNatalie.Li@Sun.COM * Adds the given share to cache, publishes the share in ADS 3727961SNatalie.Li@Sun.COM * if it has an AD container, calls kernel to take a hold on 3737961SNatalie.Li@Sun.COM * the shared file system. If it can't take a hold on the 3747961SNatalie.Li@Sun.COM * shared file system, it's either because shared directory 3757961SNatalie.Li@Sun.COM * does not exist or some other error has occurred, in any 3767961SNatalie.Li@Sun.COM * case the share is removed from the cache. 3777052Samw * 3787961SNatalie.Li@Sun.COM * If the specified share is an autohome share which already 3797961SNatalie.Li@Sun.COM * exists in the cache, just increments the reference count. 3807052Samw */ 3817052Samw uint32_t 3827961SNatalie.Li@Sun.COM smb_shr_add(smb_share_t *si) 3837052Samw { 3847961SNatalie.Li@Sun.COM smb_share_t *cached_si; 3857961SNatalie.Li@Sun.COM uint32_t status; 3867348SJose.Borrego@Sun.COM int rc; 3877052Samw 3887348SJose.Borrego@Sun.COM assert(si != NULL); 3897052Samw 3907348SJose.Borrego@Sun.COM if (!smb_shr_chkname(si->shr_name)) 3917348SJose.Borrego@Sun.COM return (ERROR_INVALID_NAME); 3927052Samw 3937961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success) 3947961SNatalie.Li@Sun.COM return (NERR_InternalError); 3957052Samw 3967961SNatalie.Li@Sun.COM cached_si = smb_shr_cache_findent(si->shr_name); 3977961SNatalie.Li@Sun.COM if (cached_si) { 3987961SNatalie.Li@Sun.COM if (si->shr_flags & SMB_SHRF_AUTOHOME) { 3997961SNatalie.Li@Sun.COM cached_si->shr_refcnt++; 4007961SNatalie.Li@Sun.COM status = NERR_Success; 4017961SNatalie.Li@Sun.COM } else { 4027961SNatalie.Li@Sun.COM status = NERR_DuplicateShare; 4037961SNatalie.Li@Sun.COM } 4047961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 4057052Samw return (status); 4067052Samw } 4077052Samw 4087961SNatalie.Li@Sun.COM if ((status = smb_shr_cache_addent(si)) != NERR_Success) { 4097961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 4107961SNatalie.Li@Sun.COM return (status); 4117961SNatalie.Li@Sun.COM } 4127961SNatalie.Li@Sun.COM 4137961SNatalie.Li@Sun.COM /* don't hold the lock across door call */ 4147961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 4157961SNatalie.Li@Sun.COM 4167961SNatalie.Li@Sun.COM /* call kernel to take a hold on the shared file system */ 41710122SJordan.Brown@Sun.COM rc = smb_kmod_share(si->shr_path, si->shr_name); 4187348SJose.Borrego@Sun.COM 4197348SJose.Borrego@Sun.COM if (rc == 0) { 4207961SNatalie.Li@Sun.COM smb_shr_publish(si->shr_name, si->shr_container); 4218845Samw@Sun.COM 4228845Samw@Sun.COM /* If path is ZFS, add the .zfs/shares/<share> entry. */ 4238845Samw@Sun.COM smb_shr_zfs_add(si); 4248845Samw@Sun.COM 4257961SNatalie.Li@Sun.COM return (NERR_Success); 4267052Samw } 4277052Samw 4287961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) == NERR_Success) { 4297961SNatalie.Li@Sun.COM smb_shr_cache_delent(si->shr_name); 4307961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 4317961SNatalie.Li@Sun.COM } 4327052Samw 4337052Samw /* 4347348SJose.Borrego@Sun.COM * rc == ENOENT means the shared directory doesn't exist 4357052Samw */ 4367348SJose.Borrego@Sun.COM return ((rc == ENOENT) ? NERR_UnknownDevDir : NERR_InternalError); 4377052Samw } 4387052Samw 4397052Samw /* 4407961SNatalie.Li@Sun.COM * Removes the specified share from cache, removes it from AD 4417961SNatalie.Li@Sun.COM * if it has an AD container, and calls the kernel to release 4427961SNatalie.Li@Sun.COM * the hold on the shared file system. 4437052Samw * 4447961SNatalie.Li@Sun.COM * If this is an autohome share then decrement the reference 4457961SNatalie.Li@Sun.COM * count. If it reaches 0 then it proceeds with removing steps. 4467052Samw */ 4477348SJose.Borrego@Sun.COM uint32_t 4487961SNatalie.Li@Sun.COM smb_shr_remove(char *sharename) 4497052Samw { 4507961SNatalie.Li@Sun.COM smb_share_t *si; 4517961SNatalie.Li@Sun.COM char path[MAXPATHLEN]; 4527961SNatalie.Li@Sun.COM char container[MAXPATHLEN]; 4537348SJose.Borrego@Sun.COM 4547348SJose.Borrego@Sun.COM assert(sharename != NULL); 4557348SJose.Borrego@Sun.COM 4567961SNatalie.Li@Sun.COM if (!smb_shr_chkname(sharename)) 4577961SNatalie.Li@Sun.COM return (ERROR_INVALID_NAME); 4587052Samw 4597961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success) 4607961SNatalie.Li@Sun.COM return (NERR_InternalError); 4617961SNatalie.Li@Sun.COM 4627961SNatalie.Li@Sun.COM if ((si = smb_shr_cache_findent(sharename)) == NULL) { 4637961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 4647961SNatalie.Li@Sun.COM return (NERR_NetNameNotFound); 4657961SNatalie.Li@Sun.COM } 4667348SJose.Borrego@Sun.COM 4677961SNatalie.Li@Sun.COM if (si->shr_type & STYPE_IPC) { 4687961SNatalie.Li@Sun.COM /* IPC$ share cannot be removed */ 4697961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 4707961SNatalie.Li@Sun.COM return (ERROR_ACCESS_DENIED); 4717961SNatalie.Li@Sun.COM } 4727961SNatalie.Li@Sun.COM 4737961SNatalie.Li@Sun.COM if (si->shr_flags & SMB_SHRF_AUTOHOME) { 4747961SNatalie.Li@Sun.COM if ((--si->shr_refcnt) > 0) { 4757961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 4767961SNatalie.Li@Sun.COM return (NERR_Success); 4777348SJose.Borrego@Sun.COM } 4787052Samw } 4797052Samw 4808845Samw@Sun.COM /* 4818845Samw@Sun.COM * If path is ZFS, remove the .zfs/shares/<share> entry. Need 4828845Samw@Sun.COM * to remove before cleanup of cache occurs. 4838845Samw@Sun.COM */ 4848845Samw@Sun.COM smb_shr_zfs_remove(si); 4858845Samw@Sun.COM 4867961SNatalie.Li@Sun.COM (void) strlcpy(path, si->shr_path, sizeof (path)); 4877961SNatalie.Li@Sun.COM (void) strlcpy(container, si->shr_container, sizeof (container)); 4887961SNatalie.Li@Sun.COM smb_shr_cache_delent(sharename); 4897961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 4907348SJose.Borrego@Sun.COM 4917961SNatalie.Li@Sun.COM smb_shr_unpublish(sharename, container); 4927961SNatalie.Li@Sun.COM 4937961SNatalie.Li@Sun.COM /* call kernel to release the hold on the shared file system */ 49410122SJordan.Brown@Sun.COM (void) smb_kmod_unshare(path, sharename); 4957348SJose.Borrego@Sun.COM 4967052Samw return (NERR_Success); 4977052Samw } 4987052Samw 4997052Samw /* 5007052Samw * Rename a share. Check that the current name exists and the new name 5017052Samw * doesn't exist. The rename is performed by deleting the current share 5027052Samw * definition and creating a new share with the new name. 5037052Samw */ 5047052Samw uint32_t 5057348SJose.Borrego@Sun.COM smb_shr_rename(char *from_name, char *to_name) 5067052Samw { 5077961SNatalie.Li@Sun.COM smb_share_t *from_si; 5087961SNatalie.Li@Sun.COM smb_share_t to_si; 5097348SJose.Borrego@Sun.COM uint32_t status; 5107348SJose.Borrego@Sun.COM 5117348SJose.Borrego@Sun.COM assert((from_name != NULL) && (to_name != NULL)); 5127052Samw 5137348SJose.Borrego@Sun.COM if (!smb_shr_chkname(from_name) || !smb_shr_chkname(to_name)) 5147348SJose.Borrego@Sun.COM return (ERROR_INVALID_NAME); 5157052Samw 5167961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success) 5177961SNatalie.Li@Sun.COM return (NERR_InternalError); 5187961SNatalie.Li@Sun.COM 5197961SNatalie.Li@Sun.COM if ((from_si = smb_shr_cache_findent(from_name)) == NULL) { 5207961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 5217052Samw return (NERR_NetNameNotFound); 5227961SNatalie.Li@Sun.COM } 5237052Samw 5247961SNatalie.Li@Sun.COM if (from_si->shr_type & STYPE_IPC) { 5257961SNatalie.Li@Sun.COM /* IPC$ share cannot be renamed */ 5267961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 5277961SNatalie.Li@Sun.COM return (ERROR_ACCESS_DENIED); 5287961SNatalie.Li@Sun.COM } 5297961SNatalie.Li@Sun.COM 5307961SNatalie.Li@Sun.COM if (smb_shr_cache_findent(to_name) != NULL) { 5317961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 5327052Samw return (NERR_DuplicateShare); 5337961SNatalie.Li@Sun.COM } 5347052Samw 5357961SNatalie.Li@Sun.COM bcopy(from_si, &to_si, sizeof (smb_share_t)); 5367961SNatalie.Li@Sun.COM (void) strlcpy(to_si.shr_name, to_name, sizeof (to_si.shr_name)); 5377961SNatalie.Li@Sun.COM 5388845Samw@Sun.COM /* If path is ZFS, rename the .zfs/shares/<share> entry. */ 5398845Samw@Sun.COM smb_shr_zfs_rename(from_si, &to_si); 5408845Samw@Sun.COM 5417961SNatalie.Li@Sun.COM if ((status = smb_shr_cache_addent(&to_si)) != NERR_Success) { 5427961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 5437348SJose.Borrego@Sun.COM return (status); 5447961SNatalie.Li@Sun.COM } 5457348SJose.Borrego@Sun.COM 5467348SJose.Borrego@Sun.COM smb_shr_cache_delent(from_name); 5477961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 5487961SNatalie.Li@Sun.COM 5497961SNatalie.Li@Sun.COM smb_shr_unpublish(from_name, to_si.shr_container); 5507961SNatalie.Li@Sun.COM smb_shr_publish(to_name, to_si.shr_container); 5517348SJose.Borrego@Sun.COM 5527348SJose.Borrego@Sun.COM return (NERR_Success); 5537348SJose.Borrego@Sun.COM } 5547348SJose.Borrego@Sun.COM 5557348SJose.Borrego@Sun.COM /* 5567348SJose.Borrego@Sun.COM * Load the information for the specified share into the supplied share 5577348SJose.Borrego@Sun.COM * info structure. 5588334SJose.Borrego@Sun.COM * 5598334SJose.Borrego@Sun.COM * First looks up the cache to see if the specified share exists, if there 5608334SJose.Borrego@Sun.COM * is a miss then it looks up sharemgr. 5617348SJose.Borrego@Sun.COM */ 5627348SJose.Borrego@Sun.COM uint32_t 5637348SJose.Borrego@Sun.COM smb_shr_get(char *sharename, smb_share_t *si) 5647348SJose.Borrego@Sun.COM { 5658334SJose.Borrego@Sun.COM uint32_t status; 5667348SJose.Borrego@Sun.COM 5677961SNatalie.Li@Sun.COM if (sharename == NULL || *sharename == '\0') 5687961SNatalie.Li@Sun.COM return (NERR_NetNameNotFound); 5697348SJose.Borrego@Sun.COM 5708334SJose.Borrego@Sun.COM if ((status = smb_shr_lookup(sharename, si)) == NERR_Success) 5718334SJose.Borrego@Sun.COM return (status); 5727961SNatalie.Li@Sun.COM 5738334SJose.Borrego@Sun.COM if ((status = smb_shr_sa_loadbyname(sharename)) == NERR_Success) 5748334SJose.Borrego@Sun.COM status = smb_shr_lookup(sharename, si); 5757348SJose.Borrego@Sun.COM 5767961SNatalie.Li@Sun.COM return (status); 5777348SJose.Borrego@Sun.COM } 5787348SJose.Borrego@Sun.COM 5797348SJose.Borrego@Sun.COM /* 5807348SJose.Borrego@Sun.COM * Modifies an existing share. Properties that can be modified are: 5817348SJose.Borrego@Sun.COM * 5827348SJose.Borrego@Sun.COM * o comment 5837348SJose.Borrego@Sun.COM * o AD container 5847961SNatalie.Li@Sun.COM * o host access 585*10504SKeyur.Desai@Sun.COM * o abe 5867348SJose.Borrego@Sun.COM */ 5877348SJose.Borrego@Sun.COM uint32_t 5887961SNatalie.Li@Sun.COM smb_shr_modify(smb_share_t *new_si) 5897348SJose.Borrego@Sun.COM { 5907961SNatalie.Li@Sun.COM smb_share_t *si; 5917348SJose.Borrego@Sun.COM boolean_t adc_changed = B_FALSE; 5927961SNatalie.Li@Sun.COM char old_container[MAXPATHLEN]; 593*10504SKeyur.Desai@Sun.COM uint32_t catia, cscflg, access, abe; 5947348SJose.Borrego@Sun.COM 5957961SNatalie.Li@Sun.COM assert(new_si != NULL); 5967348SJose.Borrego@Sun.COM 5977961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success) 5987961SNatalie.Li@Sun.COM return (NERR_InternalError); 5997348SJose.Borrego@Sun.COM 6007961SNatalie.Li@Sun.COM if ((si = smb_shr_cache_findent(new_si->shr_name)) == NULL) { 6017961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 6027961SNatalie.Li@Sun.COM return (NERR_NetNameNotFound); 6037961SNatalie.Li@Sun.COM } 6047348SJose.Borrego@Sun.COM 6057961SNatalie.Li@Sun.COM if (si->shr_type & STYPE_IPC) { 6067961SNatalie.Li@Sun.COM /* IPC$ share cannot be modified */ 6077961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 6087961SNatalie.Li@Sun.COM return (ERROR_ACCESS_DENIED); 6097348SJose.Borrego@Sun.COM } 6107348SJose.Borrego@Sun.COM 6118474SJose.Borrego@Sun.COM (void) strlcpy(si->shr_cmnt, new_si->shr_cmnt, sizeof (si->shr_cmnt)); 6127961SNatalie.Li@Sun.COM 6137961SNatalie.Li@Sun.COM adc_changed = (strcmp(new_si->shr_container, si->shr_container) != 0); 6147961SNatalie.Li@Sun.COM if (adc_changed) { 6157961SNatalie.Li@Sun.COM /* save current container - needed for unpublishing */ 6167961SNatalie.Li@Sun.COM (void) strlcpy(old_container, si->shr_container, 6177961SNatalie.Li@Sun.COM sizeof (old_container)); 6187961SNatalie.Li@Sun.COM (void) strlcpy(si->shr_container, new_si->shr_container, 6197961SNatalie.Li@Sun.COM sizeof (si->shr_container)); 6207348SJose.Borrego@Sun.COM } 6217348SJose.Borrego@Sun.COM 622*10504SKeyur.Desai@Sun.COM abe = (new_si->shr_flags & SMB_SHRF_ABE); 623*10504SKeyur.Desai@Sun.COM si->shr_flags &= ~SMB_SHRF_ABE; 624*10504SKeyur.Desai@Sun.COM si->shr_flags |= abe; 625*10504SKeyur.Desai@Sun.COM 6269231SAfshin.Ardakani@Sun.COM catia = (new_si->shr_flags & SMB_SHRF_CATIA); 6279231SAfshin.Ardakani@Sun.COM si->shr_flags &= ~SMB_SHRF_CATIA; 6289231SAfshin.Ardakani@Sun.COM si->shr_flags |= catia; 6299231SAfshin.Ardakani@Sun.COM 6309832Samw@Sun.COM cscflg = (new_si->shr_flags & SMB_SHRF_CSC_MASK); 6318334SJose.Borrego@Sun.COM si->shr_flags &= ~SMB_SHRF_CSC_MASK; 6329832Samw@Sun.COM si->shr_flags |= cscflg; 6339832Samw@Sun.COM 6349832Samw@Sun.COM if (new_si->shr_flags & SMB_SHRF_GUEST_OK) 6359832Samw@Sun.COM si->shr_flags |= SMB_SHRF_GUEST_OK; 6369832Samw@Sun.COM else 6379832Samw@Sun.COM si->shr_flags &= ~SMB_SHRF_GUEST_OK; 6388334SJose.Borrego@Sun.COM 6397961SNatalie.Li@Sun.COM access = (new_si->shr_flags & SMB_SHRF_ACC_ALL); 6408474SJose.Borrego@Sun.COM si->shr_flags &= ~SMB_SHRF_ACC_ALL; 6417961SNatalie.Li@Sun.COM si->shr_flags |= access; 6427961SNatalie.Li@Sun.COM 6437961SNatalie.Li@Sun.COM if (access & SMB_SHRF_ACC_NONE) 6447961SNatalie.Li@Sun.COM (void) strlcpy(si->shr_access_none, new_si->shr_access_none, 6457961SNatalie.Li@Sun.COM sizeof (si->shr_access_none)); 6467348SJose.Borrego@Sun.COM 6477961SNatalie.Li@Sun.COM if (access & SMB_SHRF_ACC_RO) 6487961SNatalie.Li@Sun.COM (void) strlcpy(si->shr_access_ro, new_si->shr_access_ro, 6497961SNatalie.Li@Sun.COM sizeof (si->shr_access_ro)); 6507348SJose.Borrego@Sun.COM 6517961SNatalie.Li@Sun.COM if (access & SMB_SHRF_ACC_RW) 6527961SNatalie.Li@Sun.COM (void) strlcpy(si->shr_access_rw, new_si->shr_access_rw, 6537961SNatalie.Li@Sun.COM sizeof (si->shr_access_rw)); 6547961SNatalie.Li@Sun.COM 6557961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 6567052Samw 6577348SJose.Borrego@Sun.COM if (adc_changed) { 6587961SNatalie.Li@Sun.COM smb_shr_unpublish(new_si->shr_name, old_container); 6597961SNatalie.Li@Sun.COM smb_shr_publish(new_si->shr_name, new_si->shr_container); 6607348SJose.Borrego@Sun.COM } 6617348SJose.Borrego@Sun.COM 6627348SJose.Borrego@Sun.COM return (NERR_Success); 6637052Samw } 6647052Samw 6657052Samw /* 6667052Samw * smb_shr_exists 6677052Samw * 6687348SJose.Borrego@Sun.COM * Returns B_TRUE if the share exists. Otherwise returns B_FALSE 6697052Samw */ 6707348SJose.Borrego@Sun.COM boolean_t 6717348SJose.Borrego@Sun.COM smb_shr_exists(char *sharename) 6727052Samw { 6737961SNatalie.Li@Sun.COM boolean_t exists = B_FALSE; 6747348SJose.Borrego@Sun.COM 6757348SJose.Borrego@Sun.COM if (sharename == NULL || *sharename == '\0') 6767348SJose.Borrego@Sun.COM return (B_FALSE); 6777052Samw 6787961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) { 6797961SNatalie.Li@Sun.COM exists = (smb_shr_cache_findent(sharename) != NULL); 6807961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 6817961SNatalie.Li@Sun.COM } 6827348SJose.Borrego@Sun.COM 6837348SJose.Borrego@Sun.COM return (exists); 6847052Samw } 6857052Samw 6867052Samw /* 6877961SNatalie.Li@Sun.COM * If the shared directory does not begin with a /, one will be 6887961SNatalie.Li@Sun.COM * inserted as a prefix. If ipaddr is not zero, then also return 6897961SNatalie.Li@Sun.COM * information about access based on the host level access lists, if 6907961SNatalie.Li@Sun.COM * present. Also return access check if there is an IP address and 6917961SNatalie.Li@Sun.COM * shr_accflags. 6927961SNatalie.Li@Sun.COM * 6937961SNatalie.Li@Sun.COM * The value of smb_chk_hostaccess is checked for an access match. 6947961SNatalie.Li@Sun.COM * -1 is wildcard match 6957961SNatalie.Li@Sun.COM * 0 is no match 6967961SNatalie.Li@Sun.COM * 1 is match 6977961SNatalie.Li@Sun.COM * 6987961SNatalie.Li@Sun.COM * Precedence is none is checked first followed by ro then rw if 6997961SNatalie.Li@Sun.COM * needed. If x is wildcard (< 0) then check to see if the other 7007961SNatalie.Li@Sun.COM * values are a match. If a match, that wins. 7018670SJose.Borrego@Sun.COM * 7028670SJose.Borrego@Sun.COM * ipv6 is wide open for now, see smb_chk_hostaccess 7037961SNatalie.Li@Sun.COM */ 7047961SNatalie.Li@Sun.COM void 7058670SJose.Borrego@Sun.COM smb_shr_hostaccess(smb_share_t *si, smb_inaddr_t *ipaddr) 7067961SNatalie.Li@Sun.COM { 7077961SNatalie.Li@Sun.COM int acc = SMB_SHRF_ACC_OPEN; 7087961SNatalie.Li@Sun.COM 7097961SNatalie.Li@Sun.COM /* 7107961SNatalie.Li@Sun.COM * Check to see if there area any share level access 7117961SNatalie.Li@Sun.COM * restrictions. 7127961SNatalie.Li@Sun.COM */ 7138670SJose.Borrego@Sun.COM if ((!smb_inet_iszero(ipaddr)) && 7148670SJose.Borrego@Sun.COM (si->shr_flags & SMB_SHRF_ACC_ALL) != 0) { 7157961SNatalie.Li@Sun.COM int none = SMB_SHRF_ACC_OPEN; 7167961SNatalie.Li@Sun.COM int rw = SMB_SHRF_ACC_OPEN; 7177961SNatalie.Li@Sun.COM int ro = SMB_SHRF_ACC_OPEN; 7187961SNatalie.Li@Sun.COM 7197961SNatalie.Li@Sun.COM if (si->shr_flags & SMB_SHRF_ACC_NONE) 7207961SNatalie.Li@Sun.COM none = smb_chk_hostaccess(ipaddr, si->shr_access_none); 7217961SNatalie.Li@Sun.COM if (si->shr_flags & SMB_SHRF_ACC_RW) 7227961SNatalie.Li@Sun.COM rw = smb_chk_hostaccess(ipaddr, si->shr_access_rw); 7237961SNatalie.Li@Sun.COM if (si->shr_flags & SMB_SHRF_ACC_RO) 7247961SNatalie.Li@Sun.COM ro = smb_chk_hostaccess(ipaddr, si->shr_access_ro); 7257961SNatalie.Li@Sun.COM /* make first pass to get basic value */ 7267961SNatalie.Li@Sun.COM if (none != 0) 7277961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_NONE; 7287961SNatalie.Li@Sun.COM else if (ro != 0) 7297961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RO; 7307961SNatalie.Li@Sun.COM else if (rw != 0) 7317961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RW; 7327961SNatalie.Li@Sun.COM 7337961SNatalie.Li@Sun.COM /* make second pass to handle '*' case */ 7347961SNatalie.Li@Sun.COM if (none < 0) { 7357961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_NONE; 7367961SNatalie.Li@Sun.COM if (ro > 0) 7377961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RO; 7387961SNatalie.Li@Sun.COM else if (rw > 0) 7397961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RW; 7407961SNatalie.Li@Sun.COM } else if (ro < 0) { 7417961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RO; 7427961SNatalie.Li@Sun.COM if (none > 0) 7437961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_NONE; 7447961SNatalie.Li@Sun.COM else if (rw > 0) 7457961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RW; 7467961SNatalie.Li@Sun.COM } else if (rw < 0) { 7477961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RW; 7487961SNatalie.Li@Sun.COM if (none > 0) 7497961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_NONE; 7507961SNatalie.Li@Sun.COM else if (ro > 0) 7517961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RO; 7527961SNatalie.Li@Sun.COM } 7537961SNatalie.Li@Sun.COM } 7547961SNatalie.Li@Sun.COM si->shr_access_value = acc; /* return access here */ 7557961SNatalie.Li@Sun.COM } 7567961SNatalie.Li@Sun.COM 7577961SNatalie.Li@Sun.COM /* 7587052Samw * smb_shr_is_special 7597052Samw * 7607348SJose.Borrego@Sun.COM * Special share reserved for interprocess communication (IPC$) or 7617348SJose.Borrego@Sun.COM * remote administration of the server (ADMIN$). Can also refer to 7627348SJose.Borrego@Sun.COM * administrative shares such as C$, D$, E$, and so forth. 7637052Samw */ 7647052Samw int 7657348SJose.Borrego@Sun.COM smb_shr_is_special(char *sharename) 7667052Samw { 7677052Samw int len; 7687052Samw 7697348SJose.Borrego@Sun.COM if (sharename == NULL) 7707052Samw return (0); 7717052Samw 7727348SJose.Borrego@Sun.COM if ((len = strlen(sharename)) == 0) 7737052Samw return (0); 7747052Samw 7757348SJose.Borrego@Sun.COM if (sharename[len - 1] == '$') 7767052Samw return (STYPE_SPECIAL); 7777348SJose.Borrego@Sun.COM 7787348SJose.Borrego@Sun.COM return (0); 7797052Samw } 7807052Samw 7817052Samw /* 7827052Samw * smb_shr_is_restricted 7837052Samw * 7847052Samw * Check whether or not there is a restriction on a share. Restricted 7857052Samw * shares are generally STYPE_SPECIAL, for example, IPC$. All the 7867348SJose.Borrego@Sun.COM * administration share names are restricted: C$, D$ etc. Returns B_TRUE 7877348SJose.Borrego@Sun.COM * if the share is restricted. Otherwise B_FALSE is returned to indicate 7887052Samw * that there are no restrictions. 7897052Samw */ 7907348SJose.Borrego@Sun.COM boolean_t 7917348SJose.Borrego@Sun.COM smb_shr_is_restricted(char *sharename) 7927052Samw { 7937052Samw static char *restricted[] = { 7947052Samw "IPC$" 7957052Samw }; 7967052Samw 7977052Samw int i; 7987052Samw 7997348SJose.Borrego@Sun.COM if (sharename == NULL) 8007348SJose.Borrego@Sun.COM return (B_FALSE); 8017348SJose.Borrego@Sun.COM 8027052Samw for (i = 0; i < sizeof (restricted)/sizeof (restricted[0]); i++) { 8037348SJose.Borrego@Sun.COM if (utf8_strcasecmp(restricted[i], sharename) == 0) 8047348SJose.Borrego@Sun.COM return (B_TRUE); 8057052Samw } 8067052Samw 8077348SJose.Borrego@Sun.COM return (smb_shr_is_admin(sharename)); 8087052Samw } 8097052Samw 8107052Samw /* 8117052Samw * smb_shr_is_admin 8127052Samw * 8137052Samw * Check whether or not access to the share should be restricted to 8147052Samw * administrators. This is a bit of a hack because what we're doing 8157052Samw * is checking for the default admin shares: C$, D$ etc.. There are 8167052Samw * other shares that have restrictions: see smb_shr_is_restricted(). 8177052Samw * 8187348SJose.Borrego@Sun.COM * Returns B_TRUE if the shares is an admin share. Otherwise B_FALSE 8197348SJose.Borrego@Sun.COM * is returned to indicate that there are no restrictions. 8207052Samw */ 8217348SJose.Borrego@Sun.COM boolean_t 8227348SJose.Borrego@Sun.COM smb_shr_is_admin(char *sharename) 8237052Samw { 8247348SJose.Borrego@Sun.COM if (sharename == NULL) 8257348SJose.Borrego@Sun.COM return (B_FALSE); 8267052Samw 8277348SJose.Borrego@Sun.COM if (strlen(sharename) == 2 && 8287348SJose.Borrego@Sun.COM mts_isalpha(sharename[0]) && sharename[1] == '$') { 8297348SJose.Borrego@Sun.COM return (B_TRUE); 8307052Samw } 8317052Samw 8327348SJose.Borrego@Sun.COM return (B_FALSE); 8337052Samw } 8347052Samw 8357052Samw /* 8367348SJose.Borrego@Sun.COM * smb_shr_chkname 8377052Samw * 8387961SNatalie.Li@Sun.COM * Check for invalid characters in a share name. The list of invalid 8397961SNatalie.Li@Sun.COM * characters includes control characters and the following: 8407052Samw * 8417052Samw * " / \ [ ] : | < > + ; , ? * = 8427052Samw */ 8437348SJose.Borrego@Sun.COM boolean_t 8447348SJose.Borrego@Sun.COM smb_shr_chkname(char *sharename) 8457052Samw { 8467052Samw char *invalid = "\"/\\[]:|<>+;,?*="; 8477052Samw char *cp; 8487052Samw 8497348SJose.Borrego@Sun.COM if (sharename == NULL) 8507348SJose.Borrego@Sun.COM return (B_FALSE); 8517052Samw 8527348SJose.Borrego@Sun.COM if (strpbrk(sharename, invalid)) 8537348SJose.Borrego@Sun.COM return (B_FALSE); 8547052Samw 8557348SJose.Borrego@Sun.COM for (cp = sharename; *cp != '\0'; cp++) { 8567348SJose.Borrego@Sun.COM if (iscntrl(*cp)) 8577348SJose.Borrego@Sun.COM return (B_FALSE); 8587052Samw } 8597052Samw 8607348SJose.Borrego@Sun.COM return (B_TRUE); 8617052Samw } 8627052Samw 8637052Samw /* 8647052Samw * smb_shr_get_realpath 8657052Samw * 8667961SNatalie.Li@Sun.COM * Derive the real path for a share from the path provided by a client. 8677961SNatalie.Li@Sun.COM * For instance, the real path of C:\ may be /cvol or the real path of 8687961SNatalie.Li@Sun.COM * F:\home may be /vol1/home. 8697052Samw * 8707961SNatalie.Li@Sun.COM * clntpath - path provided by the Windows client is in the 8717052Samw * format of <drive letter>:\<dir> 8727052Samw * realpath - path that will be stored as the directory field of 8737052Samw * the smb_share_t structure of the share. 8747961SNatalie.Li@Sun.COM * maxlen - maximum length of the realpath buffer 8757052Samw * 8767052Samw * Return LAN Manager network error code. 8777052Samw */ 8787052Samw uint32_t 8797961SNatalie.Li@Sun.COM smb_shr_get_realpath(const char *clntpath, char *realpath, int maxlen) 8807052Samw { 8817961SNatalie.Li@Sun.COM const char *p; 8827961SNatalie.Li@Sun.COM int len; 8837348SJose.Borrego@Sun.COM 8847961SNatalie.Li@Sun.COM if ((p = strchr(clntpath, ':')) != NULL) 8857961SNatalie.Li@Sun.COM ++p; 8867961SNatalie.Li@Sun.COM else 8877961SNatalie.Li@Sun.COM p = clntpath; 8887348SJose.Borrego@Sun.COM 8897961SNatalie.Li@Sun.COM (void) strlcpy(realpath, p, maxlen); 8907961SNatalie.Li@Sun.COM (void) strcanon(realpath, "/\\"); 8917961SNatalie.Li@Sun.COM (void) strsubst(realpath, '\\', '/'); 8927348SJose.Borrego@Sun.COM 8937961SNatalie.Li@Sun.COM len = strlen(realpath); 8947961SNatalie.Li@Sun.COM if ((len > 1) && (realpath[len - 1] == '/')) 8957961SNatalie.Li@Sun.COM realpath[len - 1] = '\0'; 8967348SJose.Borrego@Sun.COM 8977348SJose.Borrego@Sun.COM return (NERR_Success); 8987348SJose.Borrego@Sun.COM } 8997348SJose.Borrego@Sun.COM 9007961SNatalie.Li@Sun.COM void 9017961SNatalie.Li@Sun.COM smb_shr_list(int offset, smb_shrlist_t *list) 9027348SJose.Borrego@Sun.COM { 9037961SNatalie.Li@Sun.COM smb_shriter_t iterator; 9047961SNatalie.Li@Sun.COM smb_share_t *si; 9057961SNatalie.Li@Sun.COM int n = 0; 9067961SNatalie.Li@Sun.COM 9077961SNatalie.Li@Sun.COM bzero(list, sizeof (smb_shrlist_t)); 9087961SNatalie.Li@Sun.COM smb_shr_iterinit(&iterator); 9097961SNatalie.Li@Sun.COM 9107961SNatalie.Li@Sun.COM while ((si = smb_shr_iterate(&iterator)) != NULL) { 9117961SNatalie.Li@Sun.COM if (--offset > 0) 9127961SNatalie.Li@Sun.COM continue; 9137961SNatalie.Li@Sun.COM 9147961SNatalie.Li@Sun.COM if ((si->shr_flags & SMB_SHRF_TRANS) && 9157961SNatalie.Li@Sun.COM ((si->shr_type & STYPE_IPC) == 0)) { 9167961SNatalie.Li@Sun.COM bcopy(si, &list->sl_shares[n], sizeof (smb_share_t)); 9177961SNatalie.Li@Sun.COM if (++n == LMSHARES_PER_REQUEST) 9187961SNatalie.Li@Sun.COM break; 9197961SNatalie.Li@Sun.COM } 9207348SJose.Borrego@Sun.COM } 9217961SNatalie.Li@Sun.COM 9227961SNatalie.Li@Sun.COM list->sl_cnt = n; 9237348SJose.Borrego@Sun.COM } 9247348SJose.Borrego@Sun.COM 9257348SJose.Borrego@Sun.COM /* 9269832Samw@Sun.COM * Executes the map/unmap command associated with a share. 9279832Samw@Sun.COM * 9289832Samw@Sun.COM * Returns 0 on success. Otherwise non-zero for errors. 9299832Samw@Sun.COM */ 9309832Samw@Sun.COM int 9319832Samw@Sun.COM smb_shr_exec(char *share, smb_execsub_info_t *subs, int exec_type) 9329832Samw@Sun.COM { 9339832Samw@Sun.COM char cmd[MAXPATHLEN], **cmd_tokens, *path, *ptr; 9349832Samw@Sun.COM pid_t child_pid; 9359832Samw@Sun.COM int child_status; 9369832Samw@Sun.COM struct sigaction pact, cact; 9379832Samw@Sun.COM smb_share_t si; 9389832Samw@Sun.COM 9399832Samw@Sun.COM if (smb_shr_get(share, &si) != 0) 9409832Samw@Sun.COM return (-1); 9419832Samw@Sun.COM 9429832Samw@Sun.COM *cmd = '\0'; 9439832Samw@Sun.COM 9449832Samw@Sun.COM (void) mutex_lock(&smb_shr_exec_mtx); 9459832Samw@Sun.COM 9469832Samw@Sun.COM switch (exec_type) { 9479832Samw@Sun.COM case SMB_SHR_MAP: 9489832Samw@Sun.COM (void) strlcpy(cmd, smb_shr_exec_map, sizeof (cmd)); 9499832Samw@Sun.COM break; 9509832Samw@Sun.COM case SMB_SHR_UNMAP: 9519832Samw@Sun.COM (void) strlcpy(cmd, smb_shr_exec_unmap, sizeof (cmd)); 9529832Samw@Sun.COM break; 9539832Samw@Sun.COM default: 9549832Samw@Sun.COM (void) mutex_unlock(&smb_shr_exec_mtx); 9559832Samw@Sun.COM return (-1); 9569832Samw@Sun.COM } 9579832Samw@Sun.COM 9589832Samw@Sun.COM (void) mutex_unlock(&smb_shr_exec_mtx); 9599832Samw@Sun.COM 9609832Samw@Sun.COM if (*cmd == '\0') 9619832Samw@Sun.COM return (0); 9629832Samw@Sun.COM 963*10504SKeyur.Desai@Sun.COM if (smb_proc_takesem() != 0) 964*10504SKeyur.Desai@Sun.COM return (-1); 965*10504SKeyur.Desai@Sun.COM 9669832Samw@Sun.COM pact.sa_handler = smb_shr_sig_child; 9679832Samw@Sun.COM pact.sa_flags = 0; 9689832Samw@Sun.COM (void) sigemptyset(&pact.sa_mask); 9699832Samw@Sun.COM sigaction(SIGCHLD, &pact, NULL); 9709832Samw@Sun.COM 9719832Samw@Sun.COM (void) priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_FORK, NULL); 9729832Samw@Sun.COM 9739832Samw@Sun.COM if ((child_pid = fork()) == -1) { 9749832Samw@Sun.COM (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_FORK, NULL); 975*10504SKeyur.Desai@Sun.COM smb_proc_givesem(); 9769832Samw@Sun.COM return (-1); 9779832Samw@Sun.COM } 9789832Samw@Sun.COM 9799832Samw@Sun.COM if (child_pid == 0) { 9809832Samw@Sun.COM 9819832Samw@Sun.COM /* child process */ 9829832Samw@Sun.COM 9839832Samw@Sun.COM cact.sa_handler = smb_shr_sig_abnormal_term; 9849832Samw@Sun.COM cact.sa_flags = 0; 9859832Samw@Sun.COM (void) sigemptyset(&cact.sa_mask); 9869832Samw@Sun.COM sigaction(SIGTERM, &cact, NULL); 9879832Samw@Sun.COM sigaction(SIGABRT, &cact, NULL); 9889832Samw@Sun.COM sigaction(SIGSEGV, &cact, NULL); 9899832Samw@Sun.COM 9909832Samw@Sun.COM if (priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_EXEC, 9919832Samw@Sun.COM PRIV_FILE_DAC_EXECUTE, NULL)) 9929832Samw@Sun.COM _exit(-1); 9939832Samw@Sun.COM 9949832Samw@Sun.COM if (smb_shr_enable_all_privs()) 9959832Samw@Sun.COM _exit(-1); 9969832Samw@Sun.COM 997*10504SKeyur.Desai@Sun.COM smb_proc_initsem(); 998*10504SKeyur.Desai@Sun.COM 9999832Samw@Sun.COM (void) trim_whitespace(cmd); 10009832Samw@Sun.COM (void) strcanon(cmd, " "); 10019832Samw@Sun.COM 10029832Samw@Sun.COM if ((cmd_tokens = smb_shr_tokenize_cmd(cmd)) != NULL) { 10039832Samw@Sun.COM 10049832Samw@Sun.COM if (smb_shr_expand_subs(cmd_tokens, &si, subs) != 0) { 10059832Samw@Sun.COM free(cmd_tokens[0]); 10069832Samw@Sun.COM free(cmd_tokens); 10079832Samw@Sun.COM _exit(-1); 10089832Samw@Sun.COM } 10099832Samw@Sun.COM 10109832Samw@Sun.COM ptr = cmd; 10119832Samw@Sun.COM path = strsep(&ptr, " "); 10129832Samw@Sun.COM 10139832Samw@Sun.COM (void) execv(path, cmd_tokens); 10149832Samw@Sun.COM } 10159832Samw@Sun.COM 10169832Samw@Sun.COM _exit(-1); 10179832Samw@Sun.COM } 10189832Samw@Sun.COM 1019*10504SKeyur.Desai@Sun.COM (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_FORK, NULL); 1020*10504SKeyur.Desai@Sun.COM smb_proc_givesem(); 1021*10504SKeyur.Desai@Sun.COM 10229832Samw@Sun.COM /* parent process */ 10239832Samw@Sun.COM 10249832Samw@Sun.COM while (waitpid(child_pid, &child_status, 0) < 0) { 10259832Samw@Sun.COM if (errno != EINTR) 10269832Samw@Sun.COM break; 10279832Samw@Sun.COM 10289832Samw@Sun.COM /* continue if waitpid got interrupted by a signal */ 10299832Samw@Sun.COM errno = 0; 10309832Samw@Sun.COM continue; 10319832Samw@Sun.COM } 10329832Samw@Sun.COM 10339832Samw@Sun.COM if (WIFEXITED(child_status)) 10349832Samw@Sun.COM return (WEXITSTATUS(child_status)); 10359832Samw@Sun.COM 10369832Samw@Sun.COM return (child_status); 10379832Samw@Sun.COM } 10389832Samw@Sun.COM 10399832Samw@Sun.COM /* 1040*10504SKeyur.Desai@Sun.COM * Locking for process-wide settings (i.e. privileges) 1041*10504SKeyur.Desai@Sun.COM */ 1042*10504SKeyur.Desai@Sun.COM void 1043*10504SKeyur.Desai@Sun.COM smb_proc_initsem(void) 1044*10504SKeyur.Desai@Sun.COM { 1045*10504SKeyur.Desai@Sun.COM (void) sema_init(&smb_proc_sem, 1, USYNC_THREAD, NULL); 1046*10504SKeyur.Desai@Sun.COM } 1047*10504SKeyur.Desai@Sun.COM 1048*10504SKeyur.Desai@Sun.COM int 1049*10504SKeyur.Desai@Sun.COM smb_proc_takesem(void) 1050*10504SKeyur.Desai@Sun.COM { 1051*10504SKeyur.Desai@Sun.COM return (sema_wait(&smb_proc_sem)); 1052*10504SKeyur.Desai@Sun.COM } 1053*10504SKeyur.Desai@Sun.COM 1054*10504SKeyur.Desai@Sun.COM void 1055*10504SKeyur.Desai@Sun.COM smb_proc_givesem(void) 1056*10504SKeyur.Desai@Sun.COM { 1057*10504SKeyur.Desai@Sun.COM (void) sema_post(&smb_proc_sem); 1058*10504SKeyur.Desai@Sun.COM } 1059*10504SKeyur.Desai@Sun.COM 1060*10504SKeyur.Desai@Sun.COM /* 10617961SNatalie.Li@Sun.COM * ============================================ 10627961SNatalie.Li@Sun.COM * Private helper/utility functions 10637961SNatalie.Li@Sun.COM * ============================================ 10647348SJose.Borrego@Sun.COM */ 10657348SJose.Borrego@Sun.COM 10667961SNatalie.Li@Sun.COM /* 10678334SJose.Borrego@Sun.COM * Looks up the given share in the cache and return 10688334SJose.Borrego@Sun.COM * the info in 'si' 10698334SJose.Borrego@Sun.COM */ 10708334SJose.Borrego@Sun.COM static uint32_t 10718334SJose.Borrego@Sun.COM smb_shr_lookup(char *sharename, smb_share_t *si) 10728334SJose.Borrego@Sun.COM { 10738334SJose.Borrego@Sun.COM smb_share_t *cached_si; 10748334SJose.Borrego@Sun.COM uint32_t status = NERR_NetNameNotFound; 10758334SJose.Borrego@Sun.COM 10768334SJose.Borrego@Sun.COM if (sharename == NULL || *sharename == '\0') 10778334SJose.Borrego@Sun.COM return (NERR_NetNameNotFound); 10788334SJose.Borrego@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) { 10798334SJose.Borrego@Sun.COM cached_si = smb_shr_cache_findent(sharename); 10808334SJose.Borrego@Sun.COM if (cached_si != NULL) { 10818334SJose.Borrego@Sun.COM bcopy(cached_si, si, sizeof (smb_share_t)); 10829832Samw@Sun.COM smb_shr_set_exec_flags(si); 10838334SJose.Borrego@Sun.COM status = NERR_Success; 10848334SJose.Borrego@Sun.COM } 10858334SJose.Borrego@Sun.COM 10868334SJose.Borrego@Sun.COM smb_shr_cache_unlock(); 10878334SJose.Borrego@Sun.COM } 10888334SJose.Borrego@Sun.COM return (status); 10898334SJose.Borrego@Sun.COM } 10908334SJose.Borrego@Sun.COM 10918334SJose.Borrego@Sun.COM /* 10927961SNatalie.Li@Sun.COM * Add IPC$ to the cache upon startup. 10937961SNatalie.Li@Sun.COM */ 10947348SJose.Borrego@Sun.COM static uint32_t 10957961SNatalie.Li@Sun.COM smb_shr_addipc(void) 10967348SJose.Borrego@Sun.COM { 10977348SJose.Borrego@Sun.COM smb_share_t ipc; 10987961SNatalie.Li@Sun.COM uint32_t status = NERR_InternalError; 10997348SJose.Borrego@Sun.COM 11007348SJose.Borrego@Sun.COM bzero(&ipc, sizeof (smb_share_t)); 11017348SJose.Borrego@Sun.COM (void) strcpy(ipc.shr_name, "IPC$"); 11027348SJose.Borrego@Sun.COM (void) strcpy(ipc.shr_cmnt, "Remote IPC"); 11037348SJose.Borrego@Sun.COM ipc.shr_flags = SMB_SHRF_TRANS; 11047348SJose.Borrego@Sun.COM ipc.shr_type = STYPE_IPC; 11057348SJose.Borrego@Sun.COM 11067961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) == NERR_Success) { 11077961SNatalie.Li@Sun.COM status = smb_shr_cache_addent(&ipc); 11087961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 11097348SJose.Borrego@Sun.COM } 11107348SJose.Borrego@Sun.COM 11117348SJose.Borrego@Sun.COM return (status); 11127348SJose.Borrego@Sun.COM } 11137348SJose.Borrego@Sun.COM 11147348SJose.Borrego@Sun.COM /* 11157052Samw * smb_shr_set_oemname 11167052Samw * 11177961SNatalie.Li@Sun.COM * Generate the OEM name for the specified share. If the name is 11187961SNatalie.Li@Sun.COM * shorter than 13 bytes the oemname will be saved in si->shr_oemname. 11197961SNatalie.Li@Sun.COM * Otherwise si->shr_oemname will be empty and SMB_SHRF_LONGNAME will 11207961SNatalie.Li@Sun.COM * be set in si->shr_flags. 11217052Samw */ 11227052Samw static void 11237052Samw smb_shr_set_oemname(smb_share_t *si) 11247052Samw { 11257052Samw unsigned int cpid = oem_get_smb_cpid(); 11267052Samw mts_wchar_t *unibuf; 11277052Samw char *oem_name; 11287052Samw int length; 11297052Samw 11307052Samw length = strlen(si->shr_name) + 1; 11317052Samw 11327052Samw oem_name = malloc(length); 11337052Samw unibuf = malloc(length * sizeof (mts_wchar_t)); 11347052Samw if ((oem_name == NULL) || (unibuf == NULL)) { 11357052Samw free(oem_name); 11367052Samw free(unibuf); 11377052Samw return; 11387052Samw } 11397052Samw 11407052Samw (void) mts_mbstowcs(unibuf, si->shr_name, length); 11417052Samw 11427052Samw if (unicodestooems(oem_name, unibuf, length, cpid) == 0) 11437052Samw (void) strcpy(oem_name, si->shr_name); 11447052Samw 11457052Samw free(unibuf); 11467052Samw 11477052Samw if (strlen(oem_name) + 1 > SMB_SHARE_OEMNAME_MAX) { 11487052Samw si->shr_flags |= SMB_SHRF_LONGNAME; 11497052Samw *si->shr_oemname = '\0'; 11507052Samw } else { 11517052Samw si->shr_flags &= ~SMB_SHRF_LONGNAME; 11527052Samw (void) strlcpy(si->shr_oemname, oem_name, 11537052Samw SMB_SHARE_OEMNAME_MAX); 11547052Samw } 11557052Samw 11567052Samw free(oem_name); 11577052Samw } 11587348SJose.Borrego@Sun.COM 11597348SJose.Borrego@Sun.COM /* 11607348SJose.Borrego@Sun.COM * ============================================ 11617961SNatalie.Li@Sun.COM * Cache management functions 11627961SNatalie.Li@Sun.COM * 11637961SNatalie.Li@Sun.COM * All cache functions are private 11647348SJose.Borrego@Sun.COM * ============================================ 11657348SJose.Borrego@Sun.COM */ 11667348SJose.Borrego@Sun.COM 11677348SJose.Borrego@Sun.COM /* 11687961SNatalie.Li@Sun.COM * Create the share cache (hash table). 11697348SJose.Borrego@Sun.COM */ 11707348SJose.Borrego@Sun.COM static uint32_t 11717961SNatalie.Li@Sun.COM smb_shr_cache_create(void) 11727348SJose.Borrego@Sun.COM { 11737961SNatalie.Li@Sun.COM uint32_t status = NERR_Success; 11747348SJose.Borrego@Sun.COM 11757961SNatalie.Li@Sun.COM (void) mutex_lock(&smb_shr_cache.sc_mtx); 11767961SNatalie.Li@Sun.COM switch (smb_shr_cache.sc_state) { 11777961SNatalie.Li@Sun.COM case SMB_SHR_CACHE_STATE_NONE: 11787961SNatalie.Li@Sun.COM smb_shr_cache.sc_cache = ht_create_table(SMB_SHR_HTAB_SZ, 11797961SNatalie.Li@Sun.COM MAXNAMELEN, 0); 11807961SNatalie.Li@Sun.COM if (smb_shr_cache.sc_cache == NULL) { 11817961SNatalie.Li@Sun.COM status = NERR_InternalError; 11827961SNatalie.Li@Sun.COM break; 11837348SJose.Borrego@Sun.COM } 11847348SJose.Borrego@Sun.COM 11857961SNatalie.Li@Sun.COM (void) ht_register_callback(smb_shr_cache.sc_cache, 11867961SNatalie.Li@Sun.COM smb_shr_cache_freent); 11877961SNatalie.Li@Sun.COM smb_shr_cache.sc_nops = 0; 11887961SNatalie.Li@Sun.COM smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_CREATED; 11897961SNatalie.Li@Sun.COM break; 11907961SNatalie.Li@Sun.COM 11917961SNatalie.Li@Sun.COM default: 11927961SNatalie.Li@Sun.COM assert(0); 11937961SNatalie.Li@Sun.COM status = NERR_InternalError; 11947961SNatalie.Li@Sun.COM break; 11957961SNatalie.Li@Sun.COM } 11967961SNatalie.Li@Sun.COM (void) mutex_unlock(&smb_shr_cache.sc_mtx); 11977961SNatalie.Li@Sun.COM 11987961SNatalie.Li@Sun.COM return (status); 11997961SNatalie.Li@Sun.COM } 12007961SNatalie.Li@Sun.COM 12017961SNatalie.Li@Sun.COM /* 12027961SNatalie.Li@Sun.COM * Destroy the share cache (hash table). 12037961SNatalie.Li@Sun.COM * Wait for inflight/pending operations to finish or abort before 12047961SNatalie.Li@Sun.COM * destroying the cache. 12057961SNatalie.Li@Sun.COM */ 12067961SNatalie.Li@Sun.COM static void 12077961SNatalie.Li@Sun.COM smb_shr_cache_destroy(void) 12087961SNatalie.Li@Sun.COM { 12097961SNatalie.Li@Sun.COM (void) mutex_lock(&smb_shr_cache.sc_mtx); 12107961SNatalie.Li@Sun.COM if (smb_shr_cache.sc_state == SMB_SHR_CACHE_STATE_CREATED) { 12117961SNatalie.Li@Sun.COM smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_DESTROYING; 12127961SNatalie.Li@Sun.COM while (smb_shr_cache.sc_nops > 0) 12137961SNatalie.Li@Sun.COM (void) cond_wait(&smb_shr_cache.sc_cv, 12147961SNatalie.Li@Sun.COM &smb_shr_cache.sc_mtx); 12157961SNatalie.Li@Sun.COM 12167961SNatalie.Li@Sun.COM smb_shr_cache.sc_cache = NULL; 12177961SNatalie.Li@Sun.COM smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_NONE; 12187961SNatalie.Li@Sun.COM } 12197961SNatalie.Li@Sun.COM (void) mutex_unlock(&smb_shr_cache.sc_mtx); 12207961SNatalie.Li@Sun.COM } 12217961SNatalie.Li@Sun.COM 12227961SNatalie.Li@Sun.COM /* 12237961SNatalie.Li@Sun.COM * If the cache is in "created" state, lock the cache for read 12247961SNatalie.Li@Sun.COM * or read/write based on the specified mode. 12257961SNatalie.Li@Sun.COM * 12267961SNatalie.Li@Sun.COM * Whenever a lock is granted, the number of inflight cache 12277961SNatalie.Li@Sun.COM * operations is incremented. 12287961SNatalie.Li@Sun.COM */ 12297961SNatalie.Li@Sun.COM static uint32_t 12307961SNatalie.Li@Sun.COM smb_shr_cache_lock(int mode) 12317961SNatalie.Li@Sun.COM { 12327961SNatalie.Li@Sun.COM (void) mutex_lock(&smb_shr_cache.sc_mtx); 12338334SJose.Borrego@Sun.COM if (smb_shr_cache.sc_state != SMB_SHR_CACHE_STATE_CREATED) { 12347961SNatalie.Li@Sun.COM (void) mutex_unlock(&smb_shr_cache.sc_mtx); 12357961SNatalie.Li@Sun.COM return (NERR_InternalError); 12367961SNatalie.Li@Sun.COM } 12378334SJose.Borrego@Sun.COM smb_shr_cache.sc_nops++; 12387961SNatalie.Li@Sun.COM (void) mutex_unlock(&smb_shr_cache.sc_mtx); 12397961SNatalie.Li@Sun.COM 12407961SNatalie.Li@Sun.COM /* 12417961SNatalie.Li@Sun.COM * Lock has to be taken outside the mutex otherwise 12427961SNatalie.Li@Sun.COM * there could be a deadlock 12437961SNatalie.Li@Sun.COM */ 12447961SNatalie.Li@Sun.COM if (mode == SMB_SHR_CACHE_RDLOCK) 12457961SNatalie.Li@Sun.COM (void) rw_rdlock(&smb_shr_cache.sc_cache_lck); 12467961SNatalie.Li@Sun.COM else 12477961SNatalie.Li@Sun.COM (void) rw_wrlock(&smb_shr_cache.sc_cache_lck); 12487961SNatalie.Li@Sun.COM 12497961SNatalie.Li@Sun.COM return (NERR_Success); 12507961SNatalie.Li@Sun.COM } 12517961SNatalie.Li@Sun.COM 12527961SNatalie.Li@Sun.COM /* 12537961SNatalie.Li@Sun.COM * Decrement the number of inflight operations and then unlock. 12547961SNatalie.Li@Sun.COM */ 12557961SNatalie.Li@Sun.COM static void 12567961SNatalie.Li@Sun.COM smb_shr_cache_unlock(void) 12577961SNatalie.Li@Sun.COM { 12587961SNatalie.Li@Sun.COM (void) mutex_lock(&smb_shr_cache.sc_mtx); 12597961SNatalie.Li@Sun.COM assert(smb_shr_cache.sc_nops > 0); 12607961SNatalie.Li@Sun.COM smb_shr_cache.sc_nops--; 12617961SNatalie.Li@Sun.COM (void) cond_broadcast(&smb_shr_cache.sc_cv); 12627961SNatalie.Li@Sun.COM (void) mutex_unlock(&smb_shr_cache.sc_mtx); 12637961SNatalie.Li@Sun.COM 12647961SNatalie.Li@Sun.COM (void) rw_unlock(&smb_shr_cache.sc_cache_lck); 12657961SNatalie.Li@Sun.COM } 12667961SNatalie.Li@Sun.COM 12677961SNatalie.Li@Sun.COM /* 12687961SNatalie.Li@Sun.COM * Return the total number of shares 12697961SNatalie.Li@Sun.COM */ 12707961SNatalie.Li@Sun.COM static int 12717961SNatalie.Li@Sun.COM smb_shr_cache_count(void) 12727961SNatalie.Li@Sun.COM { 12737961SNatalie.Li@Sun.COM return (ht_get_total_items(smb_shr_cache.sc_cache)); 12747961SNatalie.Li@Sun.COM } 12757961SNatalie.Li@Sun.COM 12767961SNatalie.Li@Sun.COM /* 12777961SNatalie.Li@Sun.COM * looks up the given share name in the cache and if it 12787961SNatalie.Li@Sun.COM * finds a match returns a pointer to the cached entry. 12797961SNatalie.Li@Sun.COM * Note that since a pointer is returned this function 12807961SNatalie.Li@Sun.COM * MUST be protected by smb_shr_cache_lock/unlock pair 12817961SNatalie.Li@Sun.COM */ 12827961SNatalie.Li@Sun.COM static smb_share_t * 12837961SNatalie.Li@Sun.COM smb_shr_cache_findent(char *sharename) 12847961SNatalie.Li@Sun.COM { 12857961SNatalie.Li@Sun.COM HT_ITEM *item; 12867961SNatalie.Li@Sun.COM 12877961SNatalie.Li@Sun.COM (void) utf8_strlwr(sharename); 12887961SNatalie.Li@Sun.COM item = ht_find_item(smb_shr_cache.sc_cache, sharename); 12897961SNatalie.Li@Sun.COM if (item && item->hi_data) 12907961SNatalie.Li@Sun.COM return ((smb_share_t *)item->hi_data); 12917961SNatalie.Li@Sun.COM 12927961SNatalie.Li@Sun.COM return (NULL); 12937961SNatalie.Li@Sun.COM } 12947961SNatalie.Li@Sun.COM 12957961SNatalie.Li@Sun.COM /* 12967961SNatalie.Li@Sun.COM * Return a pointer to the first/next entry in 12977961SNatalie.Li@Sun.COM * the cache based on the given iterator. 12987961SNatalie.Li@Sun.COM * 12997961SNatalie.Li@Sun.COM * Calls to this function MUST be protected by 13007961SNatalie.Li@Sun.COM * smb_shr_cache_lock/unlock. 13017961SNatalie.Li@Sun.COM */ 13027961SNatalie.Li@Sun.COM static smb_share_t * 13037961SNatalie.Li@Sun.COM smb_shr_cache_iterate(smb_shriter_t *shi) 13047961SNatalie.Li@Sun.COM { 13057961SNatalie.Li@Sun.COM HT_ITEM *item; 13067961SNatalie.Li@Sun.COM 13077961SNatalie.Li@Sun.COM if (shi->si_first) { 13087961SNatalie.Li@Sun.COM item = ht_findfirst(smb_shr_cache.sc_cache, &shi->si_hashiter); 13097961SNatalie.Li@Sun.COM shi->si_first = B_FALSE; 13107961SNatalie.Li@Sun.COM } else { 13117961SNatalie.Li@Sun.COM item = ht_findnext(&shi->si_hashiter); 13127348SJose.Borrego@Sun.COM } 13137348SJose.Borrego@Sun.COM 13147961SNatalie.Li@Sun.COM if (item && item->hi_data) 13157961SNatalie.Li@Sun.COM return ((smb_share_t *)item->hi_data); 13167961SNatalie.Li@Sun.COM 13177961SNatalie.Li@Sun.COM return (NULL); 13187961SNatalie.Li@Sun.COM } 13197961SNatalie.Li@Sun.COM 13207961SNatalie.Li@Sun.COM /* 13217961SNatalie.Li@Sun.COM * Add the specified share to the cache. Memory needs to be allocated 13227961SNatalie.Li@Sun.COM * for the cache entry and the passed information is copied to the 13237961SNatalie.Li@Sun.COM * allocated space. 13247961SNatalie.Li@Sun.COM */ 13257961SNatalie.Li@Sun.COM static uint32_t 13267961SNatalie.Li@Sun.COM smb_shr_cache_addent(smb_share_t *si) 13277961SNatalie.Li@Sun.COM { 13287961SNatalie.Li@Sun.COM smb_share_t *cache_ent; 13297961SNatalie.Li@Sun.COM uint32_t status = NERR_Success; 13307961SNatalie.Li@Sun.COM 13317961SNatalie.Li@Sun.COM if ((cache_ent = malloc(sizeof (smb_share_t))) == NULL) 13327961SNatalie.Li@Sun.COM return (ERROR_NOT_ENOUGH_MEMORY); 13337961SNatalie.Li@Sun.COM 13347961SNatalie.Li@Sun.COM bcopy(si, cache_ent, sizeof (smb_share_t)); 13357961SNatalie.Li@Sun.COM 13367961SNatalie.Li@Sun.COM (void) utf8_strlwr(cache_ent->shr_name); 13377961SNatalie.Li@Sun.COM smb_shr_set_oemname(cache_ent); 13387961SNatalie.Li@Sun.COM 13397961SNatalie.Li@Sun.COM if ((si->shr_type & STYPE_IPC) == 0) 13407961SNatalie.Li@Sun.COM cache_ent->shr_type = STYPE_DISKTREE; 13417961SNatalie.Li@Sun.COM cache_ent->shr_type |= smb_shr_is_special(cache_ent->shr_name); 13427961SNatalie.Li@Sun.COM 13437961SNatalie.Li@Sun.COM if (smb_shr_is_admin(cache_ent->shr_name)) 13447961SNatalie.Li@Sun.COM cache_ent->shr_flags |= SMB_SHRF_ADMIN; 13457961SNatalie.Li@Sun.COM 13467961SNatalie.Li@Sun.COM if (si->shr_flags & SMB_SHRF_AUTOHOME) 13477961SNatalie.Li@Sun.COM cache_ent->shr_refcnt = 1; 13487961SNatalie.Li@Sun.COM 13497961SNatalie.Li@Sun.COM if (ht_add_item(smb_shr_cache.sc_cache, cache_ent->shr_name, cache_ent) 13507961SNatalie.Li@Sun.COM == NULL) { 13517961SNatalie.Li@Sun.COM syslog(LOG_DEBUG, "share: %s: cache update failed", 13527961SNatalie.Li@Sun.COM cache_ent->shr_name); 13537961SNatalie.Li@Sun.COM free(cache_ent); 13547961SNatalie.Li@Sun.COM status = NERR_InternalError; 13557348SJose.Borrego@Sun.COM } 13567348SJose.Borrego@Sun.COM 13577961SNatalie.Li@Sun.COM return (status); 13587961SNatalie.Li@Sun.COM } 13597961SNatalie.Li@Sun.COM 13607961SNatalie.Li@Sun.COM /* 13617961SNatalie.Li@Sun.COM * Delete the specified share from the cache. 13627961SNatalie.Li@Sun.COM */ 13637961SNatalie.Li@Sun.COM static void 13647961SNatalie.Li@Sun.COM smb_shr_cache_delent(char *sharename) 13657961SNatalie.Li@Sun.COM { 13667961SNatalie.Li@Sun.COM (void) utf8_strlwr(sharename); 13677961SNatalie.Li@Sun.COM (void) ht_remove_item(smb_shr_cache.sc_cache, sharename); 13687961SNatalie.Li@Sun.COM } 13697961SNatalie.Li@Sun.COM 13707961SNatalie.Li@Sun.COM /* 13717961SNatalie.Li@Sun.COM * Call back to free the given cache entry. 13727961SNatalie.Li@Sun.COM */ 13737961SNatalie.Li@Sun.COM static void 13747961SNatalie.Li@Sun.COM smb_shr_cache_freent(HT_ITEM *item) 13757961SNatalie.Li@Sun.COM { 13767961SNatalie.Li@Sun.COM if (item && item->hi_data) 13777961SNatalie.Li@Sun.COM free(item->hi_data); 13787961SNatalie.Li@Sun.COM } 13797961SNatalie.Li@Sun.COM 13807961SNatalie.Li@Sun.COM /* 13817961SNatalie.Li@Sun.COM * ============================================ 13827961SNatalie.Li@Sun.COM * Interfaces to sharemgr 13837961SNatalie.Li@Sun.COM * 13847961SNatalie.Li@Sun.COM * All functions in this section are private 13857961SNatalie.Li@Sun.COM * ============================================ 13867961SNatalie.Li@Sun.COM */ 13877961SNatalie.Li@Sun.COM 13887961SNatalie.Li@Sun.COM /* 13897961SNatalie.Li@Sun.COM * Load shares from sharemgr 13907961SNatalie.Li@Sun.COM */ 13917961SNatalie.Li@Sun.COM /*ARGSUSED*/ 13927961SNatalie.Li@Sun.COM static void * 13937961SNatalie.Li@Sun.COM smb_shr_sa_loadall(void *args) 13947961SNatalie.Li@Sun.COM { 13957961SNatalie.Li@Sun.COM sa_handle_t handle; 13967961SNatalie.Li@Sun.COM sa_group_t group, subgroup; 13977961SNatalie.Li@Sun.COM char *gstate; 13987961SNatalie.Li@Sun.COM boolean_t gdisabled; 13997961SNatalie.Li@Sun.COM 14008474SJose.Borrego@Sun.COM if ((handle = smb_shr_sa_enter()) == NULL) 14017961SNatalie.Li@Sun.COM return (NULL); 14027348SJose.Borrego@Sun.COM 14037961SNatalie.Li@Sun.COM for (group = sa_get_group(handle, NULL); 14047961SNatalie.Li@Sun.COM group != NULL; group = sa_get_next_group(group)) { 14057961SNatalie.Li@Sun.COM gstate = sa_get_group_attr(group, "state"); 14067961SNatalie.Li@Sun.COM if (gstate == NULL) 14077961SNatalie.Li@Sun.COM continue; 14087961SNatalie.Li@Sun.COM 14097961SNatalie.Li@Sun.COM gdisabled = (strcasecmp(gstate, "disabled") == 0); 14107961SNatalie.Li@Sun.COM sa_free_attr_string(gstate); 14117961SNatalie.Li@Sun.COM if (gdisabled) 14127961SNatalie.Li@Sun.COM continue; 14137961SNatalie.Li@Sun.COM 14147961SNatalie.Li@Sun.COM smb_shr_sa_loadgrp(group); 14157961SNatalie.Li@Sun.COM 14167961SNatalie.Li@Sun.COM for (subgroup = sa_get_sub_group(group); 14177961SNatalie.Li@Sun.COM subgroup != NULL; 14187961SNatalie.Li@Sun.COM subgroup = sa_get_next_group(subgroup)) { 14197961SNatalie.Li@Sun.COM smb_shr_sa_loadgrp(subgroup); 14207961SNatalie.Li@Sun.COM } 14217961SNatalie.Li@Sun.COM 14227348SJose.Borrego@Sun.COM } 14237348SJose.Borrego@Sun.COM 14248474SJose.Borrego@Sun.COM smb_shr_sa_exit(); 14257961SNatalie.Li@Sun.COM return (NULL); 14267348SJose.Borrego@Sun.COM } 14277348SJose.Borrego@Sun.COM 14287961SNatalie.Li@Sun.COM /* 14297961SNatalie.Li@Sun.COM * Load the shares contained in the specified group. 14307961SNatalie.Li@Sun.COM * 14317961SNatalie.Li@Sun.COM * Don't process groups on which the smb protocol is disabled. 14327961SNatalie.Li@Sun.COM * The top level ZFS group won't have the smb protocol enabled 14337961SNatalie.Li@Sun.COM * but sub-groups will. 14347961SNatalie.Li@Sun.COM * 14357961SNatalie.Li@Sun.COM * We will tolerate a limited number of errors and then give 14367961SNatalie.Li@Sun.COM * up on the current group. A typical error might be that the 14377961SNatalie.Li@Sun.COM * shared directory no longer exists. 14387961SNatalie.Li@Sun.COM */ 14397961SNatalie.Li@Sun.COM static void 14407961SNatalie.Li@Sun.COM smb_shr_sa_loadgrp(sa_group_t group) 14417961SNatalie.Li@Sun.COM { 14427961SNatalie.Li@Sun.COM sa_share_t share; 14437961SNatalie.Li@Sun.COM sa_resource_t resource; 14447961SNatalie.Li@Sun.COM int error_count = 0; 14457961SNatalie.Li@Sun.COM 14467961SNatalie.Li@Sun.COM if (sa_get_optionset(group, SMB_PROTOCOL_NAME) == NULL) 14477961SNatalie.Li@Sun.COM return; 14487961SNatalie.Li@Sun.COM 14497961SNatalie.Li@Sun.COM for (share = sa_get_share(group, NULL); 14507961SNatalie.Li@Sun.COM share != NULL; 14517961SNatalie.Li@Sun.COM share = sa_get_next_share(share)) { 14527961SNatalie.Li@Sun.COM for (resource = sa_get_share_resource(share, NULL); 14537961SNatalie.Li@Sun.COM resource != NULL; 14547961SNatalie.Li@Sun.COM resource = sa_get_next_resource(resource)) { 14557961SNatalie.Li@Sun.COM if (smb_shr_sa_load(share, resource)) 14567961SNatalie.Li@Sun.COM ++error_count; 14577961SNatalie.Li@Sun.COM 14587961SNatalie.Li@Sun.COM if (error_count > SMB_SHR_ERROR_THRESHOLD) 14597961SNatalie.Li@Sun.COM break; 14607961SNatalie.Li@Sun.COM } 14617961SNatalie.Li@Sun.COM 14627961SNatalie.Li@Sun.COM if (error_count > SMB_SHR_ERROR_THRESHOLD) 14637961SNatalie.Li@Sun.COM break; 14647961SNatalie.Li@Sun.COM } 14657961SNatalie.Li@Sun.COM } 14667961SNatalie.Li@Sun.COM 14677961SNatalie.Li@Sun.COM /* 14687961SNatalie.Li@Sun.COM * Load a share definition from sharemgr and add it to the cache. 14698334SJose.Borrego@Sun.COM * If the share is already in the cache then it doesn't do anything. 14708334SJose.Borrego@Sun.COM * 14718334SJose.Borrego@Sun.COM * This function does not report duplicate shares as error since 14728334SJose.Borrego@Sun.COM * a share might have been added by smb_shr_get() while load is 14738334SJose.Borrego@Sun.COM * in progress. 14747961SNatalie.Li@Sun.COM */ 14757348SJose.Borrego@Sun.COM static uint32_t 14767961SNatalie.Li@Sun.COM smb_shr_sa_load(sa_share_t share, sa_resource_t resource) 14777961SNatalie.Li@Sun.COM { 14787961SNatalie.Li@Sun.COM smb_share_t si; 14798334SJose.Borrego@Sun.COM char *sharename; 14807961SNatalie.Li@Sun.COM uint32_t status; 14818334SJose.Borrego@Sun.COM boolean_t loaded; 14828334SJose.Borrego@Sun.COM 14838334SJose.Borrego@Sun.COM if ((sharename = sa_get_resource_attr(resource, "name")) == NULL) 14848334SJose.Borrego@Sun.COM return (NERR_InternalError); 14858334SJose.Borrego@Sun.COM 14868334SJose.Borrego@Sun.COM loaded = smb_shr_exists(sharename); 14878334SJose.Borrego@Sun.COM sa_free_attr_string(sharename); 14888334SJose.Borrego@Sun.COM 14898334SJose.Borrego@Sun.COM if (loaded) 14908334SJose.Borrego@Sun.COM return (NERR_Success); 14917961SNatalie.Li@Sun.COM 14927961SNatalie.Li@Sun.COM if ((status = smb_shr_sa_get(share, resource, &si)) != NERR_Success) { 14937961SNatalie.Li@Sun.COM syslog(LOG_DEBUG, "share: failed to load %s (%d)", 14947961SNatalie.Li@Sun.COM si.shr_name, status); 14957961SNatalie.Li@Sun.COM return (status); 14967961SNatalie.Li@Sun.COM } 14977961SNatalie.Li@Sun.COM 14988334SJose.Borrego@Sun.COM status = smb_shr_add(&si); 14998334SJose.Borrego@Sun.COM if ((status != NERR_Success) && (status != NERR_DuplicateShare)) { 15007961SNatalie.Li@Sun.COM syslog(LOG_DEBUG, "share: failed to cache %s (%d)", 15017961SNatalie.Li@Sun.COM si.shr_name, status); 15027961SNatalie.Li@Sun.COM return (status); 15037961SNatalie.Li@Sun.COM } 15047961SNatalie.Li@Sun.COM 15057961SNatalie.Li@Sun.COM return (NERR_Success); 15067961SNatalie.Li@Sun.COM } 15077961SNatalie.Li@Sun.COM 15087961SNatalie.Li@Sun.COM /* 15097961SNatalie.Li@Sun.COM * Read the specified share information from sharemgr and return 15107961SNatalie.Li@Sun.COM * it in the given smb_share_t structure. 15117961SNatalie.Li@Sun.COM * 15127961SNatalie.Li@Sun.COM * Shares read from sharemgr are marked as permanent/persistent. 15137961SNatalie.Li@Sun.COM */ 15147961SNatalie.Li@Sun.COM static uint32_t 15157961SNatalie.Li@Sun.COM smb_shr_sa_get(sa_share_t share, sa_resource_t resource, smb_share_t *si) 15167348SJose.Borrego@Sun.COM { 15177348SJose.Borrego@Sun.COM sa_property_t prop; 15187348SJose.Borrego@Sun.COM sa_optionset_t opts; 15197348SJose.Borrego@Sun.COM char *val = NULL; 15207348SJose.Borrego@Sun.COM char *path; 15217348SJose.Borrego@Sun.COM char *rname; 15227348SJose.Borrego@Sun.COM 15237348SJose.Borrego@Sun.COM if ((path = sa_get_share_attr(share, "path")) == NULL) 15247348SJose.Borrego@Sun.COM return (NERR_InternalError); 15257348SJose.Borrego@Sun.COM 15267348SJose.Borrego@Sun.COM if ((rname = sa_get_resource_attr(resource, "name")) == NULL) { 15277348SJose.Borrego@Sun.COM sa_free_attr_string(path); 15287348SJose.Borrego@Sun.COM return (NERR_InternalError); 15297348SJose.Borrego@Sun.COM } 15307348SJose.Borrego@Sun.COM 15317348SJose.Borrego@Sun.COM bzero(si, sizeof (smb_share_t)); 15327348SJose.Borrego@Sun.COM si->shr_flags = SMB_SHRF_PERM; 15337348SJose.Borrego@Sun.COM 15347348SJose.Borrego@Sun.COM (void) strlcpy(si->shr_path, path, sizeof (si->shr_path)); 15357348SJose.Borrego@Sun.COM (void) strlcpy(si->shr_name, rname, sizeof (si->shr_name)); 15367348SJose.Borrego@Sun.COM sa_free_attr_string(path); 15377348SJose.Borrego@Sun.COM sa_free_attr_string(rname); 15387348SJose.Borrego@Sun.COM 15397348SJose.Borrego@Sun.COM val = sa_get_resource_description(resource); 15407348SJose.Borrego@Sun.COM if (val == NULL) 15417348SJose.Borrego@Sun.COM val = sa_get_share_description(share); 15427348SJose.Borrego@Sun.COM 15437348SJose.Borrego@Sun.COM if (val != NULL) { 15447348SJose.Borrego@Sun.COM (void) strlcpy(si->shr_cmnt, val, sizeof (si->shr_cmnt)); 15457348SJose.Borrego@Sun.COM sa_free_share_description(val); 15467348SJose.Borrego@Sun.COM } 15477348SJose.Borrego@Sun.COM 15487348SJose.Borrego@Sun.COM opts = sa_get_derived_optionset(resource, SMB_PROTOCOL_NAME, 1); 15497348SJose.Borrego@Sun.COM if (opts == NULL) 15507348SJose.Borrego@Sun.COM return (NERR_Success); 15517348SJose.Borrego@Sun.COM 15528334SJose.Borrego@Sun.COM prop = (sa_property_t)sa_get_property(opts, SHOPT_AD_CONTAINER); 15537348SJose.Borrego@Sun.COM if (prop != NULL) { 15547348SJose.Borrego@Sun.COM if ((val = sa_get_property_attr(prop, "value")) != NULL) { 15557348SJose.Borrego@Sun.COM (void) strlcpy(si->shr_container, val, 15567348SJose.Borrego@Sun.COM sizeof (si->shr_container)); 15577348SJose.Borrego@Sun.COM free(val); 15587348SJose.Borrego@Sun.COM } 15597348SJose.Borrego@Sun.COM } 15607348SJose.Borrego@Sun.COM 15619231SAfshin.Ardakani@Sun.COM prop = (sa_property_t)sa_get_property(opts, SHOPT_CATIA); 15629231SAfshin.Ardakani@Sun.COM if (prop != NULL) { 15639231SAfshin.Ardakani@Sun.COM if ((val = sa_get_property_attr(prop, "value")) != NULL) { 15649231SAfshin.Ardakani@Sun.COM smb_shr_sa_catia_option(val, si); 15659231SAfshin.Ardakani@Sun.COM free(val); 15669231SAfshin.Ardakani@Sun.COM } 15679231SAfshin.Ardakani@Sun.COM } 15689231SAfshin.Ardakani@Sun.COM 1569*10504SKeyur.Desai@Sun.COM prop = (sa_property_t)sa_get_property(opts, SHOPT_ABE); 1570*10504SKeyur.Desai@Sun.COM if (prop != NULL) { 1571*10504SKeyur.Desai@Sun.COM if ((val = sa_get_property_attr(prop, "value")) != NULL) { 1572*10504SKeyur.Desai@Sun.COM smb_shr_sa_abe_option(val, si); 1573*10504SKeyur.Desai@Sun.COM free(val); 1574*10504SKeyur.Desai@Sun.COM } 1575*10504SKeyur.Desai@Sun.COM } 1576*10504SKeyur.Desai@Sun.COM 15778334SJose.Borrego@Sun.COM prop = (sa_property_t)sa_get_property(opts, SHOPT_CSC); 15788334SJose.Borrego@Sun.COM if (prop != NULL) { 15798334SJose.Borrego@Sun.COM if ((val = sa_get_property_attr(prop, "value")) != NULL) { 15808334SJose.Borrego@Sun.COM smb_shr_sa_csc_option(val, si); 15818334SJose.Borrego@Sun.COM free(val); 15828334SJose.Borrego@Sun.COM } 15838334SJose.Borrego@Sun.COM } 15848334SJose.Borrego@Sun.COM 15859832Samw@Sun.COM prop = (sa_property_t)sa_get_property(opts, SHOPT_GUEST); 15869832Samw@Sun.COM if (prop != NULL) { 15879832Samw@Sun.COM if ((val = sa_get_property_attr(prop, "value")) != NULL) { 15889832Samw@Sun.COM smb_shr_sa_guest_option(val, si); 15899832Samw@Sun.COM free(val); 15909832Samw@Sun.COM } 15919832Samw@Sun.COM } 15929832Samw@Sun.COM 15937961SNatalie.Li@Sun.COM prop = (sa_property_t)sa_get_property(opts, SHOPT_NONE); 15947961SNatalie.Li@Sun.COM if (prop != NULL) { 15957961SNatalie.Li@Sun.COM if ((val = sa_get_property_attr(prop, "value")) != NULL) { 15967961SNatalie.Li@Sun.COM (void) strlcpy(si->shr_access_none, val, 15977961SNatalie.Li@Sun.COM sizeof (si->shr_access_none)); 15987961SNatalie.Li@Sun.COM free(val); 15997961SNatalie.Li@Sun.COM si->shr_flags |= SMB_SHRF_ACC_NONE; 16007961SNatalie.Li@Sun.COM } 16017348SJose.Borrego@Sun.COM } 16027348SJose.Borrego@Sun.COM 16037961SNatalie.Li@Sun.COM prop = (sa_property_t)sa_get_property(opts, SHOPT_RO); 16047961SNatalie.Li@Sun.COM if (prop != NULL) { 16057961SNatalie.Li@Sun.COM if ((val = sa_get_property_attr(prop, "value")) != NULL) { 16067961SNatalie.Li@Sun.COM (void) strlcpy(si->shr_access_ro, val, 16077961SNatalie.Li@Sun.COM sizeof (si->shr_access_ro)); 16087961SNatalie.Li@Sun.COM free(val); 16097961SNatalie.Li@Sun.COM si->shr_flags |= SMB_SHRF_ACC_RO; 16107961SNatalie.Li@Sun.COM } 16117348SJose.Borrego@Sun.COM } 16127348SJose.Borrego@Sun.COM 16137961SNatalie.Li@Sun.COM prop = (sa_property_t)sa_get_property(opts, SHOPT_RW); 16147961SNatalie.Li@Sun.COM if (prop != NULL) { 16157961SNatalie.Li@Sun.COM if ((val = sa_get_property_attr(prop, "value")) != NULL) { 16167961SNatalie.Li@Sun.COM (void) strlcpy(si->shr_access_rw, val, 16177961SNatalie.Li@Sun.COM sizeof (si->shr_access_rw)); 16187961SNatalie.Li@Sun.COM free(val); 16197961SNatalie.Li@Sun.COM si->shr_flags |= SMB_SHRF_ACC_RW; 16207961SNatalie.Li@Sun.COM } 16217961SNatalie.Li@Sun.COM } 16227961SNatalie.Li@Sun.COM 16237961SNatalie.Li@Sun.COM sa_free_derived_optionset(opts); 16247961SNatalie.Li@Sun.COM return (NERR_Success); 16257348SJose.Borrego@Sun.COM } 16267348SJose.Borrego@Sun.COM 16277348SJose.Borrego@Sun.COM /* 16288334SJose.Borrego@Sun.COM * Map a client-side caching (CSC) option to the appropriate share 16298334SJose.Borrego@Sun.COM * flag. Only one option is allowed; an error will be logged if 16308334SJose.Borrego@Sun.COM * multiple options have been specified. We don't need to do anything 16318334SJose.Borrego@Sun.COM * about multiple values here because the SRVSVC will not recognize 16328334SJose.Borrego@Sun.COM * a value containing multiple flags and will return the default value. 16338334SJose.Borrego@Sun.COM * 16348334SJose.Borrego@Sun.COM * If the option value is not recognized, it will be ignored: invalid 16358334SJose.Borrego@Sun.COM * values will typically be caught and rejected by sharemgr. 16368334SJose.Borrego@Sun.COM */ 16378474SJose.Borrego@Sun.COM void 16388334SJose.Borrego@Sun.COM smb_shr_sa_csc_option(const char *value, smb_share_t *si) 16398334SJose.Borrego@Sun.COM { 16408334SJose.Borrego@Sun.COM int i; 16418334SJose.Borrego@Sun.COM 16428334SJose.Borrego@Sun.COM for (i = 0; i < (sizeof (cscopt) / sizeof (cscopt[0])); ++i) { 16438334SJose.Borrego@Sun.COM if (strcasecmp(value, cscopt[i].value) == 0) { 16448334SJose.Borrego@Sun.COM si->shr_flags |= cscopt[i].flag; 16458334SJose.Borrego@Sun.COM break; 16468334SJose.Borrego@Sun.COM } 16478334SJose.Borrego@Sun.COM } 16488334SJose.Borrego@Sun.COM 16498334SJose.Borrego@Sun.COM switch (si->shr_flags & SMB_SHRF_CSC_MASK) { 16508334SJose.Borrego@Sun.COM case 0: 16518334SJose.Borrego@Sun.COM case SMB_SHRF_CSC_DISABLED: 16528334SJose.Borrego@Sun.COM case SMB_SHRF_CSC_MANUAL: 16538334SJose.Borrego@Sun.COM case SMB_SHRF_CSC_AUTO: 16548334SJose.Borrego@Sun.COM case SMB_SHRF_CSC_VDO: 16558334SJose.Borrego@Sun.COM break; 16568334SJose.Borrego@Sun.COM 16578334SJose.Borrego@Sun.COM default: 16588474SJose.Borrego@Sun.COM syslog(LOG_INFO, "csc option conflict: 0x%08x", 16598474SJose.Borrego@Sun.COM si->shr_flags & SMB_SHRF_CSC_MASK); 16608334SJose.Borrego@Sun.COM break; 16618334SJose.Borrego@Sun.COM } 16628334SJose.Borrego@Sun.COM } 16638334SJose.Borrego@Sun.COM 16648334SJose.Borrego@Sun.COM /* 16659832Samw@Sun.COM * Return the option name for the first CSC flag (there should be only 16669832Samw@Sun.COM * one) encountered in the share flags. 16679832Samw@Sun.COM */ 16689832Samw@Sun.COM char * 16699832Samw@Sun.COM smb_shr_sa_csc_name(const smb_share_t *si) 16709832Samw@Sun.COM { 16719832Samw@Sun.COM int i; 16729832Samw@Sun.COM 16739832Samw@Sun.COM for (i = 0; i < (sizeof (cscopt) / sizeof (cscopt[0])); ++i) { 16749832Samw@Sun.COM if (si->shr_flags & cscopt[i].flag) 16759832Samw@Sun.COM return (cscopt[i].value); 16769832Samw@Sun.COM } 16779832Samw@Sun.COM 16789832Samw@Sun.COM return (NULL); 16799832Samw@Sun.COM } 16809832Samw@Sun.COM 16819832Samw@Sun.COM /* 16829231SAfshin.Ardakani@Sun.COM * set SMB_SHRF_CATIA in accordance with catia property value 16839231SAfshin.Ardakani@Sun.COM */ 16849231SAfshin.Ardakani@Sun.COM void 16859231SAfshin.Ardakani@Sun.COM smb_shr_sa_catia_option(const char *value, smb_share_t *si) 16869231SAfshin.Ardakani@Sun.COM { 16879231SAfshin.Ardakani@Sun.COM if ((strcasecmp(value, "true") == 0) || (strcmp(value, "1") == 0)) { 16889231SAfshin.Ardakani@Sun.COM si->shr_flags |= SMB_SHRF_CATIA; 16899231SAfshin.Ardakani@Sun.COM } else { 16909231SAfshin.Ardakani@Sun.COM si->shr_flags &= ~SMB_SHRF_CATIA; 16919231SAfshin.Ardakani@Sun.COM } 16929231SAfshin.Ardakani@Sun.COM } 16939231SAfshin.Ardakani@Sun.COM 16949231SAfshin.Ardakani@Sun.COM /* 1695*10504SKeyur.Desai@Sun.COM * set SMB_SHRF_ABE in accordance with abe property value 1696*10504SKeyur.Desai@Sun.COM */ 1697*10504SKeyur.Desai@Sun.COM void 1698*10504SKeyur.Desai@Sun.COM smb_shr_sa_abe_option(const char *value, smb_share_t *si) 1699*10504SKeyur.Desai@Sun.COM { 1700*10504SKeyur.Desai@Sun.COM if ((strcasecmp(value, "true") == 0) || (strcmp(value, "1") == 0)) { 1701*10504SKeyur.Desai@Sun.COM si->shr_flags |= SMB_SHRF_ABE; 1702*10504SKeyur.Desai@Sun.COM } else { 1703*10504SKeyur.Desai@Sun.COM si->shr_flags &= ~SMB_SHRF_ABE; 1704*10504SKeyur.Desai@Sun.COM } 1705*10504SKeyur.Desai@Sun.COM } 1706*10504SKeyur.Desai@Sun.COM 1707*10504SKeyur.Desai@Sun.COM /* 17089832Samw@Sun.COM * set SMB_SHRF_GUEST_OK in accordance with guestok property value 17099832Samw@Sun.COM */ 17109832Samw@Sun.COM static void 17119832Samw@Sun.COM smb_shr_sa_guest_option(const char *value, smb_share_t *si) 17129832Samw@Sun.COM { 17139832Samw@Sun.COM if ((strcasecmp(value, "true") == 0) || (strcmp(value, "1") == 0)) { 17149832Samw@Sun.COM si->shr_flags |= SMB_SHRF_GUEST_OK; 17159832Samw@Sun.COM } else { 17169832Samw@Sun.COM si->shr_flags &= ~SMB_SHRF_GUEST_OK; 17179832Samw@Sun.COM } 17189832Samw@Sun.COM } 17199832Samw@Sun.COM 17209832Samw@Sun.COM /* 17218334SJose.Borrego@Sun.COM * looks up sharemgr for the given share (resource) and loads 17228334SJose.Borrego@Sun.COM * the definition into cache if lookup is successful 17238334SJose.Borrego@Sun.COM */ 17248334SJose.Borrego@Sun.COM static uint32_t 17258334SJose.Borrego@Sun.COM smb_shr_sa_loadbyname(char *sharename) 17268334SJose.Borrego@Sun.COM { 17278334SJose.Borrego@Sun.COM sa_handle_t handle; 17288334SJose.Borrego@Sun.COM sa_share_t share; 17298334SJose.Borrego@Sun.COM sa_resource_t resource; 17308334SJose.Borrego@Sun.COM uint32_t status; 17318334SJose.Borrego@Sun.COM 17328474SJose.Borrego@Sun.COM if ((handle = smb_shr_sa_enter()) == NULL) 17338334SJose.Borrego@Sun.COM return (NERR_InternalError); 17348334SJose.Borrego@Sun.COM 17358334SJose.Borrego@Sun.COM resource = sa_find_resource(handle, sharename); 17368334SJose.Borrego@Sun.COM if (resource == NULL) { 17378474SJose.Borrego@Sun.COM smb_shr_sa_exit(); 17388334SJose.Borrego@Sun.COM return (NERR_NetNameNotFound); 17398334SJose.Borrego@Sun.COM } 17408334SJose.Borrego@Sun.COM 17418334SJose.Borrego@Sun.COM share = sa_get_resource_parent(resource); 17428334SJose.Borrego@Sun.COM if (share == NULL) { 17438474SJose.Borrego@Sun.COM smb_shr_sa_exit(); 17448334SJose.Borrego@Sun.COM return (NERR_InternalError); 17458334SJose.Borrego@Sun.COM } 17468334SJose.Borrego@Sun.COM 17478334SJose.Borrego@Sun.COM status = smb_shr_sa_load(share, resource); 17488334SJose.Borrego@Sun.COM 17498474SJose.Borrego@Sun.COM smb_shr_sa_exit(); 17508334SJose.Borrego@Sun.COM return (status); 17518334SJose.Borrego@Sun.COM } 17528334SJose.Borrego@Sun.COM 17538334SJose.Borrego@Sun.COM /* 17547348SJose.Borrego@Sun.COM * ============================================ 17557348SJose.Borrego@Sun.COM * Share publishing functions 17567961SNatalie.Li@Sun.COM * 17577961SNatalie.Li@Sun.COM * All the functions are private 17587348SJose.Borrego@Sun.COM * ============================================ 17597348SJose.Borrego@Sun.COM */ 17607348SJose.Borrego@Sun.COM 17617961SNatalie.Li@Sun.COM static void 17627961SNatalie.Li@Sun.COM smb_shr_publish(const char *sharename, const char *container) 17637961SNatalie.Li@Sun.COM { 17647961SNatalie.Li@Sun.COM smb_shr_publisher_queue(sharename, container, SMB_SHR_PUBLISH); 17657961SNatalie.Li@Sun.COM } 17667961SNatalie.Li@Sun.COM 17677961SNatalie.Li@Sun.COM static void 17687961SNatalie.Li@Sun.COM smb_shr_unpublish(const char *sharename, const char *container) 17697961SNatalie.Li@Sun.COM { 17707961SNatalie.Li@Sun.COM smb_shr_publisher_queue(sharename, container, SMB_SHR_UNPUBLISH); 17717961SNatalie.Li@Sun.COM } 17727961SNatalie.Li@Sun.COM 17737348SJose.Borrego@Sun.COM /* 17747961SNatalie.Li@Sun.COM * In domain mode, put a share on the publisher queue. 17757961SNatalie.Li@Sun.COM * This is a no-op if the smb service is in Workgroup mode. 17767348SJose.Borrego@Sun.COM */ 17777348SJose.Borrego@Sun.COM static void 17787961SNatalie.Li@Sun.COM smb_shr_publisher_queue(const char *sharename, const char *container, char op) 17797348SJose.Borrego@Sun.COM { 17807348SJose.Borrego@Sun.COM smb_shr_pitem_t *item = NULL; 17817348SJose.Borrego@Sun.COM 17827348SJose.Borrego@Sun.COM if (container == NULL || *container == '\0') 17837348SJose.Borrego@Sun.COM return; 17847348SJose.Borrego@Sun.COM 17857961SNatalie.Li@Sun.COM if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN) 17867961SNatalie.Li@Sun.COM return; 17877961SNatalie.Li@Sun.COM 17887348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 17897348SJose.Borrego@Sun.COM switch (ad_queue.spq_state) { 17907348SJose.Borrego@Sun.COM case SMB_SHR_PQS_READY: 17917348SJose.Borrego@Sun.COM case SMB_SHR_PQS_PUBLISHING: 17927348SJose.Borrego@Sun.COM break; 17937348SJose.Borrego@Sun.COM default: 17947348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 17957348SJose.Borrego@Sun.COM return; 17967348SJose.Borrego@Sun.COM } 17977348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 17987348SJose.Borrego@Sun.COM 17997961SNatalie.Li@Sun.COM if ((item = malloc(sizeof (smb_shr_pitem_t))) == NULL) 18007348SJose.Borrego@Sun.COM return; 18017348SJose.Borrego@Sun.COM 18027348SJose.Borrego@Sun.COM item->spi_op = op; 18037348SJose.Borrego@Sun.COM (void) strlcpy(item->spi_name, sharename, sizeof (item->spi_name)); 18047348SJose.Borrego@Sun.COM (void) strlcpy(item->spi_container, container, 18057348SJose.Borrego@Sun.COM sizeof (item->spi_container)); 18067348SJose.Borrego@Sun.COM 18077348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 18087348SJose.Borrego@Sun.COM list_insert_tail(&ad_queue.spq_list, item); 18097348SJose.Borrego@Sun.COM (void) cond_signal(&ad_queue.spq_cv); 18107348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 18117348SJose.Borrego@Sun.COM } 18127348SJose.Borrego@Sun.COM 18137961SNatalie.Li@Sun.COM /* 18147961SNatalie.Li@Sun.COM * Publishing won't be activated if the smb service is running in 18157961SNatalie.Li@Sun.COM * Workgroup mode. 18167961SNatalie.Li@Sun.COM */ 18177348SJose.Borrego@Sun.COM static int 18187348SJose.Borrego@Sun.COM smb_shr_publisher_start(void) 18197348SJose.Borrego@Sun.COM { 18207961SNatalie.Li@Sun.COM pthread_t publish_thr; 18217348SJose.Borrego@Sun.COM pthread_attr_t tattr; 18227348SJose.Borrego@Sun.COM int rc; 18237348SJose.Borrego@Sun.COM 18247961SNatalie.Li@Sun.COM if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN) 18257961SNatalie.Li@Sun.COM return (0); 18267961SNatalie.Li@Sun.COM 18277348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 18287348SJose.Borrego@Sun.COM if (ad_queue.spq_state != SMB_SHR_PQS_NOQUEUE) { 18297348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 18307348SJose.Borrego@Sun.COM errno = EINVAL; 18317348SJose.Borrego@Sun.COM return (-1); 18327348SJose.Borrego@Sun.COM } 18337348SJose.Borrego@Sun.COM 18347348SJose.Borrego@Sun.COM list_create(&ad_queue.spq_list, sizeof (smb_shr_pitem_t), 18357348SJose.Borrego@Sun.COM offsetof(smb_shr_pitem_t, spi_lnd)); 18367348SJose.Borrego@Sun.COM ad_queue.spq_state = SMB_SHR_PQS_READY; 18377348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 18387348SJose.Borrego@Sun.COM 18397348SJose.Borrego@Sun.COM (void) pthread_attr_init(&tattr); 18407348SJose.Borrego@Sun.COM (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); 18417961SNatalie.Li@Sun.COM rc = pthread_create(&publish_thr, &tattr, smb_shr_publisher, 0); 18427348SJose.Borrego@Sun.COM (void) pthread_attr_destroy(&tattr); 18437348SJose.Borrego@Sun.COM 18447348SJose.Borrego@Sun.COM return (rc); 18457348SJose.Borrego@Sun.COM } 18467348SJose.Borrego@Sun.COM 18477348SJose.Borrego@Sun.COM static void 18487348SJose.Borrego@Sun.COM smb_shr_publisher_stop(void) 18497348SJose.Borrego@Sun.COM { 18507961SNatalie.Li@Sun.COM if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN) 18517961SNatalie.Li@Sun.COM return; 18527961SNatalie.Li@Sun.COM 18537348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 18547348SJose.Borrego@Sun.COM switch (ad_queue.spq_state) { 18557348SJose.Borrego@Sun.COM case SMB_SHR_PQS_READY: 18567348SJose.Borrego@Sun.COM case SMB_SHR_PQS_PUBLISHING: 18577348SJose.Borrego@Sun.COM ad_queue.spq_state = SMB_SHR_PQS_STOPPING; 18587348SJose.Borrego@Sun.COM (void) cond_signal(&ad_queue.spq_cv); 18597348SJose.Borrego@Sun.COM break; 18607348SJose.Borrego@Sun.COM default: 18617348SJose.Borrego@Sun.COM break; 18627348SJose.Borrego@Sun.COM } 18637348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 18647348SJose.Borrego@Sun.COM } 18657348SJose.Borrego@Sun.COM 18667348SJose.Borrego@Sun.COM /* 18677961SNatalie.Li@Sun.COM * This is the publisher daemon thread. While running, the thread waits 18687961SNatalie.Li@Sun.COM * on a conditional variable until notified that a share needs to be 18697961SNatalie.Li@Sun.COM * [un]published or that the thread should be terminated. 18707961SNatalie.Li@Sun.COM * 18717961SNatalie.Li@Sun.COM * Entries may remain in the outgoing queue if the Active Directory 18727961SNatalie.Li@Sun.COM * service is inaccessible, in which case the thread wakes up every 60 18737961SNatalie.Li@Sun.COM * seconds to retry. 18747348SJose.Borrego@Sun.COM */ 18757348SJose.Borrego@Sun.COM /*ARGSUSED*/ 18767348SJose.Borrego@Sun.COM static void * 18777348SJose.Borrego@Sun.COM smb_shr_publisher(void *arg) 18787348SJose.Borrego@Sun.COM { 18797348SJose.Borrego@Sun.COM smb_ads_handle_t *ah; 18807348SJose.Borrego@Sun.COM smb_shr_pitem_t *shr; 18817348SJose.Borrego@Sun.COM list_t publist; 18827961SNatalie.Li@Sun.COM timestruc_t pubretry; 18837348SJose.Borrego@Sun.COM char hostname[MAXHOSTNAMELEN]; 18847348SJose.Borrego@Sun.COM 18857348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 18867961SNatalie.Li@Sun.COM if (ad_queue.spq_state != SMB_SHR_PQS_READY) { 18877348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 18887348SJose.Borrego@Sun.COM return (NULL); 18897348SJose.Borrego@Sun.COM } 18907961SNatalie.Li@Sun.COM ad_queue.spq_state = SMB_SHR_PQS_PUBLISHING; 18917348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 18927348SJose.Borrego@Sun.COM 18937348SJose.Borrego@Sun.COM (void) smb_gethostname(hostname, MAXHOSTNAMELEN, 0); 18947961SNatalie.Li@Sun.COM 18957348SJose.Borrego@Sun.COM list_create(&publist, sizeof (smb_shr_pitem_t), 18967348SJose.Borrego@Sun.COM offsetof(smb_shr_pitem_t, spi_lnd)); 18977348SJose.Borrego@Sun.COM 18987348SJose.Borrego@Sun.COM for (;;) { 18997348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 19007961SNatalie.Li@Sun.COM 19017961SNatalie.Li@Sun.COM while (list_is_empty(&ad_queue.spq_list) && 19027961SNatalie.Li@Sun.COM (ad_queue.spq_state == SMB_SHR_PQS_PUBLISHING)) { 19037961SNatalie.Li@Sun.COM if (list_is_empty(&publist)) { 19047961SNatalie.Li@Sun.COM (void) cond_wait(&ad_queue.spq_cv, 19057961SNatalie.Li@Sun.COM &ad_queue.spq_mtx); 19067961SNatalie.Li@Sun.COM } else { 19077961SNatalie.Li@Sun.COM pubretry.tv_sec = 60; 19087961SNatalie.Li@Sun.COM pubretry.tv_nsec = 0; 19097961SNatalie.Li@Sun.COM (void) cond_reltimedwait(&ad_queue.spq_cv, 19107961SNatalie.Li@Sun.COM &ad_queue.spq_mtx, &pubretry); 19117961SNatalie.Li@Sun.COM break; 19127961SNatalie.Li@Sun.COM } 19137961SNatalie.Li@Sun.COM } 19147348SJose.Borrego@Sun.COM 19157348SJose.Borrego@Sun.COM if (ad_queue.spq_state != SMB_SHR_PQS_PUBLISHING) { 19167348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 19177348SJose.Borrego@Sun.COM break; 19187348SJose.Borrego@Sun.COM } 19197348SJose.Borrego@Sun.COM 19207348SJose.Borrego@Sun.COM /* 19217961SNatalie.Li@Sun.COM * Transfer queued items to the local list so that 19227961SNatalie.Li@Sun.COM * the mutex can be released. 19237348SJose.Borrego@Sun.COM */ 19247348SJose.Borrego@Sun.COM while ((shr = list_head(&ad_queue.spq_list)) != NULL) { 19257348SJose.Borrego@Sun.COM list_remove(&ad_queue.spq_list, shr); 19267348SJose.Borrego@Sun.COM list_insert_tail(&publist, shr); 19277348SJose.Borrego@Sun.COM } 19287961SNatalie.Li@Sun.COM 19297348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 19307348SJose.Borrego@Sun.COM 19317961SNatalie.Li@Sun.COM if ((ah = smb_ads_open()) != NULL) { 19327961SNatalie.Li@Sun.COM smb_shr_publisher_send(ah, &publist, hostname); 19337961SNatalie.Li@Sun.COM smb_ads_close(ah); 19347961SNatalie.Li@Sun.COM } 19357348SJose.Borrego@Sun.COM } 19367348SJose.Borrego@Sun.COM 19377348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 19387961SNatalie.Li@Sun.COM smb_shr_publisher_flush(&ad_queue.spq_list); 19397348SJose.Borrego@Sun.COM list_destroy(&ad_queue.spq_list); 19407348SJose.Borrego@Sun.COM ad_queue.spq_state = SMB_SHR_PQS_NOQUEUE; 19417348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 19427348SJose.Borrego@Sun.COM 19437961SNatalie.Li@Sun.COM smb_shr_publisher_flush(&publist); 19447348SJose.Borrego@Sun.COM list_destroy(&publist); 19457348SJose.Borrego@Sun.COM return (NULL); 19467348SJose.Borrego@Sun.COM } 19477348SJose.Borrego@Sun.COM 19487348SJose.Borrego@Sun.COM /* 19497961SNatalie.Li@Sun.COM * Remove items from the specified queue and [un]publish them. 19507348SJose.Borrego@Sun.COM */ 19517348SJose.Borrego@Sun.COM static void 19527348SJose.Borrego@Sun.COM smb_shr_publisher_send(smb_ads_handle_t *ah, list_t *publist, const char *host) 19537348SJose.Borrego@Sun.COM { 19547348SJose.Borrego@Sun.COM smb_shr_pitem_t *shr; 19557348SJose.Borrego@Sun.COM 19567348SJose.Borrego@Sun.COM while ((shr = list_head(publist)) != NULL) { 19577961SNatalie.Li@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 19587961SNatalie.Li@Sun.COM if (ad_queue.spq_state != SMB_SHR_PQS_PUBLISHING) { 19597348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 19607961SNatalie.Li@Sun.COM return; 19617961SNatalie.Li@Sun.COM } 19627961SNatalie.Li@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 19637348SJose.Borrego@Sun.COM 19647961SNatalie.Li@Sun.COM list_remove(publist, shr); 19657961SNatalie.Li@Sun.COM 19667961SNatalie.Li@Sun.COM if (shr->spi_op == SMB_SHR_PUBLISH) 19677961SNatalie.Li@Sun.COM (void) smb_ads_publish_share(ah, shr->spi_name, 19687961SNatalie.Li@Sun.COM NULL, shr->spi_container, host); 19697961SNatalie.Li@Sun.COM else 19707961SNatalie.Li@Sun.COM (void) smb_ads_remove_share(ah, shr->spi_name, 19717961SNatalie.Li@Sun.COM NULL, shr->spi_container, host); 19727961SNatalie.Li@Sun.COM 19737348SJose.Borrego@Sun.COM free(shr); 19747348SJose.Borrego@Sun.COM } 19757348SJose.Borrego@Sun.COM } 19767961SNatalie.Li@Sun.COM 19777961SNatalie.Li@Sun.COM /* 19787961SNatalie.Li@Sun.COM * Flush all remaining items from the specified list/queue. 19797961SNatalie.Li@Sun.COM */ 19807961SNatalie.Li@Sun.COM static void 19817961SNatalie.Li@Sun.COM smb_shr_publisher_flush(list_t *lst) 19827961SNatalie.Li@Sun.COM { 19837961SNatalie.Li@Sun.COM smb_shr_pitem_t *shr; 19847961SNatalie.Li@Sun.COM 19857961SNatalie.Li@Sun.COM while ((shr = list_head(lst)) != NULL) { 19867961SNatalie.Li@Sun.COM list_remove(lst, shr); 19877961SNatalie.Li@Sun.COM free(shr); 19887961SNatalie.Li@Sun.COM } 19897961SNatalie.Li@Sun.COM } 19908845Samw@Sun.COM 19918845Samw@Sun.COM /* 19928871Samw@Sun.COM * If the share path refers to a ZFS file system, add the 19938845Samw@Sun.COM * .zfs/shares/<share> object. 19948845Samw@Sun.COM */ 19958845Samw@Sun.COM 19968845Samw@Sun.COM static void 19978845Samw@Sun.COM smb_shr_zfs_add(smb_share_t *si) 19988845Samw@Sun.COM { 19998871Samw@Sun.COM libzfs_handle_t *libhd; 20008871Samw@Sun.COM zfs_handle_t *zfshd; 20018871Samw@Sun.COM int ret; 20028845Samw@Sun.COM char dataset[MAXPATHLEN]; 20038845Samw@Sun.COM 20048871Samw@Sun.COM if (smb_getdataset(si->shr_path, dataset, MAXPATHLEN) != 0) 20058871Samw@Sun.COM return; 20068871Samw@Sun.COM 20078871Samw@Sun.COM if ((libhd = libzfs_init()) == NULL) 20088871Samw@Sun.COM return; 20098871Samw@Sun.COM 20108871Samw@Sun.COM if ((zfshd = zfs_open(libhd, dataset, ZFS_TYPE_FILESYSTEM)) == NULL) { 20118871Samw@Sun.COM libzfs_fini(libhd); 20128871Samw@Sun.COM return; 20138845Samw@Sun.COM } 20148871Samw@Sun.COM 20158871Samw@Sun.COM errno = 0; 20168871Samw@Sun.COM ret = zfs_smb_acl_add(libhd, dataset, si->shr_path, si->shr_name); 20178871Samw@Sun.COM if (ret != 0 && errno != EAGAIN && errno != EEXIST) 20188871Samw@Sun.COM syslog(LOG_INFO, "share: failed to add ACL object: %s: %s\n", 20198871Samw@Sun.COM si->shr_name, strerror(errno)); 20208871Samw@Sun.COM 20218871Samw@Sun.COM zfs_close(zfshd); 20228871Samw@Sun.COM libzfs_fini(libhd); 20238845Samw@Sun.COM } 20248845Samw@Sun.COM 20258845Samw@Sun.COM /* 20268871Samw@Sun.COM * If the share path refers to a ZFS file system, remove the 20278845Samw@Sun.COM * .zfs/shares/<share> object. 20288845Samw@Sun.COM */ 20298845Samw@Sun.COM 20308845Samw@Sun.COM static void 20318845Samw@Sun.COM smb_shr_zfs_remove(smb_share_t *si) 20328845Samw@Sun.COM { 20338871Samw@Sun.COM libzfs_handle_t *libhd; 20348871Samw@Sun.COM zfs_handle_t *zfshd; 20358871Samw@Sun.COM int ret; 20368845Samw@Sun.COM char dataset[MAXPATHLEN]; 20378845Samw@Sun.COM 20388871Samw@Sun.COM if (smb_getdataset(si->shr_path, dataset, MAXPATHLEN) != 0) 20398871Samw@Sun.COM return; 20408871Samw@Sun.COM 20418871Samw@Sun.COM if ((libhd = libzfs_init()) == NULL) 20428871Samw@Sun.COM return; 20438871Samw@Sun.COM 20448871Samw@Sun.COM if ((zfshd = zfs_open(libhd, dataset, ZFS_TYPE_FILESYSTEM)) == NULL) { 20458871Samw@Sun.COM libzfs_fini(libhd); 20468871Samw@Sun.COM return; 20478845Samw@Sun.COM } 20488871Samw@Sun.COM 20498871Samw@Sun.COM errno = 0; 20508871Samw@Sun.COM ret = zfs_smb_acl_remove(libhd, dataset, si->shr_path, si->shr_name); 20518871Samw@Sun.COM if (ret != 0 && errno != EAGAIN) 20528871Samw@Sun.COM syslog(LOG_INFO, "share: failed to remove ACL object: %s: %s\n", 20538871Samw@Sun.COM si->shr_name, strerror(errno)); 20548871Samw@Sun.COM 20558871Samw@Sun.COM zfs_close(zfshd); 20568871Samw@Sun.COM libzfs_fini(libhd); 20578845Samw@Sun.COM } 20588845Samw@Sun.COM 20598845Samw@Sun.COM /* 20608871Samw@Sun.COM * If the share path refers to a ZFS file system, rename the 20618845Samw@Sun.COM * .zfs/shares/<share> object. 20628845Samw@Sun.COM */ 20638845Samw@Sun.COM 20648845Samw@Sun.COM static void 20658845Samw@Sun.COM smb_shr_zfs_rename(smb_share_t *from, smb_share_t *to) 20668845Samw@Sun.COM { 20678871Samw@Sun.COM libzfs_handle_t *libhd; 20688871Samw@Sun.COM zfs_handle_t *zfshd; 20698871Samw@Sun.COM int ret; 20708845Samw@Sun.COM char dataset[MAXPATHLEN]; 20718845Samw@Sun.COM 20728871Samw@Sun.COM if (smb_getdataset(from->shr_path, dataset, MAXPATHLEN) != 0) 20738871Samw@Sun.COM return; 20748871Samw@Sun.COM 20758871Samw@Sun.COM if ((libhd = libzfs_init()) == NULL) 20768871Samw@Sun.COM return; 20778871Samw@Sun.COM 20788871Samw@Sun.COM if ((zfshd = zfs_open(libhd, dataset, ZFS_TYPE_FILESYSTEM)) == NULL) { 20798871Samw@Sun.COM libzfs_fini(libhd); 20808871Samw@Sun.COM return; 20818845Samw@Sun.COM } 20828871Samw@Sun.COM 20838871Samw@Sun.COM errno = 0; 20848871Samw@Sun.COM ret = zfs_smb_acl_rename(libhd, dataset, from->shr_path, 20858871Samw@Sun.COM from->shr_name, to->shr_name); 20868871Samw@Sun.COM if (ret != 0 && errno != EAGAIN) 20878871Samw@Sun.COM syslog(LOG_INFO, "share: failed to rename ACL object: %s: %s\n", 20888871Samw@Sun.COM from->shr_name, strerror(errno)); 20898871Samw@Sun.COM 20908871Samw@Sun.COM zfs_close(zfshd); 20918871Samw@Sun.COM libzfs_fini(libhd); 20928845Samw@Sun.COM } 20939832Samw@Sun.COM 20949832Samw@Sun.COM /* 20959832Samw@Sun.COM * Enable all privileges in the inheritable set to execute command. 20969832Samw@Sun.COM */ 20979832Samw@Sun.COM static int 20989832Samw@Sun.COM smb_shr_enable_all_privs(void) 20999832Samw@Sun.COM { 21009832Samw@Sun.COM priv_set_t *pset; 21019832Samw@Sun.COM 21029832Samw@Sun.COM pset = priv_allocset(); 21039832Samw@Sun.COM if (pset == NULL) 21049832Samw@Sun.COM return (-1); 21059832Samw@Sun.COM 21069832Samw@Sun.COM if (getppriv(PRIV_LIMIT, pset)) { 21079832Samw@Sun.COM priv_freeset(pset); 21089832Samw@Sun.COM return (-1); 21099832Samw@Sun.COM } 21109832Samw@Sun.COM 21119832Samw@Sun.COM if (setppriv(PRIV_ON, PRIV_INHERITABLE, pset)) { 21129832Samw@Sun.COM priv_freeset(pset); 21139832Samw@Sun.COM return (-1); 21149832Samw@Sun.COM } 21159832Samw@Sun.COM 21169832Samw@Sun.COM priv_freeset(pset); 21179832Samw@Sun.COM return (0); 21189832Samw@Sun.COM } 21199832Samw@Sun.COM 21209832Samw@Sun.COM /* 21219832Samw@Sun.COM * Tokenizes the command string and returns the list of tokens in an array. 21229832Samw@Sun.COM * 21239832Samw@Sun.COM * Returns NULL if there are no tokens. 21249832Samw@Sun.COM */ 21259832Samw@Sun.COM static char ** 21269832Samw@Sun.COM smb_shr_tokenize_cmd(char *cmdstr) 21279832Samw@Sun.COM { 21289832Samw@Sun.COM char *cmd, *buf, *bp, *value; 21299832Samw@Sun.COM char **argv, **ap; 21309832Samw@Sun.COM int argc, i; 21319832Samw@Sun.COM 21329832Samw@Sun.COM if (cmdstr == NULL || *cmdstr == '\0') 21339832Samw@Sun.COM return (NULL); 21349832Samw@Sun.COM 21359832Samw@Sun.COM if ((buf = malloc(MAXPATHLEN)) == NULL) 21369832Samw@Sun.COM return (NULL); 21379832Samw@Sun.COM 21389832Samw@Sun.COM (void) strlcpy(buf, cmdstr, MAXPATHLEN); 21399832Samw@Sun.COM 21409832Samw@Sun.COM for (argc = 2, bp = cmdstr; *bp != '\0'; ++bp) 21419832Samw@Sun.COM if (*bp == ' ') 21429832Samw@Sun.COM ++argc; 21439832Samw@Sun.COM 21449832Samw@Sun.COM if ((argv = calloc(argc, sizeof (char *))) == NULL) { 21459832Samw@Sun.COM free(buf); 21469832Samw@Sun.COM return (NULL); 21479832Samw@Sun.COM } 21489832Samw@Sun.COM 21499832Samw@Sun.COM ap = argv; 21509832Samw@Sun.COM for (bp = buf, i = 0; i < argc; ++i) { 21519832Samw@Sun.COM do { 21529832Samw@Sun.COM if ((value = strsep(&bp, " ")) == NULL) 21539832Samw@Sun.COM break; 21549832Samw@Sun.COM } while (*value == '\0'); 21559832Samw@Sun.COM 21569832Samw@Sun.COM if (value == NULL) 21579832Samw@Sun.COM break; 21589832Samw@Sun.COM 21599832Samw@Sun.COM *ap++ = value; 21609832Samw@Sun.COM } 21619832Samw@Sun.COM 21629832Samw@Sun.COM /* get the filename of the command from the path */ 21639832Samw@Sun.COM if ((cmd = strrchr(argv[0], '/')) != NULL) 21649832Samw@Sun.COM (void) strlcpy(argv[0], ++cmd, strlen(argv[0])); 21659832Samw@Sun.COM 21669832Samw@Sun.COM return (argv); 21679832Samw@Sun.COM } 21689832Samw@Sun.COM 21699832Samw@Sun.COM /* 21709832Samw@Sun.COM * Expands the command string for the following substitution tokens: 21719832Samw@Sun.COM * 21729832Samw@Sun.COM * %U - Windows username 21739832Samw@Sun.COM * %D - Name of the domain or workgroup of %U 21749832Samw@Sun.COM * %h - The server hostname 21759832Samw@Sun.COM * %M - The client hostname 21769832Samw@Sun.COM * %L - The server NetBIOS name 21779832Samw@Sun.COM * %m - The client NetBIOS name. This option is only valid for NetBIOS 21789832Samw@Sun.COM * connections (port 139). 21799832Samw@Sun.COM * %I - The IP address of the client machine 21809832Samw@Sun.COM * %i - The local IP address to which the client is connected 21819832Samw@Sun.COM * %S - The name of the share 21829832Samw@Sun.COM * %P - The root directory of the share 21839832Samw@Sun.COM * %u - The UID of the Unix user 21849832Samw@Sun.COM * 21859832Samw@Sun.COM * Returns 0 on success. Otherwise -1. 21869832Samw@Sun.COM */ 21879832Samw@Sun.COM static int 21889832Samw@Sun.COM smb_shr_expand_subs(char **cmd_toks, smb_share_t *si, smb_execsub_info_t *subs) 21899832Samw@Sun.COM { 21909832Samw@Sun.COM char *fmt, *sub_chr, *ptr; 21919832Samw@Sun.COM boolean_t unknown; 21929832Samw@Sun.COM char hostname[MAXHOSTNAMELEN]; 21939832Samw@Sun.COM char ip_str[INET6_ADDRSTRLEN]; 21949832Samw@Sun.COM char name[SMB_PI_MAX_HOST]; 21959832Samw@Sun.COM mts_wchar_t wbuf[SMB_PI_MAX_HOST]; 21969832Samw@Sun.COM unsigned int cpid = oem_get_smb_cpid(); 21979832Samw@Sun.COM int i; 21989832Samw@Sun.COM 21999832Samw@Sun.COM if (cmd_toks == NULL || *cmd_toks == NULL) 22009832Samw@Sun.COM return (-1); 22019832Samw@Sun.COM 22029832Samw@Sun.COM for (i = 1; cmd_toks[i]; i++) { 22039832Samw@Sun.COM fmt = cmd_toks[i]; 22049832Samw@Sun.COM if (*fmt == '%') { 22059832Samw@Sun.COM sub_chr = fmt + 1; 22069832Samw@Sun.COM unknown = B_FALSE; 22079832Samw@Sun.COM 22089832Samw@Sun.COM switch (*sub_chr) { 22099832Samw@Sun.COM case 'U': 22109832Samw@Sun.COM ptr = strdup(subs->e_winname); 22119832Samw@Sun.COM break; 22129832Samw@Sun.COM case 'D': 22139832Samw@Sun.COM ptr = strdup(subs->e_userdom); 22149832Samw@Sun.COM break; 22159832Samw@Sun.COM case 'h': 22169832Samw@Sun.COM if (gethostname(hostname, MAXHOSTNAMELEN) != 0) 22179832Samw@Sun.COM unknown = B_TRUE; 22189832Samw@Sun.COM else 22199832Samw@Sun.COM ptr = strdup(hostname); 22209832Samw@Sun.COM break; 22219832Samw@Sun.COM case 'M': 22229832Samw@Sun.COM if (smb_getnameinfo(&subs->e_cli_ipaddr, 22239832Samw@Sun.COM hostname, sizeof (hostname), 0) != 0) 22249832Samw@Sun.COM unknown = B_TRUE; 22259832Samw@Sun.COM else 22269832Samw@Sun.COM ptr = strdup(hostname); 22279832Samw@Sun.COM break; 22289832Samw@Sun.COM case 'L': 22299832Samw@Sun.COM if (smb_getnetbiosname(hostname, 22309832Samw@Sun.COM NETBIOS_NAME_SZ) != 0) 22319832Samw@Sun.COM unknown = B_TRUE; 22329832Samw@Sun.COM else 22339832Samw@Sun.COM ptr = strdup(hostname); 22349832Samw@Sun.COM break; 22359832Samw@Sun.COM case 'm': 22369832Samw@Sun.COM if (*subs->e_cli_netbiosname == '\0') 22379832Samw@Sun.COM unknown = B_TRUE; 22389832Samw@Sun.COM else { 22399832Samw@Sun.COM (void) mts_mbstowcs(wbuf, 22409832Samw@Sun.COM subs->e_cli_netbiosname, 22419832Samw@Sun.COM SMB_PI_MAX_HOST - 1); 22429832Samw@Sun.COM 22439832Samw@Sun.COM if (unicodestooems(name, wbuf, 22449832Samw@Sun.COM SMB_PI_MAX_HOST, cpid) == 0) 22459832Samw@Sun.COM (void) strlcpy(name, 22469832Samw@Sun.COM subs->e_cli_netbiosname, 22479832Samw@Sun.COM SMB_PI_MAX_HOST); 22489832Samw@Sun.COM 22499832Samw@Sun.COM ptr = strdup(name); 22509832Samw@Sun.COM } 22519832Samw@Sun.COM break; 22529832Samw@Sun.COM case 'I': 22539832Samw@Sun.COM if (smb_inet_ntop(&subs->e_cli_ipaddr, ip_str, 22549832Samw@Sun.COM SMB_IPSTRLEN(subs->e_cli_ipaddr.a_family)) 22559832Samw@Sun.COM != NULL) 22569832Samw@Sun.COM ptr = strdup(ip_str); 22579832Samw@Sun.COM else 22589832Samw@Sun.COM unknown = B_TRUE; 22599832Samw@Sun.COM break; 22609832Samw@Sun.COM case 'i': 22619832Samw@Sun.COM if (smb_inet_ntop(&subs->e_srv_ipaddr, ip_str, 22629832Samw@Sun.COM SMB_IPSTRLEN(subs->e_srv_ipaddr.a_family)) 22639832Samw@Sun.COM != NULL) 22649832Samw@Sun.COM ptr = strdup(ip_str); 22659832Samw@Sun.COM else 22669832Samw@Sun.COM unknown = B_TRUE; 22679832Samw@Sun.COM break; 22689832Samw@Sun.COM case 'S': 22699832Samw@Sun.COM ptr = strdup(si->shr_name); 22709832Samw@Sun.COM break; 22719832Samw@Sun.COM case 'P': 22729832Samw@Sun.COM ptr = strdup(si->shr_path); 22739832Samw@Sun.COM break; 22749832Samw@Sun.COM case 'u': 22759832Samw@Sun.COM (void) snprintf(name, sizeof (name), "%u", 22769832Samw@Sun.COM subs->e_uid); 22779832Samw@Sun.COM ptr = strdup(name); 22789832Samw@Sun.COM break; 22799832Samw@Sun.COM default: 22809832Samw@Sun.COM /* unknown sub char */ 22819832Samw@Sun.COM unknown = B_TRUE; 22829832Samw@Sun.COM break; 22839832Samw@Sun.COM } 22849832Samw@Sun.COM 22859832Samw@Sun.COM if (unknown) 22869832Samw@Sun.COM ptr = strdup(""); 22879832Samw@Sun.COM 22889832Samw@Sun.COM } else /* first char of cmd's arg is not '%' char */ 22899832Samw@Sun.COM ptr = strdup(""); 22909832Samw@Sun.COM 22919832Samw@Sun.COM cmd_toks[i] = ptr; 22929832Samw@Sun.COM 22939832Samw@Sun.COM if (ptr == NULL) { 22949832Samw@Sun.COM for (i = 1; cmd_toks[i]; i++) 22959832Samw@Sun.COM free(cmd_toks[i]); 22969832Samw@Sun.COM 22979832Samw@Sun.COM return (-1); 22989832Samw@Sun.COM } 22999832Samw@Sun.COM } 23009832Samw@Sun.COM 23019832Samw@Sun.COM return (0); 23029832Samw@Sun.COM } 23039832Samw@Sun.COM 23049832Samw@Sun.COM /*ARGSUSED*/ 23059832Samw@Sun.COM static void 23069832Samw@Sun.COM smb_shr_sig_abnormal_term(int sig_val) 23079832Samw@Sun.COM { 23089832Samw@Sun.COM /* 23099832Samw@Sun.COM * Calling _exit() prevents parent process from getting SIGTERM/SIGINT 23109832Samw@Sun.COM * signal. 23119832Samw@Sun.COM */ 23129832Samw@Sun.COM _exit(-1); 23139832Samw@Sun.COM } 23149832Samw@Sun.COM 23159832Samw@Sun.COM /*ARGSUSED*/ 23169832Samw@Sun.COM static void 23179832Samw@Sun.COM smb_shr_sig_child(int sig_val) 23189832Samw@Sun.COM { 23199832Samw@Sun.COM /* 23209832Samw@Sun.COM * Catch the signal and allow the exit status of the child process 23219832Samw@Sun.COM * to be available for reaping. 23229832Samw@Sun.COM */ 23239832Samw@Sun.COM } 23249832Samw@Sun.COM 23259832Samw@Sun.COM /* 23269832Samw@Sun.COM * Gets the exec bit flags for each share. 23279832Samw@Sun.COM */ 23289832Samw@Sun.COM static void 23299832Samw@Sun.COM smb_shr_get_exec_info(void) 23309832Samw@Sun.COM { 23319832Samw@Sun.COM char buf[MAXPATHLEN]; 23329832Samw@Sun.COM 23339832Samw@Sun.COM (void) mutex_lock(&smb_shr_exec_mtx); 23349832Samw@Sun.COM 23359832Samw@Sun.COM smb_shr_exec_flags = 0; 23369832Samw@Sun.COM 23379832Samw@Sun.COM *smb_shr_exec_map = '\0'; 23389832Samw@Sun.COM (void) smb_config_getstr(SMB_CI_MAP, smb_shr_exec_map, 23399832Samw@Sun.COM sizeof (smb_shr_exec_map)); 23409832Samw@Sun.COM if (*smb_shr_exec_map != '\0') 23419832Samw@Sun.COM smb_shr_exec_flags |= SMB_SHRF_MAP; 23429832Samw@Sun.COM 23439832Samw@Sun.COM *smb_shr_exec_unmap = '\0'; 23449832Samw@Sun.COM (void) smb_config_getstr(SMB_CI_UNMAP, smb_shr_exec_unmap, 23459832Samw@Sun.COM sizeof (smb_shr_exec_unmap)); 23469832Samw@Sun.COM if (*smb_shr_exec_unmap != '\0') 23479832Samw@Sun.COM smb_shr_exec_flags |= SMB_SHRF_UNMAP; 23489832Samw@Sun.COM 23499832Samw@Sun.COM *buf = '\0'; 23509832Samw@Sun.COM (void) smb_config_getstr(SMB_CI_DISPOSITION, buf, sizeof (buf)); 23519832Samw@Sun.COM if (*buf != '\0') 23529832Samw@Sun.COM if (strcasecmp(buf, SMB_SHR_DISP_TERM_STR) == 0) 23539832Samw@Sun.COM smb_shr_exec_flags |= SMB_SHRF_DISP_TERM; 23549832Samw@Sun.COM 23559832Samw@Sun.COM (void) mutex_unlock(&smb_shr_exec_mtx); 23569832Samw@Sun.COM } 23579832Samw@Sun.COM 23589832Samw@Sun.COM /* 23599832Samw@Sun.COM * Sets the exec bit flags for each share. 23609832Samw@Sun.COM */ 23619832Samw@Sun.COM static void 23629832Samw@Sun.COM smb_shr_set_exec_flags(smb_share_t *si) 23639832Samw@Sun.COM { 23649832Samw@Sun.COM (void) mutex_lock(&smb_shr_exec_mtx); 23659832Samw@Sun.COM si->shr_flags &= ~SMB_SHRF_EXEC_MASK; 23669832Samw@Sun.COM si->shr_flags |= smb_shr_exec_flags; 23679832Samw@Sun.COM (void) mutex_unlock(&smb_shr_exec_mtx); 23689832Samw@Sun.COM } 2369