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 /* 2212065SKeyur.Desai@Sun.COM * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 237052Samw */ 247052Samw 257052Samw /* 267961SNatalie.Li@Sun.COM * SMB/CIFS share cache implementation. 277052Samw */ 287052Samw 297052Samw #include <errno.h> 307052Samw #include <synch.h> 317052Samw #include <stdlib.h> 327052Samw #include <strings.h> 337052Samw #include <syslog.h> 347052Samw #include <thread.h> 357052Samw #include <pthread.h> 367348SJose.Borrego@Sun.COM #include <assert.h> 377961SNatalie.Li@Sun.COM #include <libshare.h> 388845Samw@Sun.COM #include <libzfs.h> 399832Samw@Sun.COM #include <priv_utils.h> 409832Samw@Sun.COM #include <sys/types.h> 419832Samw@Sun.COM #include <sys/wait.h> 429832Samw@Sun.COM #include <unistd.h> 439832Samw@Sun.COM #include <pwd.h> 449832Samw@Sun.COM #include <signal.h> 4512065SKeyur.Desai@Sun.COM #include <dirent.h> 467052Samw 477052Samw #include <smbsrv/libsmb.h> 487052Samw #include <smbsrv/libsmbns.h> 497588Samw@Sun.COM #include <smbsrv/libmlsvc.h> 507052Samw #include <smbsrv/smb_share.h> 5110966SJordan.Brown@Sun.COM #include <smbsrv/smb.h> 5210504SKeyur.Desai@Sun.COM #include <mlsvc.h> 5311963SAfshin.Ardakani@Sun.COM #include <dfs.h> 547052Samw 557961SNatalie.Li@Sun.COM #define SMB_SHR_ERROR_THRESHOLD 3 568334SJose.Borrego@Sun.COM #define SMB_SHR_CSC_BUFSZ 64 578334SJose.Borrego@Sun.COM 5812065SKeyur.Desai@Sun.COM typedef struct smb_transient { 5912065SKeyur.Desai@Sun.COM char *name; 6012065SKeyur.Desai@Sun.COM char *cmnt; 6112065SKeyur.Desai@Sun.COM char *path; 6212065SKeyur.Desai@Sun.COM char drive; 6312065SKeyur.Desai@Sun.COM boolean_t check; 6412065SKeyur.Desai@Sun.COM } smb_transient_t; 6512065SKeyur.Desai@Sun.COM 6612065SKeyur.Desai@Sun.COM static smb_transient_t tshare[] = { 6712065SKeyur.Desai@Sun.COM { "IPC$", "Remote IPC", NULL, '\0', B_FALSE }, 6812065SKeyur.Desai@Sun.COM { "c$", "Default Share", SMB_CVOL, 'C', B_FALSE }, 6912065SKeyur.Desai@Sun.COM { "vss$", "VSS", SMB_VSS, 'V', B_TRUE } 7012065SKeyur.Desai@Sun.COM }; 7112065SKeyur.Desai@Sun.COM 729832Samw@Sun.COM static struct { 739832Samw@Sun.COM char *value; 749832Samw@Sun.COM uint32_t flag; 759832Samw@Sun.COM } cscopt[] = { 769832Samw@Sun.COM { "disabled", SMB_SHRF_CSC_DISABLED }, 779832Samw@Sun.COM { "manual", SMB_SHRF_CSC_MANUAL }, 789832Samw@Sun.COM { "auto", SMB_SHRF_CSC_AUTO }, 799832Samw@Sun.COM { "vdo", SMB_SHRF_CSC_VDO } 809832Samw@Sun.COM }; 819832Samw@Sun.COM 827348SJose.Borrego@Sun.COM /* 837348SJose.Borrego@Sun.COM * Cache functions and vars 847348SJose.Borrego@Sun.COM */ 857961SNatalie.Li@Sun.COM #define SMB_SHR_HTAB_SZ 1024 867052Samw 877961SNatalie.Li@Sun.COM /* 887961SNatalie.Li@Sun.COM * Cache handle 897961SNatalie.Li@Sun.COM * 907961SNatalie.Li@Sun.COM * Shares cache is a hash table. 917961SNatalie.Li@Sun.COM * 927961SNatalie.Li@Sun.COM * sc_cache pointer to hash table handle 937961SNatalie.Li@Sun.COM * sc_cache_lck synchronize cache read/write accesses 947961SNatalie.Li@Sun.COM * sc_state cache state machine values 957961SNatalie.Li@Sun.COM * sc_nops number of inflight/pending cache operations 967961SNatalie.Li@Sun.COM * sc_mtx protects handle fields 977961SNatalie.Li@Sun.COM */ 987961SNatalie.Li@Sun.COM typedef struct smb_shr_cache { 997961SNatalie.Li@Sun.COM HT_HANDLE *sc_cache; 1007961SNatalie.Li@Sun.COM rwlock_t sc_cache_lck; 1017961SNatalie.Li@Sun.COM mutex_t sc_mtx; 1027961SNatalie.Li@Sun.COM cond_t sc_cv; 1037961SNatalie.Li@Sun.COM uint32_t sc_state; 1047961SNatalie.Li@Sun.COM uint32_t sc_nops; 1057961SNatalie.Li@Sun.COM } smb_shr_cache_t; 1067961SNatalie.Li@Sun.COM 1077961SNatalie.Li@Sun.COM /* 1087961SNatalie.Li@Sun.COM * Cache states 1097961SNatalie.Li@Sun.COM */ 1107961SNatalie.Li@Sun.COM #define SMB_SHR_CACHE_STATE_NONE 0 1117961SNatalie.Li@Sun.COM #define SMB_SHR_CACHE_STATE_CREATED 1 1127961SNatalie.Li@Sun.COM #define SMB_SHR_CACHE_STATE_DESTROYING 2 1137961SNatalie.Li@Sun.COM 1147961SNatalie.Li@Sun.COM /* 1157961SNatalie.Li@Sun.COM * Cache lock modes 1167961SNatalie.Li@Sun.COM */ 1177961SNatalie.Li@Sun.COM #define SMB_SHR_CACHE_RDLOCK 0 1187961SNatalie.Li@Sun.COM #define SMB_SHR_CACHE_WRLOCK 1 1197961SNatalie.Li@Sun.COM 1207961SNatalie.Li@Sun.COM static smb_shr_cache_t smb_shr_cache; 1217052Samw 1227052Samw static uint32_t smb_shr_cache_create(void); 1237348SJose.Borrego@Sun.COM static void smb_shr_cache_destroy(void); 1247961SNatalie.Li@Sun.COM static uint32_t smb_shr_cache_lock(int); 1257961SNatalie.Li@Sun.COM static void smb_shr_cache_unlock(void); 1267961SNatalie.Li@Sun.COM static int smb_shr_cache_count(void); 1277961SNatalie.Li@Sun.COM static smb_share_t *smb_shr_cache_iterate(smb_shriter_t *); 1287961SNatalie.Li@Sun.COM 1297961SNatalie.Li@Sun.COM static smb_share_t *smb_shr_cache_findent(char *); 1307348SJose.Borrego@Sun.COM static uint32_t smb_shr_cache_addent(smb_share_t *); 1317348SJose.Borrego@Sun.COM static void smb_shr_cache_delent(char *); 1327348SJose.Borrego@Sun.COM static void smb_shr_cache_freent(HT_ITEM *); 1337052Samw 13412065SKeyur.Desai@Sun.COM static boolean_t smb_shr_is_empty(const char *); 13512065SKeyur.Desai@Sun.COM static boolean_t smb_shr_is_dot_or_dotdot(const char *); 13612065SKeyur.Desai@Sun.COM 1377348SJose.Borrego@Sun.COM /* 1387348SJose.Borrego@Sun.COM * sharemgr functions 1397348SJose.Borrego@Sun.COM */ 1407961SNatalie.Li@Sun.COM static void *smb_shr_sa_loadall(void *); 1417961SNatalie.Li@Sun.COM static void smb_shr_sa_loadgrp(sa_group_t); 1427961SNatalie.Li@Sun.COM static uint32_t smb_shr_sa_load(sa_share_t, sa_resource_t); 1438334SJose.Borrego@Sun.COM static uint32_t smb_shr_sa_loadbyname(char *); 1447961SNatalie.Li@Sun.COM static uint32_t smb_shr_sa_get(sa_share_t, sa_resource_t, smb_share_t *); 1457052Samw 1467052Samw /* 1478845Samw@Sun.COM * .ZFS management functions 1488845Samw@Sun.COM */ 1498845Samw@Sun.COM static void smb_shr_zfs_add(smb_share_t *); 1508845Samw@Sun.COM static void smb_shr_zfs_remove(smb_share_t *); 1518845Samw@Sun.COM static void smb_shr_zfs_rename(smb_share_t *, smb_share_t *); 1528845Samw@Sun.COM 1538845Samw@Sun.COM /* 1547348SJose.Borrego@Sun.COM * share publishing 1557348SJose.Borrego@Sun.COM */ 1567348SJose.Borrego@Sun.COM #define SMB_SHR_PUBLISH 0 1577348SJose.Borrego@Sun.COM #define SMB_SHR_UNPUBLISH 1 1587348SJose.Borrego@Sun.COM 1597348SJose.Borrego@Sun.COM typedef struct smb_shr_pitem { 1607348SJose.Borrego@Sun.COM list_node_t spi_lnd; 1617348SJose.Borrego@Sun.COM char spi_name[MAXNAMELEN]; 1627348SJose.Borrego@Sun.COM char spi_container[MAXPATHLEN]; 1637348SJose.Borrego@Sun.COM char spi_op; 1647348SJose.Borrego@Sun.COM } smb_shr_pitem_t; 1657348SJose.Borrego@Sun.COM 1667348SJose.Borrego@Sun.COM /* 1677348SJose.Borrego@Sun.COM * publish queue states 1687348SJose.Borrego@Sun.COM */ 1697348SJose.Borrego@Sun.COM #define SMB_SHR_PQS_NOQUEUE 0 1707348SJose.Borrego@Sun.COM #define SMB_SHR_PQS_READY 1 /* the queue is ready */ 1717348SJose.Borrego@Sun.COM #define SMB_SHR_PQS_PUBLISHING 2 /* publisher thread is running */ 1727348SJose.Borrego@Sun.COM #define SMB_SHR_PQS_STOPPING 3 1737348SJose.Borrego@Sun.COM 1747348SJose.Borrego@Sun.COM /* 1757348SJose.Borrego@Sun.COM * share publishing queue 1767348SJose.Borrego@Sun.COM */ 1777348SJose.Borrego@Sun.COM typedef struct smb_shr_pqueue { 1787348SJose.Borrego@Sun.COM list_t spq_list; 1797348SJose.Borrego@Sun.COM mutex_t spq_mtx; 1807348SJose.Borrego@Sun.COM cond_t spq_cv; 1817348SJose.Borrego@Sun.COM uint32_t spq_state; 1827348SJose.Borrego@Sun.COM } smb_shr_pqueue_t; 1837348SJose.Borrego@Sun.COM 1847348SJose.Borrego@Sun.COM static smb_shr_pqueue_t ad_queue; 1857348SJose.Borrego@Sun.COM 1867348SJose.Borrego@Sun.COM static int smb_shr_publisher_start(void); 1877348SJose.Borrego@Sun.COM static void smb_shr_publisher_stop(void); 1887348SJose.Borrego@Sun.COM static void smb_shr_publisher_send(smb_ads_handle_t *, list_t *, const char *); 1897961SNatalie.Li@Sun.COM static void smb_shr_publisher_queue(const char *, const char *, char); 1907348SJose.Borrego@Sun.COM static void *smb_shr_publisher(void *); 1917961SNatalie.Li@Sun.COM static void smb_shr_publisher_flush(list_t *); 1927961SNatalie.Li@Sun.COM static void smb_shr_publish(const char *, const char *); 1937961SNatalie.Li@Sun.COM static void smb_shr_unpublish(const char *, const char *); 1947348SJose.Borrego@Sun.COM 1957348SJose.Borrego@Sun.COM /* 1967961SNatalie.Li@Sun.COM * Utility/helper functions 1977961SNatalie.Li@Sun.COM */ 1988334SJose.Borrego@Sun.COM static uint32_t smb_shr_lookup(char *, smb_share_t *); 19911963SAfshin.Ardakani@Sun.COM static uint32_t smb_shr_add_transient(char *, char *, char *); 2009832Samw@Sun.COM static int smb_shr_enable_all_privs(void); 201*12508Samw@Sun.COM static int smb_shr_expand_subs(char **, smb_share_t *, smb_shr_execinfo_t *); 2029832Samw@Sun.COM static char **smb_shr_tokenize_cmd(char *); 2039832Samw@Sun.COM static void smb_shr_sig_abnormal_term(int); 2049832Samw@Sun.COM static void smb_shr_sig_child(int); 205*12508Samw@Sun.COM static int smb_shr_encode(smb_share_t *, nvlist_t **); 2068474SJose.Borrego@Sun.COM 2078474SJose.Borrego@Sun.COM /* 2088474SJose.Borrego@Sun.COM * libshare handle and synchronization 2098474SJose.Borrego@Sun.COM */ 2108474SJose.Borrego@Sun.COM typedef struct smb_sa_handle { 2118474SJose.Borrego@Sun.COM sa_handle_t sa_handle; 2128474SJose.Borrego@Sun.COM mutex_t sa_mtx; 2138474SJose.Borrego@Sun.COM boolean_t sa_in_service; 2148474SJose.Borrego@Sun.COM } smb_sa_handle_t; 2158474SJose.Borrego@Sun.COM 2168474SJose.Borrego@Sun.COM static smb_sa_handle_t smb_sa_handle; 2178474SJose.Borrego@Sun.COM 2189832Samw@Sun.COM static char smb_shr_exec_map[MAXPATHLEN]; 2199832Samw@Sun.COM static char smb_shr_exec_unmap[MAXPATHLEN]; 2209832Samw@Sun.COM static mutex_t smb_shr_exec_mtx; 2219832Samw@Sun.COM 2227961SNatalie.Li@Sun.COM /* 22310504SKeyur.Desai@Sun.COM * Semaphore held during temporary, process-wide changes 22410504SKeyur.Desai@Sun.COM * such as process privileges. It is a seamaphore and 22510504SKeyur.Desai@Sun.COM * not a mutex so a child of fork can reset it. 22610504SKeyur.Desai@Sun.COM */ 22710504SKeyur.Desai@Sun.COM static sema_t smb_proc_sem = DEFAULTSEMA; 22810504SKeyur.Desai@Sun.COM 22910504SKeyur.Desai@Sun.COM /* 2308334SJose.Borrego@Sun.COM * Creates and initializes the cache and starts the publisher 2318334SJose.Borrego@Sun.COM * thread. 2327052Samw */ 2337052Samw int 2347052Samw smb_shr_start(void) 2357052Samw { 23612065SKeyur.Desai@Sun.COM smb_transient_t *ts; 23712065SKeyur.Desai@Sun.COM uint32_t nerr; 23812065SKeyur.Desai@Sun.COM int i; 23911963SAfshin.Ardakani@Sun.COM 2408474SJose.Borrego@Sun.COM (void) mutex_lock(&smb_sa_handle.sa_mtx); 2418474SJose.Borrego@Sun.COM smb_sa_handle.sa_in_service = B_TRUE; 2428474SJose.Borrego@Sun.COM (void) mutex_unlock(&smb_sa_handle.sa_mtx); 2438474SJose.Borrego@Sun.COM 2447961SNatalie.Li@Sun.COM if (smb_shr_cache_create() != NERR_Success) 2457961SNatalie.Li@Sun.COM return (ENOMEM); 2467961SNatalie.Li@Sun.COM 24711963SAfshin.Ardakani@Sun.COM for (i = 0; i < sizeof (tshare)/sizeof (tshare[0]); ++i) { 24812065SKeyur.Desai@Sun.COM ts = &tshare[i]; 24912065SKeyur.Desai@Sun.COM 25012065SKeyur.Desai@Sun.COM if (ts->check && smb_shr_is_empty(ts->path)) 25112065SKeyur.Desai@Sun.COM continue; 25212065SKeyur.Desai@Sun.COM 25312065SKeyur.Desai@Sun.COM nerr = smb_shr_add_transient(ts->name, ts->cmnt, ts->path); 25412065SKeyur.Desai@Sun.COM if (nerr != NERR_Success) 25511963SAfshin.Ardakani@Sun.COM return (ENOMEM); 25611963SAfshin.Ardakani@Sun.COM } 2577961SNatalie.Li@Sun.COM 2588334SJose.Borrego@Sun.COM return (smb_shr_publisher_start()); 2598334SJose.Borrego@Sun.COM } 2608334SJose.Borrego@Sun.COM 2618334SJose.Borrego@Sun.COM void 2628334SJose.Borrego@Sun.COM smb_shr_stop(void) 2638334SJose.Borrego@Sun.COM { 2648334SJose.Borrego@Sun.COM smb_shr_cache_destroy(); 2658334SJose.Borrego@Sun.COM smb_shr_publisher_stop(); 2668474SJose.Borrego@Sun.COM 2678474SJose.Borrego@Sun.COM (void) mutex_lock(&smb_sa_handle.sa_mtx); 2688474SJose.Borrego@Sun.COM smb_sa_handle.sa_in_service = B_FALSE; 2698474SJose.Borrego@Sun.COM 2708474SJose.Borrego@Sun.COM if (smb_sa_handle.sa_handle != NULL) { 2718474SJose.Borrego@Sun.COM sa_fini(smb_sa_handle.sa_handle); 2728474SJose.Borrego@Sun.COM smb_sa_handle.sa_handle = NULL; 2738474SJose.Borrego@Sun.COM } 2748474SJose.Borrego@Sun.COM 2758474SJose.Borrego@Sun.COM (void) mutex_unlock(&smb_sa_handle.sa_mtx); 2768474SJose.Borrego@Sun.COM } 2778474SJose.Borrego@Sun.COM 2788474SJose.Borrego@Sun.COM /* 2798474SJose.Borrego@Sun.COM * Get a handle and exclusive access to the libshare API. 2808474SJose.Borrego@Sun.COM */ 2818474SJose.Borrego@Sun.COM sa_handle_t 2828474SJose.Borrego@Sun.COM smb_shr_sa_enter(void) 2838474SJose.Borrego@Sun.COM { 2848474SJose.Borrego@Sun.COM (void) mutex_lock(&smb_sa_handle.sa_mtx); 2858474SJose.Borrego@Sun.COM if (!smb_sa_handle.sa_in_service) { 2868474SJose.Borrego@Sun.COM (void) mutex_unlock(&smb_sa_handle.sa_mtx); 2878474SJose.Borrego@Sun.COM return (NULL); 2888474SJose.Borrego@Sun.COM } 2898474SJose.Borrego@Sun.COM 2908474SJose.Borrego@Sun.COM if (smb_sa_handle.sa_handle == NULL) { 2918474SJose.Borrego@Sun.COM smb_sa_handle.sa_handle = sa_init(SA_INIT_SHARE_API); 2928474SJose.Borrego@Sun.COM if (smb_sa_handle.sa_handle == NULL) { 2938474SJose.Borrego@Sun.COM syslog(LOG_ERR, "share: failed to get libshare handle"); 2948474SJose.Borrego@Sun.COM (void) mutex_unlock(&smb_sa_handle.sa_mtx); 2958474SJose.Borrego@Sun.COM return (NULL); 2968474SJose.Borrego@Sun.COM } 2978474SJose.Borrego@Sun.COM } 2988474SJose.Borrego@Sun.COM 2998474SJose.Borrego@Sun.COM return (smb_sa_handle.sa_handle); 3008474SJose.Borrego@Sun.COM } 3018474SJose.Borrego@Sun.COM 3028474SJose.Borrego@Sun.COM /* 3038474SJose.Borrego@Sun.COM * Release exclusive access to the libshare API. 3048474SJose.Borrego@Sun.COM */ 3058474SJose.Borrego@Sun.COM void 3068474SJose.Borrego@Sun.COM smb_shr_sa_exit(void) 3078474SJose.Borrego@Sun.COM { 3088474SJose.Borrego@Sun.COM (void) mutex_unlock(&smb_sa_handle.sa_mtx); 3098334SJose.Borrego@Sun.COM } 3108334SJose.Borrego@Sun.COM 3118334SJose.Borrego@Sun.COM /* 3128334SJose.Borrego@Sun.COM * Launches a thread to populate the share cache by share information 3138334SJose.Borrego@Sun.COM * stored in sharemgr 3148334SJose.Borrego@Sun.COM */ 3158334SJose.Borrego@Sun.COM int 3168334SJose.Borrego@Sun.COM smb_shr_load(void) 3178334SJose.Borrego@Sun.COM { 3188334SJose.Borrego@Sun.COM pthread_t load_thr; 3198334SJose.Borrego@Sun.COM pthread_attr_t tattr; 3208334SJose.Borrego@Sun.COM int rc; 3218334SJose.Borrego@Sun.COM 3227348SJose.Borrego@Sun.COM (void) pthread_attr_init(&tattr); 3237348SJose.Borrego@Sun.COM (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); 3247961SNatalie.Li@Sun.COM rc = pthread_create(&load_thr, &tattr, smb_shr_sa_loadall, 0); 3257348SJose.Borrego@Sun.COM (void) pthread_attr_destroy(&tattr); 3267052Samw 327*12508Samw@Sun.COM (void) mutex_lock(&smb_shr_exec_mtx); 328*12508Samw@Sun.COM (void) smb_config_get_execinfo(smb_shr_exec_map, smb_shr_exec_unmap, 329*12508Samw@Sun.COM MAXPATHLEN); 330*12508Samw@Sun.COM (void) mutex_unlock(&smb_shr_exec_mtx); 3319832Samw@Sun.COM 3327052Samw return (rc); 3337052Samw } 3347052Samw 3357052Samw /* 3367348SJose.Borrego@Sun.COM * Return the total number of shares 3377052Samw */ 3387052Samw int 3397052Samw smb_shr_count(void) 3407052Samw { 3417961SNatalie.Li@Sun.COM int n_shares = 0; 3427052Samw 3437961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) { 3447961SNatalie.Li@Sun.COM n_shares = smb_shr_cache_count(); 3457961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 3467961SNatalie.Li@Sun.COM } 3477052Samw 3487052Samw return (n_shares); 3497052Samw } 3507052Samw 3517052Samw /* 3527052Samw * smb_shr_iterinit 3537052Samw * 3547348SJose.Borrego@Sun.COM * Initialize given iterator for traversing hash table. 3557052Samw */ 3567052Samw void 3577348SJose.Borrego@Sun.COM smb_shr_iterinit(smb_shriter_t *shi) 3587052Samw { 3597052Samw bzero(shi, sizeof (smb_shriter_t)); 3607348SJose.Borrego@Sun.COM shi->si_first = B_TRUE; 3617052Samw } 3627052Samw 3637052Samw /* 3647052Samw * smb_shr_iterate 3657052Samw * 3667052Samw * Iterate on the shares in the hash table. The iterator must be initialized 3677052Samw * before the first iteration. On subsequent calls, the iterator must be 3687052Samw * passed unchanged. 3697052Samw * 3707052Samw * Returns NULL on failure or when all shares are visited, otherwise 3717052Samw * returns information of visited share. 3727052Samw */ 3737052Samw smb_share_t * 3747052Samw smb_shr_iterate(smb_shriter_t *shi) 3757052Samw { 3767348SJose.Borrego@Sun.COM smb_share_t *share = NULL; 3777961SNatalie.Li@Sun.COM smb_share_t *cached_si; 3787052Samw 3797961SNatalie.Li@Sun.COM if (shi == NULL) 3807052Samw return (NULL); 3817052Samw 3827961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) { 3837961SNatalie.Li@Sun.COM if ((cached_si = smb_shr_cache_iterate(shi)) != NULL) { 3847961SNatalie.Li@Sun.COM share = &shi->si_share; 3857961SNatalie.Li@Sun.COM bcopy(cached_si, share, sizeof (smb_share_t)); 3867961SNatalie.Li@Sun.COM } 3877961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 3887052Samw } 3897052Samw 3907348SJose.Borrego@Sun.COM return (share); 3917052Samw } 3927052Samw 3937052Samw /* 3947961SNatalie.Li@Sun.COM * Adds the given share to cache, publishes the share in ADS 3957961SNatalie.Li@Sun.COM * if it has an AD container, calls kernel to take a hold on 3967961SNatalie.Li@Sun.COM * the shared file system. If it can't take a hold on the 3977961SNatalie.Li@Sun.COM * shared file system, it's either because shared directory 3987961SNatalie.Li@Sun.COM * does not exist or some other error has occurred, in any 3997961SNatalie.Li@Sun.COM * case the share is removed from the cache. 4007052Samw * 4017961SNatalie.Li@Sun.COM * If the specified share is an autohome share which already 4027961SNatalie.Li@Sun.COM * exists in the cache, just increments the reference count. 4037052Samw */ 4047052Samw uint32_t 4057961SNatalie.Li@Sun.COM smb_shr_add(smb_share_t *si) 4067052Samw { 4077961SNatalie.Li@Sun.COM smb_share_t *cached_si; 408*12508Samw@Sun.COM nvlist_t *shrlist; 4097961SNatalie.Li@Sun.COM uint32_t status; 4107348SJose.Borrego@Sun.COM int rc; 4117052Samw 4127348SJose.Borrego@Sun.COM assert(si != NULL); 4137052Samw 41411337SWilliam.Krier@Sun.COM if (smb_name_validate_share(si->shr_name) != ERROR_SUCCESS) 4157348SJose.Borrego@Sun.COM return (ERROR_INVALID_NAME); 4167052Samw 4177961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success) 4187961SNatalie.Li@Sun.COM return (NERR_InternalError); 4197052Samw 4207961SNatalie.Li@Sun.COM cached_si = smb_shr_cache_findent(si->shr_name); 4217961SNatalie.Li@Sun.COM if (cached_si) { 4227961SNatalie.Li@Sun.COM if (si->shr_flags & SMB_SHRF_AUTOHOME) { 4237961SNatalie.Li@Sun.COM cached_si->shr_refcnt++; 4247961SNatalie.Li@Sun.COM status = NERR_Success; 4257961SNatalie.Li@Sun.COM } else { 4267961SNatalie.Li@Sun.COM status = NERR_DuplicateShare; 4277961SNatalie.Li@Sun.COM } 4287961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 4297052Samw return (status); 4307052Samw } 4317052Samw 4327961SNatalie.Li@Sun.COM if ((status = smb_shr_cache_addent(si)) != NERR_Success) { 4337961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 4347961SNatalie.Li@Sun.COM return (status); 4357961SNatalie.Li@Sun.COM } 4367961SNatalie.Li@Sun.COM 4377961SNatalie.Li@Sun.COM /* don't hold the lock across door call */ 4387961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 4397961SNatalie.Li@Sun.COM 440*12508Samw@Sun.COM if ((rc = smb_shr_encode(si, &shrlist)) == 0) { 441*12508Samw@Sun.COM /* send the share to kernel */ 442*12508Samw@Sun.COM rc = smb_kmod_share(shrlist); 443*12508Samw@Sun.COM nvlist_free(shrlist); 4447348SJose.Borrego@Sun.COM 445*12508Samw@Sun.COM if (rc == 0) { 446*12508Samw@Sun.COM smb_shr_publish(si->shr_name, si->shr_container); 4478845Samw@Sun.COM 448*12508Samw@Sun.COM /* If path is ZFS, add the .zfs/shares/<share> entry. */ 449*12508Samw@Sun.COM smb_shr_zfs_add(si); 4508845Samw@Sun.COM 451*12508Samw@Sun.COM return (NERR_Success); 452*12508Samw@Sun.COM } 4537052Samw } 4547052Samw 4557961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) == NERR_Success) { 4567961SNatalie.Li@Sun.COM smb_shr_cache_delent(si->shr_name); 4577961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 4587961SNatalie.Li@Sun.COM } 4597052Samw 4607052Samw /* 4617348SJose.Borrego@Sun.COM * rc == ENOENT means the shared directory doesn't exist 4627052Samw */ 4637348SJose.Borrego@Sun.COM return ((rc == ENOENT) ? NERR_UnknownDevDir : NERR_InternalError); 4647052Samw } 4657052Samw 4667052Samw /* 4677961SNatalie.Li@Sun.COM * Removes the specified share from cache, removes it from AD 4687961SNatalie.Li@Sun.COM * if it has an AD container, and calls the kernel to release 4697961SNatalie.Li@Sun.COM * the hold on the shared file system. 4707052Samw * 4717961SNatalie.Li@Sun.COM * If this is an autohome share then decrement the reference 4727961SNatalie.Li@Sun.COM * count. If it reaches 0 then it proceeds with removing steps. 4737052Samw */ 4747348SJose.Borrego@Sun.COM uint32_t 4757961SNatalie.Li@Sun.COM smb_shr_remove(char *sharename) 4767052Samw { 4777961SNatalie.Li@Sun.COM smb_share_t *si; 4787961SNatalie.Li@Sun.COM char container[MAXPATHLEN]; 47911963SAfshin.Ardakani@Sun.COM boolean_t dfsroot; 480*12508Samw@Sun.COM nvlist_t *shrlist; 4817348SJose.Borrego@Sun.COM 4827348SJose.Borrego@Sun.COM assert(sharename != NULL); 4837348SJose.Borrego@Sun.COM 48411337SWilliam.Krier@Sun.COM if (smb_name_validate_share(sharename) != ERROR_SUCCESS) 4857961SNatalie.Li@Sun.COM return (ERROR_INVALID_NAME); 4867052Samw 4877961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success) 4887961SNatalie.Li@Sun.COM return (NERR_InternalError); 4897961SNatalie.Li@Sun.COM 4907961SNatalie.Li@Sun.COM if ((si = smb_shr_cache_findent(sharename)) == NULL) { 4917961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 4927961SNatalie.Li@Sun.COM return (NERR_NetNameNotFound); 4937961SNatalie.Li@Sun.COM } 4947348SJose.Borrego@Sun.COM 4957961SNatalie.Li@Sun.COM if (si->shr_type & STYPE_IPC) { 4967961SNatalie.Li@Sun.COM /* IPC$ share cannot be removed */ 4977961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 4987961SNatalie.Li@Sun.COM return (ERROR_ACCESS_DENIED); 4997961SNatalie.Li@Sun.COM } 5007961SNatalie.Li@Sun.COM 5017961SNatalie.Li@Sun.COM if (si->shr_flags & SMB_SHRF_AUTOHOME) { 5027961SNatalie.Li@Sun.COM if ((--si->shr_refcnt) > 0) { 5037961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 5047961SNatalie.Li@Sun.COM return (NERR_Success); 5057348SJose.Borrego@Sun.COM } 5067052Samw } 5077052Samw 5088845Samw@Sun.COM /* 5098845Samw@Sun.COM * If path is ZFS, remove the .zfs/shares/<share> entry. Need 5108845Samw@Sun.COM * to remove before cleanup of cache occurs. 5118845Samw@Sun.COM */ 5128845Samw@Sun.COM smb_shr_zfs_remove(si); 513*12508Samw@Sun.COM (void) smb_shr_encode(si, &shrlist); 5148845Samw@Sun.COM 5157961SNatalie.Li@Sun.COM (void) strlcpy(container, si->shr_container, sizeof (container)); 51611963SAfshin.Ardakani@Sun.COM dfsroot = ((si->shr_flags & SMB_SHRF_DFSROOT) != 0); 5177961SNatalie.Li@Sun.COM smb_shr_cache_delent(sharename); 5187961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 5197348SJose.Borrego@Sun.COM 5207961SNatalie.Li@Sun.COM smb_shr_unpublish(sharename, container); 5217961SNatalie.Li@Sun.COM 5227961SNatalie.Li@Sun.COM /* call kernel to release the hold on the shared file system */ 523*12508Samw@Sun.COM if (shrlist != NULL) { 524*12508Samw@Sun.COM (void) smb_kmod_unshare(shrlist); 525*12508Samw@Sun.COM nvlist_free(shrlist); 526*12508Samw@Sun.COM } 5277348SJose.Borrego@Sun.COM 52811963SAfshin.Ardakani@Sun.COM if (dfsroot) 52911963SAfshin.Ardakani@Sun.COM dfs_namespace_unload(sharename); 53011963SAfshin.Ardakani@Sun.COM 5317052Samw return (NERR_Success); 5327052Samw } 5337052Samw 5347052Samw /* 5357052Samw * Rename a share. Check that the current name exists and the new name 5367052Samw * doesn't exist. The rename is performed by deleting the current share 5377052Samw * definition and creating a new share with the new name. 5387052Samw */ 5397052Samw uint32_t 5407348SJose.Borrego@Sun.COM smb_shr_rename(char *from_name, char *to_name) 5417052Samw { 5427961SNatalie.Li@Sun.COM smb_share_t *from_si; 5437961SNatalie.Li@Sun.COM smb_share_t to_si; 5447348SJose.Borrego@Sun.COM uint32_t status; 545*12508Samw@Sun.COM nvlist_t *shrlist; 5467348SJose.Borrego@Sun.COM 5477348SJose.Borrego@Sun.COM assert((from_name != NULL) && (to_name != NULL)); 5487052Samw 54911337SWilliam.Krier@Sun.COM if (smb_name_validate_share(from_name) != ERROR_SUCCESS || 55011337SWilliam.Krier@Sun.COM smb_name_validate_share(to_name) != ERROR_SUCCESS) 5517348SJose.Borrego@Sun.COM return (ERROR_INVALID_NAME); 5527052Samw 5537961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success) 5547961SNatalie.Li@Sun.COM return (NERR_InternalError); 5557961SNatalie.Li@Sun.COM 5567961SNatalie.Li@Sun.COM if ((from_si = smb_shr_cache_findent(from_name)) == NULL) { 5577961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 5587052Samw return (NERR_NetNameNotFound); 5597961SNatalie.Li@Sun.COM } 5607052Samw 5617961SNatalie.Li@Sun.COM if (from_si->shr_type & STYPE_IPC) { 5627961SNatalie.Li@Sun.COM /* IPC$ share cannot be renamed */ 5637961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 5647961SNatalie.Li@Sun.COM return (ERROR_ACCESS_DENIED); 5657961SNatalie.Li@Sun.COM } 5667961SNatalie.Li@Sun.COM 5677961SNatalie.Li@Sun.COM if (smb_shr_cache_findent(to_name) != NULL) { 5687961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 5697052Samw return (NERR_DuplicateShare); 5707961SNatalie.Li@Sun.COM } 5717052Samw 5727961SNatalie.Li@Sun.COM bcopy(from_si, &to_si, sizeof (smb_share_t)); 5737961SNatalie.Li@Sun.COM (void) strlcpy(to_si.shr_name, to_name, sizeof (to_si.shr_name)); 5747961SNatalie.Li@Sun.COM 5758845Samw@Sun.COM /* If path is ZFS, rename the .zfs/shares/<share> entry. */ 5768845Samw@Sun.COM smb_shr_zfs_rename(from_si, &to_si); 5778845Samw@Sun.COM 5787961SNatalie.Li@Sun.COM if ((status = smb_shr_cache_addent(&to_si)) != NERR_Success) { 5797961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 5807348SJose.Borrego@Sun.COM return (status); 5817961SNatalie.Li@Sun.COM } 5827348SJose.Borrego@Sun.COM 5837348SJose.Borrego@Sun.COM smb_shr_cache_delent(from_name); 5847961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 5857961SNatalie.Li@Sun.COM 586*12508Samw@Sun.COM if (smb_shr_encode(from_si, &shrlist) == 0) { 587*12508Samw@Sun.COM (void) smb_kmod_unshare(shrlist); 588*12508Samw@Sun.COM nvlist_free(shrlist); 589*12508Samw@Sun.COM 590*12508Samw@Sun.COM if (smb_shr_encode(&to_si, &shrlist) == 0) { 591*12508Samw@Sun.COM (void) smb_kmod_share(shrlist); 592*12508Samw@Sun.COM nvlist_free(shrlist); 593*12508Samw@Sun.COM } 594*12508Samw@Sun.COM } 595*12508Samw@Sun.COM 5967961SNatalie.Li@Sun.COM smb_shr_unpublish(from_name, to_si.shr_container); 5977961SNatalie.Li@Sun.COM smb_shr_publish(to_name, to_si.shr_container); 5987348SJose.Borrego@Sun.COM 5997348SJose.Borrego@Sun.COM return (NERR_Success); 6007348SJose.Borrego@Sun.COM } 6017348SJose.Borrego@Sun.COM 6027348SJose.Borrego@Sun.COM /* 6037348SJose.Borrego@Sun.COM * Load the information for the specified share into the supplied share 6047348SJose.Borrego@Sun.COM * info structure. 6058334SJose.Borrego@Sun.COM * 6068334SJose.Borrego@Sun.COM * First looks up the cache to see if the specified share exists, if there 6078334SJose.Borrego@Sun.COM * is a miss then it looks up sharemgr. 6087348SJose.Borrego@Sun.COM */ 6097348SJose.Borrego@Sun.COM uint32_t 6107348SJose.Borrego@Sun.COM smb_shr_get(char *sharename, smb_share_t *si) 6117348SJose.Borrego@Sun.COM { 6128334SJose.Borrego@Sun.COM uint32_t status; 6137348SJose.Borrego@Sun.COM 6147961SNatalie.Li@Sun.COM if (sharename == NULL || *sharename == '\0') 6157961SNatalie.Li@Sun.COM return (NERR_NetNameNotFound); 6167348SJose.Borrego@Sun.COM 6178334SJose.Borrego@Sun.COM if ((status = smb_shr_lookup(sharename, si)) == NERR_Success) 6188334SJose.Borrego@Sun.COM return (status); 6197961SNatalie.Li@Sun.COM 6208334SJose.Borrego@Sun.COM if ((status = smb_shr_sa_loadbyname(sharename)) == NERR_Success) 6218334SJose.Borrego@Sun.COM status = smb_shr_lookup(sharename, si); 6227348SJose.Borrego@Sun.COM 6237961SNatalie.Li@Sun.COM return (status); 6247348SJose.Borrego@Sun.COM } 6257348SJose.Borrego@Sun.COM 6267348SJose.Borrego@Sun.COM /* 6277348SJose.Borrego@Sun.COM * Modifies an existing share. Properties that can be modified are: 6287348SJose.Borrego@Sun.COM * 6297348SJose.Borrego@Sun.COM * o comment 6307348SJose.Borrego@Sun.COM * o AD container 6317961SNatalie.Li@Sun.COM * o host access 63210504SKeyur.Desai@Sun.COM * o abe 6337348SJose.Borrego@Sun.COM */ 6347348SJose.Borrego@Sun.COM uint32_t 6357961SNatalie.Li@Sun.COM smb_shr_modify(smb_share_t *new_si) 6367348SJose.Borrego@Sun.COM { 6377961SNatalie.Li@Sun.COM smb_share_t *si; 6387348SJose.Borrego@Sun.COM boolean_t adc_changed = B_FALSE; 6397961SNatalie.Li@Sun.COM char old_container[MAXPATHLEN]; 64011963SAfshin.Ardakani@Sun.COM uint32_t access, flag; 641*12508Samw@Sun.COM nvlist_t *shrlist; 6427348SJose.Borrego@Sun.COM 6437961SNatalie.Li@Sun.COM assert(new_si != NULL); 6447348SJose.Borrego@Sun.COM 6457961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success) 6467961SNatalie.Li@Sun.COM return (NERR_InternalError); 6477348SJose.Borrego@Sun.COM 6487961SNatalie.Li@Sun.COM if ((si = smb_shr_cache_findent(new_si->shr_name)) == NULL) { 6497961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 6507961SNatalie.Li@Sun.COM return (NERR_NetNameNotFound); 6517961SNatalie.Li@Sun.COM } 6527348SJose.Borrego@Sun.COM 6537961SNatalie.Li@Sun.COM if (si->shr_type & STYPE_IPC) { 6547961SNatalie.Li@Sun.COM /* IPC$ share cannot be modified */ 6557961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 6567961SNatalie.Li@Sun.COM return (ERROR_ACCESS_DENIED); 6577348SJose.Borrego@Sun.COM } 6587348SJose.Borrego@Sun.COM 6598474SJose.Borrego@Sun.COM (void) strlcpy(si->shr_cmnt, new_si->shr_cmnt, sizeof (si->shr_cmnt)); 6607961SNatalie.Li@Sun.COM 6617961SNatalie.Li@Sun.COM adc_changed = (strcmp(new_si->shr_container, si->shr_container) != 0); 6627961SNatalie.Li@Sun.COM if (adc_changed) { 6637961SNatalie.Li@Sun.COM /* save current container - needed for unpublishing */ 6647961SNatalie.Li@Sun.COM (void) strlcpy(old_container, si->shr_container, 6657961SNatalie.Li@Sun.COM sizeof (old_container)); 6667961SNatalie.Li@Sun.COM (void) strlcpy(si->shr_container, new_si->shr_container, 6677961SNatalie.Li@Sun.COM sizeof (si->shr_container)); 6687348SJose.Borrego@Sun.COM } 6697348SJose.Borrego@Sun.COM 67011963SAfshin.Ardakani@Sun.COM flag = (new_si->shr_flags & SMB_SHRF_ABE); 67110504SKeyur.Desai@Sun.COM si->shr_flags &= ~SMB_SHRF_ABE; 67211963SAfshin.Ardakani@Sun.COM si->shr_flags |= flag; 67310504SKeyur.Desai@Sun.COM 67411963SAfshin.Ardakani@Sun.COM flag = (new_si->shr_flags & SMB_SHRF_CATIA); 6759231SAfshin.Ardakani@Sun.COM si->shr_flags &= ~SMB_SHRF_CATIA; 67611963SAfshin.Ardakani@Sun.COM si->shr_flags |= flag; 6779231SAfshin.Ardakani@Sun.COM 67811963SAfshin.Ardakani@Sun.COM flag = (new_si->shr_flags & SMB_SHRF_GUEST_OK); 67911963SAfshin.Ardakani@Sun.COM si->shr_flags &= ~SMB_SHRF_GUEST_OK; 68011963SAfshin.Ardakani@Sun.COM si->shr_flags |= flag; 6819832Samw@Sun.COM 68211963SAfshin.Ardakani@Sun.COM flag = (new_si->shr_flags & SMB_SHRF_DFSROOT); 68311963SAfshin.Ardakani@Sun.COM si->shr_flags &= ~SMB_SHRF_DFSROOT; 68411963SAfshin.Ardakani@Sun.COM si->shr_flags |= flag; 68511963SAfshin.Ardakani@Sun.COM 68611963SAfshin.Ardakani@Sun.COM flag = (new_si->shr_flags & SMB_SHRF_CSC_MASK); 68711963SAfshin.Ardakani@Sun.COM si->shr_flags &= ~SMB_SHRF_CSC_MASK; 68811963SAfshin.Ardakani@Sun.COM si->shr_flags |= flag; 6898334SJose.Borrego@Sun.COM 6907961SNatalie.Li@Sun.COM access = (new_si->shr_flags & SMB_SHRF_ACC_ALL); 6918474SJose.Borrego@Sun.COM si->shr_flags &= ~SMB_SHRF_ACC_ALL; 6927961SNatalie.Li@Sun.COM si->shr_flags |= access; 6937961SNatalie.Li@Sun.COM 6947961SNatalie.Li@Sun.COM if (access & SMB_SHRF_ACC_NONE) 6957961SNatalie.Li@Sun.COM (void) strlcpy(si->shr_access_none, new_si->shr_access_none, 6967961SNatalie.Li@Sun.COM sizeof (si->shr_access_none)); 6977348SJose.Borrego@Sun.COM 6987961SNatalie.Li@Sun.COM if (access & SMB_SHRF_ACC_RO) 6997961SNatalie.Li@Sun.COM (void) strlcpy(si->shr_access_ro, new_si->shr_access_ro, 7007961SNatalie.Li@Sun.COM sizeof (si->shr_access_ro)); 7017348SJose.Borrego@Sun.COM 7027961SNatalie.Li@Sun.COM if (access & SMB_SHRF_ACC_RW) 7037961SNatalie.Li@Sun.COM (void) strlcpy(si->shr_access_rw, new_si->shr_access_rw, 7047961SNatalie.Li@Sun.COM sizeof (si->shr_access_rw)); 7057961SNatalie.Li@Sun.COM 7067961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 7077052Samw 708*12508Samw@Sun.COM if (smb_shr_encode(si, &shrlist) == 0) { 709*12508Samw@Sun.COM (void) smb_kmod_unshare(shrlist); 710*12508Samw@Sun.COM nvlist_free(shrlist); 711*12508Samw@Sun.COM 712*12508Samw@Sun.COM if (smb_shr_encode(new_si, &shrlist) == 0) { 713*12508Samw@Sun.COM (void) smb_kmod_share(shrlist); 714*12508Samw@Sun.COM nvlist_free(shrlist); 715*12508Samw@Sun.COM } 716*12508Samw@Sun.COM } 717*12508Samw@Sun.COM 7187348SJose.Borrego@Sun.COM if (adc_changed) { 7197961SNatalie.Li@Sun.COM smb_shr_unpublish(new_si->shr_name, old_container); 7207961SNatalie.Li@Sun.COM smb_shr_publish(new_si->shr_name, new_si->shr_container); 7217348SJose.Borrego@Sun.COM } 7227348SJose.Borrego@Sun.COM 7237348SJose.Borrego@Sun.COM return (NERR_Success); 7247052Samw } 7257052Samw 7267052Samw /* 7277052Samw * smb_shr_exists 7287052Samw * 7297348SJose.Borrego@Sun.COM * Returns B_TRUE if the share exists. Otherwise returns B_FALSE 7307052Samw */ 7317348SJose.Borrego@Sun.COM boolean_t 7327348SJose.Borrego@Sun.COM smb_shr_exists(char *sharename) 7337052Samw { 7347961SNatalie.Li@Sun.COM boolean_t exists = B_FALSE; 7357348SJose.Borrego@Sun.COM 7367348SJose.Borrego@Sun.COM if (sharename == NULL || *sharename == '\0') 7377348SJose.Borrego@Sun.COM return (B_FALSE); 7387052Samw 7397961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) { 7407961SNatalie.Li@Sun.COM exists = (smb_shr_cache_findent(sharename) != NULL); 7417961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 7427961SNatalie.Li@Sun.COM } 7437348SJose.Borrego@Sun.COM 7447348SJose.Borrego@Sun.COM return (exists); 7457052Samw } 7467052Samw 7477052Samw /* 7487961SNatalie.Li@Sun.COM * If the shared directory does not begin with a /, one will be 7497961SNatalie.Li@Sun.COM * inserted as a prefix. If ipaddr is not zero, then also return 7507961SNatalie.Li@Sun.COM * information about access based on the host level access lists, if 7517961SNatalie.Li@Sun.COM * present. Also return access check if there is an IP address and 7527961SNatalie.Li@Sun.COM * shr_accflags. 7537961SNatalie.Li@Sun.COM * 7547961SNatalie.Li@Sun.COM * The value of smb_chk_hostaccess is checked for an access match. 7557961SNatalie.Li@Sun.COM * -1 is wildcard match 7567961SNatalie.Li@Sun.COM * 0 is no match 7577961SNatalie.Li@Sun.COM * 1 is match 7587961SNatalie.Li@Sun.COM * 7597961SNatalie.Li@Sun.COM * Precedence is none is checked first followed by ro then rw if 7607961SNatalie.Li@Sun.COM * needed. If x is wildcard (< 0) then check to see if the other 7617961SNatalie.Li@Sun.COM * values are a match. If a match, that wins. 7628670SJose.Borrego@Sun.COM * 763*12508Samw@Sun.COM * ipv6 is wide open (returns SMB_SHRF_ACC_OPEN) for now until the underlying 764*12508Samw@Sun.COM * functions support ipv6. 7657961SNatalie.Li@Sun.COM */ 766*12508Samw@Sun.COM uint32_t 767*12508Samw@Sun.COM smb_shr_hostaccess(smb_inaddr_t *ipaddr, char *none_list, char *ro_list, 768*12508Samw@Sun.COM char *rw_list, uint32_t flag) 7697961SNatalie.Li@Sun.COM { 770*12508Samw@Sun.COM uint32_t acc = SMB_SHRF_ACC_NONE; 771*12508Samw@Sun.COM int none = 0; 772*12508Samw@Sun.COM int ro = 0; 773*12508Samw@Sun.COM int rw = 0; 7747961SNatalie.Li@Sun.COM 775*12508Samw@Sun.COM if (!smb_inet_iszero(ipaddr)) { 776*12508Samw@Sun.COM 777*12508Samw@Sun.COM if (ipaddr->a_family == AF_INET6) 778*12508Samw@Sun.COM return (SMB_SHRF_ACC_OPEN); 7797961SNatalie.Li@Sun.COM 780*12508Samw@Sun.COM if ((flag & SMB_SHRF_ACC_NONE) != 0) 781*12508Samw@Sun.COM none = smb_chk_hostaccess(ipaddr, none_list); 782*12508Samw@Sun.COM if ((flag & SMB_SHRF_ACC_RO) != 0) 783*12508Samw@Sun.COM ro = smb_chk_hostaccess(ipaddr, ro_list); 784*12508Samw@Sun.COM if ((flag & SMB_SHRF_ACC_RW) != 0) 785*12508Samw@Sun.COM rw = smb_chk_hostaccess(ipaddr, rw_list); 786*12508Samw@Sun.COM 7877961SNatalie.Li@Sun.COM /* make first pass to get basic value */ 7887961SNatalie.Li@Sun.COM if (none != 0) 7897961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_NONE; 7907961SNatalie.Li@Sun.COM else if (ro != 0) 7917961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RO; 7927961SNatalie.Li@Sun.COM else if (rw != 0) 7937961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RW; 7947961SNatalie.Li@Sun.COM 7957961SNatalie.Li@Sun.COM /* make second pass to handle '*' case */ 7967961SNatalie.Li@Sun.COM if (none < 0) { 7977961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_NONE; 7987961SNatalie.Li@Sun.COM if (ro > 0) 7997961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RO; 8007961SNatalie.Li@Sun.COM else if (rw > 0) 8017961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RW; 8027961SNatalie.Li@Sun.COM } else if (ro < 0) { 8037961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RO; 8047961SNatalie.Li@Sun.COM if (none > 0) 8057961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_NONE; 8067961SNatalie.Li@Sun.COM else if (rw > 0) 8077961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RW; 8087961SNatalie.Li@Sun.COM } else if (rw < 0) { 8097961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RW; 8107961SNatalie.Li@Sun.COM if (none > 0) 8117961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_NONE; 8127961SNatalie.Li@Sun.COM else if (ro > 0) 8137961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RO; 8147961SNatalie.Li@Sun.COM } 8157961SNatalie.Li@Sun.COM } 816*12508Samw@Sun.COM 817*12508Samw@Sun.COM return (acc); 8187961SNatalie.Li@Sun.COM } 8197961SNatalie.Li@Sun.COM 8207961SNatalie.Li@Sun.COM /* 8217052Samw * smb_shr_is_special 8227052Samw * 8237348SJose.Borrego@Sun.COM * Special share reserved for interprocess communication (IPC$) or 8247348SJose.Borrego@Sun.COM * remote administration of the server (ADMIN$). Can also refer to 8257348SJose.Borrego@Sun.COM * administrative shares such as C$, D$, E$, and so forth. 8267052Samw */ 8277052Samw int 8287348SJose.Borrego@Sun.COM smb_shr_is_special(char *sharename) 8297052Samw { 8307052Samw int len; 8317052Samw 8327348SJose.Borrego@Sun.COM if (sharename == NULL) 8337052Samw return (0); 8347052Samw 8357348SJose.Borrego@Sun.COM if ((len = strlen(sharename)) == 0) 8367052Samw return (0); 8377052Samw 8387348SJose.Borrego@Sun.COM if (sharename[len - 1] == '$') 8397052Samw return (STYPE_SPECIAL); 8407348SJose.Borrego@Sun.COM 8417348SJose.Borrego@Sun.COM return (0); 8427052Samw } 8437052Samw 8447052Samw /* 8457052Samw * smb_shr_is_restricted 8467052Samw * 8477052Samw * Check whether or not there is a restriction on a share. Restricted 8487052Samw * shares are generally STYPE_SPECIAL, for example, IPC$. All the 8497348SJose.Borrego@Sun.COM * administration share names are restricted: C$, D$ etc. Returns B_TRUE 8507348SJose.Borrego@Sun.COM * if the share is restricted. Otherwise B_FALSE is returned to indicate 8517052Samw * that there are no restrictions. 8527052Samw */ 8537348SJose.Borrego@Sun.COM boolean_t 8547348SJose.Borrego@Sun.COM smb_shr_is_restricted(char *sharename) 8557052Samw { 8567052Samw static char *restricted[] = { 8577052Samw "IPC$" 8587052Samw }; 8597052Samw 8607052Samw int i; 8617052Samw 8627348SJose.Borrego@Sun.COM if (sharename == NULL) 8637348SJose.Borrego@Sun.COM return (B_FALSE); 8647348SJose.Borrego@Sun.COM 8657052Samw for (i = 0; i < sizeof (restricted)/sizeof (restricted[0]); i++) { 86610966SJordan.Brown@Sun.COM if (smb_strcasecmp(restricted[i], sharename, 0) == 0) 8677348SJose.Borrego@Sun.COM return (B_TRUE); 8687052Samw } 8697052Samw 8707348SJose.Borrego@Sun.COM return (smb_shr_is_admin(sharename)); 8717052Samw } 8727052Samw 8737052Samw /* 8747052Samw * smb_shr_is_admin 8757052Samw * 8767052Samw * Check whether or not access to the share should be restricted to 8777052Samw * administrators. This is a bit of a hack because what we're doing 8787052Samw * is checking for the default admin shares: C$, D$ etc.. There are 8797052Samw * other shares that have restrictions: see smb_shr_is_restricted(). 8807052Samw * 8817348SJose.Borrego@Sun.COM * Returns B_TRUE if the shares is an admin share. Otherwise B_FALSE 8827348SJose.Borrego@Sun.COM * is returned to indicate that there are no restrictions. 8837052Samw */ 8847348SJose.Borrego@Sun.COM boolean_t 8857348SJose.Borrego@Sun.COM smb_shr_is_admin(char *sharename) 8867052Samw { 8877348SJose.Borrego@Sun.COM if (sharename == NULL) 8887348SJose.Borrego@Sun.COM return (B_FALSE); 8897052Samw 8907348SJose.Borrego@Sun.COM if (strlen(sharename) == 2 && 89110966SJordan.Brown@Sun.COM smb_isalpha(sharename[0]) && sharename[1] == '$') { 8927348SJose.Borrego@Sun.COM return (B_TRUE); 8937052Samw } 8947052Samw 8957348SJose.Borrego@Sun.COM return (B_FALSE); 8967052Samw } 8977052Samw 89812065SKeyur.Desai@Sun.COM char 89912065SKeyur.Desai@Sun.COM smb_shr_drive_letter(const char *path) 90012065SKeyur.Desai@Sun.COM { 90112065SKeyur.Desai@Sun.COM smb_transient_t *ts; 90212065SKeyur.Desai@Sun.COM int i; 90312065SKeyur.Desai@Sun.COM 90412065SKeyur.Desai@Sun.COM if (path == NULL) 90512065SKeyur.Desai@Sun.COM return ('\0'); 90612065SKeyur.Desai@Sun.COM 90712065SKeyur.Desai@Sun.COM for (i = 0; i < sizeof (tshare)/sizeof (tshare[0]); ++i) { 90812065SKeyur.Desai@Sun.COM ts = &tshare[i]; 90912065SKeyur.Desai@Sun.COM 91012065SKeyur.Desai@Sun.COM if (ts->path == NULL) 91112065SKeyur.Desai@Sun.COM continue; 91212065SKeyur.Desai@Sun.COM 91312065SKeyur.Desai@Sun.COM if (strcasecmp(ts->path, path) == 0) 91412065SKeyur.Desai@Sun.COM return (ts->drive); 91512065SKeyur.Desai@Sun.COM } 91612065SKeyur.Desai@Sun.COM 91712065SKeyur.Desai@Sun.COM return ('\0'); 91812065SKeyur.Desai@Sun.COM } 91912065SKeyur.Desai@Sun.COM 92012065SKeyur.Desai@Sun.COM /* 92112065SKeyur.Desai@Sun.COM * Returns true if the specified directory is empty, 92212065SKeyur.Desai@Sun.COM * otherwise returns false. 92312065SKeyur.Desai@Sun.COM */ 92412065SKeyur.Desai@Sun.COM static boolean_t 92512065SKeyur.Desai@Sun.COM smb_shr_is_empty(const char *path) 92612065SKeyur.Desai@Sun.COM { 92712065SKeyur.Desai@Sun.COM DIR *dirp; 92812065SKeyur.Desai@Sun.COM struct dirent *dp; 92912065SKeyur.Desai@Sun.COM 93012065SKeyur.Desai@Sun.COM if (path == NULL) 93112065SKeyur.Desai@Sun.COM return (B_TRUE); 93212065SKeyur.Desai@Sun.COM 93312065SKeyur.Desai@Sun.COM if ((dirp = opendir(path)) == NULL) 93412065SKeyur.Desai@Sun.COM return (B_TRUE); 93512065SKeyur.Desai@Sun.COM 93612065SKeyur.Desai@Sun.COM while ((dp = readdir(dirp)) != NULL) { 93712065SKeyur.Desai@Sun.COM if (!smb_shr_is_dot_or_dotdot(dp->d_name)) 93812065SKeyur.Desai@Sun.COM return (B_FALSE); 93912065SKeyur.Desai@Sun.COM } 94012065SKeyur.Desai@Sun.COM 94112065SKeyur.Desai@Sun.COM (void) closedir(dirp); 94212065SKeyur.Desai@Sun.COM return (B_TRUE); 94312065SKeyur.Desai@Sun.COM } 94412065SKeyur.Desai@Sun.COM 94512065SKeyur.Desai@Sun.COM /* 94612065SKeyur.Desai@Sun.COM * Returns true if name is "." or "..", otherwise returns false. 94712065SKeyur.Desai@Sun.COM */ 94812065SKeyur.Desai@Sun.COM static boolean_t 94912065SKeyur.Desai@Sun.COM smb_shr_is_dot_or_dotdot(const char *name) 95012065SKeyur.Desai@Sun.COM { 95112065SKeyur.Desai@Sun.COM if (*name != '.') 95212065SKeyur.Desai@Sun.COM return (B_FALSE); 95312065SKeyur.Desai@Sun.COM 95412065SKeyur.Desai@Sun.COM if ((name[1] == '\0') || (name[1] == '.' && name[2] == '\0')) 95512065SKeyur.Desai@Sun.COM return (B_TRUE); 95612065SKeyur.Desai@Sun.COM 95712065SKeyur.Desai@Sun.COM return (B_FALSE); 95812065SKeyur.Desai@Sun.COM } 95912065SKeyur.Desai@Sun.COM 9607052Samw /* 9617052Samw * smb_shr_get_realpath 9627052Samw * 9637961SNatalie.Li@Sun.COM * Derive the real path for a share from the path provided by a client. 9647961SNatalie.Li@Sun.COM * For instance, the real path of C:\ may be /cvol or the real path of 9657961SNatalie.Li@Sun.COM * F:\home may be /vol1/home. 9667052Samw * 9677961SNatalie.Li@Sun.COM * clntpath - path provided by the Windows client is in the 9687052Samw * format of <drive letter>:\<dir> 9697052Samw * realpath - path that will be stored as the directory field of 9707052Samw * the smb_share_t structure of the share. 9717961SNatalie.Li@Sun.COM * maxlen - maximum length of the realpath buffer 9727052Samw * 9737052Samw * Return LAN Manager network error code. 9747052Samw */ 9757052Samw uint32_t 9767961SNatalie.Li@Sun.COM smb_shr_get_realpath(const char *clntpath, char *realpath, int maxlen) 9777052Samw { 9787961SNatalie.Li@Sun.COM const char *p; 9797961SNatalie.Li@Sun.COM int len; 9807348SJose.Borrego@Sun.COM 9817961SNatalie.Li@Sun.COM if ((p = strchr(clntpath, ':')) != NULL) 9827961SNatalie.Li@Sun.COM ++p; 9837961SNatalie.Li@Sun.COM else 9847961SNatalie.Li@Sun.COM p = clntpath; 9857348SJose.Borrego@Sun.COM 9867961SNatalie.Li@Sun.COM (void) strlcpy(realpath, p, maxlen); 9877961SNatalie.Li@Sun.COM (void) strcanon(realpath, "/\\"); 9887961SNatalie.Li@Sun.COM (void) strsubst(realpath, '\\', '/'); 9897348SJose.Borrego@Sun.COM 9907961SNatalie.Li@Sun.COM len = strlen(realpath); 9917961SNatalie.Li@Sun.COM if ((len > 1) && (realpath[len - 1] == '/')) 9927961SNatalie.Li@Sun.COM realpath[len - 1] = '\0'; 9937348SJose.Borrego@Sun.COM 9947348SJose.Borrego@Sun.COM return (NERR_Success); 9957348SJose.Borrego@Sun.COM } 9967348SJose.Borrego@Sun.COM 9977961SNatalie.Li@Sun.COM void 9987961SNatalie.Li@Sun.COM smb_shr_list(int offset, smb_shrlist_t *list) 9997348SJose.Borrego@Sun.COM { 10007961SNatalie.Li@Sun.COM smb_shriter_t iterator; 10017961SNatalie.Li@Sun.COM smb_share_t *si; 10027961SNatalie.Li@Sun.COM int n = 0; 10037961SNatalie.Li@Sun.COM 10047961SNatalie.Li@Sun.COM bzero(list, sizeof (smb_shrlist_t)); 10057961SNatalie.Li@Sun.COM smb_shr_iterinit(&iterator); 10067961SNatalie.Li@Sun.COM 10077961SNatalie.Li@Sun.COM while ((si = smb_shr_iterate(&iterator)) != NULL) { 10087961SNatalie.Li@Sun.COM if (--offset > 0) 10097961SNatalie.Li@Sun.COM continue; 10107961SNatalie.Li@Sun.COM 10117961SNatalie.Li@Sun.COM if ((si->shr_flags & SMB_SHRF_TRANS) && 10127961SNatalie.Li@Sun.COM ((si->shr_type & STYPE_IPC) == 0)) { 10137961SNatalie.Li@Sun.COM bcopy(si, &list->sl_shares[n], sizeof (smb_share_t)); 10147961SNatalie.Li@Sun.COM if (++n == LMSHARES_PER_REQUEST) 10157961SNatalie.Li@Sun.COM break; 10167961SNatalie.Li@Sun.COM } 10177348SJose.Borrego@Sun.COM } 10187961SNatalie.Li@Sun.COM 10197961SNatalie.Li@Sun.COM list->sl_cnt = n; 10207348SJose.Borrego@Sun.COM } 10217348SJose.Borrego@Sun.COM 10227348SJose.Borrego@Sun.COM /* 10239832Samw@Sun.COM * Executes the map/unmap command associated with a share. 10249832Samw@Sun.COM * 10259832Samw@Sun.COM * Returns 0 on success. Otherwise non-zero for errors. 10269832Samw@Sun.COM */ 10279832Samw@Sun.COM int 1028*12508Samw@Sun.COM smb_shr_exec(smb_shr_execinfo_t *subs) 10299832Samw@Sun.COM { 10309832Samw@Sun.COM char cmd[MAXPATHLEN], **cmd_tokens, *path, *ptr; 10319832Samw@Sun.COM pid_t child_pid; 10329832Samw@Sun.COM int child_status; 10339832Samw@Sun.COM struct sigaction pact, cact; 10349832Samw@Sun.COM smb_share_t si; 10359832Samw@Sun.COM 1036*12508Samw@Sun.COM if (smb_shr_get(subs->e_sharename, &si) != 0) 10379832Samw@Sun.COM return (-1); 10389832Samw@Sun.COM 10399832Samw@Sun.COM *cmd = '\0'; 10409832Samw@Sun.COM 10419832Samw@Sun.COM (void) mutex_lock(&smb_shr_exec_mtx); 10429832Samw@Sun.COM 1043*12508Samw@Sun.COM switch (subs->e_type) { 1044*12508Samw@Sun.COM case SMB_EXEC_MAP: 10459832Samw@Sun.COM (void) strlcpy(cmd, smb_shr_exec_map, sizeof (cmd)); 10469832Samw@Sun.COM break; 1047*12508Samw@Sun.COM case SMB_EXEC_UNMAP: 10489832Samw@Sun.COM (void) strlcpy(cmd, smb_shr_exec_unmap, sizeof (cmd)); 10499832Samw@Sun.COM break; 10509832Samw@Sun.COM default: 10519832Samw@Sun.COM (void) mutex_unlock(&smb_shr_exec_mtx); 10529832Samw@Sun.COM return (-1); 10539832Samw@Sun.COM } 10549832Samw@Sun.COM 10559832Samw@Sun.COM (void) mutex_unlock(&smb_shr_exec_mtx); 10569832Samw@Sun.COM 10579832Samw@Sun.COM if (*cmd == '\0') 10589832Samw@Sun.COM return (0); 10599832Samw@Sun.COM 106010504SKeyur.Desai@Sun.COM if (smb_proc_takesem() != 0) 106110504SKeyur.Desai@Sun.COM return (-1); 106210504SKeyur.Desai@Sun.COM 10639832Samw@Sun.COM pact.sa_handler = smb_shr_sig_child; 10649832Samw@Sun.COM pact.sa_flags = 0; 10659832Samw@Sun.COM (void) sigemptyset(&pact.sa_mask); 10669832Samw@Sun.COM sigaction(SIGCHLD, &pact, NULL); 10679832Samw@Sun.COM 10689832Samw@Sun.COM (void) priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_FORK, NULL); 10699832Samw@Sun.COM 10709832Samw@Sun.COM if ((child_pid = fork()) == -1) { 10719832Samw@Sun.COM (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_FORK, NULL); 107210504SKeyur.Desai@Sun.COM smb_proc_givesem(); 10739832Samw@Sun.COM return (-1); 10749832Samw@Sun.COM } 10759832Samw@Sun.COM 10769832Samw@Sun.COM if (child_pid == 0) { 10779832Samw@Sun.COM 10789832Samw@Sun.COM /* child process */ 10799832Samw@Sun.COM 10809832Samw@Sun.COM cact.sa_handler = smb_shr_sig_abnormal_term; 10819832Samw@Sun.COM cact.sa_flags = 0; 10829832Samw@Sun.COM (void) sigemptyset(&cact.sa_mask); 10839832Samw@Sun.COM sigaction(SIGTERM, &cact, NULL); 10849832Samw@Sun.COM sigaction(SIGABRT, &cact, NULL); 10859832Samw@Sun.COM sigaction(SIGSEGV, &cact, NULL); 10869832Samw@Sun.COM 10879832Samw@Sun.COM if (priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_EXEC, 10889832Samw@Sun.COM PRIV_FILE_DAC_EXECUTE, NULL)) 10899832Samw@Sun.COM _exit(-1); 10909832Samw@Sun.COM 10919832Samw@Sun.COM if (smb_shr_enable_all_privs()) 10929832Samw@Sun.COM _exit(-1); 10939832Samw@Sun.COM 109410504SKeyur.Desai@Sun.COM smb_proc_initsem(); 109510504SKeyur.Desai@Sun.COM 10969832Samw@Sun.COM (void) trim_whitespace(cmd); 10979832Samw@Sun.COM (void) strcanon(cmd, " "); 10989832Samw@Sun.COM 10999832Samw@Sun.COM if ((cmd_tokens = smb_shr_tokenize_cmd(cmd)) != NULL) { 11009832Samw@Sun.COM 11019832Samw@Sun.COM if (smb_shr_expand_subs(cmd_tokens, &si, subs) != 0) { 11029832Samw@Sun.COM free(cmd_tokens[0]); 11039832Samw@Sun.COM free(cmd_tokens); 11049832Samw@Sun.COM _exit(-1); 11059832Samw@Sun.COM } 11069832Samw@Sun.COM 11079832Samw@Sun.COM ptr = cmd; 11089832Samw@Sun.COM path = strsep(&ptr, " "); 11099832Samw@Sun.COM 11109832Samw@Sun.COM (void) execv(path, cmd_tokens); 11119832Samw@Sun.COM } 11129832Samw@Sun.COM 11139832Samw@Sun.COM _exit(-1); 11149832Samw@Sun.COM } 11159832Samw@Sun.COM 111610504SKeyur.Desai@Sun.COM (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_FORK, NULL); 111710504SKeyur.Desai@Sun.COM smb_proc_givesem(); 111810504SKeyur.Desai@Sun.COM 11199832Samw@Sun.COM /* parent process */ 11209832Samw@Sun.COM 11219832Samw@Sun.COM while (waitpid(child_pid, &child_status, 0) < 0) { 11229832Samw@Sun.COM if (errno != EINTR) 11239832Samw@Sun.COM break; 11249832Samw@Sun.COM 11259832Samw@Sun.COM /* continue if waitpid got interrupted by a signal */ 11269832Samw@Sun.COM errno = 0; 11279832Samw@Sun.COM continue; 11289832Samw@Sun.COM } 11299832Samw@Sun.COM 11309832Samw@Sun.COM if (WIFEXITED(child_status)) 11319832Samw@Sun.COM return (WEXITSTATUS(child_status)); 11329832Samw@Sun.COM 11339832Samw@Sun.COM return (child_status); 11349832Samw@Sun.COM } 11359832Samw@Sun.COM 11369832Samw@Sun.COM /* 113710504SKeyur.Desai@Sun.COM * Locking for process-wide settings (i.e. privileges) 113810504SKeyur.Desai@Sun.COM */ 113910504SKeyur.Desai@Sun.COM void 114010504SKeyur.Desai@Sun.COM smb_proc_initsem(void) 114110504SKeyur.Desai@Sun.COM { 114210504SKeyur.Desai@Sun.COM (void) sema_init(&smb_proc_sem, 1, USYNC_THREAD, NULL); 114310504SKeyur.Desai@Sun.COM } 114410504SKeyur.Desai@Sun.COM 114510504SKeyur.Desai@Sun.COM int 114610504SKeyur.Desai@Sun.COM smb_proc_takesem(void) 114710504SKeyur.Desai@Sun.COM { 114810504SKeyur.Desai@Sun.COM return (sema_wait(&smb_proc_sem)); 114910504SKeyur.Desai@Sun.COM } 115010504SKeyur.Desai@Sun.COM 115110504SKeyur.Desai@Sun.COM void 115210504SKeyur.Desai@Sun.COM smb_proc_givesem(void) 115310504SKeyur.Desai@Sun.COM { 115410504SKeyur.Desai@Sun.COM (void) sema_post(&smb_proc_sem); 115510504SKeyur.Desai@Sun.COM } 115610504SKeyur.Desai@Sun.COM 115710504SKeyur.Desai@Sun.COM /* 11587961SNatalie.Li@Sun.COM * ============================================ 11597961SNatalie.Li@Sun.COM * Private helper/utility functions 11607961SNatalie.Li@Sun.COM * ============================================ 11617348SJose.Borrego@Sun.COM */ 11627348SJose.Borrego@Sun.COM 11637961SNatalie.Li@Sun.COM /* 11648334SJose.Borrego@Sun.COM * Looks up the given share in the cache and return 11658334SJose.Borrego@Sun.COM * the info in 'si' 11668334SJose.Borrego@Sun.COM */ 11678334SJose.Borrego@Sun.COM static uint32_t 11688334SJose.Borrego@Sun.COM smb_shr_lookup(char *sharename, smb_share_t *si) 11698334SJose.Borrego@Sun.COM { 11708334SJose.Borrego@Sun.COM smb_share_t *cached_si; 11718334SJose.Borrego@Sun.COM uint32_t status = NERR_NetNameNotFound; 11728334SJose.Borrego@Sun.COM 11738334SJose.Borrego@Sun.COM if (sharename == NULL || *sharename == '\0') 11748334SJose.Borrego@Sun.COM return (NERR_NetNameNotFound); 11758334SJose.Borrego@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) { 11768334SJose.Borrego@Sun.COM cached_si = smb_shr_cache_findent(sharename); 11778334SJose.Borrego@Sun.COM if (cached_si != NULL) { 11788334SJose.Borrego@Sun.COM bcopy(cached_si, si, sizeof (smb_share_t)); 11798334SJose.Borrego@Sun.COM status = NERR_Success; 11808334SJose.Borrego@Sun.COM } 11818334SJose.Borrego@Sun.COM 11828334SJose.Borrego@Sun.COM smb_shr_cache_unlock(); 11838334SJose.Borrego@Sun.COM } 11848334SJose.Borrego@Sun.COM return (status); 11858334SJose.Borrego@Sun.COM } 11868334SJose.Borrego@Sun.COM 11878334SJose.Borrego@Sun.COM /* 118811963SAfshin.Ardakani@Sun.COM * Add IPC$ or Admin shares to the cache upon startup. 11897961SNatalie.Li@Sun.COM */ 11907348SJose.Borrego@Sun.COM static uint32_t 119111963SAfshin.Ardakani@Sun.COM smb_shr_add_transient(char *name, char *cmnt, char *path) 11927348SJose.Borrego@Sun.COM { 119311963SAfshin.Ardakani@Sun.COM smb_share_t trans; 11947961SNatalie.Li@Sun.COM uint32_t status = NERR_InternalError; 11957348SJose.Borrego@Sun.COM 119611963SAfshin.Ardakani@Sun.COM if (name == NULL) 119711963SAfshin.Ardakani@Sun.COM return (status); 119811963SAfshin.Ardakani@Sun.COM 119911963SAfshin.Ardakani@Sun.COM bzero(&trans, sizeof (smb_share_t)); 120011963SAfshin.Ardakani@Sun.COM (void) strlcpy(trans.shr_name, name, MAXNAMELEN); 120111963SAfshin.Ardakani@Sun.COM if (cmnt) 120211963SAfshin.Ardakani@Sun.COM (void) strlcpy(trans.shr_cmnt, cmnt, SMB_SHARE_CMNT_MAX); 120311963SAfshin.Ardakani@Sun.COM 120411963SAfshin.Ardakani@Sun.COM if (path) 120511963SAfshin.Ardakani@Sun.COM (void) strlcpy(trans.shr_path, path, MAXPATHLEN); 120611963SAfshin.Ardakani@Sun.COM 120711963SAfshin.Ardakani@Sun.COM if (strcasecmp(name, "IPC$") == 0) 120811963SAfshin.Ardakani@Sun.COM trans.shr_type = STYPE_IPC; 120911963SAfshin.Ardakani@Sun.COM 121011963SAfshin.Ardakani@Sun.COM trans.shr_flags = SMB_SHRF_TRANS; 12117348SJose.Borrego@Sun.COM 12127961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) == NERR_Success) { 121311963SAfshin.Ardakani@Sun.COM status = smb_shr_cache_addent(&trans); 12147961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 12157348SJose.Borrego@Sun.COM } 12167348SJose.Borrego@Sun.COM 12177348SJose.Borrego@Sun.COM return (status); 12187348SJose.Borrego@Sun.COM } 12197348SJose.Borrego@Sun.COM 12207348SJose.Borrego@Sun.COM /* 12217348SJose.Borrego@Sun.COM * ============================================ 12227961SNatalie.Li@Sun.COM * Cache management functions 12237961SNatalie.Li@Sun.COM * 12247961SNatalie.Li@Sun.COM * All cache functions are private 12257348SJose.Borrego@Sun.COM * ============================================ 12267348SJose.Borrego@Sun.COM */ 12277348SJose.Borrego@Sun.COM 12287348SJose.Borrego@Sun.COM /* 12297961SNatalie.Li@Sun.COM * Create the share cache (hash table). 12307348SJose.Borrego@Sun.COM */ 12317348SJose.Borrego@Sun.COM static uint32_t 12327961SNatalie.Li@Sun.COM smb_shr_cache_create(void) 12337348SJose.Borrego@Sun.COM { 12347961SNatalie.Li@Sun.COM uint32_t status = NERR_Success; 12357348SJose.Borrego@Sun.COM 12367961SNatalie.Li@Sun.COM (void) mutex_lock(&smb_shr_cache.sc_mtx); 12377961SNatalie.Li@Sun.COM switch (smb_shr_cache.sc_state) { 12387961SNatalie.Li@Sun.COM case SMB_SHR_CACHE_STATE_NONE: 12397961SNatalie.Li@Sun.COM smb_shr_cache.sc_cache = ht_create_table(SMB_SHR_HTAB_SZ, 12407961SNatalie.Li@Sun.COM MAXNAMELEN, 0); 12417961SNatalie.Li@Sun.COM if (smb_shr_cache.sc_cache == NULL) { 12427961SNatalie.Li@Sun.COM status = NERR_InternalError; 12437961SNatalie.Li@Sun.COM break; 12447348SJose.Borrego@Sun.COM } 12457348SJose.Borrego@Sun.COM 12467961SNatalie.Li@Sun.COM (void) ht_register_callback(smb_shr_cache.sc_cache, 12477961SNatalie.Li@Sun.COM smb_shr_cache_freent); 12487961SNatalie.Li@Sun.COM smb_shr_cache.sc_nops = 0; 12497961SNatalie.Li@Sun.COM smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_CREATED; 12507961SNatalie.Li@Sun.COM break; 12517961SNatalie.Li@Sun.COM 12527961SNatalie.Li@Sun.COM default: 12537961SNatalie.Li@Sun.COM assert(0); 12547961SNatalie.Li@Sun.COM status = NERR_InternalError; 12557961SNatalie.Li@Sun.COM break; 12567961SNatalie.Li@Sun.COM } 12577961SNatalie.Li@Sun.COM (void) mutex_unlock(&smb_shr_cache.sc_mtx); 12587961SNatalie.Li@Sun.COM 12597961SNatalie.Li@Sun.COM return (status); 12607961SNatalie.Li@Sun.COM } 12617961SNatalie.Li@Sun.COM 12627961SNatalie.Li@Sun.COM /* 12637961SNatalie.Li@Sun.COM * Destroy the share cache (hash table). 12647961SNatalie.Li@Sun.COM * Wait for inflight/pending operations to finish or abort before 12657961SNatalie.Li@Sun.COM * destroying the cache. 12667961SNatalie.Li@Sun.COM */ 12677961SNatalie.Li@Sun.COM static void 12687961SNatalie.Li@Sun.COM smb_shr_cache_destroy(void) 12697961SNatalie.Li@Sun.COM { 12707961SNatalie.Li@Sun.COM (void) mutex_lock(&smb_shr_cache.sc_mtx); 12717961SNatalie.Li@Sun.COM if (smb_shr_cache.sc_state == SMB_SHR_CACHE_STATE_CREATED) { 12727961SNatalie.Li@Sun.COM smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_DESTROYING; 12737961SNatalie.Li@Sun.COM while (smb_shr_cache.sc_nops > 0) 12747961SNatalie.Li@Sun.COM (void) cond_wait(&smb_shr_cache.sc_cv, 12757961SNatalie.Li@Sun.COM &smb_shr_cache.sc_mtx); 12767961SNatalie.Li@Sun.COM 12777961SNatalie.Li@Sun.COM smb_shr_cache.sc_cache = NULL; 12787961SNatalie.Li@Sun.COM smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_NONE; 12797961SNatalie.Li@Sun.COM } 12807961SNatalie.Li@Sun.COM (void) mutex_unlock(&smb_shr_cache.sc_mtx); 12817961SNatalie.Li@Sun.COM } 12827961SNatalie.Li@Sun.COM 12837961SNatalie.Li@Sun.COM /* 12847961SNatalie.Li@Sun.COM * If the cache is in "created" state, lock the cache for read 12857961SNatalie.Li@Sun.COM * or read/write based on the specified mode. 12867961SNatalie.Li@Sun.COM * 12877961SNatalie.Li@Sun.COM * Whenever a lock is granted, the number of inflight cache 12887961SNatalie.Li@Sun.COM * operations is incremented. 12897961SNatalie.Li@Sun.COM */ 12907961SNatalie.Li@Sun.COM static uint32_t 12917961SNatalie.Li@Sun.COM smb_shr_cache_lock(int mode) 12927961SNatalie.Li@Sun.COM { 12937961SNatalie.Li@Sun.COM (void) mutex_lock(&smb_shr_cache.sc_mtx); 12948334SJose.Borrego@Sun.COM if (smb_shr_cache.sc_state != SMB_SHR_CACHE_STATE_CREATED) { 12957961SNatalie.Li@Sun.COM (void) mutex_unlock(&smb_shr_cache.sc_mtx); 12967961SNatalie.Li@Sun.COM return (NERR_InternalError); 12977961SNatalie.Li@Sun.COM } 12988334SJose.Borrego@Sun.COM smb_shr_cache.sc_nops++; 12997961SNatalie.Li@Sun.COM (void) mutex_unlock(&smb_shr_cache.sc_mtx); 13007961SNatalie.Li@Sun.COM 13017961SNatalie.Li@Sun.COM /* 13027961SNatalie.Li@Sun.COM * Lock has to be taken outside the mutex otherwise 13037961SNatalie.Li@Sun.COM * there could be a deadlock 13047961SNatalie.Li@Sun.COM */ 13057961SNatalie.Li@Sun.COM if (mode == SMB_SHR_CACHE_RDLOCK) 13067961SNatalie.Li@Sun.COM (void) rw_rdlock(&smb_shr_cache.sc_cache_lck); 13077961SNatalie.Li@Sun.COM else 13087961SNatalie.Li@Sun.COM (void) rw_wrlock(&smb_shr_cache.sc_cache_lck); 13097961SNatalie.Li@Sun.COM 13107961SNatalie.Li@Sun.COM return (NERR_Success); 13117961SNatalie.Li@Sun.COM } 13127961SNatalie.Li@Sun.COM 13137961SNatalie.Li@Sun.COM /* 13147961SNatalie.Li@Sun.COM * Decrement the number of inflight operations and then unlock. 13157961SNatalie.Li@Sun.COM */ 13167961SNatalie.Li@Sun.COM static void 13177961SNatalie.Li@Sun.COM smb_shr_cache_unlock(void) 13187961SNatalie.Li@Sun.COM { 13197961SNatalie.Li@Sun.COM (void) mutex_lock(&smb_shr_cache.sc_mtx); 13207961SNatalie.Li@Sun.COM assert(smb_shr_cache.sc_nops > 0); 13217961SNatalie.Li@Sun.COM smb_shr_cache.sc_nops--; 13227961SNatalie.Li@Sun.COM (void) cond_broadcast(&smb_shr_cache.sc_cv); 13237961SNatalie.Li@Sun.COM (void) mutex_unlock(&smb_shr_cache.sc_mtx); 13247961SNatalie.Li@Sun.COM 13257961SNatalie.Li@Sun.COM (void) rw_unlock(&smb_shr_cache.sc_cache_lck); 13267961SNatalie.Li@Sun.COM } 13277961SNatalie.Li@Sun.COM 13287961SNatalie.Li@Sun.COM /* 13297961SNatalie.Li@Sun.COM * Return the total number of shares 13307961SNatalie.Li@Sun.COM */ 13317961SNatalie.Li@Sun.COM static int 13327961SNatalie.Li@Sun.COM smb_shr_cache_count(void) 13337961SNatalie.Li@Sun.COM { 13347961SNatalie.Li@Sun.COM return (ht_get_total_items(smb_shr_cache.sc_cache)); 13357961SNatalie.Li@Sun.COM } 13367961SNatalie.Li@Sun.COM 13377961SNatalie.Li@Sun.COM /* 13387961SNatalie.Li@Sun.COM * looks up the given share name in the cache and if it 13397961SNatalie.Li@Sun.COM * finds a match returns a pointer to the cached entry. 13407961SNatalie.Li@Sun.COM * Note that since a pointer is returned this function 13417961SNatalie.Li@Sun.COM * MUST be protected by smb_shr_cache_lock/unlock pair 13427961SNatalie.Li@Sun.COM */ 13437961SNatalie.Li@Sun.COM static smb_share_t * 13447961SNatalie.Li@Sun.COM smb_shr_cache_findent(char *sharename) 13457961SNatalie.Li@Sun.COM { 13467961SNatalie.Li@Sun.COM HT_ITEM *item; 13477961SNatalie.Li@Sun.COM 134810966SJordan.Brown@Sun.COM (void) smb_strlwr(sharename); 13497961SNatalie.Li@Sun.COM item = ht_find_item(smb_shr_cache.sc_cache, sharename); 13507961SNatalie.Li@Sun.COM if (item && item->hi_data) 13517961SNatalie.Li@Sun.COM return ((smb_share_t *)item->hi_data); 13527961SNatalie.Li@Sun.COM 13537961SNatalie.Li@Sun.COM return (NULL); 13547961SNatalie.Li@Sun.COM } 13557961SNatalie.Li@Sun.COM 13567961SNatalie.Li@Sun.COM /* 13577961SNatalie.Li@Sun.COM * Return a pointer to the first/next entry in 13587961SNatalie.Li@Sun.COM * the cache based on the given iterator. 13597961SNatalie.Li@Sun.COM * 13607961SNatalie.Li@Sun.COM * Calls to this function MUST be protected by 13617961SNatalie.Li@Sun.COM * smb_shr_cache_lock/unlock. 13627961SNatalie.Li@Sun.COM */ 13637961SNatalie.Li@Sun.COM static smb_share_t * 13647961SNatalie.Li@Sun.COM smb_shr_cache_iterate(smb_shriter_t *shi) 13657961SNatalie.Li@Sun.COM { 13667961SNatalie.Li@Sun.COM HT_ITEM *item; 13677961SNatalie.Li@Sun.COM 13687961SNatalie.Li@Sun.COM if (shi->si_first) { 13697961SNatalie.Li@Sun.COM item = ht_findfirst(smb_shr_cache.sc_cache, &shi->si_hashiter); 13707961SNatalie.Li@Sun.COM shi->si_first = B_FALSE; 13717961SNatalie.Li@Sun.COM } else { 13727961SNatalie.Li@Sun.COM item = ht_findnext(&shi->si_hashiter); 13737348SJose.Borrego@Sun.COM } 13747348SJose.Borrego@Sun.COM 13757961SNatalie.Li@Sun.COM if (item && item->hi_data) 13767961SNatalie.Li@Sun.COM return ((smb_share_t *)item->hi_data); 13777961SNatalie.Li@Sun.COM 13787961SNatalie.Li@Sun.COM return (NULL); 13797961SNatalie.Li@Sun.COM } 13807961SNatalie.Li@Sun.COM 13817961SNatalie.Li@Sun.COM /* 13827961SNatalie.Li@Sun.COM * Add the specified share to the cache. Memory needs to be allocated 13837961SNatalie.Li@Sun.COM * for the cache entry and the passed information is copied to the 13847961SNatalie.Li@Sun.COM * allocated space. 13857961SNatalie.Li@Sun.COM */ 13867961SNatalie.Li@Sun.COM static uint32_t 13877961SNatalie.Li@Sun.COM smb_shr_cache_addent(smb_share_t *si) 13887961SNatalie.Li@Sun.COM { 13897961SNatalie.Li@Sun.COM smb_share_t *cache_ent; 13907961SNatalie.Li@Sun.COM uint32_t status = NERR_Success; 13917961SNatalie.Li@Sun.COM 13927961SNatalie.Li@Sun.COM if ((cache_ent = malloc(sizeof (smb_share_t))) == NULL) 13937961SNatalie.Li@Sun.COM return (ERROR_NOT_ENOUGH_MEMORY); 13947961SNatalie.Li@Sun.COM 1395*12508Samw@Sun.COM (void) smb_strlwr(si->shr_name); 13967961SNatalie.Li@Sun.COM 13977961SNatalie.Li@Sun.COM if ((si->shr_type & STYPE_IPC) == 0) 1398*12508Samw@Sun.COM si->shr_type = STYPE_DISKTREE; 1399*12508Samw@Sun.COM si->shr_type |= smb_shr_is_special(cache_ent->shr_name); 14007961SNatalie.Li@Sun.COM 14017961SNatalie.Li@Sun.COM if (smb_shr_is_admin(cache_ent->shr_name)) 1402*12508Samw@Sun.COM si->shr_flags |= SMB_SHRF_ADMIN; 1403*12508Samw@Sun.COM 1404*12508Samw@Sun.COM bcopy(si, cache_ent, sizeof (smb_share_t)); 14057961SNatalie.Li@Sun.COM 14067961SNatalie.Li@Sun.COM if (si->shr_flags & SMB_SHRF_AUTOHOME) 14077961SNatalie.Li@Sun.COM cache_ent->shr_refcnt = 1; 14087961SNatalie.Li@Sun.COM 14097961SNatalie.Li@Sun.COM if (ht_add_item(smb_shr_cache.sc_cache, cache_ent->shr_name, cache_ent) 14107961SNatalie.Li@Sun.COM == NULL) { 14117961SNatalie.Li@Sun.COM syslog(LOG_DEBUG, "share: %s: cache update failed", 14127961SNatalie.Li@Sun.COM cache_ent->shr_name); 14137961SNatalie.Li@Sun.COM free(cache_ent); 14147961SNatalie.Li@Sun.COM status = NERR_InternalError; 14157348SJose.Borrego@Sun.COM } 14167348SJose.Borrego@Sun.COM 14177961SNatalie.Li@Sun.COM return (status); 14187961SNatalie.Li@Sun.COM } 14197961SNatalie.Li@Sun.COM 14207961SNatalie.Li@Sun.COM /* 14217961SNatalie.Li@Sun.COM * Delete the specified share from the cache. 14227961SNatalie.Li@Sun.COM */ 14237961SNatalie.Li@Sun.COM static void 14247961SNatalie.Li@Sun.COM smb_shr_cache_delent(char *sharename) 14257961SNatalie.Li@Sun.COM { 142610966SJordan.Brown@Sun.COM (void) smb_strlwr(sharename); 14277961SNatalie.Li@Sun.COM (void) ht_remove_item(smb_shr_cache.sc_cache, sharename); 14287961SNatalie.Li@Sun.COM } 14297961SNatalie.Li@Sun.COM 14307961SNatalie.Li@Sun.COM /* 14317961SNatalie.Li@Sun.COM * Call back to free the given cache entry. 14327961SNatalie.Li@Sun.COM */ 14337961SNatalie.Li@Sun.COM static void 14347961SNatalie.Li@Sun.COM smb_shr_cache_freent(HT_ITEM *item) 14357961SNatalie.Li@Sun.COM { 14367961SNatalie.Li@Sun.COM if (item && item->hi_data) 14377961SNatalie.Li@Sun.COM free(item->hi_data); 14387961SNatalie.Li@Sun.COM } 14397961SNatalie.Li@Sun.COM 14407961SNatalie.Li@Sun.COM /* 14417961SNatalie.Li@Sun.COM * ============================================ 14427961SNatalie.Li@Sun.COM * Interfaces to sharemgr 14437961SNatalie.Li@Sun.COM * 14447961SNatalie.Li@Sun.COM * All functions in this section are private 14457961SNatalie.Li@Sun.COM * ============================================ 14467961SNatalie.Li@Sun.COM */ 14477961SNatalie.Li@Sun.COM 14487961SNatalie.Li@Sun.COM /* 14497961SNatalie.Li@Sun.COM * Load shares from sharemgr 14507961SNatalie.Li@Sun.COM */ 14517961SNatalie.Li@Sun.COM /*ARGSUSED*/ 14527961SNatalie.Li@Sun.COM static void * 14537961SNatalie.Li@Sun.COM smb_shr_sa_loadall(void *args) 14547961SNatalie.Li@Sun.COM { 14557961SNatalie.Li@Sun.COM sa_handle_t handle; 14567961SNatalie.Li@Sun.COM sa_group_t group, subgroup; 14577961SNatalie.Li@Sun.COM char *gstate; 14587961SNatalie.Li@Sun.COM boolean_t gdisabled; 14597961SNatalie.Li@Sun.COM 14608474SJose.Borrego@Sun.COM if ((handle = smb_shr_sa_enter()) == NULL) 14617961SNatalie.Li@Sun.COM return (NULL); 14627348SJose.Borrego@Sun.COM 14637961SNatalie.Li@Sun.COM for (group = sa_get_group(handle, NULL); 14647961SNatalie.Li@Sun.COM group != NULL; group = sa_get_next_group(group)) { 14657961SNatalie.Li@Sun.COM gstate = sa_get_group_attr(group, "state"); 14667961SNatalie.Li@Sun.COM if (gstate == NULL) 14677961SNatalie.Li@Sun.COM continue; 14687961SNatalie.Li@Sun.COM 14697961SNatalie.Li@Sun.COM gdisabled = (strcasecmp(gstate, "disabled") == 0); 14707961SNatalie.Li@Sun.COM sa_free_attr_string(gstate); 14717961SNatalie.Li@Sun.COM if (gdisabled) 14727961SNatalie.Li@Sun.COM continue; 14737961SNatalie.Li@Sun.COM 14747961SNatalie.Li@Sun.COM smb_shr_sa_loadgrp(group); 14757961SNatalie.Li@Sun.COM 14767961SNatalie.Li@Sun.COM for (subgroup = sa_get_sub_group(group); 14777961SNatalie.Li@Sun.COM subgroup != NULL; 14787961SNatalie.Li@Sun.COM subgroup = sa_get_next_group(subgroup)) { 14797961SNatalie.Li@Sun.COM smb_shr_sa_loadgrp(subgroup); 14807961SNatalie.Li@Sun.COM } 14817961SNatalie.Li@Sun.COM 14827348SJose.Borrego@Sun.COM } 14837348SJose.Borrego@Sun.COM 14848474SJose.Borrego@Sun.COM smb_shr_sa_exit(); 14857961SNatalie.Li@Sun.COM return (NULL); 14867348SJose.Borrego@Sun.COM } 14877348SJose.Borrego@Sun.COM 14887961SNatalie.Li@Sun.COM /* 14897961SNatalie.Li@Sun.COM * Load the shares contained in the specified group. 14907961SNatalie.Li@Sun.COM * 14917961SNatalie.Li@Sun.COM * Don't process groups on which the smb protocol is disabled. 14927961SNatalie.Li@Sun.COM * The top level ZFS group won't have the smb protocol enabled 14937961SNatalie.Li@Sun.COM * but sub-groups will. 14947961SNatalie.Li@Sun.COM * 14957961SNatalie.Li@Sun.COM * We will tolerate a limited number of errors and then give 14967961SNatalie.Li@Sun.COM * up on the current group. A typical error might be that the 14977961SNatalie.Li@Sun.COM * shared directory no longer exists. 14987961SNatalie.Li@Sun.COM */ 14997961SNatalie.Li@Sun.COM static void 15007961SNatalie.Li@Sun.COM smb_shr_sa_loadgrp(sa_group_t group) 15017961SNatalie.Li@Sun.COM { 15027961SNatalie.Li@Sun.COM sa_share_t share; 15037961SNatalie.Li@Sun.COM sa_resource_t resource; 15047961SNatalie.Li@Sun.COM int error_count = 0; 15057961SNatalie.Li@Sun.COM 15067961SNatalie.Li@Sun.COM if (sa_get_optionset(group, SMB_PROTOCOL_NAME) == NULL) 15077961SNatalie.Li@Sun.COM return; 15087961SNatalie.Li@Sun.COM 15097961SNatalie.Li@Sun.COM for (share = sa_get_share(group, NULL); 15107961SNatalie.Li@Sun.COM share != NULL; 15117961SNatalie.Li@Sun.COM share = sa_get_next_share(share)) { 15127961SNatalie.Li@Sun.COM for (resource = sa_get_share_resource(share, NULL); 15137961SNatalie.Li@Sun.COM resource != NULL; 15147961SNatalie.Li@Sun.COM resource = sa_get_next_resource(resource)) { 15157961SNatalie.Li@Sun.COM if (smb_shr_sa_load(share, resource)) 15167961SNatalie.Li@Sun.COM ++error_count; 15177961SNatalie.Li@Sun.COM 15187961SNatalie.Li@Sun.COM if (error_count > SMB_SHR_ERROR_THRESHOLD) 15197961SNatalie.Li@Sun.COM break; 15207961SNatalie.Li@Sun.COM } 15217961SNatalie.Li@Sun.COM 15227961SNatalie.Li@Sun.COM if (error_count > SMB_SHR_ERROR_THRESHOLD) 15237961SNatalie.Li@Sun.COM break; 15247961SNatalie.Li@Sun.COM } 15257961SNatalie.Li@Sun.COM } 15267961SNatalie.Li@Sun.COM 15277961SNatalie.Li@Sun.COM /* 15287961SNatalie.Li@Sun.COM * Load a share definition from sharemgr and add it to the cache. 15298334SJose.Borrego@Sun.COM * If the share is already in the cache then it doesn't do anything. 15308334SJose.Borrego@Sun.COM * 15318334SJose.Borrego@Sun.COM * This function does not report duplicate shares as error since 15328334SJose.Borrego@Sun.COM * a share might have been added by smb_shr_get() while load is 15338334SJose.Borrego@Sun.COM * in progress. 15347961SNatalie.Li@Sun.COM */ 15357348SJose.Borrego@Sun.COM static uint32_t 15367961SNatalie.Li@Sun.COM smb_shr_sa_load(sa_share_t share, sa_resource_t resource) 15377961SNatalie.Li@Sun.COM { 15387961SNatalie.Li@Sun.COM smb_share_t si; 15398334SJose.Borrego@Sun.COM char *sharename; 15407961SNatalie.Li@Sun.COM uint32_t status; 15418334SJose.Borrego@Sun.COM boolean_t loaded; 15428334SJose.Borrego@Sun.COM 15438334SJose.Borrego@Sun.COM if ((sharename = sa_get_resource_attr(resource, "name")) == NULL) 15448334SJose.Borrego@Sun.COM return (NERR_InternalError); 15458334SJose.Borrego@Sun.COM 15468334SJose.Borrego@Sun.COM loaded = smb_shr_exists(sharename); 15478334SJose.Borrego@Sun.COM sa_free_attr_string(sharename); 15488334SJose.Borrego@Sun.COM 15498334SJose.Borrego@Sun.COM if (loaded) 15508334SJose.Borrego@Sun.COM return (NERR_Success); 15517961SNatalie.Li@Sun.COM 15527961SNatalie.Li@Sun.COM if ((status = smb_shr_sa_get(share, resource, &si)) != NERR_Success) { 15537961SNatalie.Li@Sun.COM syslog(LOG_DEBUG, "share: failed to load %s (%d)", 15547961SNatalie.Li@Sun.COM si.shr_name, status); 15557961SNatalie.Li@Sun.COM return (status); 15567961SNatalie.Li@Sun.COM } 15577961SNatalie.Li@Sun.COM 15588334SJose.Borrego@Sun.COM status = smb_shr_add(&si); 15598334SJose.Borrego@Sun.COM if ((status != NERR_Success) && (status != NERR_DuplicateShare)) { 15607961SNatalie.Li@Sun.COM syslog(LOG_DEBUG, "share: failed to cache %s (%d)", 15617961SNatalie.Li@Sun.COM si.shr_name, status); 15627961SNatalie.Li@Sun.COM return (status); 15637961SNatalie.Li@Sun.COM } 15647961SNatalie.Li@Sun.COM 156511963SAfshin.Ardakani@Sun.COM if ((si.shr_flags & SMB_SHRF_DFSROOT) != 0) 156611963SAfshin.Ardakani@Sun.COM dfs_namespace_load(si.shr_name); 156711963SAfshin.Ardakani@Sun.COM 15687961SNatalie.Li@Sun.COM return (NERR_Success); 15697961SNatalie.Li@Sun.COM } 15707961SNatalie.Li@Sun.COM 157111963SAfshin.Ardakani@Sun.COM static char * 157211963SAfshin.Ardakani@Sun.COM smb_shr_sa_getprop(sa_optionset_t opts, char *propname) 157311963SAfshin.Ardakani@Sun.COM { 157411963SAfshin.Ardakani@Sun.COM sa_property_t prop; 157511963SAfshin.Ardakani@Sun.COM char *val = NULL; 157611963SAfshin.Ardakani@Sun.COM 157711963SAfshin.Ardakani@Sun.COM prop = sa_get_property(opts, propname); 157811963SAfshin.Ardakani@Sun.COM if (prop != NULL) 157911963SAfshin.Ardakani@Sun.COM val = sa_get_property_attr(prop, "value"); 158011963SAfshin.Ardakani@Sun.COM 158111963SAfshin.Ardakani@Sun.COM return (val); 158211963SAfshin.Ardakani@Sun.COM } 158311963SAfshin.Ardakani@Sun.COM 15847961SNatalie.Li@Sun.COM /* 15857961SNatalie.Li@Sun.COM * Read the specified share information from sharemgr and return 15867961SNatalie.Li@Sun.COM * it in the given smb_share_t structure. 15877961SNatalie.Li@Sun.COM * 15887961SNatalie.Li@Sun.COM * Shares read from sharemgr are marked as permanent/persistent. 15897961SNatalie.Li@Sun.COM */ 15907961SNatalie.Li@Sun.COM static uint32_t 15917961SNatalie.Li@Sun.COM smb_shr_sa_get(sa_share_t share, sa_resource_t resource, smb_share_t *si) 15927348SJose.Borrego@Sun.COM { 15937348SJose.Borrego@Sun.COM sa_optionset_t opts; 15947348SJose.Borrego@Sun.COM char *val = NULL; 15957348SJose.Borrego@Sun.COM char *path; 15967348SJose.Borrego@Sun.COM char *rname; 15977348SJose.Borrego@Sun.COM 15987348SJose.Borrego@Sun.COM if ((path = sa_get_share_attr(share, "path")) == NULL) 15997348SJose.Borrego@Sun.COM return (NERR_InternalError); 16007348SJose.Borrego@Sun.COM 16017348SJose.Borrego@Sun.COM if ((rname = sa_get_resource_attr(resource, "name")) == NULL) { 16027348SJose.Borrego@Sun.COM sa_free_attr_string(path); 16037348SJose.Borrego@Sun.COM return (NERR_InternalError); 16047348SJose.Borrego@Sun.COM } 16057348SJose.Borrego@Sun.COM 16067348SJose.Borrego@Sun.COM bzero(si, sizeof (smb_share_t)); 16077348SJose.Borrego@Sun.COM si->shr_flags = SMB_SHRF_PERM; 16087348SJose.Borrego@Sun.COM 16097348SJose.Borrego@Sun.COM (void) strlcpy(si->shr_path, path, sizeof (si->shr_path)); 16107348SJose.Borrego@Sun.COM (void) strlcpy(si->shr_name, rname, sizeof (si->shr_name)); 16117348SJose.Borrego@Sun.COM sa_free_attr_string(path); 16127348SJose.Borrego@Sun.COM sa_free_attr_string(rname); 16137348SJose.Borrego@Sun.COM 16147348SJose.Borrego@Sun.COM val = sa_get_resource_description(resource); 16157348SJose.Borrego@Sun.COM if (val == NULL) 16167348SJose.Borrego@Sun.COM val = sa_get_share_description(share); 16177348SJose.Borrego@Sun.COM 16187348SJose.Borrego@Sun.COM if (val != NULL) { 16197348SJose.Borrego@Sun.COM (void) strlcpy(si->shr_cmnt, val, sizeof (si->shr_cmnt)); 16207348SJose.Borrego@Sun.COM sa_free_share_description(val); 16217348SJose.Borrego@Sun.COM } 16227348SJose.Borrego@Sun.COM 16237348SJose.Borrego@Sun.COM opts = sa_get_derived_optionset(resource, SMB_PROTOCOL_NAME, 1); 16247348SJose.Borrego@Sun.COM if (opts == NULL) 16257348SJose.Borrego@Sun.COM return (NERR_Success); 16267348SJose.Borrego@Sun.COM 162711963SAfshin.Ardakani@Sun.COM val = smb_shr_sa_getprop(opts, SHOPT_AD_CONTAINER); 162811963SAfshin.Ardakani@Sun.COM if (val != NULL) { 162911963SAfshin.Ardakani@Sun.COM (void) strlcpy(si->shr_container, val, 163011963SAfshin.Ardakani@Sun.COM sizeof (si->shr_container)); 163111963SAfshin.Ardakani@Sun.COM free(val); 16327348SJose.Borrego@Sun.COM } 16337348SJose.Borrego@Sun.COM 163411963SAfshin.Ardakani@Sun.COM val = smb_shr_sa_getprop(opts, SHOPT_CATIA); 163511963SAfshin.Ardakani@Sun.COM if (val != NULL) { 163611963SAfshin.Ardakani@Sun.COM smb_shr_sa_setflag(val, si, SMB_SHRF_CATIA); 163711963SAfshin.Ardakani@Sun.COM free(val); 16389231SAfshin.Ardakani@Sun.COM } 16399231SAfshin.Ardakani@Sun.COM 164011963SAfshin.Ardakani@Sun.COM val = smb_shr_sa_getprop(opts, SHOPT_ABE); 164111963SAfshin.Ardakani@Sun.COM if (val != NULL) { 164211963SAfshin.Ardakani@Sun.COM smb_shr_sa_setflag(val, si, SMB_SHRF_ABE); 164311963SAfshin.Ardakani@Sun.COM free(val); 164410504SKeyur.Desai@Sun.COM } 164510504SKeyur.Desai@Sun.COM 164611963SAfshin.Ardakani@Sun.COM val = smb_shr_sa_getprop(opts, SHOPT_GUEST); 164711963SAfshin.Ardakani@Sun.COM if (val != NULL) { 164811963SAfshin.Ardakani@Sun.COM smb_shr_sa_setflag(val, si, SMB_SHRF_GUEST_OK); 164911963SAfshin.Ardakani@Sun.COM free(val); 16508334SJose.Borrego@Sun.COM } 16518334SJose.Borrego@Sun.COM 165211963SAfshin.Ardakani@Sun.COM val = smb_shr_sa_getprop(opts, SHOPT_DFSROOT); 165311963SAfshin.Ardakani@Sun.COM if (val != NULL) { 165411963SAfshin.Ardakani@Sun.COM smb_shr_sa_setflag(val, si, SMB_SHRF_DFSROOT); 165511963SAfshin.Ardakani@Sun.COM free(val); 16569832Samw@Sun.COM } 16579832Samw@Sun.COM 165811963SAfshin.Ardakani@Sun.COM val = smb_shr_sa_getprop(opts, SHOPT_CSC); 165911963SAfshin.Ardakani@Sun.COM if (val != NULL) { 166011963SAfshin.Ardakani@Sun.COM smb_shr_sa_csc_option(val, si); 166111963SAfshin.Ardakani@Sun.COM free(val); 16627348SJose.Borrego@Sun.COM } 16637348SJose.Borrego@Sun.COM 166411963SAfshin.Ardakani@Sun.COM val = smb_shr_sa_getprop(opts, SHOPT_NONE); 166511963SAfshin.Ardakani@Sun.COM if (val != NULL) { 166611963SAfshin.Ardakani@Sun.COM (void) strlcpy(si->shr_access_none, val, 166711963SAfshin.Ardakani@Sun.COM sizeof (si->shr_access_none)); 166811963SAfshin.Ardakani@Sun.COM free(val); 166911963SAfshin.Ardakani@Sun.COM si->shr_flags |= SMB_SHRF_ACC_NONE; 16707348SJose.Borrego@Sun.COM } 16717348SJose.Borrego@Sun.COM 167211963SAfshin.Ardakani@Sun.COM val = smb_shr_sa_getprop(opts, SHOPT_RO); 167311963SAfshin.Ardakani@Sun.COM if (val != NULL) { 167411963SAfshin.Ardakani@Sun.COM (void) strlcpy(si->shr_access_ro, val, 167511963SAfshin.Ardakani@Sun.COM sizeof (si->shr_access_ro)); 167611963SAfshin.Ardakani@Sun.COM free(val); 167711963SAfshin.Ardakani@Sun.COM si->shr_flags |= SMB_SHRF_ACC_RO; 167811963SAfshin.Ardakani@Sun.COM } 167911963SAfshin.Ardakani@Sun.COM 168011963SAfshin.Ardakani@Sun.COM val = smb_shr_sa_getprop(opts, SHOPT_RW); 168111963SAfshin.Ardakani@Sun.COM if (val != NULL) { 168211963SAfshin.Ardakani@Sun.COM (void) strlcpy(si->shr_access_rw, val, 168311963SAfshin.Ardakani@Sun.COM sizeof (si->shr_access_rw)); 168411963SAfshin.Ardakani@Sun.COM free(val); 168511963SAfshin.Ardakani@Sun.COM si->shr_flags |= SMB_SHRF_ACC_RW; 16867961SNatalie.Li@Sun.COM } 16877961SNatalie.Li@Sun.COM 16887961SNatalie.Li@Sun.COM sa_free_derived_optionset(opts); 16897961SNatalie.Li@Sun.COM return (NERR_Success); 16907348SJose.Borrego@Sun.COM } 16917348SJose.Borrego@Sun.COM 16927348SJose.Borrego@Sun.COM /* 16938334SJose.Borrego@Sun.COM * Map a client-side caching (CSC) option to the appropriate share 16948334SJose.Borrego@Sun.COM * flag. Only one option is allowed; an error will be logged if 16958334SJose.Borrego@Sun.COM * multiple options have been specified. We don't need to do anything 16968334SJose.Borrego@Sun.COM * about multiple values here because the SRVSVC will not recognize 16978334SJose.Borrego@Sun.COM * a value containing multiple flags and will return the default value. 16988334SJose.Borrego@Sun.COM * 16998334SJose.Borrego@Sun.COM * If the option value is not recognized, it will be ignored: invalid 17008334SJose.Borrego@Sun.COM * values will typically be caught and rejected by sharemgr. 17018334SJose.Borrego@Sun.COM */ 17028474SJose.Borrego@Sun.COM void 17038334SJose.Borrego@Sun.COM smb_shr_sa_csc_option(const char *value, smb_share_t *si) 17048334SJose.Borrego@Sun.COM { 17058334SJose.Borrego@Sun.COM int i; 17068334SJose.Borrego@Sun.COM 17078334SJose.Borrego@Sun.COM for (i = 0; i < (sizeof (cscopt) / sizeof (cscopt[0])); ++i) { 17088334SJose.Borrego@Sun.COM if (strcasecmp(value, cscopt[i].value) == 0) { 17098334SJose.Borrego@Sun.COM si->shr_flags |= cscopt[i].flag; 17108334SJose.Borrego@Sun.COM break; 17118334SJose.Borrego@Sun.COM } 17128334SJose.Borrego@Sun.COM } 17138334SJose.Borrego@Sun.COM 17148334SJose.Borrego@Sun.COM switch (si->shr_flags & SMB_SHRF_CSC_MASK) { 17158334SJose.Borrego@Sun.COM case 0: 17168334SJose.Borrego@Sun.COM case SMB_SHRF_CSC_DISABLED: 17178334SJose.Borrego@Sun.COM case SMB_SHRF_CSC_MANUAL: 17188334SJose.Borrego@Sun.COM case SMB_SHRF_CSC_AUTO: 17198334SJose.Borrego@Sun.COM case SMB_SHRF_CSC_VDO: 17208334SJose.Borrego@Sun.COM break; 17218334SJose.Borrego@Sun.COM 17228334SJose.Borrego@Sun.COM default: 17238474SJose.Borrego@Sun.COM syslog(LOG_INFO, "csc option conflict: 0x%08x", 17248474SJose.Borrego@Sun.COM si->shr_flags & SMB_SHRF_CSC_MASK); 17258334SJose.Borrego@Sun.COM break; 17268334SJose.Borrego@Sun.COM } 17278334SJose.Borrego@Sun.COM } 17288334SJose.Borrego@Sun.COM 17298334SJose.Borrego@Sun.COM /* 17309832Samw@Sun.COM * Return the option name for the first CSC flag (there should be only 17319832Samw@Sun.COM * one) encountered in the share flags. 17329832Samw@Sun.COM */ 17339832Samw@Sun.COM char * 17349832Samw@Sun.COM smb_shr_sa_csc_name(const smb_share_t *si) 17359832Samw@Sun.COM { 17369832Samw@Sun.COM int i; 17379832Samw@Sun.COM 17389832Samw@Sun.COM for (i = 0; i < (sizeof (cscopt) / sizeof (cscopt[0])); ++i) { 17399832Samw@Sun.COM if (si->shr_flags & cscopt[i].flag) 17409832Samw@Sun.COM return (cscopt[i].value); 17419832Samw@Sun.COM } 17429832Samw@Sun.COM 17439832Samw@Sun.COM return (NULL); 17449832Samw@Sun.COM } 17459832Samw@Sun.COM 17469832Samw@Sun.COM /* 174711963SAfshin.Ardakani@Sun.COM * Takes the value of a boolean share property and set/clear the 174811963SAfshin.Ardakani@Sun.COM * specified flag based on the property's value. 174910504SKeyur.Desai@Sun.COM */ 175010504SKeyur.Desai@Sun.COM void 175111963SAfshin.Ardakani@Sun.COM smb_shr_sa_setflag(const char *value, smb_share_t *si, uint32_t flag) 175210504SKeyur.Desai@Sun.COM { 175311963SAfshin.Ardakani@Sun.COM if ((strcasecmp(value, "true") == 0) || (strcmp(value, "1") == 0)) 175411963SAfshin.Ardakani@Sun.COM si->shr_flags |= flag; 175511963SAfshin.Ardakani@Sun.COM else 175611963SAfshin.Ardakani@Sun.COM si->shr_flags &= ~flag; 17579832Samw@Sun.COM } 17589832Samw@Sun.COM 17599832Samw@Sun.COM /* 17608334SJose.Borrego@Sun.COM * looks up sharemgr for the given share (resource) and loads 17618334SJose.Borrego@Sun.COM * the definition into cache if lookup is successful 17628334SJose.Borrego@Sun.COM */ 17638334SJose.Borrego@Sun.COM static uint32_t 17648334SJose.Borrego@Sun.COM smb_shr_sa_loadbyname(char *sharename) 17658334SJose.Borrego@Sun.COM { 17668334SJose.Borrego@Sun.COM sa_handle_t handle; 17678334SJose.Borrego@Sun.COM sa_share_t share; 17688334SJose.Borrego@Sun.COM sa_resource_t resource; 17698334SJose.Borrego@Sun.COM uint32_t status; 17708334SJose.Borrego@Sun.COM 17718474SJose.Borrego@Sun.COM if ((handle = smb_shr_sa_enter()) == NULL) 17728334SJose.Borrego@Sun.COM return (NERR_InternalError); 17738334SJose.Borrego@Sun.COM 17748334SJose.Borrego@Sun.COM resource = sa_find_resource(handle, sharename); 17758334SJose.Borrego@Sun.COM if (resource == NULL) { 17768474SJose.Borrego@Sun.COM smb_shr_sa_exit(); 17778334SJose.Borrego@Sun.COM return (NERR_NetNameNotFound); 17788334SJose.Borrego@Sun.COM } 17798334SJose.Borrego@Sun.COM 17808334SJose.Borrego@Sun.COM share = sa_get_resource_parent(resource); 17818334SJose.Borrego@Sun.COM if (share == NULL) { 17828474SJose.Borrego@Sun.COM smb_shr_sa_exit(); 17838334SJose.Borrego@Sun.COM return (NERR_InternalError); 17848334SJose.Borrego@Sun.COM } 17858334SJose.Borrego@Sun.COM 17868334SJose.Borrego@Sun.COM status = smb_shr_sa_load(share, resource); 17878334SJose.Borrego@Sun.COM 17888474SJose.Borrego@Sun.COM smb_shr_sa_exit(); 17898334SJose.Borrego@Sun.COM return (status); 17908334SJose.Borrego@Sun.COM } 17918334SJose.Borrego@Sun.COM 17928334SJose.Borrego@Sun.COM /* 17937348SJose.Borrego@Sun.COM * ============================================ 17947348SJose.Borrego@Sun.COM * Share publishing functions 17957961SNatalie.Li@Sun.COM * 17967961SNatalie.Li@Sun.COM * All the functions are private 17977348SJose.Borrego@Sun.COM * ============================================ 17987348SJose.Borrego@Sun.COM */ 17997348SJose.Borrego@Sun.COM 18007961SNatalie.Li@Sun.COM static void 18017961SNatalie.Li@Sun.COM smb_shr_publish(const char *sharename, const char *container) 18027961SNatalie.Li@Sun.COM { 18037961SNatalie.Li@Sun.COM smb_shr_publisher_queue(sharename, container, SMB_SHR_PUBLISH); 18047961SNatalie.Li@Sun.COM } 18057961SNatalie.Li@Sun.COM 18067961SNatalie.Li@Sun.COM static void 18077961SNatalie.Li@Sun.COM smb_shr_unpublish(const char *sharename, const char *container) 18087961SNatalie.Li@Sun.COM { 18097961SNatalie.Li@Sun.COM smb_shr_publisher_queue(sharename, container, SMB_SHR_UNPUBLISH); 18107961SNatalie.Li@Sun.COM } 18117961SNatalie.Li@Sun.COM 18127348SJose.Borrego@Sun.COM /* 18137961SNatalie.Li@Sun.COM * In domain mode, put a share on the publisher queue. 18147961SNatalie.Li@Sun.COM * This is a no-op if the smb service is in Workgroup mode. 18157348SJose.Borrego@Sun.COM */ 18167348SJose.Borrego@Sun.COM static void 18177961SNatalie.Li@Sun.COM smb_shr_publisher_queue(const char *sharename, const char *container, char op) 18187348SJose.Borrego@Sun.COM { 18197348SJose.Borrego@Sun.COM smb_shr_pitem_t *item = NULL; 18207348SJose.Borrego@Sun.COM 18217348SJose.Borrego@Sun.COM if (container == NULL || *container == '\0') 18227348SJose.Borrego@Sun.COM return; 18237348SJose.Borrego@Sun.COM 18247961SNatalie.Li@Sun.COM if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN) 18257961SNatalie.Li@Sun.COM return; 18267961SNatalie.Li@Sun.COM 18277348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 18287348SJose.Borrego@Sun.COM switch (ad_queue.spq_state) { 18297348SJose.Borrego@Sun.COM case SMB_SHR_PQS_READY: 18307348SJose.Borrego@Sun.COM case SMB_SHR_PQS_PUBLISHING: 18317348SJose.Borrego@Sun.COM break; 18327348SJose.Borrego@Sun.COM default: 18337348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 18347348SJose.Borrego@Sun.COM return; 18357348SJose.Borrego@Sun.COM } 18367348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 18377348SJose.Borrego@Sun.COM 18387961SNatalie.Li@Sun.COM if ((item = malloc(sizeof (smb_shr_pitem_t))) == NULL) 18397348SJose.Borrego@Sun.COM return; 18407348SJose.Borrego@Sun.COM 18417348SJose.Borrego@Sun.COM item->spi_op = op; 18427348SJose.Borrego@Sun.COM (void) strlcpy(item->spi_name, sharename, sizeof (item->spi_name)); 18437348SJose.Borrego@Sun.COM (void) strlcpy(item->spi_container, container, 18447348SJose.Borrego@Sun.COM sizeof (item->spi_container)); 18457348SJose.Borrego@Sun.COM 18467348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 18477348SJose.Borrego@Sun.COM list_insert_tail(&ad_queue.spq_list, item); 18487348SJose.Borrego@Sun.COM (void) cond_signal(&ad_queue.spq_cv); 18497348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 18507348SJose.Borrego@Sun.COM } 18517348SJose.Borrego@Sun.COM 18527961SNatalie.Li@Sun.COM /* 18537961SNatalie.Li@Sun.COM * Publishing won't be activated if the smb service is running in 18547961SNatalie.Li@Sun.COM * Workgroup mode. 18557961SNatalie.Li@Sun.COM */ 18567348SJose.Borrego@Sun.COM static int 18577348SJose.Borrego@Sun.COM smb_shr_publisher_start(void) 18587348SJose.Borrego@Sun.COM { 18597961SNatalie.Li@Sun.COM pthread_t publish_thr; 18607348SJose.Borrego@Sun.COM pthread_attr_t tattr; 18617348SJose.Borrego@Sun.COM int rc; 18627348SJose.Borrego@Sun.COM 18637961SNatalie.Li@Sun.COM if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN) 18647961SNatalie.Li@Sun.COM return (0); 18657961SNatalie.Li@Sun.COM 18667348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 18677348SJose.Borrego@Sun.COM if (ad_queue.spq_state != SMB_SHR_PQS_NOQUEUE) { 18687348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 18697348SJose.Borrego@Sun.COM errno = EINVAL; 18707348SJose.Borrego@Sun.COM return (-1); 18717348SJose.Borrego@Sun.COM } 18727348SJose.Borrego@Sun.COM 18737348SJose.Borrego@Sun.COM list_create(&ad_queue.spq_list, sizeof (smb_shr_pitem_t), 18747348SJose.Borrego@Sun.COM offsetof(smb_shr_pitem_t, spi_lnd)); 18757348SJose.Borrego@Sun.COM ad_queue.spq_state = SMB_SHR_PQS_READY; 18767348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 18777348SJose.Borrego@Sun.COM 18787348SJose.Borrego@Sun.COM (void) pthread_attr_init(&tattr); 18797348SJose.Borrego@Sun.COM (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); 18807961SNatalie.Li@Sun.COM rc = pthread_create(&publish_thr, &tattr, smb_shr_publisher, 0); 18817348SJose.Borrego@Sun.COM (void) pthread_attr_destroy(&tattr); 18827348SJose.Borrego@Sun.COM 18837348SJose.Borrego@Sun.COM return (rc); 18847348SJose.Borrego@Sun.COM } 18857348SJose.Borrego@Sun.COM 18867348SJose.Borrego@Sun.COM static void 18877348SJose.Borrego@Sun.COM smb_shr_publisher_stop(void) 18887348SJose.Borrego@Sun.COM { 18897961SNatalie.Li@Sun.COM if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN) 18907961SNatalie.Li@Sun.COM return; 18917961SNatalie.Li@Sun.COM 18927348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 18937348SJose.Borrego@Sun.COM switch (ad_queue.spq_state) { 18947348SJose.Borrego@Sun.COM case SMB_SHR_PQS_READY: 18957348SJose.Borrego@Sun.COM case SMB_SHR_PQS_PUBLISHING: 18967348SJose.Borrego@Sun.COM ad_queue.spq_state = SMB_SHR_PQS_STOPPING; 18977348SJose.Borrego@Sun.COM (void) cond_signal(&ad_queue.spq_cv); 18987348SJose.Borrego@Sun.COM break; 18997348SJose.Borrego@Sun.COM default: 19007348SJose.Borrego@Sun.COM break; 19017348SJose.Borrego@Sun.COM } 19027348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 19037348SJose.Borrego@Sun.COM } 19047348SJose.Borrego@Sun.COM 19057348SJose.Borrego@Sun.COM /* 19067961SNatalie.Li@Sun.COM * This is the publisher daemon thread. While running, the thread waits 19077961SNatalie.Li@Sun.COM * on a conditional variable until notified that a share needs to be 19087961SNatalie.Li@Sun.COM * [un]published or that the thread should be terminated. 19097961SNatalie.Li@Sun.COM * 19107961SNatalie.Li@Sun.COM * Entries may remain in the outgoing queue if the Active Directory 19117961SNatalie.Li@Sun.COM * service is inaccessible, in which case the thread wakes up every 60 19127961SNatalie.Li@Sun.COM * seconds to retry. 19137348SJose.Borrego@Sun.COM */ 19147348SJose.Borrego@Sun.COM /*ARGSUSED*/ 19157348SJose.Borrego@Sun.COM static void * 19167348SJose.Borrego@Sun.COM smb_shr_publisher(void *arg) 19177348SJose.Borrego@Sun.COM { 19187348SJose.Borrego@Sun.COM smb_ads_handle_t *ah; 19197348SJose.Borrego@Sun.COM smb_shr_pitem_t *shr; 19207348SJose.Borrego@Sun.COM list_t publist; 19217961SNatalie.Li@Sun.COM timestruc_t pubretry; 19227348SJose.Borrego@Sun.COM char hostname[MAXHOSTNAMELEN]; 19237348SJose.Borrego@Sun.COM 19247348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 19257961SNatalie.Li@Sun.COM if (ad_queue.spq_state != SMB_SHR_PQS_READY) { 19267348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 19277348SJose.Borrego@Sun.COM return (NULL); 19287348SJose.Borrego@Sun.COM } 19297961SNatalie.Li@Sun.COM ad_queue.spq_state = SMB_SHR_PQS_PUBLISHING; 19307348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 19317348SJose.Borrego@Sun.COM 193211963SAfshin.Ardakani@Sun.COM (void) smb_gethostname(hostname, MAXHOSTNAMELEN, 193311963SAfshin.Ardakani@Sun.COM SMB_CASE_PRESERVE); 19347961SNatalie.Li@Sun.COM 19357348SJose.Borrego@Sun.COM list_create(&publist, sizeof (smb_shr_pitem_t), 19367348SJose.Borrego@Sun.COM offsetof(smb_shr_pitem_t, spi_lnd)); 19377348SJose.Borrego@Sun.COM 19387348SJose.Borrego@Sun.COM for (;;) { 19397348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 19407961SNatalie.Li@Sun.COM 19417961SNatalie.Li@Sun.COM while (list_is_empty(&ad_queue.spq_list) && 19427961SNatalie.Li@Sun.COM (ad_queue.spq_state == SMB_SHR_PQS_PUBLISHING)) { 19437961SNatalie.Li@Sun.COM if (list_is_empty(&publist)) { 19447961SNatalie.Li@Sun.COM (void) cond_wait(&ad_queue.spq_cv, 19457961SNatalie.Li@Sun.COM &ad_queue.spq_mtx); 19467961SNatalie.Li@Sun.COM } else { 19477961SNatalie.Li@Sun.COM pubretry.tv_sec = 60; 19487961SNatalie.Li@Sun.COM pubretry.tv_nsec = 0; 19497961SNatalie.Li@Sun.COM (void) cond_reltimedwait(&ad_queue.spq_cv, 19507961SNatalie.Li@Sun.COM &ad_queue.spq_mtx, &pubretry); 19517961SNatalie.Li@Sun.COM break; 19527961SNatalie.Li@Sun.COM } 19537961SNatalie.Li@Sun.COM } 19547348SJose.Borrego@Sun.COM 19557348SJose.Borrego@Sun.COM if (ad_queue.spq_state != SMB_SHR_PQS_PUBLISHING) { 19567348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 19577348SJose.Borrego@Sun.COM break; 19587348SJose.Borrego@Sun.COM } 19597348SJose.Borrego@Sun.COM 19607348SJose.Borrego@Sun.COM /* 19617961SNatalie.Li@Sun.COM * Transfer queued items to the local list so that 19627961SNatalie.Li@Sun.COM * the mutex can be released. 19637348SJose.Borrego@Sun.COM */ 19647348SJose.Borrego@Sun.COM while ((shr = list_head(&ad_queue.spq_list)) != NULL) { 19657348SJose.Borrego@Sun.COM list_remove(&ad_queue.spq_list, shr); 19667348SJose.Borrego@Sun.COM list_insert_tail(&publist, shr); 19677348SJose.Borrego@Sun.COM } 19687961SNatalie.Li@Sun.COM 19697348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 19707348SJose.Borrego@Sun.COM 19717961SNatalie.Li@Sun.COM if ((ah = smb_ads_open()) != NULL) { 19727961SNatalie.Li@Sun.COM smb_shr_publisher_send(ah, &publist, hostname); 19737961SNatalie.Li@Sun.COM smb_ads_close(ah); 19747961SNatalie.Li@Sun.COM } 19757348SJose.Borrego@Sun.COM } 19767348SJose.Borrego@Sun.COM 19777348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 19787961SNatalie.Li@Sun.COM smb_shr_publisher_flush(&ad_queue.spq_list); 19797348SJose.Borrego@Sun.COM list_destroy(&ad_queue.spq_list); 19807348SJose.Borrego@Sun.COM ad_queue.spq_state = SMB_SHR_PQS_NOQUEUE; 19817348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 19827348SJose.Borrego@Sun.COM 19837961SNatalie.Li@Sun.COM smb_shr_publisher_flush(&publist); 19847348SJose.Borrego@Sun.COM list_destroy(&publist); 19857348SJose.Borrego@Sun.COM return (NULL); 19867348SJose.Borrego@Sun.COM } 19877348SJose.Borrego@Sun.COM 19887348SJose.Borrego@Sun.COM /* 19897961SNatalie.Li@Sun.COM * Remove items from the specified queue and [un]publish them. 19907348SJose.Borrego@Sun.COM */ 19917348SJose.Borrego@Sun.COM static void 19927348SJose.Borrego@Sun.COM smb_shr_publisher_send(smb_ads_handle_t *ah, list_t *publist, const char *host) 19937348SJose.Borrego@Sun.COM { 19947348SJose.Borrego@Sun.COM smb_shr_pitem_t *shr; 19957348SJose.Borrego@Sun.COM 19967348SJose.Borrego@Sun.COM while ((shr = list_head(publist)) != NULL) { 19977961SNatalie.Li@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 19987961SNatalie.Li@Sun.COM if (ad_queue.spq_state != SMB_SHR_PQS_PUBLISHING) { 19997348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 20007961SNatalie.Li@Sun.COM return; 20017961SNatalie.Li@Sun.COM } 20027961SNatalie.Li@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 20037348SJose.Borrego@Sun.COM 20047961SNatalie.Li@Sun.COM list_remove(publist, shr); 20057961SNatalie.Li@Sun.COM 20067961SNatalie.Li@Sun.COM if (shr->spi_op == SMB_SHR_PUBLISH) 20077961SNatalie.Li@Sun.COM (void) smb_ads_publish_share(ah, shr->spi_name, 20087961SNatalie.Li@Sun.COM NULL, shr->spi_container, host); 20097961SNatalie.Li@Sun.COM else 20107961SNatalie.Li@Sun.COM (void) smb_ads_remove_share(ah, shr->spi_name, 20117961SNatalie.Li@Sun.COM NULL, shr->spi_container, host); 20127961SNatalie.Li@Sun.COM 20137348SJose.Borrego@Sun.COM free(shr); 20147348SJose.Borrego@Sun.COM } 20157348SJose.Borrego@Sun.COM } 20167961SNatalie.Li@Sun.COM 20177961SNatalie.Li@Sun.COM /* 20187961SNatalie.Li@Sun.COM * Flush all remaining items from the specified list/queue. 20197961SNatalie.Li@Sun.COM */ 20207961SNatalie.Li@Sun.COM static void 20217961SNatalie.Li@Sun.COM smb_shr_publisher_flush(list_t *lst) 20227961SNatalie.Li@Sun.COM { 20237961SNatalie.Li@Sun.COM smb_shr_pitem_t *shr; 20247961SNatalie.Li@Sun.COM 20257961SNatalie.Li@Sun.COM while ((shr = list_head(lst)) != NULL) { 20267961SNatalie.Li@Sun.COM list_remove(lst, shr); 20277961SNatalie.Li@Sun.COM free(shr); 20287961SNatalie.Li@Sun.COM } 20297961SNatalie.Li@Sun.COM } 20308845Samw@Sun.COM 20318845Samw@Sun.COM /* 20328871Samw@Sun.COM * If the share path refers to a ZFS file system, add the 203311963SAfshin.Ardakani@Sun.COM * .zfs/shares/<share> object and call smb_quota_add_fs() 203411963SAfshin.Ardakani@Sun.COM * to initialize quota support for the share. 20358845Samw@Sun.COM */ 20368845Samw@Sun.COM static void 20378845Samw@Sun.COM smb_shr_zfs_add(smb_share_t *si) 20388845Samw@Sun.COM { 20398871Samw@Sun.COM libzfs_handle_t *libhd; 20408871Samw@Sun.COM zfs_handle_t *zfshd; 20418871Samw@Sun.COM int ret; 204211963SAfshin.Ardakani@Sun.COM char buf[MAXPATHLEN]; /* dataset or mountpoint */ 20438845Samw@Sun.COM 204411963SAfshin.Ardakani@Sun.COM if (smb_getdataset(si->shr_path, buf, MAXPATHLEN) != 0) 20458871Samw@Sun.COM return; 20468871Samw@Sun.COM 20478871Samw@Sun.COM if ((libhd = libzfs_init()) == NULL) 20488871Samw@Sun.COM return; 20498871Samw@Sun.COM 205011963SAfshin.Ardakani@Sun.COM if ((zfshd = zfs_open(libhd, buf, ZFS_TYPE_FILESYSTEM)) == NULL) { 20518871Samw@Sun.COM libzfs_fini(libhd); 20528871Samw@Sun.COM return; 20538845Samw@Sun.COM } 20548871Samw@Sun.COM 20558871Samw@Sun.COM errno = 0; 205611963SAfshin.Ardakani@Sun.COM ret = zfs_smb_acl_add(libhd, buf, si->shr_path, si->shr_name); 20578871Samw@Sun.COM if (ret != 0 && errno != EAGAIN && errno != EEXIST) 20588871Samw@Sun.COM syslog(LOG_INFO, "share: failed to add ACL object: %s: %s\n", 20598871Samw@Sun.COM si->shr_name, strerror(errno)); 20608871Samw@Sun.COM 206111963SAfshin.Ardakani@Sun.COM if (zfs_prop_get(zfshd, ZFS_PROP_MOUNTPOINT, buf, MAXPATHLEN, 206211963SAfshin.Ardakani@Sun.COM NULL, NULL, 0, B_FALSE) == 0) { 206311963SAfshin.Ardakani@Sun.COM smb_quota_add_fs(buf); 206411963SAfshin.Ardakani@Sun.COM } 206511963SAfshin.Ardakani@Sun.COM 206611963SAfshin.Ardakani@Sun.COM 20678871Samw@Sun.COM zfs_close(zfshd); 20688871Samw@Sun.COM libzfs_fini(libhd); 20698845Samw@Sun.COM } 20708845Samw@Sun.COM 20718845Samw@Sun.COM /* 20728871Samw@Sun.COM * If the share path refers to a ZFS file system, remove the 207311963SAfshin.Ardakani@Sun.COM * .zfs/shares/<share> object, and call smb_quota_remove_fs() 207411963SAfshin.Ardakani@Sun.COM * to end quota support for the share. 20758845Samw@Sun.COM */ 20768845Samw@Sun.COM static void 20778845Samw@Sun.COM smb_shr_zfs_remove(smb_share_t *si) 20788845Samw@Sun.COM { 20798871Samw@Sun.COM libzfs_handle_t *libhd; 20808871Samw@Sun.COM zfs_handle_t *zfshd; 20818871Samw@Sun.COM int ret; 208211963SAfshin.Ardakani@Sun.COM char buf[MAXPATHLEN]; /* dataset or mountpoint */ 20838845Samw@Sun.COM 208411963SAfshin.Ardakani@Sun.COM if (smb_getdataset(si->shr_path, buf, MAXPATHLEN) != 0) 20858871Samw@Sun.COM return; 20868871Samw@Sun.COM 20878871Samw@Sun.COM if ((libhd = libzfs_init()) == NULL) 20888871Samw@Sun.COM return; 20898871Samw@Sun.COM 209011963SAfshin.Ardakani@Sun.COM if ((zfshd = zfs_open(libhd, buf, ZFS_TYPE_FILESYSTEM)) == NULL) { 20918871Samw@Sun.COM libzfs_fini(libhd); 20928871Samw@Sun.COM return; 20938845Samw@Sun.COM } 20948871Samw@Sun.COM 20958871Samw@Sun.COM errno = 0; 209611963SAfshin.Ardakani@Sun.COM ret = zfs_smb_acl_remove(libhd, buf, si->shr_path, si->shr_name); 20978871Samw@Sun.COM if (ret != 0 && errno != EAGAIN) 20988871Samw@Sun.COM syslog(LOG_INFO, "share: failed to remove ACL object: %s: %s\n", 20998871Samw@Sun.COM si->shr_name, strerror(errno)); 21008871Samw@Sun.COM 210111963SAfshin.Ardakani@Sun.COM if (zfs_prop_get(zfshd, ZFS_PROP_MOUNTPOINT, buf, MAXPATHLEN, 210211963SAfshin.Ardakani@Sun.COM NULL, NULL, 0, B_FALSE) == 0) { 210311963SAfshin.Ardakani@Sun.COM smb_quota_remove_fs(buf); 210411963SAfshin.Ardakani@Sun.COM } 210511963SAfshin.Ardakani@Sun.COM 21068871Samw@Sun.COM zfs_close(zfshd); 21078871Samw@Sun.COM libzfs_fini(libhd); 21088845Samw@Sun.COM } 21098845Samw@Sun.COM 21108845Samw@Sun.COM /* 21118871Samw@Sun.COM * If the share path refers to a ZFS file system, rename the 21128845Samw@Sun.COM * .zfs/shares/<share> object. 21138845Samw@Sun.COM */ 21148845Samw@Sun.COM static void 21158845Samw@Sun.COM smb_shr_zfs_rename(smb_share_t *from, smb_share_t *to) 21168845Samw@Sun.COM { 21178871Samw@Sun.COM libzfs_handle_t *libhd; 21188871Samw@Sun.COM zfs_handle_t *zfshd; 21198871Samw@Sun.COM int ret; 21208845Samw@Sun.COM char dataset[MAXPATHLEN]; 21218845Samw@Sun.COM 21228871Samw@Sun.COM if (smb_getdataset(from->shr_path, dataset, MAXPATHLEN) != 0) 21238871Samw@Sun.COM return; 21248871Samw@Sun.COM 21258871Samw@Sun.COM if ((libhd = libzfs_init()) == NULL) 21268871Samw@Sun.COM return; 21278871Samw@Sun.COM 21288871Samw@Sun.COM if ((zfshd = zfs_open(libhd, dataset, ZFS_TYPE_FILESYSTEM)) == NULL) { 21298871Samw@Sun.COM libzfs_fini(libhd); 21308871Samw@Sun.COM return; 21318845Samw@Sun.COM } 21328871Samw@Sun.COM 21338871Samw@Sun.COM errno = 0; 21348871Samw@Sun.COM ret = zfs_smb_acl_rename(libhd, dataset, from->shr_path, 21358871Samw@Sun.COM from->shr_name, to->shr_name); 21368871Samw@Sun.COM if (ret != 0 && errno != EAGAIN) 21378871Samw@Sun.COM syslog(LOG_INFO, "share: failed to rename ACL object: %s: %s\n", 21388871Samw@Sun.COM from->shr_name, strerror(errno)); 21398871Samw@Sun.COM 21408871Samw@Sun.COM zfs_close(zfshd); 21418871Samw@Sun.COM libzfs_fini(libhd); 21428845Samw@Sun.COM } 21439832Samw@Sun.COM 21449832Samw@Sun.COM /* 21459832Samw@Sun.COM * Enable all privileges in the inheritable set to execute command. 21469832Samw@Sun.COM */ 21479832Samw@Sun.COM static int 21489832Samw@Sun.COM smb_shr_enable_all_privs(void) 21499832Samw@Sun.COM { 21509832Samw@Sun.COM priv_set_t *pset; 21519832Samw@Sun.COM 21529832Samw@Sun.COM pset = priv_allocset(); 21539832Samw@Sun.COM if (pset == NULL) 21549832Samw@Sun.COM return (-1); 21559832Samw@Sun.COM 21569832Samw@Sun.COM if (getppriv(PRIV_LIMIT, pset)) { 21579832Samw@Sun.COM priv_freeset(pset); 21589832Samw@Sun.COM return (-1); 21599832Samw@Sun.COM } 21609832Samw@Sun.COM 21619832Samw@Sun.COM if (setppriv(PRIV_ON, PRIV_INHERITABLE, pset)) { 21629832Samw@Sun.COM priv_freeset(pset); 21639832Samw@Sun.COM return (-1); 21649832Samw@Sun.COM } 21659832Samw@Sun.COM 21669832Samw@Sun.COM priv_freeset(pset); 21679832Samw@Sun.COM return (0); 21689832Samw@Sun.COM } 21699832Samw@Sun.COM 21709832Samw@Sun.COM /* 21719832Samw@Sun.COM * Tokenizes the command string and returns the list of tokens in an array. 21729832Samw@Sun.COM * 21739832Samw@Sun.COM * Returns NULL if there are no tokens. 21749832Samw@Sun.COM */ 21759832Samw@Sun.COM static char ** 21769832Samw@Sun.COM smb_shr_tokenize_cmd(char *cmdstr) 21779832Samw@Sun.COM { 21789832Samw@Sun.COM char *cmd, *buf, *bp, *value; 21799832Samw@Sun.COM char **argv, **ap; 21809832Samw@Sun.COM int argc, i; 21819832Samw@Sun.COM 21829832Samw@Sun.COM if (cmdstr == NULL || *cmdstr == '\0') 21839832Samw@Sun.COM return (NULL); 21849832Samw@Sun.COM 21859832Samw@Sun.COM if ((buf = malloc(MAXPATHLEN)) == NULL) 21869832Samw@Sun.COM return (NULL); 21879832Samw@Sun.COM 21889832Samw@Sun.COM (void) strlcpy(buf, cmdstr, MAXPATHLEN); 21899832Samw@Sun.COM 21909832Samw@Sun.COM for (argc = 2, bp = cmdstr; *bp != '\0'; ++bp) 21919832Samw@Sun.COM if (*bp == ' ') 21929832Samw@Sun.COM ++argc; 21939832Samw@Sun.COM 21949832Samw@Sun.COM if ((argv = calloc(argc, sizeof (char *))) == NULL) { 21959832Samw@Sun.COM free(buf); 21969832Samw@Sun.COM return (NULL); 21979832Samw@Sun.COM } 21989832Samw@Sun.COM 21999832Samw@Sun.COM ap = argv; 22009832Samw@Sun.COM for (bp = buf, i = 0; i < argc; ++i) { 22019832Samw@Sun.COM do { 22029832Samw@Sun.COM if ((value = strsep(&bp, " ")) == NULL) 22039832Samw@Sun.COM break; 22049832Samw@Sun.COM } while (*value == '\0'); 22059832Samw@Sun.COM 22069832Samw@Sun.COM if (value == NULL) 22079832Samw@Sun.COM break; 22089832Samw@Sun.COM 22099832Samw@Sun.COM *ap++ = value; 22109832Samw@Sun.COM } 22119832Samw@Sun.COM 22129832Samw@Sun.COM /* get the filename of the command from the path */ 22139832Samw@Sun.COM if ((cmd = strrchr(argv[0], '/')) != NULL) 22149832Samw@Sun.COM (void) strlcpy(argv[0], ++cmd, strlen(argv[0])); 22159832Samw@Sun.COM 22169832Samw@Sun.COM return (argv); 22179832Samw@Sun.COM } 22189832Samw@Sun.COM 22199832Samw@Sun.COM /* 22209832Samw@Sun.COM * Expands the command string for the following substitution tokens: 22219832Samw@Sun.COM * 22229832Samw@Sun.COM * %U - Windows username 22239832Samw@Sun.COM * %D - Name of the domain or workgroup of %U 22249832Samw@Sun.COM * %h - The server hostname 22259832Samw@Sun.COM * %M - The client hostname 22269832Samw@Sun.COM * %L - The server NetBIOS name 22279832Samw@Sun.COM * %m - The client NetBIOS name. This option is only valid for NetBIOS 22289832Samw@Sun.COM * connections (port 139). 22299832Samw@Sun.COM * %I - The IP address of the client machine 22309832Samw@Sun.COM * %i - The local IP address to which the client is connected 22319832Samw@Sun.COM * %S - The name of the share 22329832Samw@Sun.COM * %P - The root directory of the share 22339832Samw@Sun.COM * %u - The UID of the Unix user 22349832Samw@Sun.COM * 22359832Samw@Sun.COM * Returns 0 on success. Otherwise -1. 22369832Samw@Sun.COM */ 22379832Samw@Sun.COM static int 2238*12508Samw@Sun.COM smb_shr_expand_subs(char **cmd_toks, smb_share_t *si, smb_shr_execinfo_t *subs) 22399832Samw@Sun.COM { 22409832Samw@Sun.COM char *fmt, *sub_chr, *ptr; 22419832Samw@Sun.COM boolean_t unknown; 22429832Samw@Sun.COM char hostname[MAXHOSTNAMELEN]; 22439832Samw@Sun.COM char ip_str[INET6_ADDRSTRLEN]; 22449832Samw@Sun.COM char name[SMB_PI_MAX_HOST]; 224510966SJordan.Brown@Sun.COM smb_wchar_t wbuf[SMB_PI_MAX_HOST]; 22469832Samw@Sun.COM int i; 22479832Samw@Sun.COM 22489832Samw@Sun.COM if (cmd_toks == NULL || *cmd_toks == NULL) 22499832Samw@Sun.COM return (-1); 22509832Samw@Sun.COM 22519832Samw@Sun.COM for (i = 1; cmd_toks[i]; i++) { 22529832Samw@Sun.COM fmt = cmd_toks[i]; 22539832Samw@Sun.COM if (*fmt == '%') { 22549832Samw@Sun.COM sub_chr = fmt + 1; 22559832Samw@Sun.COM unknown = B_FALSE; 22569832Samw@Sun.COM 22579832Samw@Sun.COM switch (*sub_chr) { 22589832Samw@Sun.COM case 'U': 22599832Samw@Sun.COM ptr = strdup(subs->e_winname); 22609832Samw@Sun.COM break; 22619832Samw@Sun.COM case 'D': 22629832Samw@Sun.COM ptr = strdup(subs->e_userdom); 22639832Samw@Sun.COM break; 22649832Samw@Sun.COM case 'h': 22659832Samw@Sun.COM if (gethostname(hostname, MAXHOSTNAMELEN) != 0) 22669832Samw@Sun.COM unknown = B_TRUE; 22679832Samw@Sun.COM else 22689832Samw@Sun.COM ptr = strdup(hostname); 22699832Samw@Sun.COM break; 22709832Samw@Sun.COM case 'M': 22719832Samw@Sun.COM if (smb_getnameinfo(&subs->e_cli_ipaddr, 22729832Samw@Sun.COM hostname, sizeof (hostname), 0) != 0) 22739832Samw@Sun.COM unknown = B_TRUE; 22749832Samw@Sun.COM else 22759832Samw@Sun.COM ptr = strdup(hostname); 22769832Samw@Sun.COM break; 22779832Samw@Sun.COM case 'L': 22789832Samw@Sun.COM if (smb_getnetbiosname(hostname, 22799832Samw@Sun.COM NETBIOS_NAME_SZ) != 0) 22809832Samw@Sun.COM unknown = B_TRUE; 22819832Samw@Sun.COM else 22829832Samw@Sun.COM ptr = strdup(hostname); 22839832Samw@Sun.COM break; 22849832Samw@Sun.COM case 'm': 22859832Samw@Sun.COM if (*subs->e_cli_netbiosname == '\0') 22869832Samw@Sun.COM unknown = B_TRUE; 22879832Samw@Sun.COM else { 228810966SJordan.Brown@Sun.COM (void) smb_mbstowcs(wbuf, 22899832Samw@Sun.COM subs->e_cli_netbiosname, 22909832Samw@Sun.COM SMB_PI_MAX_HOST - 1); 22919832Samw@Sun.COM 229210966SJordan.Brown@Sun.COM if (ucstooem(name, wbuf, 229310966SJordan.Brown@Sun.COM SMB_PI_MAX_HOST, OEM_CPG_850) == 0) 22949832Samw@Sun.COM (void) strlcpy(name, 22959832Samw@Sun.COM subs->e_cli_netbiosname, 22969832Samw@Sun.COM SMB_PI_MAX_HOST); 22979832Samw@Sun.COM 22989832Samw@Sun.COM ptr = strdup(name); 22999832Samw@Sun.COM } 23009832Samw@Sun.COM break; 23019832Samw@Sun.COM case 'I': 23029832Samw@Sun.COM if (smb_inet_ntop(&subs->e_cli_ipaddr, ip_str, 23039832Samw@Sun.COM SMB_IPSTRLEN(subs->e_cli_ipaddr.a_family)) 23049832Samw@Sun.COM != NULL) 23059832Samw@Sun.COM ptr = strdup(ip_str); 23069832Samw@Sun.COM else 23079832Samw@Sun.COM unknown = B_TRUE; 23089832Samw@Sun.COM break; 23099832Samw@Sun.COM case 'i': 23109832Samw@Sun.COM if (smb_inet_ntop(&subs->e_srv_ipaddr, ip_str, 23119832Samw@Sun.COM SMB_IPSTRLEN(subs->e_srv_ipaddr.a_family)) 23129832Samw@Sun.COM != NULL) 23139832Samw@Sun.COM ptr = strdup(ip_str); 23149832Samw@Sun.COM else 23159832Samw@Sun.COM unknown = B_TRUE; 23169832Samw@Sun.COM break; 23179832Samw@Sun.COM case 'S': 23189832Samw@Sun.COM ptr = strdup(si->shr_name); 23199832Samw@Sun.COM break; 23209832Samw@Sun.COM case 'P': 23219832Samw@Sun.COM ptr = strdup(si->shr_path); 23229832Samw@Sun.COM break; 23239832Samw@Sun.COM case 'u': 23249832Samw@Sun.COM (void) snprintf(name, sizeof (name), "%u", 23259832Samw@Sun.COM subs->e_uid); 23269832Samw@Sun.COM ptr = strdup(name); 23279832Samw@Sun.COM break; 23289832Samw@Sun.COM default: 23299832Samw@Sun.COM /* unknown sub char */ 23309832Samw@Sun.COM unknown = B_TRUE; 23319832Samw@Sun.COM break; 23329832Samw@Sun.COM } 23339832Samw@Sun.COM 23349832Samw@Sun.COM if (unknown) 23359832Samw@Sun.COM ptr = strdup(""); 23369832Samw@Sun.COM 23379832Samw@Sun.COM } else /* first char of cmd's arg is not '%' char */ 23389832Samw@Sun.COM ptr = strdup(""); 23399832Samw@Sun.COM 23409832Samw@Sun.COM cmd_toks[i] = ptr; 23419832Samw@Sun.COM 23429832Samw@Sun.COM if (ptr == NULL) { 23439832Samw@Sun.COM for (i = 1; cmd_toks[i]; i++) 23449832Samw@Sun.COM free(cmd_toks[i]); 23459832Samw@Sun.COM 23469832Samw@Sun.COM return (-1); 23479832Samw@Sun.COM } 23489832Samw@Sun.COM } 23499832Samw@Sun.COM 23509832Samw@Sun.COM return (0); 23519832Samw@Sun.COM } 23529832Samw@Sun.COM 23539832Samw@Sun.COM /*ARGSUSED*/ 23549832Samw@Sun.COM static void 23559832Samw@Sun.COM smb_shr_sig_abnormal_term(int sig_val) 23569832Samw@Sun.COM { 23579832Samw@Sun.COM /* 23589832Samw@Sun.COM * Calling _exit() prevents parent process from getting SIGTERM/SIGINT 23599832Samw@Sun.COM * signal. 23609832Samw@Sun.COM */ 23619832Samw@Sun.COM _exit(-1); 23629832Samw@Sun.COM } 23639832Samw@Sun.COM 23649832Samw@Sun.COM /*ARGSUSED*/ 23659832Samw@Sun.COM static void 23669832Samw@Sun.COM smb_shr_sig_child(int sig_val) 23679832Samw@Sun.COM { 23689832Samw@Sun.COM /* 23699832Samw@Sun.COM * Catch the signal and allow the exit status of the child process 23709832Samw@Sun.COM * to be available for reaping. 23719832Samw@Sun.COM */ 23729832Samw@Sun.COM } 23739832Samw@Sun.COM 23749832Samw@Sun.COM /* 2375*12508Samw@Sun.COM * This is a temporary function which converts the given smb_share_t 2376*12508Samw@Sun.COM * structure to the nvlist format that will be provided by libsharev2 23779832Samw@Sun.COM */ 2378*12508Samw@Sun.COM static int 2379*12508Samw@Sun.COM smb_shr_encode(smb_share_t *si, nvlist_t **nvlist) 23809832Samw@Sun.COM { 2381*12508Samw@Sun.COM nvlist_t *list; 2382*12508Samw@Sun.COM nvlist_t *share; 2383*12508Samw@Sun.COM nvlist_t *smb; 2384*12508Samw@Sun.COM char *csc; 2385*12508Samw@Sun.COM int rc = 0; 2386*12508Samw@Sun.COM 2387*12508Samw@Sun.COM *nvlist = NULL; 23889832Samw@Sun.COM 2389*12508Samw@Sun.COM if ((rc = nvlist_alloc(&list, NV_UNIQUE_NAME, 0)) != 0) 2390*12508Samw@Sun.COM return (rc); 23919832Samw@Sun.COM 2392*12508Samw@Sun.COM if ((rc = nvlist_alloc(&share, NV_UNIQUE_NAME, 0)) != 0) { 2393*12508Samw@Sun.COM nvlist_free(list); 2394*12508Samw@Sun.COM return (rc); 2395*12508Samw@Sun.COM } 23969832Samw@Sun.COM 2397*12508Samw@Sun.COM if ((rc = nvlist_alloc(&smb, NV_UNIQUE_NAME, 0)) != 0) { 2398*12508Samw@Sun.COM nvlist_free(share); 2399*12508Samw@Sun.COM nvlist_free(list); 2400*12508Samw@Sun.COM return (rc); 2401*12508Samw@Sun.COM } 2402*12508Samw@Sun.COM 2403*12508Samw@Sun.COM /* global share properties */ 2404*12508Samw@Sun.COM rc |= nvlist_add_string(share, "name", si->shr_name); 2405*12508Samw@Sun.COM rc |= nvlist_add_string(share, "path", si->shr_path); 2406*12508Samw@Sun.COM rc |= nvlist_add_string(share, "desc", si->shr_cmnt); 24079832Samw@Sun.COM 2408*12508Samw@Sun.COM /* smb protocol properties */ 2409*12508Samw@Sun.COM rc = nvlist_add_string(smb, SHOPT_AD_CONTAINER, si->shr_container); 2410*12508Samw@Sun.COM if ((si->shr_flags & SMB_SHRF_ACC_NONE) != 0) 2411*12508Samw@Sun.COM rc |= nvlist_add_string(smb, SHOPT_NONE, si->shr_access_none); 2412*12508Samw@Sun.COM if ((si->shr_flags & SMB_SHRF_ACC_RO) != 0) 2413*12508Samw@Sun.COM rc |= nvlist_add_string(smb, SHOPT_RO, si->shr_access_ro); 2414*12508Samw@Sun.COM if ((si->shr_flags & SMB_SHRF_ACC_RW) != 0) 2415*12508Samw@Sun.COM rc |= nvlist_add_string(smb, SHOPT_RW, si->shr_access_rw); 24169832Samw@Sun.COM 2417*12508Samw@Sun.COM if ((si->shr_flags & SMB_SHRF_ABE) != 0) 2418*12508Samw@Sun.COM rc |= nvlist_add_string(smb, SHOPT_ABE, "true"); 2419*12508Samw@Sun.COM if ((si->shr_flags & SMB_SHRF_CATIA) != 0) 2420*12508Samw@Sun.COM rc |= nvlist_add_string(smb, SHOPT_CATIA, "true"); 2421*12508Samw@Sun.COM if ((si->shr_flags & SMB_SHRF_GUEST_OK) != 0) 2422*12508Samw@Sun.COM rc |= nvlist_add_string(smb, SHOPT_GUEST, "true"); 2423*12508Samw@Sun.COM if ((si->shr_flags & SMB_SHRF_DFSROOT) != 0) 2424*12508Samw@Sun.COM rc |= nvlist_add_string(smb, SHOPT_DFSROOT, "true"); 24259832Samw@Sun.COM 2426*12508Samw@Sun.COM if ((si->shr_flags & SMB_SHRF_AUTOHOME) != 0) { 2427*12508Samw@Sun.COM rc |= nvlist_add_string(smb, "Autohome", "true"); 2428*12508Samw@Sun.COM rc |= nvlist_add_uint32(smb, "uid", si->shr_uid); 2429*12508Samw@Sun.COM rc |= nvlist_add_uint32(smb, "gid", si->shr_gid); 2430*12508Samw@Sun.COM } 2431*12508Samw@Sun.COM 2432*12508Samw@Sun.COM if ((csc = smb_shr_sa_csc_name(si)) != NULL) 2433*12508Samw@Sun.COM rc |= nvlist_add_string(smb, SHOPT_CSC, csc); 24349832Samw@Sun.COM 2435*12508Samw@Sun.COM rc |= nvlist_add_nvlist(share, "smb", smb); 2436*12508Samw@Sun.COM rc |= nvlist_add_nvlist(list, si->shr_name, share); 2437*12508Samw@Sun.COM 2438*12508Samw@Sun.COM nvlist_free(share); 2439*12508Samw@Sun.COM nvlist_free(smb); 2440*12508Samw@Sun.COM 2441*12508Samw@Sun.COM if (rc != 0) 2442*12508Samw@Sun.COM nvlist_free(list); 2443*12508Samw@Sun.COM else 2444*12508Samw@Sun.COM *nvlist = list; 2445*12508Samw@Sun.COM 2446*12508Samw@Sun.COM return (rc); 24479832Samw@Sun.COM } 2448