17052Samw /* 27052Samw * CDDL HEADER START 37052Samw * 47052Samw * The contents of this file are subject to the terms of the 57052Samw * Common Development and Distribution License (the "License"). 67052Samw * You may not use this file except in compliance with the License. 77052Samw * 87052Samw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97052Samw * or http://www.opensolaris.org/os/licensing. 107052Samw * See the License for the specific language governing permissions 117052Samw * and limitations under the License. 127052Samw * 137052Samw * When distributing Covered Code, include this CDDL HEADER in each 147052Samw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157052Samw * If applicable, add the following below this CDDL HEADER, with the 167052Samw * fields enclosed by brackets "[]" replaced with your own identifying 177052Samw * information: Portions Copyright [yyyy] [name of copyright owner] 187052Samw * 197052Samw * CDDL HEADER END 207052Samw */ 217052Samw /* 228474SJose.Borrego@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 237052Samw * Use is subject to license terms. 247052Samw */ 257052Samw 267052Samw /* 277961SNatalie.Li@Sun.COM * SMB/CIFS share cache implementation. 287052Samw */ 297052Samw 307052Samw #include <errno.h> 317052Samw #include <synch.h> 327052Samw #include <stdlib.h> 337052Samw #include <strings.h> 347052Samw #include <syslog.h> 357052Samw #include <thread.h> 367052Samw #include <pthread.h> 377348SJose.Borrego@Sun.COM #include <assert.h> 387961SNatalie.Li@Sun.COM #include <libshare.h> 398845Samw@Sun.COM #include <libzfs.h> 407052Samw 417052Samw #include <smbsrv/libsmb.h> 427052Samw #include <smbsrv/libsmbns.h> 437588Samw@Sun.COM #include <smbsrv/libmlsvc.h> 447052Samw 457052Samw #include <smbsrv/lm.h> 467052Samw #include <smbsrv/smb_share.h> 477052Samw #include <smbsrv/cifs.h> 487961SNatalie.Li@Sun.COM #include <smbsrv/nterror.h> 497052Samw 507961SNatalie.Li@Sun.COM #define SMB_SHR_ERROR_THRESHOLD 3 517052Samw 528334SJose.Borrego@Sun.COM #define SMB_SHR_CSC_BUFSZ 64 538334SJose.Borrego@Sun.COM 547348SJose.Borrego@Sun.COM /* 557348SJose.Borrego@Sun.COM * Cache functions and vars 567348SJose.Borrego@Sun.COM */ 577961SNatalie.Li@Sun.COM #define SMB_SHR_HTAB_SZ 1024 587052Samw 597961SNatalie.Li@Sun.COM /* 607961SNatalie.Li@Sun.COM * Cache handle 617961SNatalie.Li@Sun.COM * 627961SNatalie.Li@Sun.COM * Shares cache is a hash table. 637961SNatalie.Li@Sun.COM * 647961SNatalie.Li@Sun.COM * sc_cache pointer to hash table handle 657961SNatalie.Li@Sun.COM * sc_cache_lck synchronize cache read/write accesses 667961SNatalie.Li@Sun.COM * sc_state cache state machine values 677961SNatalie.Li@Sun.COM * sc_nops number of inflight/pending cache operations 687961SNatalie.Li@Sun.COM * sc_mtx protects handle fields 697961SNatalie.Li@Sun.COM */ 707961SNatalie.Li@Sun.COM typedef struct smb_shr_cache { 717961SNatalie.Li@Sun.COM HT_HANDLE *sc_cache; 727961SNatalie.Li@Sun.COM rwlock_t sc_cache_lck; 737961SNatalie.Li@Sun.COM mutex_t sc_mtx; 747961SNatalie.Li@Sun.COM cond_t sc_cv; 757961SNatalie.Li@Sun.COM uint32_t sc_state; 767961SNatalie.Li@Sun.COM uint32_t sc_nops; 777961SNatalie.Li@Sun.COM } smb_shr_cache_t; 787961SNatalie.Li@Sun.COM 797961SNatalie.Li@Sun.COM /* 807961SNatalie.Li@Sun.COM * Cache states 817961SNatalie.Li@Sun.COM */ 827961SNatalie.Li@Sun.COM #define SMB_SHR_CACHE_STATE_NONE 0 837961SNatalie.Li@Sun.COM #define SMB_SHR_CACHE_STATE_CREATED 1 847961SNatalie.Li@Sun.COM #define SMB_SHR_CACHE_STATE_DESTROYING 2 857961SNatalie.Li@Sun.COM 867961SNatalie.Li@Sun.COM /* 877961SNatalie.Li@Sun.COM * Cache lock modes 887961SNatalie.Li@Sun.COM */ 897961SNatalie.Li@Sun.COM #define SMB_SHR_CACHE_RDLOCK 0 907961SNatalie.Li@Sun.COM #define SMB_SHR_CACHE_WRLOCK 1 917961SNatalie.Li@Sun.COM 927961SNatalie.Li@Sun.COM static smb_shr_cache_t smb_shr_cache; 937052Samw 947052Samw static uint32_t smb_shr_cache_create(void); 957348SJose.Borrego@Sun.COM static void smb_shr_cache_destroy(void); 967961SNatalie.Li@Sun.COM static uint32_t smb_shr_cache_lock(int); 977961SNatalie.Li@Sun.COM static void smb_shr_cache_unlock(void); 987961SNatalie.Li@Sun.COM static int smb_shr_cache_count(void); 997961SNatalie.Li@Sun.COM static smb_share_t *smb_shr_cache_iterate(smb_shriter_t *); 1007961SNatalie.Li@Sun.COM 1017961SNatalie.Li@Sun.COM static smb_share_t *smb_shr_cache_findent(char *); 1027348SJose.Borrego@Sun.COM static uint32_t smb_shr_cache_addent(smb_share_t *); 1037348SJose.Borrego@Sun.COM static void smb_shr_cache_delent(char *); 1047348SJose.Borrego@Sun.COM static void smb_shr_cache_freent(HT_ITEM *); 1057052Samw 1067348SJose.Borrego@Sun.COM /* 1077348SJose.Borrego@Sun.COM * sharemgr functions 1087348SJose.Borrego@Sun.COM */ 1097961SNatalie.Li@Sun.COM static void *smb_shr_sa_loadall(void *); 1107961SNatalie.Li@Sun.COM static void smb_shr_sa_loadgrp(sa_group_t); 1117961SNatalie.Li@Sun.COM static uint32_t smb_shr_sa_load(sa_share_t, sa_resource_t); 1128334SJose.Borrego@Sun.COM static uint32_t smb_shr_sa_loadbyname(char *); 1137961SNatalie.Li@Sun.COM static uint32_t smb_shr_sa_get(sa_share_t, sa_resource_t, smb_share_t *); 1147052Samw 1157052Samw /* 1168845Samw@Sun.COM * .ZFS management functions 1178845Samw@Sun.COM */ 1188845Samw@Sun.COM static void smb_shr_zfs_add(smb_share_t *); 1198845Samw@Sun.COM static void smb_shr_zfs_remove(smb_share_t *); 1208845Samw@Sun.COM static void smb_shr_zfs_rename(smb_share_t *, smb_share_t *); 1218845Samw@Sun.COM 1228845Samw@Sun.COM /* 1237348SJose.Borrego@Sun.COM * share publishing 1247348SJose.Borrego@Sun.COM */ 1257348SJose.Borrego@Sun.COM #define SMB_SHR_PUBLISH 0 1267348SJose.Borrego@Sun.COM #define SMB_SHR_UNPUBLISH 1 1277348SJose.Borrego@Sun.COM 1287348SJose.Borrego@Sun.COM typedef struct smb_shr_pitem { 1297348SJose.Borrego@Sun.COM list_node_t spi_lnd; 1307348SJose.Borrego@Sun.COM char spi_name[MAXNAMELEN]; 1317348SJose.Borrego@Sun.COM char spi_container[MAXPATHLEN]; 1327348SJose.Borrego@Sun.COM char spi_op; 1337348SJose.Borrego@Sun.COM } smb_shr_pitem_t; 1347348SJose.Borrego@Sun.COM 1357348SJose.Borrego@Sun.COM /* 1367348SJose.Borrego@Sun.COM * publish queue states 1377348SJose.Borrego@Sun.COM */ 1387348SJose.Borrego@Sun.COM #define SMB_SHR_PQS_NOQUEUE 0 1397348SJose.Borrego@Sun.COM #define SMB_SHR_PQS_READY 1 /* the queue is ready */ 1407348SJose.Borrego@Sun.COM #define SMB_SHR_PQS_PUBLISHING 2 /* publisher thread is running */ 1417348SJose.Borrego@Sun.COM #define SMB_SHR_PQS_STOPPING 3 1427348SJose.Borrego@Sun.COM 1437348SJose.Borrego@Sun.COM /* 1447348SJose.Borrego@Sun.COM * share publishing queue 1457348SJose.Borrego@Sun.COM */ 1467348SJose.Borrego@Sun.COM typedef struct smb_shr_pqueue { 1477348SJose.Borrego@Sun.COM list_t spq_list; 1487348SJose.Borrego@Sun.COM mutex_t spq_mtx; 1497348SJose.Borrego@Sun.COM cond_t spq_cv; 1507348SJose.Borrego@Sun.COM uint32_t spq_state; 1517348SJose.Borrego@Sun.COM } smb_shr_pqueue_t; 1527348SJose.Borrego@Sun.COM 1537348SJose.Borrego@Sun.COM static smb_shr_pqueue_t ad_queue; 1547348SJose.Borrego@Sun.COM 1557348SJose.Borrego@Sun.COM static int smb_shr_publisher_start(void); 1567348SJose.Borrego@Sun.COM static void smb_shr_publisher_stop(void); 1577348SJose.Borrego@Sun.COM static void smb_shr_publisher_send(smb_ads_handle_t *, list_t *, const char *); 1587961SNatalie.Li@Sun.COM static void smb_shr_publisher_queue(const char *, const char *, char); 1597348SJose.Borrego@Sun.COM static void *smb_shr_publisher(void *); 1607961SNatalie.Li@Sun.COM static void smb_shr_publisher_flush(list_t *); 1617961SNatalie.Li@Sun.COM static void smb_shr_publish(const char *, const char *); 1627961SNatalie.Li@Sun.COM static void smb_shr_unpublish(const char *, const char *); 1637348SJose.Borrego@Sun.COM 1647348SJose.Borrego@Sun.COM /* 1657961SNatalie.Li@Sun.COM * Utility/helper functions 1667961SNatalie.Li@Sun.COM */ 1678334SJose.Borrego@Sun.COM static uint32_t smb_shr_lookup(char *, smb_share_t *); 1687961SNatalie.Li@Sun.COM static uint32_t smb_shr_addipc(void); 1697961SNatalie.Li@Sun.COM static void smb_shr_set_oemname(smb_share_t *); 1707961SNatalie.Li@Sun.COM 1718474SJose.Borrego@Sun.COM 1728474SJose.Borrego@Sun.COM /* 1738474SJose.Borrego@Sun.COM * libshare handle and synchronization 1748474SJose.Borrego@Sun.COM */ 1758474SJose.Borrego@Sun.COM typedef struct smb_sa_handle { 1768474SJose.Borrego@Sun.COM sa_handle_t sa_handle; 1778474SJose.Borrego@Sun.COM mutex_t sa_mtx; 1788474SJose.Borrego@Sun.COM boolean_t sa_in_service; 1798474SJose.Borrego@Sun.COM } smb_sa_handle_t; 1808474SJose.Borrego@Sun.COM 1818474SJose.Borrego@Sun.COM static smb_sa_handle_t smb_sa_handle; 1828474SJose.Borrego@Sun.COM 1837961SNatalie.Li@Sun.COM /* 1848334SJose.Borrego@Sun.COM * Creates and initializes the cache and starts the publisher 1858334SJose.Borrego@Sun.COM * thread. 1867052Samw */ 1877052Samw int 1887052Samw smb_shr_start(void) 1897052Samw { 1908474SJose.Borrego@Sun.COM (void) mutex_lock(&smb_sa_handle.sa_mtx); 1918474SJose.Borrego@Sun.COM smb_sa_handle.sa_in_service = B_TRUE; 1928474SJose.Borrego@Sun.COM (void) mutex_unlock(&smb_sa_handle.sa_mtx); 1938474SJose.Borrego@Sun.COM 1947961SNatalie.Li@Sun.COM if (smb_shr_cache_create() != NERR_Success) 1957961SNatalie.Li@Sun.COM return (ENOMEM); 1967961SNatalie.Li@Sun.COM 1977961SNatalie.Li@Sun.COM if (smb_shr_addipc() != NERR_Success) 1987961SNatalie.Li@Sun.COM return (ENOMEM); 1997961SNatalie.Li@Sun.COM 2008334SJose.Borrego@Sun.COM return (smb_shr_publisher_start()); 2018334SJose.Borrego@Sun.COM } 2028334SJose.Borrego@Sun.COM 2038334SJose.Borrego@Sun.COM void 2048334SJose.Borrego@Sun.COM smb_shr_stop(void) 2058334SJose.Borrego@Sun.COM { 2068334SJose.Borrego@Sun.COM smb_shr_cache_destroy(); 2078334SJose.Borrego@Sun.COM smb_shr_publisher_stop(); 2088474SJose.Borrego@Sun.COM 2098474SJose.Borrego@Sun.COM (void) mutex_lock(&smb_sa_handle.sa_mtx); 2108474SJose.Borrego@Sun.COM smb_sa_handle.sa_in_service = B_FALSE; 2118474SJose.Borrego@Sun.COM 2128474SJose.Borrego@Sun.COM if (smb_sa_handle.sa_handle != NULL) { 2138474SJose.Borrego@Sun.COM sa_fini(smb_sa_handle.sa_handle); 2148474SJose.Borrego@Sun.COM smb_sa_handle.sa_handle = NULL; 2158474SJose.Borrego@Sun.COM } 2168474SJose.Borrego@Sun.COM 2178474SJose.Borrego@Sun.COM (void) mutex_unlock(&smb_sa_handle.sa_mtx); 2188474SJose.Borrego@Sun.COM } 2198474SJose.Borrego@Sun.COM 2208474SJose.Borrego@Sun.COM /* 2218474SJose.Borrego@Sun.COM * Get a handle and exclusive access to the libshare API. 2228474SJose.Borrego@Sun.COM */ 2238474SJose.Borrego@Sun.COM sa_handle_t 2248474SJose.Borrego@Sun.COM smb_shr_sa_enter(void) 2258474SJose.Borrego@Sun.COM { 2268474SJose.Borrego@Sun.COM (void) mutex_lock(&smb_sa_handle.sa_mtx); 2278474SJose.Borrego@Sun.COM if (!smb_sa_handle.sa_in_service) { 2288474SJose.Borrego@Sun.COM (void) mutex_unlock(&smb_sa_handle.sa_mtx); 2298474SJose.Borrego@Sun.COM return (NULL); 2308474SJose.Borrego@Sun.COM } 2318474SJose.Borrego@Sun.COM 2328474SJose.Borrego@Sun.COM if (smb_sa_handle.sa_handle == NULL) { 2338474SJose.Borrego@Sun.COM smb_sa_handle.sa_handle = sa_init(SA_INIT_SHARE_API); 2348474SJose.Borrego@Sun.COM if (smb_sa_handle.sa_handle == NULL) { 2358474SJose.Borrego@Sun.COM syslog(LOG_ERR, "share: failed to get libshare handle"); 2368474SJose.Borrego@Sun.COM (void) mutex_unlock(&smb_sa_handle.sa_mtx); 2378474SJose.Borrego@Sun.COM return (NULL); 2388474SJose.Borrego@Sun.COM } 2398474SJose.Borrego@Sun.COM } 2408474SJose.Borrego@Sun.COM 2418474SJose.Borrego@Sun.COM return (smb_sa_handle.sa_handle); 2428474SJose.Borrego@Sun.COM } 2438474SJose.Borrego@Sun.COM 2448474SJose.Borrego@Sun.COM /* 2458474SJose.Borrego@Sun.COM * Release exclusive access to the libshare API. 2468474SJose.Borrego@Sun.COM */ 2478474SJose.Borrego@Sun.COM void 2488474SJose.Borrego@Sun.COM smb_shr_sa_exit(void) 2498474SJose.Borrego@Sun.COM { 2508474SJose.Borrego@Sun.COM (void) mutex_unlock(&smb_sa_handle.sa_mtx); 2518334SJose.Borrego@Sun.COM } 2528334SJose.Borrego@Sun.COM 2538334SJose.Borrego@Sun.COM /* 2548334SJose.Borrego@Sun.COM * Launches a thread to populate the share cache by share information 2558334SJose.Borrego@Sun.COM * stored in sharemgr 2568334SJose.Borrego@Sun.COM */ 2578334SJose.Borrego@Sun.COM int 2588334SJose.Borrego@Sun.COM smb_shr_load(void) 2598334SJose.Borrego@Sun.COM { 2608334SJose.Borrego@Sun.COM pthread_t load_thr; 2618334SJose.Borrego@Sun.COM pthread_attr_t tattr; 2628334SJose.Borrego@Sun.COM int rc; 2638334SJose.Borrego@Sun.COM 2647348SJose.Borrego@Sun.COM (void) pthread_attr_init(&tattr); 2657348SJose.Borrego@Sun.COM (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); 2667961SNatalie.Li@Sun.COM rc = pthread_create(&load_thr, &tattr, smb_shr_sa_loadall, 0); 2677348SJose.Borrego@Sun.COM (void) pthread_attr_destroy(&tattr); 2687052Samw 2697052Samw return (rc); 2707052Samw } 2717052Samw 2727052Samw /* 2737348SJose.Borrego@Sun.COM * Return the total number of shares 2747052Samw */ 2757052Samw int 2767052Samw smb_shr_count(void) 2777052Samw { 2787961SNatalie.Li@Sun.COM int n_shares = 0; 2797052Samw 2807961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) { 2817961SNatalie.Li@Sun.COM n_shares = smb_shr_cache_count(); 2827961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 2837961SNatalie.Li@Sun.COM } 2847052Samw 2857052Samw return (n_shares); 2867052Samw } 2877052Samw 2887052Samw /* 2897052Samw * smb_shr_iterinit 2907052Samw * 2917348SJose.Borrego@Sun.COM * Initialize given iterator for traversing hash table. 2927052Samw */ 2937052Samw void 2947348SJose.Borrego@Sun.COM smb_shr_iterinit(smb_shriter_t *shi) 2957052Samw { 2967052Samw bzero(shi, sizeof (smb_shriter_t)); 2977348SJose.Borrego@Sun.COM shi->si_first = B_TRUE; 2987052Samw } 2997052Samw 3007052Samw /* 3017052Samw * smb_shr_iterate 3027052Samw * 3037052Samw * Iterate on the shares in the hash table. The iterator must be initialized 3047052Samw * before the first iteration. On subsequent calls, the iterator must be 3057052Samw * passed unchanged. 3067052Samw * 3077052Samw * Returns NULL on failure or when all shares are visited, otherwise 3087052Samw * returns information of visited share. 3097052Samw */ 3107052Samw smb_share_t * 3117052Samw smb_shr_iterate(smb_shriter_t *shi) 3127052Samw { 3137348SJose.Borrego@Sun.COM smb_share_t *share = NULL; 3147961SNatalie.Li@Sun.COM smb_share_t *cached_si; 3157052Samw 3167961SNatalie.Li@Sun.COM if (shi == NULL) 3177052Samw return (NULL); 3187052Samw 3197961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) { 3207961SNatalie.Li@Sun.COM if ((cached_si = smb_shr_cache_iterate(shi)) != NULL) { 3217961SNatalie.Li@Sun.COM share = &shi->si_share; 3227961SNatalie.Li@Sun.COM bcopy(cached_si, share, sizeof (smb_share_t)); 3237961SNatalie.Li@Sun.COM } 3247961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 3257052Samw } 3267052Samw 3277348SJose.Borrego@Sun.COM return (share); 3287052Samw } 3297052Samw 3307052Samw /* 3317961SNatalie.Li@Sun.COM * Adds the given share to cache, publishes the share in ADS 3327961SNatalie.Li@Sun.COM * if it has an AD container, calls kernel to take a hold on 3337961SNatalie.Li@Sun.COM * the shared file system. If it can't take a hold on the 3347961SNatalie.Li@Sun.COM * shared file system, it's either because shared directory 3357961SNatalie.Li@Sun.COM * does not exist or some other error has occurred, in any 3367961SNatalie.Li@Sun.COM * case the share is removed from the cache. 3377052Samw * 3387961SNatalie.Li@Sun.COM * If the specified share is an autohome share which already 3397961SNatalie.Li@Sun.COM * exists in the cache, just increments the reference count. 3407052Samw */ 3417052Samw uint32_t 3427961SNatalie.Li@Sun.COM smb_shr_add(smb_share_t *si) 3437052Samw { 3447961SNatalie.Li@Sun.COM smb_share_t *cached_si; 3457961SNatalie.Li@Sun.COM uint32_t status; 3467348SJose.Borrego@Sun.COM int rc; 3477052Samw 3487348SJose.Borrego@Sun.COM assert(si != NULL); 3497052Samw 3507348SJose.Borrego@Sun.COM if (!smb_shr_chkname(si->shr_name)) 3517348SJose.Borrego@Sun.COM return (ERROR_INVALID_NAME); 3527052Samw 3537961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success) 3547961SNatalie.Li@Sun.COM return (NERR_InternalError); 3557052Samw 3567961SNatalie.Li@Sun.COM cached_si = smb_shr_cache_findent(si->shr_name); 3577961SNatalie.Li@Sun.COM if (cached_si) { 3587961SNatalie.Li@Sun.COM if (si->shr_flags & SMB_SHRF_AUTOHOME) { 3597961SNatalie.Li@Sun.COM cached_si->shr_refcnt++; 3607961SNatalie.Li@Sun.COM status = NERR_Success; 3617961SNatalie.Li@Sun.COM } else { 3627961SNatalie.Li@Sun.COM status = NERR_DuplicateShare; 3637961SNatalie.Li@Sun.COM } 3647961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 3657052Samw return (status); 3667052Samw } 3677052Samw 3687961SNatalie.Li@Sun.COM if ((status = smb_shr_cache_addent(si)) != NERR_Success) { 3697961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 3707961SNatalie.Li@Sun.COM return (status); 3717961SNatalie.Li@Sun.COM } 3727961SNatalie.Li@Sun.COM 3737961SNatalie.Li@Sun.COM /* don't hold the lock across door call */ 3747961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 3757961SNatalie.Li@Sun.COM 3767961SNatalie.Li@Sun.COM /* call kernel to take a hold on the shared file system */ 3777588Samw@Sun.COM rc = mlsvc_set_share(SMB_SHROP_ADD, si->shr_path, si->shr_name); 3787348SJose.Borrego@Sun.COM 3797348SJose.Borrego@Sun.COM if (rc == 0) { 3807961SNatalie.Li@Sun.COM smb_shr_publish(si->shr_name, si->shr_container); 3818845Samw@Sun.COM 3828845Samw@Sun.COM /* If path is ZFS, add the .zfs/shares/<share> entry. */ 3838845Samw@Sun.COM smb_shr_zfs_add(si); 3848845Samw@Sun.COM 3857961SNatalie.Li@Sun.COM return (NERR_Success); 3867052Samw } 3877052Samw 3887961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) == NERR_Success) { 3897961SNatalie.Li@Sun.COM smb_shr_cache_delent(si->shr_name); 3907961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 3917961SNatalie.Li@Sun.COM } 3927052Samw 3937052Samw /* 3947348SJose.Borrego@Sun.COM * rc == ENOENT means the shared directory doesn't exist 3957052Samw */ 3967348SJose.Borrego@Sun.COM return ((rc == ENOENT) ? NERR_UnknownDevDir : NERR_InternalError); 3977052Samw } 3987052Samw 3997052Samw /* 4007961SNatalie.Li@Sun.COM * Removes the specified share from cache, removes it from AD 4017961SNatalie.Li@Sun.COM * if it has an AD container, and calls the kernel to release 4027961SNatalie.Li@Sun.COM * the hold on the shared file system. 4037052Samw * 4047961SNatalie.Li@Sun.COM * If this is an autohome share then decrement the reference 4057961SNatalie.Li@Sun.COM * count. If it reaches 0 then it proceeds with removing steps. 4067052Samw */ 4077348SJose.Borrego@Sun.COM uint32_t 4087961SNatalie.Li@Sun.COM smb_shr_remove(char *sharename) 4097052Samw { 4107961SNatalie.Li@Sun.COM smb_share_t *si; 4117961SNatalie.Li@Sun.COM char path[MAXPATHLEN]; 4127961SNatalie.Li@Sun.COM char container[MAXPATHLEN]; 4137348SJose.Borrego@Sun.COM 4147348SJose.Borrego@Sun.COM assert(sharename != NULL); 4157348SJose.Borrego@Sun.COM 4167961SNatalie.Li@Sun.COM if (!smb_shr_chkname(sharename)) 4177961SNatalie.Li@Sun.COM return (ERROR_INVALID_NAME); 4187052Samw 4197961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success) 4207961SNatalie.Li@Sun.COM return (NERR_InternalError); 4217961SNatalie.Li@Sun.COM 4227961SNatalie.Li@Sun.COM if ((si = smb_shr_cache_findent(sharename)) == NULL) { 4237961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 4247961SNatalie.Li@Sun.COM return (NERR_NetNameNotFound); 4257961SNatalie.Li@Sun.COM } 4267348SJose.Borrego@Sun.COM 4277961SNatalie.Li@Sun.COM if (si->shr_type & STYPE_IPC) { 4287961SNatalie.Li@Sun.COM /* IPC$ share cannot be removed */ 4297961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 4307961SNatalie.Li@Sun.COM return (ERROR_ACCESS_DENIED); 4317961SNatalie.Li@Sun.COM } 4327961SNatalie.Li@Sun.COM 4337961SNatalie.Li@Sun.COM if (si->shr_flags & SMB_SHRF_AUTOHOME) { 4347961SNatalie.Li@Sun.COM if ((--si->shr_refcnt) > 0) { 4357961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 4367961SNatalie.Li@Sun.COM return (NERR_Success); 4377348SJose.Borrego@Sun.COM } 4387052Samw } 4397052Samw 4408845Samw@Sun.COM /* 4418845Samw@Sun.COM * If path is ZFS, remove the .zfs/shares/<share> entry. Need 4428845Samw@Sun.COM * to remove before cleanup of cache occurs. 4438845Samw@Sun.COM */ 4448845Samw@Sun.COM smb_shr_zfs_remove(si); 4458845Samw@Sun.COM 4467961SNatalie.Li@Sun.COM (void) strlcpy(path, si->shr_path, sizeof (path)); 4477961SNatalie.Li@Sun.COM (void) strlcpy(container, si->shr_container, sizeof (container)); 4487961SNatalie.Li@Sun.COM smb_shr_cache_delent(sharename); 4497961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 4507348SJose.Borrego@Sun.COM 4517961SNatalie.Li@Sun.COM smb_shr_unpublish(sharename, container); 4527961SNatalie.Li@Sun.COM 4537961SNatalie.Li@Sun.COM /* call kernel to release the hold on the shared file system */ 4547961SNatalie.Li@Sun.COM (void) mlsvc_set_share(SMB_SHROP_DELETE, path, sharename); 4557348SJose.Borrego@Sun.COM 4567052Samw return (NERR_Success); 4577052Samw } 4587052Samw 4597052Samw /* 4607052Samw * Rename a share. Check that the current name exists and the new name 4617052Samw * doesn't exist. The rename is performed by deleting the current share 4627052Samw * definition and creating a new share with the new name. 4637052Samw */ 4647052Samw uint32_t 4657348SJose.Borrego@Sun.COM smb_shr_rename(char *from_name, char *to_name) 4667052Samw { 4677961SNatalie.Li@Sun.COM smb_share_t *from_si; 4687961SNatalie.Li@Sun.COM smb_share_t to_si; 4697348SJose.Borrego@Sun.COM uint32_t status; 4707348SJose.Borrego@Sun.COM 4717348SJose.Borrego@Sun.COM assert((from_name != NULL) && (to_name != NULL)); 4727052Samw 4737348SJose.Borrego@Sun.COM if (!smb_shr_chkname(from_name) || !smb_shr_chkname(to_name)) 4747348SJose.Borrego@Sun.COM return (ERROR_INVALID_NAME); 4757052Samw 4767961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success) 4777961SNatalie.Li@Sun.COM return (NERR_InternalError); 4787961SNatalie.Li@Sun.COM 4797961SNatalie.Li@Sun.COM if ((from_si = smb_shr_cache_findent(from_name)) == NULL) { 4807961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 4817052Samw return (NERR_NetNameNotFound); 4827961SNatalie.Li@Sun.COM } 4837052Samw 4847961SNatalie.Li@Sun.COM if (from_si->shr_type & STYPE_IPC) { 4857961SNatalie.Li@Sun.COM /* IPC$ share cannot be renamed */ 4867961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 4877961SNatalie.Li@Sun.COM return (ERROR_ACCESS_DENIED); 4887961SNatalie.Li@Sun.COM } 4897961SNatalie.Li@Sun.COM 4907961SNatalie.Li@Sun.COM if (smb_shr_cache_findent(to_name) != NULL) { 4917961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 4927052Samw return (NERR_DuplicateShare); 4937961SNatalie.Li@Sun.COM } 4947052Samw 4957961SNatalie.Li@Sun.COM bcopy(from_si, &to_si, sizeof (smb_share_t)); 4967961SNatalie.Li@Sun.COM (void) strlcpy(to_si.shr_name, to_name, sizeof (to_si.shr_name)); 4977961SNatalie.Li@Sun.COM 4988845Samw@Sun.COM /* If path is ZFS, rename the .zfs/shares/<share> entry. */ 4998845Samw@Sun.COM smb_shr_zfs_rename(from_si, &to_si); 5008845Samw@Sun.COM 5017961SNatalie.Li@Sun.COM if ((status = smb_shr_cache_addent(&to_si)) != NERR_Success) { 5027961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 5037348SJose.Borrego@Sun.COM return (status); 5047961SNatalie.Li@Sun.COM } 5057348SJose.Borrego@Sun.COM 5067348SJose.Borrego@Sun.COM smb_shr_cache_delent(from_name); 5077961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 5087961SNatalie.Li@Sun.COM 5097961SNatalie.Li@Sun.COM smb_shr_unpublish(from_name, to_si.shr_container); 5107961SNatalie.Li@Sun.COM smb_shr_publish(to_name, to_si.shr_container); 5117348SJose.Borrego@Sun.COM 5127348SJose.Borrego@Sun.COM return (NERR_Success); 5137348SJose.Borrego@Sun.COM } 5147348SJose.Borrego@Sun.COM 5157348SJose.Borrego@Sun.COM /* 5167348SJose.Borrego@Sun.COM * Load the information for the specified share into the supplied share 5177348SJose.Borrego@Sun.COM * info structure. 5188334SJose.Borrego@Sun.COM * 5198334SJose.Borrego@Sun.COM * First looks up the cache to see if the specified share exists, if there 5208334SJose.Borrego@Sun.COM * is a miss then it looks up sharemgr. 5217348SJose.Borrego@Sun.COM */ 5227348SJose.Borrego@Sun.COM uint32_t 5237348SJose.Borrego@Sun.COM smb_shr_get(char *sharename, smb_share_t *si) 5247348SJose.Borrego@Sun.COM { 5258334SJose.Borrego@Sun.COM uint32_t status; 5267348SJose.Borrego@Sun.COM 5277961SNatalie.Li@Sun.COM if (sharename == NULL || *sharename == '\0') 5287961SNatalie.Li@Sun.COM return (NERR_NetNameNotFound); 5297348SJose.Borrego@Sun.COM 5308334SJose.Borrego@Sun.COM if ((status = smb_shr_lookup(sharename, si)) == NERR_Success) 5318334SJose.Borrego@Sun.COM return (status); 5327961SNatalie.Li@Sun.COM 5338334SJose.Borrego@Sun.COM if ((status = smb_shr_sa_loadbyname(sharename)) == NERR_Success) 5348334SJose.Borrego@Sun.COM status = smb_shr_lookup(sharename, si); 5357348SJose.Borrego@Sun.COM 5367961SNatalie.Li@Sun.COM return (status); 5377348SJose.Borrego@Sun.COM } 5387348SJose.Borrego@Sun.COM 5397348SJose.Borrego@Sun.COM /* 5407348SJose.Borrego@Sun.COM * Modifies an existing share. Properties that can be modified are: 5417348SJose.Borrego@Sun.COM * 5427348SJose.Borrego@Sun.COM * o comment 5437348SJose.Borrego@Sun.COM * o AD container 5447961SNatalie.Li@Sun.COM * o host access 5457348SJose.Borrego@Sun.COM */ 5467348SJose.Borrego@Sun.COM uint32_t 5477961SNatalie.Li@Sun.COM smb_shr_modify(smb_share_t *new_si) 5487348SJose.Borrego@Sun.COM { 5497961SNatalie.Li@Sun.COM smb_share_t *si; 5507348SJose.Borrego@Sun.COM boolean_t adc_changed = B_FALSE; 5517961SNatalie.Li@Sun.COM char old_container[MAXPATHLEN]; 552*9231SAfshin.Ardakani@Sun.COM uint32_t catia; 5538334SJose.Borrego@Sun.COM uint32_t cscopt; 5547961SNatalie.Li@Sun.COM uint32_t access; 5557348SJose.Borrego@Sun.COM 5567961SNatalie.Li@Sun.COM assert(new_si != NULL); 5577348SJose.Borrego@Sun.COM 5587961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success) 5597961SNatalie.Li@Sun.COM return (NERR_InternalError); 5607348SJose.Borrego@Sun.COM 5617961SNatalie.Li@Sun.COM if ((si = smb_shr_cache_findent(new_si->shr_name)) == NULL) { 5627961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 5637961SNatalie.Li@Sun.COM return (NERR_NetNameNotFound); 5647961SNatalie.Li@Sun.COM } 5657348SJose.Borrego@Sun.COM 5667961SNatalie.Li@Sun.COM if (si->shr_type & STYPE_IPC) { 5677961SNatalie.Li@Sun.COM /* IPC$ share cannot be modified */ 5687961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 5697961SNatalie.Li@Sun.COM return (ERROR_ACCESS_DENIED); 5707348SJose.Borrego@Sun.COM } 5717348SJose.Borrego@Sun.COM 5728474SJose.Borrego@Sun.COM (void) strlcpy(si->shr_cmnt, new_si->shr_cmnt, sizeof (si->shr_cmnt)); 5737961SNatalie.Li@Sun.COM 5747961SNatalie.Li@Sun.COM adc_changed = (strcmp(new_si->shr_container, si->shr_container) != 0); 5757961SNatalie.Li@Sun.COM if (adc_changed) { 5767961SNatalie.Li@Sun.COM /* save current container - needed for unpublishing */ 5777961SNatalie.Li@Sun.COM (void) strlcpy(old_container, si->shr_container, 5787961SNatalie.Li@Sun.COM sizeof (old_container)); 5797961SNatalie.Li@Sun.COM (void) strlcpy(si->shr_container, new_si->shr_container, 5807961SNatalie.Li@Sun.COM sizeof (si->shr_container)); 5817348SJose.Borrego@Sun.COM } 5827348SJose.Borrego@Sun.COM 583*9231SAfshin.Ardakani@Sun.COM catia = (new_si->shr_flags & SMB_SHRF_CATIA); 584*9231SAfshin.Ardakani@Sun.COM si->shr_flags &= ~SMB_SHRF_CATIA; 585*9231SAfshin.Ardakani@Sun.COM si->shr_flags |= catia; 586*9231SAfshin.Ardakani@Sun.COM 5878334SJose.Borrego@Sun.COM cscopt = (new_si->shr_flags & SMB_SHRF_CSC_MASK); 5888334SJose.Borrego@Sun.COM si->shr_flags &= ~SMB_SHRF_CSC_MASK; 5898334SJose.Borrego@Sun.COM si->shr_flags |= cscopt; 5908334SJose.Borrego@Sun.COM 5917961SNatalie.Li@Sun.COM access = (new_si->shr_flags & SMB_SHRF_ACC_ALL); 5928474SJose.Borrego@Sun.COM si->shr_flags &= ~SMB_SHRF_ACC_ALL; 5937961SNatalie.Li@Sun.COM si->shr_flags |= access; 5947961SNatalie.Li@Sun.COM 5957961SNatalie.Li@Sun.COM if (access & SMB_SHRF_ACC_NONE) 5967961SNatalie.Li@Sun.COM (void) strlcpy(si->shr_access_none, new_si->shr_access_none, 5977961SNatalie.Li@Sun.COM sizeof (si->shr_access_none)); 5987348SJose.Borrego@Sun.COM 5997961SNatalie.Li@Sun.COM if (access & SMB_SHRF_ACC_RO) 6007961SNatalie.Li@Sun.COM (void) strlcpy(si->shr_access_ro, new_si->shr_access_ro, 6017961SNatalie.Li@Sun.COM sizeof (si->shr_access_ro)); 6027348SJose.Borrego@Sun.COM 6037961SNatalie.Li@Sun.COM if (access & SMB_SHRF_ACC_RW) 6047961SNatalie.Li@Sun.COM (void) strlcpy(si->shr_access_rw, new_si->shr_access_rw, 6057961SNatalie.Li@Sun.COM sizeof (si->shr_access_rw)); 6067961SNatalie.Li@Sun.COM 6077961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 6087052Samw 6097348SJose.Borrego@Sun.COM if (adc_changed) { 6107961SNatalie.Li@Sun.COM smb_shr_unpublish(new_si->shr_name, old_container); 6117961SNatalie.Li@Sun.COM smb_shr_publish(new_si->shr_name, new_si->shr_container); 6127348SJose.Borrego@Sun.COM } 6137348SJose.Borrego@Sun.COM 6147348SJose.Borrego@Sun.COM return (NERR_Success); 6157052Samw } 6167052Samw 6177052Samw /* 6187052Samw * smb_shr_exists 6197052Samw * 6207348SJose.Borrego@Sun.COM * Returns B_TRUE if the share exists. Otherwise returns B_FALSE 6217052Samw */ 6227348SJose.Borrego@Sun.COM boolean_t 6237348SJose.Borrego@Sun.COM smb_shr_exists(char *sharename) 6247052Samw { 6257961SNatalie.Li@Sun.COM boolean_t exists = B_FALSE; 6267348SJose.Borrego@Sun.COM 6277348SJose.Borrego@Sun.COM if (sharename == NULL || *sharename == '\0') 6287348SJose.Borrego@Sun.COM return (B_FALSE); 6297052Samw 6307961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) { 6317961SNatalie.Li@Sun.COM exists = (smb_shr_cache_findent(sharename) != NULL); 6327961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 6337961SNatalie.Li@Sun.COM } 6347348SJose.Borrego@Sun.COM 6357348SJose.Borrego@Sun.COM return (exists); 6367052Samw } 6377052Samw 6387052Samw /* 6397961SNatalie.Li@Sun.COM * If the shared directory does not begin with a /, one will be 6407961SNatalie.Li@Sun.COM * inserted as a prefix. If ipaddr is not zero, then also return 6417961SNatalie.Li@Sun.COM * information about access based on the host level access lists, if 6427961SNatalie.Li@Sun.COM * present. Also return access check if there is an IP address and 6437961SNatalie.Li@Sun.COM * shr_accflags. 6447961SNatalie.Li@Sun.COM * 6457961SNatalie.Li@Sun.COM * The value of smb_chk_hostaccess is checked for an access match. 6467961SNatalie.Li@Sun.COM * -1 is wildcard match 6477961SNatalie.Li@Sun.COM * 0 is no match 6487961SNatalie.Li@Sun.COM * 1 is match 6497961SNatalie.Li@Sun.COM * 6507961SNatalie.Li@Sun.COM * Precedence is none is checked first followed by ro then rw if 6517961SNatalie.Li@Sun.COM * needed. If x is wildcard (< 0) then check to see if the other 6527961SNatalie.Li@Sun.COM * values are a match. If a match, that wins. 6538670SJose.Borrego@Sun.COM * 6548670SJose.Borrego@Sun.COM * ipv6 is wide open for now, see smb_chk_hostaccess 6557961SNatalie.Li@Sun.COM */ 6567961SNatalie.Li@Sun.COM void 6578670SJose.Borrego@Sun.COM smb_shr_hostaccess(smb_share_t *si, smb_inaddr_t *ipaddr) 6587961SNatalie.Li@Sun.COM { 6597961SNatalie.Li@Sun.COM int acc = SMB_SHRF_ACC_OPEN; 6607961SNatalie.Li@Sun.COM 6617961SNatalie.Li@Sun.COM /* 6627961SNatalie.Li@Sun.COM * Check to see if there area any share level access 6637961SNatalie.Li@Sun.COM * restrictions. 6647961SNatalie.Li@Sun.COM */ 6658670SJose.Borrego@Sun.COM if ((!smb_inet_iszero(ipaddr)) && 6668670SJose.Borrego@Sun.COM (si->shr_flags & SMB_SHRF_ACC_ALL) != 0) { 6677961SNatalie.Li@Sun.COM int none = SMB_SHRF_ACC_OPEN; 6687961SNatalie.Li@Sun.COM int rw = SMB_SHRF_ACC_OPEN; 6697961SNatalie.Li@Sun.COM int ro = SMB_SHRF_ACC_OPEN; 6707961SNatalie.Li@Sun.COM 6717961SNatalie.Li@Sun.COM if (si->shr_flags & SMB_SHRF_ACC_NONE) 6727961SNatalie.Li@Sun.COM none = smb_chk_hostaccess(ipaddr, si->shr_access_none); 6737961SNatalie.Li@Sun.COM if (si->shr_flags & SMB_SHRF_ACC_RW) 6747961SNatalie.Li@Sun.COM rw = smb_chk_hostaccess(ipaddr, si->shr_access_rw); 6757961SNatalie.Li@Sun.COM if (si->shr_flags & SMB_SHRF_ACC_RO) 6767961SNatalie.Li@Sun.COM ro = smb_chk_hostaccess(ipaddr, si->shr_access_ro); 6777961SNatalie.Li@Sun.COM /* make first pass to get basic value */ 6787961SNatalie.Li@Sun.COM if (none != 0) 6797961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_NONE; 6807961SNatalie.Li@Sun.COM else if (ro != 0) 6817961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RO; 6827961SNatalie.Li@Sun.COM else if (rw != 0) 6837961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RW; 6847961SNatalie.Li@Sun.COM 6857961SNatalie.Li@Sun.COM /* make second pass to handle '*' case */ 6867961SNatalie.Li@Sun.COM if (none < 0) { 6877961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_NONE; 6887961SNatalie.Li@Sun.COM if (ro > 0) 6897961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RO; 6907961SNatalie.Li@Sun.COM else if (rw > 0) 6917961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RW; 6927961SNatalie.Li@Sun.COM } else if (ro < 0) { 6937961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RO; 6947961SNatalie.Li@Sun.COM if (none > 0) 6957961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_NONE; 6967961SNatalie.Li@Sun.COM else if (rw > 0) 6977961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RW; 6987961SNatalie.Li@Sun.COM } else if (rw < 0) { 6997961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RW; 7007961SNatalie.Li@Sun.COM if (none > 0) 7017961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_NONE; 7027961SNatalie.Li@Sun.COM else if (ro > 0) 7037961SNatalie.Li@Sun.COM acc = SMB_SHRF_ACC_RO; 7047961SNatalie.Li@Sun.COM } 7057961SNatalie.Li@Sun.COM } 7067961SNatalie.Li@Sun.COM si->shr_access_value = acc; /* return access here */ 7077961SNatalie.Li@Sun.COM } 7087961SNatalie.Li@Sun.COM 7097961SNatalie.Li@Sun.COM /* 7107052Samw * smb_shr_is_special 7117052Samw * 7127348SJose.Borrego@Sun.COM * Special share reserved for interprocess communication (IPC$) or 7137348SJose.Borrego@Sun.COM * remote administration of the server (ADMIN$). Can also refer to 7147348SJose.Borrego@Sun.COM * administrative shares such as C$, D$, E$, and so forth. 7157052Samw */ 7167052Samw int 7177348SJose.Borrego@Sun.COM smb_shr_is_special(char *sharename) 7187052Samw { 7197052Samw int len; 7207052Samw 7217348SJose.Borrego@Sun.COM if (sharename == NULL) 7227052Samw return (0); 7237052Samw 7247348SJose.Borrego@Sun.COM if ((len = strlen(sharename)) == 0) 7257052Samw return (0); 7267052Samw 7277348SJose.Borrego@Sun.COM if (sharename[len - 1] == '$') 7287052Samw return (STYPE_SPECIAL); 7297348SJose.Borrego@Sun.COM 7307348SJose.Borrego@Sun.COM return (0); 7317052Samw } 7327052Samw 7337052Samw /* 7347052Samw * smb_shr_is_restricted 7357052Samw * 7367052Samw * Check whether or not there is a restriction on a share. Restricted 7377052Samw * shares are generally STYPE_SPECIAL, for example, IPC$. All the 7387348SJose.Borrego@Sun.COM * administration share names are restricted: C$, D$ etc. Returns B_TRUE 7397348SJose.Borrego@Sun.COM * if the share is restricted. Otherwise B_FALSE is returned to indicate 7407052Samw * that there are no restrictions. 7417052Samw */ 7427348SJose.Borrego@Sun.COM boolean_t 7437348SJose.Borrego@Sun.COM smb_shr_is_restricted(char *sharename) 7447052Samw { 7457052Samw static char *restricted[] = { 7467052Samw "IPC$" 7477052Samw }; 7487052Samw 7497052Samw int i; 7507052Samw 7517348SJose.Borrego@Sun.COM if (sharename == NULL) 7527348SJose.Borrego@Sun.COM return (B_FALSE); 7537348SJose.Borrego@Sun.COM 7547052Samw for (i = 0; i < sizeof (restricted)/sizeof (restricted[0]); i++) { 7557348SJose.Borrego@Sun.COM if (utf8_strcasecmp(restricted[i], sharename) == 0) 7567348SJose.Borrego@Sun.COM return (B_TRUE); 7577052Samw } 7587052Samw 7597348SJose.Borrego@Sun.COM return (smb_shr_is_admin(sharename)); 7607052Samw } 7617052Samw 7627052Samw /* 7637052Samw * smb_shr_is_admin 7647052Samw * 7657052Samw * Check whether or not access to the share should be restricted to 7667052Samw * administrators. This is a bit of a hack because what we're doing 7677052Samw * is checking for the default admin shares: C$, D$ etc.. There are 7687052Samw * other shares that have restrictions: see smb_shr_is_restricted(). 7697052Samw * 7707348SJose.Borrego@Sun.COM * Returns B_TRUE if the shares is an admin share. Otherwise B_FALSE 7717348SJose.Borrego@Sun.COM * is returned to indicate that there are no restrictions. 7727052Samw */ 7737348SJose.Borrego@Sun.COM boolean_t 7747348SJose.Borrego@Sun.COM smb_shr_is_admin(char *sharename) 7757052Samw { 7767348SJose.Borrego@Sun.COM if (sharename == NULL) 7777348SJose.Borrego@Sun.COM return (B_FALSE); 7787052Samw 7797348SJose.Borrego@Sun.COM if (strlen(sharename) == 2 && 7807348SJose.Borrego@Sun.COM mts_isalpha(sharename[0]) && sharename[1] == '$') { 7817348SJose.Borrego@Sun.COM return (B_TRUE); 7827052Samw } 7837052Samw 7847348SJose.Borrego@Sun.COM return (B_FALSE); 7857052Samw } 7867052Samw 7877052Samw /* 7887348SJose.Borrego@Sun.COM * smb_shr_chkname 7897052Samw * 7907961SNatalie.Li@Sun.COM * Check for invalid characters in a share name. The list of invalid 7917961SNatalie.Li@Sun.COM * characters includes control characters and the following: 7927052Samw * 7937052Samw * " / \ [ ] : | < > + ; , ? * = 7947052Samw */ 7957348SJose.Borrego@Sun.COM boolean_t 7967348SJose.Borrego@Sun.COM smb_shr_chkname(char *sharename) 7977052Samw { 7987052Samw char *invalid = "\"/\\[]:|<>+;,?*="; 7997052Samw char *cp; 8007052Samw 8017348SJose.Borrego@Sun.COM if (sharename == NULL) 8027348SJose.Borrego@Sun.COM return (B_FALSE); 8037052Samw 8047348SJose.Borrego@Sun.COM if (strpbrk(sharename, invalid)) 8057348SJose.Borrego@Sun.COM return (B_FALSE); 8067052Samw 8077348SJose.Borrego@Sun.COM for (cp = sharename; *cp != '\0'; cp++) { 8087348SJose.Borrego@Sun.COM if (iscntrl(*cp)) 8097348SJose.Borrego@Sun.COM return (B_FALSE); 8107052Samw } 8117052Samw 8127348SJose.Borrego@Sun.COM return (B_TRUE); 8137052Samw } 8147052Samw 8157052Samw /* 8167052Samw * smb_shr_get_realpath 8177052Samw * 8187961SNatalie.Li@Sun.COM * Derive the real path for a share from the path provided by a client. 8197961SNatalie.Li@Sun.COM * For instance, the real path of C:\ may be /cvol or the real path of 8207961SNatalie.Li@Sun.COM * F:\home may be /vol1/home. 8217052Samw * 8227961SNatalie.Li@Sun.COM * clntpath - path provided by the Windows client is in the 8237052Samw * format of <drive letter>:\<dir> 8247052Samw * realpath - path that will be stored as the directory field of 8257052Samw * the smb_share_t structure of the share. 8267961SNatalie.Li@Sun.COM * maxlen - maximum length of the realpath buffer 8277052Samw * 8287052Samw * Return LAN Manager network error code. 8297052Samw */ 8307052Samw uint32_t 8317961SNatalie.Li@Sun.COM smb_shr_get_realpath(const char *clntpath, char *realpath, int maxlen) 8327052Samw { 8337961SNatalie.Li@Sun.COM const char *p; 8347961SNatalie.Li@Sun.COM int len; 8357348SJose.Borrego@Sun.COM 8367961SNatalie.Li@Sun.COM if ((p = strchr(clntpath, ':')) != NULL) 8377961SNatalie.Li@Sun.COM ++p; 8387961SNatalie.Li@Sun.COM else 8397961SNatalie.Li@Sun.COM p = clntpath; 8407348SJose.Borrego@Sun.COM 8417961SNatalie.Li@Sun.COM (void) strlcpy(realpath, p, maxlen); 8427961SNatalie.Li@Sun.COM (void) strcanon(realpath, "/\\"); 8437961SNatalie.Li@Sun.COM (void) strsubst(realpath, '\\', '/'); 8447348SJose.Borrego@Sun.COM 8457961SNatalie.Li@Sun.COM len = strlen(realpath); 8467961SNatalie.Li@Sun.COM if ((len > 1) && (realpath[len - 1] == '/')) 8477961SNatalie.Li@Sun.COM realpath[len - 1] = '\0'; 8487348SJose.Borrego@Sun.COM 8497348SJose.Borrego@Sun.COM return (NERR_Success); 8507348SJose.Borrego@Sun.COM } 8517348SJose.Borrego@Sun.COM 8527961SNatalie.Li@Sun.COM void 8537961SNatalie.Li@Sun.COM smb_shr_list(int offset, smb_shrlist_t *list) 8547348SJose.Borrego@Sun.COM { 8557961SNatalie.Li@Sun.COM smb_shriter_t iterator; 8567961SNatalie.Li@Sun.COM smb_share_t *si; 8577961SNatalie.Li@Sun.COM int n = 0; 8587961SNatalie.Li@Sun.COM 8597961SNatalie.Li@Sun.COM bzero(list, sizeof (smb_shrlist_t)); 8607961SNatalie.Li@Sun.COM smb_shr_iterinit(&iterator); 8617961SNatalie.Li@Sun.COM 8627961SNatalie.Li@Sun.COM while ((si = smb_shr_iterate(&iterator)) != NULL) { 8637961SNatalie.Li@Sun.COM if (--offset > 0) 8647961SNatalie.Li@Sun.COM continue; 8657961SNatalie.Li@Sun.COM 8667961SNatalie.Li@Sun.COM if ((si->shr_flags & SMB_SHRF_TRANS) && 8677961SNatalie.Li@Sun.COM ((si->shr_type & STYPE_IPC) == 0)) { 8687961SNatalie.Li@Sun.COM bcopy(si, &list->sl_shares[n], sizeof (smb_share_t)); 8697961SNatalie.Li@Sun.COM if (++n == LMSHARES_PER_REQUEST) 8707961SNatalie.Li@Sun.COM break; 8717961SNatalie.Li@Sun.COM } 8727348SJose.Borrego@Sun.COM } 8737961SNatalie.Li@Sun.COM 8747961SNatalie.Li@Sun.COM list->sl_cnt = n; 8757348SJose.Borrego@Sun.COM } 8767348SJose.Borrego@Sun.COM 8777348SJose.Borrego@Sun.COM /* 8787961SNatalie.Li@Sun.COM * ============================================ 8797961SNatalie.Li@Sun.COM * Private helper/utility functions 8807961SNatalie.Li@Sun.COM * ============================================ 8817348SJose.Borrego@Sun.COM */ 8827348SJose.Borrego@Sun.COM 8837961SNatalie.Li@Sun.COM /* 8848334SJose.Borrego@Sun.COM * Looks up the given share in the cache and return 8858334SJose.Borrego@Sun.COM * the info in 'si' 8868334SJose.Borrego@Sun.COM */ 8878334SJose.Borrego@Sun.COM static uint32_t 8888334SJose.Borrego@Sun.COM smb_shr_lookup(char *sharename, smb_share_t *si) 8898334SJose.Borrego@Sun.COM { 8908334SJose.Borrego@Sun.COM smb_share_t *cached_si; 8918334SJose.Borrego@Sun.COM uint32_t status = NERR_NetNameNotFound; 8928334SJose.Borrego@Sun.COM 8938334SJose.Borrego@Sun.COM if (sharename == NULL || *sharename == '\0') 8948334SJose.Borrego@Sun.COM return (NERR_NetNameNotFound); 8958334SJose.Borrego@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) { 8968334SJose.Borrego@Sun.COM cached_si = smb_shr_cache_findent(sharename); 8978334SJose.Borrego@Sun.COM if (cached_si != NULL) { 8988334SJose.Borrego@Sun.COM bcopy(cached_si, si, sizeof (smb_share_t)); 8998334SJose.Borrego@Sun.COM status = NERR_Success; 9008334SJose.Borrego@Sun.COM } 9018334SJose.Borrego@Sun.COM 9028334SJose.Borrego@Sun.COM smb_shr_cache_unlock(); 9038334SJose.Borrego@Sun.COM } 9048334SJose.Borrego@Sun.COM return (status); 9058334SJose.Borrego@Sun.COM } 9068334SJose.Borrego@Sun.COM 9078334SJose.Borrego@Sun.COM /* 9087961SNatalie.Li@Sun.COM * Add IPC$ to the cache upon startup. 9097961SNatalie.Li@Sun.COM */ 9107348SJose.Borrego@Sun.COM static uint32_t 9117961SNatalie.Li@Sun.COM smb_shr_addipc(void) 9127348SJose.Borrego@Sun.COM { 9137348SJose.Borrego@Sun.COM smb_share_t ipc; 9147961SNatalie.Li@Sun.COM uint32_t status = NERR_InternalError; 9157348SJose.Borrego@Sun.COM 9167348SJose.Borrego@Sun.COM bzero(&ipc, sizeof (smb_share_t)); 9177348SJose.Borrego@Sun.COM (void) strcpy(ipc.shr_name, "IPC$"); 9187348SJose.Borrego@Sun.COM (void) strcpy(ipc.shr_cmnt, "Remote IPC"); 9197348SJose.Borrego@Sun.COM ipc.shr_flags = SMB_SHRF_TRANS; 9207348SJose.Borrego@Sun.COM ipc.shr_type = STYPE_IPC; 9217348SJose.Borrego@Sun.COM 9227961SNatalie.Li@Sun.COM if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) == NERR_Success) { 9237961SNatalie.Li@Sun.COM status = smb_shr_cache_addent(&ipc); 9247961SNatalie.Li@Sun.COM smb_shr_cache_unlock(); 9257348SJose.Borrego@Sun.COM } 9267348SJose.Borrego@Sun.COM 9277348SJose.Borrego@Sun.COM return (status); 9287348SJose.Borrego@Sun.COM } 9297348SJose.Borrego@Sun.COM 9307348SJose.Borrego@Sun.COM /* 9317052Samw * smb_shr_set_oemname 9327052Samw * 9337961SNatalie.Li@Sun.COM * Generate the OEM name for the specified share. If the name is 9347961SNatalie.Li@Sun.COM * shorter than 13 bytes the oemname will be saved in si->shr_oemname. 9357961SNatalie.Li@Sun.COM * Otherwise si->shr_oemname will be empty and SMB_SHRF_LONGNAME will 9367961SNatalie.Li@Sun.COM * be set in si->shr_flags. 9377052Samw */ 9387052Samw static void 9397052Samw smb_shr_set_oemname(smb_share_t *si) 9407052Samw { 9417052Samw unsigned int cpid = oem_get_smb_cpid(); 9427052Samw mts_wchar_t *unibuf; 9437052Samw char *oem_name; 9447052Samw int length; 9457052Samw 9467052Samw length = strlen(si->shr_name) + 1; 9477052Samw 9487052Samw oem_name = malloc(length); 9497052Samw unibuf = malloc(length * sizeof (mts_wchar_t)); 9507052Samw if ((oem_name == NULL) || (unibuf == NULL)) { 9517052Samw free(oem_name); 9527052Samw free(unibuf); 9537052Samw return; 9547052Samw } 9557052Samw 9567052Samw (void) mts_mbstowcs(unibuf, si->shr_name, length); 9577052Samw 9587052Samw if (unicodestooems(oem_name, unibuf, length, cpid) == 0) 9597052Samw (void) strcpy(oem_name, si->shr_name); 9607052Samw 9617052Samw free(unibuf); 9627052Samw 9637052Samw if (strlen(oem_name) + 1 > SMB_SHARE_OEMNAME_MAX) { 9647052Samw si->shr_flags |= SMB_SHRF_LONGNAME; 9657052Samw *si->shr_oemname = '\0'; 9667052Samw } else { 9677052Samw si->shr_flags &= ~SMB_SHRF_LONGNAME; 9687052Samw (void) strlcpy(si->shr_oemname, oem_name, 9697052Samw SMB_SHARE_OEMNAME_MAX); 9707052Samw } 9717052Samw 9727052Samw free(oem_name); 9737052Samw } 9747348SJose.Borrego@Sun.COM 9757348SJose.Borrego@Sun.COM /* 9767348SJose.Borrego@Sun.COM * ============================================ 9777961SNatalie.Li@Sun.COM * Cache management functions 9787961SNatalie.Li@Sun.COM * 9797961SNatalie.Li@Sun.COM * All cache functions are private 9807348SJose.Borrego@Sun.COM * ============================================ 9817348SJose.Borrego@Sun.COM */ 9827348SJose.Borrego@Sun.COM 9837348SJose.Borrego@Sun.COM /* 9847961SNatalie.Li@Sun.COM * Create the share cache (hash table). 9857348SJose.Borrego@Sun.COM */ 9867348SJose.Borrego@Sun.COM static uint32_t 9877961SNatalie.Li@Sun.COM smb_shr_cache_create(void) 9887348SJose.Borrego@Sun.COM { 9897961SNatalie.Li@Sun.COM uint32_t status = NERR_Success; 9907348SJose.Borrego@Sun.COM 9917961SNatalie.Li@Sun.COM (void) mutex_lock(&smb_shr_cache.sc_mtx); 9927961SNatalie.Li@Sun.COM switch (smb_shr_cache.sc_state) { 9937961SNatalie.Li@Sun.COM case SMB_SHR_CACHE_STATE_NONE: 9947961SNatalie.Li@Sun.COM smb_shr_cache.sc_cache = ht_create_table(SMB_SHR_HTAB_SZ, 9957961SNatalie.Li@Sun.COM MAXNAMELEN, 0); 9967961SNatalie.Li@Sun.COM if (smb_shr_cache.sc_cache == NULL) { 9977961SNatalie.Li@Sun.COM status = NERR_InternalError; 9987961SNatalie.Li@Sun.COM break; 9997348SJose.Borrego@Sun.COM } 10007348SJose.Borrego@Sun.COM 10017961SNatalie.Li@Sun.COM (void) ht_register_callback(smb_shr_cache.sc_cache, 10027961SNatalie.Li@Sun.COM smb_shr_cache_freent); 10037961SNatalie.Li@Sun.COM smb_shr_cache.sc_nops = 0; 10047961SNatalie.Li@Sun.COM smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_CREATED; 10057961SNatalie.Li@Sun.COM break; 10067961SNatalie.Li@Sun.COM 10077961SNatalie.Li@Sun.COM default: 10087961SNatalie.Li@Sun.COM assert(0); 10097961SNatalie.Li@Sun.COM status = NERR_InternalError; 10107961SNatalie.Li@Sun.COM break; 10117961SNatalie.Li@Sun.COM } 10127961SNatalie.Li@Sun.COM (void) mutex_unlock(&smb_shr_cache.sc_mtx); 10137961SNatalie.Li@Sun.COM 10147961SNatalie.Li@Sun.COM return (status); 10157961SNatalie.Li@Sun.COM } 10167961SNatalie.Li@Sun.COM 10177961SNatalie.Li@Sun.COM /* 10187961SNatalie.Li@Sun.COM * Destroy the share cache (hash table). 10197961SNatalie.Li@Sun.COM * Wait for inflight/pending operations to finish or abort before 10207961SNatalie.Li@Sun.COM * destroying the cache. 10217961SNatalie.Li@Sun.COM */ 10227961SNatalie.Li@Sun.COM static void 10237961SNatalie.Li@Sun.COM smb_shr_cache_destroy(void) 10247961SNatalie.Li@Sun.COM { 10257961SNatalie.Li@Sun.COM (void) mutex_lock(&smb_shr_cache.sc_mtx); 10267961SNatalie.Li@Sun.COM if (smb_shr_cache.sc_state == SMB_SHR_CACHE_STATE_CREATED) { 10277961SNatalie.Li@Sun.COM smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_DESTROYING; 10287961SNatalie.Li@Sun.COM while (smb_shr_cache.sc_nops > 0) 10297961SNatalie.Li@Sun.COM (void) cond_wait(&smb_shr_cache.sc_cv, 10307961SNatalie.Li@Sun.COM &smb_shr_cache.sc_mtx); 10317961SNatalie.Li@Sun.COM 10327961SNatalie.Li@Sun.COM smb_shr_cache.sc_cache = NULL; 10337961SNatalie.Li@Sun.COM smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_NONE; 10347961SNatalie.Li@Sun.COM } 10357961SNatalie.Li@Sun.COM (void) mutex_unlock(&smb_shr_cache.sc_mtx); 10367961SNatalie.Li@Sun.COM } 10377961SNatalie.Li@Sun.COM 10387961SNatalie.Li@Sun.COM /* 10397961SNatalie.Li@Sun.COM * If the cache is in "created" state, lock the cache for read 10407961SNatalie.Li@Sun.COM * or read/write based on the specified mode. 10417961SNatalie.Li@Sun.COM * 10427961SNatalie.Li@Sun.COM * Whenever a lock is granted, the number of inflight cache 10437961SNatalie.Li@Sun.COM * operations is incremented. 10447961SNatalie.Li@Sun.COM */ 10457961SNatalie.Li@Sun.COM static uint32_t 10467961SNatalie.Li@Sun.COM smb_shr_cache_lock(int mode) 10477961SNatalie.Li@Sun.COM { 10487961SNatalie.Li@Sun.COM (void) mutex_lock(&smb_shr_cache.sc_mtx); 10498334SJose.Borrego@Sun.COM if (smb_shr_cache.sc_state != SMB_SHR_CACHE_STATE_CREATED) { 10507961SNatalie.Li@Sun.COM (void) mutex_unlock(&smb_shr_cache.sc_mtx); 10517961SNatalie.Li@Sun.COM return (NERR_InternalError); 10527961SNatalie.Li@Sun.COM } 10538334SJose.Borrego@Sun.COM smb_shr_cache.sc_nops++; 10547961SNatalie.Li@Sun.COM (void) mutex_unlock(&smb_shr_cache.sc_mtx); 10557961SNatalie.Li@Sun.COM 10567961SNatalie.Li@Sun.COM /* 10577961SNatalie.Li@Sun.COM * Lock has to be taken outside the mutex otherwise 10587961SNatalie.Li@Sun.COM * there could be a deadlock 10597961SNatalie.Li@Sun.COM */ 10607961SNatalie.Li@Sun.COM if (mode == SMB_SHR_CACHE_RDLOCK) 10617961SNatalie.Li@Sun.COM (void) rw_rdlock(&smb_shr_cache.sc_cache_lck); 10627961SNatalie.Li@Sun.COM else 10637961SNatalie.Li@Sun.COM (void) rw_wrlock(&smb_shr_cache.sc_cache_lck); 10647961SNatalie.Li@Sun.COM 10657961SNatalie.Li@Sun.COM return (NERR_Success); 10667961SNatalie.Li@Sun.COM } 10677961SNatalie.Li@Sun.COM 10687961SNatalie.Li@Sun.COM /* 10697961SNatalie.Li@Sun.COM * Decrement the number of inflight operations and then unlock. 10707961SNatalie.Li@Sun.COM */ 10717961SNatalie.Li@Sun.COM static void 10727961SNatalie.Li@Sun.COM smb_shr_cache_unlock(void) 10737961SNatalie.Li@Sun.COM { 10747961SNatalie.Li@Sun.COM (void) mutex_lock(&smb_shr_cache.sc_mtx); 10757961SNatalie.Li@Sun.COM assert(smb_shr_cache.sc_nops > 0); 10767961SNatalie.Li@Sun.COM smb_shr_cache.sc_nops--; 10777961SNatalie.Li@Sun.COM (void) cond_broadcast(&smb_shr_cache.sc_cv); 10787961SNatalie.Li@Sun.COM (void) mutex_unlock(&smb_shr_cache.sc_mtx); 10797961SNatalie.Li@Sun.COM 10807961SNatalie.Li@Sun.COM (void) rw_unlock(&smb_shr_cache.sc_cache_lck); 10817961SNatalie.Li@Sun.COM } 10827961SNatalie.Li@Sun.COM 10837961SNatalie.Li@Sun.COM /* 10847961SNatalie.Li@Sun.COM * Return the total number of shares 10857961SNatalie.Li@Sun.COM */ 10867961SNatalie.Li@Sun.COM static int 10877961SNatalie.Li@Sun.COM smb_shr_cache_count(void) 10887961SNatalie.Li@Sun.COM { 10897961SNatalie.Li@Sun.COM return (ht_get_total_items(smb_shr_cache.sc_cache)); 10907961SNatalie.Li@Sun.COM } 10917961SNatalie.Li@Sun.COM 10927961SNatalie.Li@Sun.COM /* 10937961SNatalie.Li@Sun.COM * looks up the given share name in the cache and if it 10947961SNatalie.Li@Sun.COM * finds a match returns a pointer to the cached entry. 10957961SNatalie.Li@Sun.COM * Note that since a pointer is returned this function 10967961SNatalie.Li@Sun.COM * MUST be protected by smb_shr_cache_lock/unlock pair 10977961SNatalie.Li@Sun.COM */ 10987961SNatalie.Li@Sun.COM static smb_share_t * 10997961SNatalie.Li@Sun.COM smb_shr_cache_findent(char *sharename) 11007961SNatalie.Li@Sun.COM { 11017961SNatalie.Li@Sun.COM HT_ITEM *item; 11027961SNatalie.Li@Sun.COM 11037961SNatalie.Li@Sun.COM (void) utf8_strlwr(sharename); 11047961SNatalie.Li@Sun.COM item = ht_find_item(smb_shr_cache.sc_cache, sharename); 11057961SNatalie.Li@Sun.COM if (item && item->hi_data) 11067961SNatalie.Li@Sun.COM return ((smb_share_t *)item->hi_data); 11077961SNatalie.Li@Sun.COM 11087961SNatalie.Li@Sun.COM return (NULL); 11097961SNatalie.Li@Sun.COM } 11107961SNatalie.Li@Sun.COM 11117961SNatalie.Li@Sun.COM /* 11127961SNatalie.Li@Sun.COM * Return a pointer to the first/next entry in 11137961SNatalie.Li@Sun.COM * the cache based on the given iterator. 11147961SNatalie.Li@Sun.COM * 11157961SNatalie.Li@Sun.COM * Calls to this function MUST be protected by 11167961SNatalie.Li@Sun.COM * smb_shr_cache_lock/unlock. 11177961SNatalie.Li@Sun.COM */ 11187961SNatalie.Li@Sun.COM static smb_share_t * 11197961SNatalie.Li@Sun.COM smb_shr_cache_iterate(smb_shriter_t *shi) 11207961SNatalie.Li@Sun.COM { 11217961SNatalie.Li@Sun.COM HT_ITEM *item; 11227961SNatalie.Li@Sun.COM 11237961SNatalie.Li@Sun.COM if (shi->si_first) { 11247961SNatalie.Li@Sun.COM item = ht_findfirst(smb_shr_cache.sc_cache, &shi->si_hashiter); 11257961SNatalie.Li@Sun.COM shi->si_first = B_FALSE; 11267961SNatalie.Li@Sun.COM } else { 11277961SNatalie.Li@Sun.COM item = ht_findnext(&shi->si_hashiter); 11287348SJose.Borrego@Sun.COM } 11297348SJose.Borrego@Sun.COM 11307961SNatalie.Li@Sun.COM if (item && item->hi_data) 11317961SNatalie.Li@Sun.COM return ((smb_share_t *)item->hi_data); 11327961SNatalie.Li@Sun.COM 11337961SNatalie.Li@Sun.COM return (NULL); 11347961SNatalie.Li@Sun.COM } 11357961SNatalie.Li@Sun.COM 11367961SNatalie.Li@Sun.COM /* 11377961SNatalie.Li@Sun.COM * Add the specified share to the cache. Memory needs to be allocated 11387961SNatalie.Li@Sun.COM * for the cache entry and the passed information is copied to the 11397961SNatalie.Li@Sun.COM * allocated space. 11407961SNatalie.Li@Sun.COM */ 11417961SNatalie.Li@Sun.COM static uint32_t 11427961SNatalie.Li@Sun.COM smb_shr_cache_addent(smb_share_t *si) 11437961SNatalie.Li@Sun.COM { 11447961SNatalie.Li@Sun.COM smb_share_t *cache_ent; 11457961SNatalie.Li@Sun.COM uint32_t status = NERR_Success; 11467961SNatalie.Li@Sun.COM 11477961SNatalie.Li@Sun.COM if ((cache_ent = malloc(sizeof (smb_share_t))) == NULL) 11487961SNatalie.Li@Sun.COM return (ERROR_NOT_ENOUGH_MEMORY); 11497961SNatalie.Li@Sun.COM 11507961SNatalie.Li@Sun.COM bcopy(si, cache_ent, sizeof (smb_share_t)); 11517961SNatalie.Li@Sun.COM 11527961SNatalie.Li@Sun.COM (void) utf8_strlwr(cache_ent->shr_name); 11537961SNatalie.Li@Sun.COM smb_shr_set_oemname(cache_ent); 11547961SNatalie.Li@Sun.COM 11557961SNatalie.Li@Sun.COM if ((si->shr_type & STYPE_IPC) == 0) 11567961SNatalie.Li@Sun.COM cache_ent->shr_type = STYPE_DISKTREE; 11577961SNatalie.Li@Sun.COM cache_ent->shr_type |= smb_shr_is_special(cache_ent->shr_name); 11587961SNatalie.Li@Sun.COM 11597961SNatalie.Li@Sun.COM if (smb_shr_is_admin(cache_ent->shr_name)) 11607961SNatalie.Li@Sun.COM cache_ent->shr_flags |= SMB_SHRF_ADMIN; 11617961SNatalie.Li@Sun.COM 11627961SNatalie.Li@Sun.COM if (si->shr_flags & SMB_SHRF_AUTOHOME) 11637961SNatalie.Li@Sun.COM cache_ent->shr_refcnt = 1; 11647961SNatalie.Li@Sun.COM 11657961SNatalie.Li@Sun.COM if (ht_add_item(smb_shr_cache.sc_cache, cache_ent->shr_name, cache_ent) 11667961SNatalie.Li@Sun.COM == NULL) { 11677961SNatalie.Li@Sun.COM syslog(LOG_DEBUG, "share: %s: cache update failed", 11687961SNatalie.Li@Sun.COM cache_ent->shr_name); 11697961SNatalie.Li@Sun.COM free(cache_ent); 11707961SNatalie.Li@Sun.COM status = NERR_InternalError; 11717348SJose.Borrego@Sun.COM } 11727348SJose.Borrego@Sun.COM 11737961SNatalie.Li@Sun.COM return (status); 11747961SNatalie.Li@Sun.COM } 11757961SNatalie.Li@Sun.COM 11767961SNatalie.Li@Sun.COM /* 11777961SNatalie.Li@Sun.COM * Delete the specified share from the cache. 11787961SNatalie.Li@Sun.COM */ 11797961SNatalie.Li@Sun.COM static void 11807961SNatalie.Li@Sun.COM smb_shr_cache_delent(char *sharename) 11817961SNatalie.Li@Sun.COM { 11827961SNatalie.Li@Sun.COM (void) utf8_strlwr(sharename); 11837961SNatalie.Li@Sun.COM (void) ht_remove_item(smb_shr_cache.sc_cache, sharename); 11847961SNatalie.Li@Sun.COM } 11857961SNatalie.Li@Sun.COM 11867961SNatalie.Li@Sun.COM /* 11877961SNatalie.Li@Sun.COM * Call back to free the given cache entry. 11887961SNatalie.Li@Sun.COM */ 11897961SNatalie.Li@Sun.COM static void 11907961SNatalie.Li@Sun.COM smb_shr_cache_freent(HT_ITEM *item) 11917961SNatalie.Li@Sun.COM { 11927961SNatalie.Li@Sun.COM if (item && item->hi_data) 11937961SNatalie.Li@Sun.COM free(item->hi_data); 11947961SNatalie.Li@Sun.COM } 11957961SNatalie.Li@Sun.COM 11967961SNatalie.Li@Sun.COM /* 11977961SNatalie.Li@Sun.COM * ============================================ 11987961SNatalie.Li@Sun.COM * Interfaces to sharemgr 11997961SNatalie.Li@Sun.COM * 12007961SNatalie.Li@Sun.COM * All functions in this section are private 12017961SNatalie.Li@Sun.COM * ============================================ 12027961SNatalie.Li@Sun.COM */ 12037961SNatalie.Li@Sun.COM 12047961SNatalie.Li@Sun.COM /* 12057961SNatalie.Li@Sun.COM * Load shares from sharemgr 12067961SNatalie.Li@Sun.COM */ 12077961SNatalie.Li@Sun.COM /*ARGSUSED*/ 12087961SNatalie.Li@Sun.COM static void * 12097961SNatalie.Li@Sun.COM smb_shr_sa_loadall(void *args) 12107961SNatalie.Li@Sun.COM { 12117961SNatalie.Li@Sun.COM sa_handle_t handle; 12127961SNatalie.Li@Sun.COM sa_group_t group, subgroup; 12137961SNatalie.Li@Sun.COM char *gstate; 12147961SNatalie.Li@Sun.COM boolean_t gdisabled; 12157961SNatalie.Li@Sun.COM 12168474SJose.Borrego@Sun.COM if ((handle = smb_shr_sa_enter()) == NULL) 12177961SNatalie.Li@Sun.COM return (NULL); 12187348SJose.Borrego@Sun.COM 12197961SNatalie.Li@Sun.COM for (group = sa_get_group(handle, NULL); 12207961SNatalie.Li@Sun.COM group != NULL; group = sa_get_next_group(group)) { 12217961SNatalie.Li@Sun.COM gstate = sa_get_group_attr(group, "state"); 12227961SNatalie.Li@Sun.COM if (gstate == NULL) 12237961SNatalie.Li@Sun.COM continue; 12247961SNatalie.Li@Sun.COM 12257961SNatalie.Li@Sun.COM gdisabled = (strcasecmp(gstate, "disabled") == 0); 12267961SNatalie.Li@Sun.COM sa_free_attr_string(gstate); 12277961SNatalie.Li@Sun.COM if (gdisabled) 12287961SNatalie.Li@Sun.COM continue; 12297961SNatalie.Li@Sun.COM 12307961SNatalie.Li@Sun.COM smb_shr_sa_loadgrp(group); 12317961SNatalie.Li@Sun.COM 12327961SNatalie.Li@Sun.COM for (subgroup = sa_get_sub_group(group); 12337961SNatalie.Li@Sun.COM subgroup != NULL; 12347961SNatalie.Li@Sun.COM subgroup = sa_get_next_group(subgroup)) { 12357961SNatalie.Li@Sun.COM smb_shr_sa_loadgrp(subgroup); 12367961SNatalie.Li@Sun.COM } 12377961SNatalie.Li@Sun.COM 12387348SJose.Borrego@Sun.COM } 12397348SJose.Borrego@Sun.COM 12408474SJose.Borrego@Sun.COM smb_shr_sa_exit(); 12417961SNatalie.Li@Sun.COM return (NULL); 12427348SJose.Borrego@Sun.COM } 12437348SJose.Borrego@Sun.COM 12447961SNatalie.Li@Sun.COM /* 12457961SNatalie.Li@Sun.COM * Load the shares contained in the specified group. 12467961SNatalie.Li@Sun.COM * 12477961SNatalie.Li@Sun.COM * Don't process groups on which the smb protocol is disabled. 12487961SNatalie.Li@Sun.COM * The top level ZFS group won't have the smb protocol enabled 12497961SNatalie.Li@Sun.COM * but sub-groups will. 12507961SNatalie.Li@Sun.COM * 12517961SNatalie.Li@Sun.COM * We will tolerate a limited number of errors and then give 12527961SNatalie.Li@Sun.COM * up on the current group. A typical error might be that the 12537961SNatalie.Li@Sun.COM * shared directory no longer exists. 12547961SNatalie.Li@Sun.COM */ 12557961SNatalie.Li@Sun.COM static void 12567961SNatalie.Li@Sun.COM smb_shr_sa_loadgrp(sa_group_t group) 12577961SNatalie.Li@Sun.COM { 12587961SNatalie.Li@Sun.COM sa_share_t share; 12597961SNatalie.Li@Sun.COM sa_resource_t resource; 12607961SNatalie.Li@Sun.COM int error_count = 0; 12617961SNatalie.Li@Sun.COM 12627961SNatalie.Li@Sun.COM if (sa_get_optionset(group, SMB_PROTOCOL_NAME) == NULL) 12637961SNatalie.Li@Sun.COM return; 12647961SNatalie.Li@Sun.COM 12657961SNatalie.Li@Sun.COM for (share = sa_get_share(group, NULL); 12667961SNatalie.Li@Sun.COM share != NULL; 12677961SNatalie.Li@Sun.COM share = sa_get_next_share(share)) { 12687961SNatalie.Li@Sun.COM for (resource = sa_get_share_resource(share, NULL); 12697961SNatalie.Li@Sun.COM resource != NULL; 12707961SNatalie.Li@Sun.COM resource = sa_get_next_resource(resource)) { 12717961SNatalie.Li@Sun.COM if (smb_shr_sa_load(share, resource)) 12727961SNatalie.Li@Sun.COM ++error_count; 12737961SNatalie.Li@Sun.COM 12747961SNatalie.Li@Sun.COM if (error_count > SMB_SHR_ERROR_THRESHOLD) 12757961SNatalie.Li@Sun.COM break; 12767961SNatalie.Li@Sun.COM } 12777961SNatalie.Li@Sun.COM 12787961SNatalie.Li@Sun.COM if (error_count > SMB_SHR_ERROR_THRESHOLD) 12797961SNatalie.Li@Sun.COM break; 12807961SNatalie.Li@Sun.COM } 12817961SNatalie.Li@Sun.COM } 12827961SNatalie.Li@Sun.COM 12837961SNatalie.Li@Sun.COM /* 12847961SNatalie.Li@Sun.COM * Load a share definition from sharemgr and add it to the cache. 12858334SJose.Borrego@Sun.COM * If the share is already in the cache then it doesn't do anything. 12868334SJose.Borrego@Sun.COM * 12878334SJose.Borrego@Sun.COM * This function does not report duplicate shares as error since 12888334SJose.Borrego@Sun.COM * a share might have been added by smb_shr_get() while load is 12898334SJose.Borrego@Sun.COM * in progress. 12907961SNatalie.Li@Sun.COM */ 12917348SJose.Borrego@Sun.COM static uint32_t 12927961SNatalie.Li@Sun.COM smb_shr_sa_load(sa_share_t share, sa_resource_t resource) 12937961SNatalie.Li@Sun.COM { 12947961SNatalie.Li@Sun.COM smb_share_t si; 12958334SJose.Borrego@Sun.COM char *sharename; 12967961SNatalie.Li@Sun.COM uint32_t status; 12978334SJose.Borrego@Sun.COM boolean_t loaded; 12988334SJose.Borrego@Sun.COM 12998334SJose.Borrego@Sun.COM if ((sharename = sa_get_resource_attr(resource, "name")) == NULL) 13008334SJose.Borrego@Sun.COM return (NERR_InternalError); 13018334SJose.Borrego@Sun.COM 13028334SJose.Borrego@Sun.COM loaded = smb_shr_exists(sharename); 13038334SJose.Borrego@Sun.COM sa_free_attr_string(sharename); 13048334SJose.Borrego@Sun.COM 13058334SJose.Borrego@Sun.COM if (loaded) 13068334SJose.Borrego@Sun.COM return (NERR_Success); 13077961SNatalie.Li@Sun.COM 13087961SNatalie.Li@Sun.COM if ((status = smb_shr_sa_get(share, resource, &si)) != NERR_Success) { 13097961SNatalie.Li@Sun.COM syslog(LOG_DEBUG, "share: failed to load %s (%d)", 13107961SNatalie.Li@Sun.COM si.shr_name, status); 13117961SNatalie.Li@Sun.COM return (status); 13127961SNatalie.Li@Sun.COM } 13137961SNatalie.Li@Sun.COM 13148334SJose.Borrego@Sun.COM status = smb_shr_add(&si); 13158334SJose.Borrego@Sun.COM if ((status != NERR_Success) && (status != NERR_DuplicateShare)) { 13167961SNatalie.Li@Sun.COM syslog(LOG_DEBUG, "share: failed to cache %s (%d)", 13177961SNatalie.Li@Sun.COM si.shr_name, status); 13187961SNatalie.Li@Sun.COM return (status); 13197961SNatalie.Li@Sun.COM } 13207961SNatalie.Li@Sun.COM 13217961SNatalie.Li@Sun.COM return (NERR_Success); 13227961SNatalie.Li@Sun.COM } 13237961SNatalie.Li@Sun.COM 13247961SNatalie.Li@Sun.COM /* 13257961SNatalie.Li@Sun.COM * Read the specified share information from sharemgr and return 13267961SNatalie.Li@Sun.COM * it in the given smb_share_t structure. 13277961SNatalie.Li@Sun.COM * 13287961SNatalie.Li@Sun.COM * Shares read from sharemgr are marked as permanent/persistent. 13297961SNatalie.Li@Sun.COM */ 13307961SNatalie.Li@Sun.COM static uint32_t 13317961SNatalie.Li@Sun.COM smb_shr_sa_get(sa_share_t share, sa_resource_t resource, smb_share_t *si) 13327348SJose.Borrego@Sun.COM { 13337348SJose.Borrego@Sun.COM sa_property_t prop; 13347348SJose.Borrego@Sun.COM sa_optionset_t opts; 13357348SJose.Borrego@Sun.COM char *val = NULL; 13367348SJose.Borrego@Sun.COM char *path; 13377348SJose.Borrego@Sun.COM char *rname; 13387348SJose.Borrego@Sun.COM 13397348SJose.Borrego@Sun.COM if ((path = sa_get_share_attr(share, "path")) == NULL) 13407348SJose.Borrego@Sun.COM return (NERR_InternalError); 13417348SJose.Borrego@Sun.COM 13427348SJose.Borrego@Sun.COM if ((rname = sa_get_resource_attr(resource, "name")) == NULL) { 13437348SJose.Borrego@Sun.COM sa_free_attr_string(path); 13447348SJose.Borrego@Sun.COM return (NERR_InternalError); 13457348SJose.Borrego@Sun.COM } 13467348SJose.Borrego@Sun.COM 13477348SJose.Borrego@Sun.COM bzero(si, sizeof (smb_share_t)); 13487348SJose.Borrego@Sun.COM si->shr_flags = SMB_SHRF_PERM; 13497348SJose.Borrego@Sun.COM 13507348SJose.Borrego@Sun.COM (void) strlcpy(si->shr_path, path, sizeof (si->shr_path)); 13517348SJose.Borrego@Sun.COM (void) strlcpy(si->shr_name, rname, sizeof (si->shr_name)); 13527348SJose.Borrego@Sun.COM sa_free_attr_string(path); 13537348SJose.Borrego@Sun.COM sa_free_attr_string(rname); 13547348SJose.Borrego@Sun.COM 13557348SJose.Borrego@Sun.COM val = sa_get_resource_description(resource); 13567348SJose.Borrego@Sun.COM if (val == NULL) 13577348SJose.Borrego@Sun.COM val = sa_get_share_description(share); 13587348SJose.Borrego@Sun.COM 13597348SJose.Borrego@Sun.COM if (val != NULL) { 13607348SJose.Borrego@Sun.COM (void) strlcpy(si->shr_cmnt, val, sizeof (si->shr_cmnt)); 13617348SJose.Borrego@Sun.COM sa_free_share_description(val); 13627348SJose.Borrego@Sun.COM } 13637348SJose.Borrego@Sun.COM 13647348SJose.Borrego@Sun.COM opts = sa_get_derived_optionset(resource, SMB_PROTOCOL_NAME, 1); 13657348SJose.Borrego@Sun.COM if (opts == NULL) 13667348SJose.Borrego@Sun.COM return (NERR_Success); 13677348SJose.Borrego@Sun.COM 13688334SJose.Borrego@Sun.COM prop = (sa_property_t)sa_get_property(opts, SHOPT_AD_CONTAINER); 13697348SJose.Borrego@Sun.COM if (prop != NULL) { 13707348SJose.Borrego@Sun.COM if ((val = sa_get_property_attr(prop, "value")) != NULL) { 13717348SJose.Borrego@Sun.COM (void) strlcpy(si->shr_container, val, 13727348SJose.Borrego@Sun.COM sizeof (si->shr_container)); 13737348SJose.Borrego@Sun.COM free(val); 13747348SJose.Borrego@Sun.COM } 13757348SJose.Borrego@Sun.COM } 13767348SJose.Borrego@Sun.COM 1377*9231SAfshin.Ardakani@Sun.COM prop = (sa_property_t)sa_get_property(opts, SHOPT_CATIA); 1378*9231SAfshin.Ardakani@Sun.COM if (prop != NULL) { 1379*9231SAfshin.Ardakani@Sun.COM if ((val = sa_get_property_attr(prop, "value")) != NULL) { 1380*9231SAfshin.Ardakani@Sun.COM smb_shr_sa_catia_option(val, si); 1381*9231SAfshin.Ardakani@Sun.COM free(val); 1382*9231SAfshin.Ardakani@Sun.COM } 1383*9231SAfshin.Ardakani@Sun.COM } 1384*9231SAfshin.Ardakani@Sun.COM 13858334SJose.Borrego@Sun.COM prop = (sa_property_t)sa_get_property(opts, SHOPT_CSC); 13868334SJose.Borrego@Sun.COM if (prop != NULL) { 13878334SJose.Borrego@Sun.COM if ((val = sa_get_property_attr(prop, "value")) != NULL) { 13888334SJose.Borrego@Sun.COM smb_shr_sa_csc_option(val, si); 13898334SJose.Borrego@Sun.COM free(val); 13908334SJose.Borrego@Sun.COM } 13918334SJose.Borrego@Sun.COM } 13928334SJose.Borrego@Sun.COM 13937961SNatalie.Li@Sun.COM prop = (sa_property_t)sa_get_property(opts, SHOPT_NONE); 13947961SNatalie.Li@Sun.COM if (prop != NULL) { 13957961SNatalie.Li@Sun.COM if ((val = sa_get_property_attr(prop, "value")) != NULL) { 13967961SNatalie.Li@Sun.COM (void) strlcpy(si->shr_access_none, val, 13977961SNatalie.Li@Sun.COM sizeof (si->shr_access_none)); 13987961SNatalie.Li@Sun.COM free(val); 13997961SNatalie.Li@Sun.COM si->shr_flags |= SMB_SHRF_ACC_NONE; 14007961SNatalie.Li@Sun.COM } 14017348SJose.Borrego@Sun.COM } 14027348SJose.Borrego@Sun.COM 14037961SNatalie.Li@Sun.COM prop = (sa_property_t)sa_get_property(opts, SHOPT_RO); 14047961SNatalie.Li@Sun.COM if (prop != NULL) { 14057961SNatalie.Li@Sun.COM if ((val = sa_get_property_attr(prop, "value")) != NULL) { 14067961SNatalie.Li@Sun.COM (void) strlcpy(si->shr_access_ro, val, 14077961SNatalie.Li@Sun.COM sizeof (si->shr_access_ro)); 14087961SNatalie.Li@Sun.COM free(val); 14097961SNatalie.Li@Sun.COM si->shr_flags |= SMB_SHRF_ACC_RO; 14107961SNatalie.Li@Sun.COM } 14117348SJose.Borrego@Sun.COM } 14127348SJose.Borrego@Sun.COM 14137961SNatalie.Li@Sun.COM prop = (sa_property_t)sa_get_property(opts, SHOPT_RW); 14147961SNatalie.Li@Sun.COM if (prop != NULL) { 14157961SNatalie.Li@Sun.COM if ((val = sa_get_property_attr(prop, "value")) != NULL) { 14167961SNatalie.Li@Sun.COM (void) strlcpy(si->shr_access_rw, val, 14177961SNatalie.Li@Sun.COM sizeof (si->shr_access_rw)); 14187961SNatalie.Li@Sun.COM free(val); 14197961SNatalie.Li@Sun.COM si->shr_flags |= SMB_SHRF_ACC_RW; 14207961SNatalie.Li@Sun.COM } 14217961SNatalie.Li@Sun.COM } 14227961SNatalie.Li@Sun.COM 14237961SNatalie.Li@Sun.COM sa_free_derived_optionset(opts); 14247961SNatalie.Li@Sun.COM return (NERR_Success); 14257348SJose.Borrego@Sun.COM } 14267348SJose.Borrego@Sun.COM 14277348SJose.Borrego@Sun.COM /* 14288334SJose.Borrego@Sun.COM * Map a client-side caching (CSC) option to the appropriate share 14298334SJose.Borrego@Sun.COM * flag. Only one option is allowed; an error will be logged if 14308334SJose.Borrego@Sun.COM * multiple options have been specified. We don't need to do anything 14318334SJose.Borrego@Sun.COM * about multiple values here because the SRVSVC will not recognize 14328334SJose.Borrego@Sun.COM * a value containing multiple flags and will return the default value. 14338334SJose.Borrego@Sun.COM * 14348334SJose.Borrego@Sun.COM * If the option value is not recognized, it will be ignored: invalid 14358334SJose.Borrego@Sun.COM * values will typically be caught and rejected by sharemgr. 14368334SJose.Borrego@Sun.COM */ 14378474SJose.Borrego@Sun.COM void 14388334SJose.Borrego@Sun.COM smb_shr_sa_csc_option(const char *value, smb_share_t *si) 14398334SJose.Borrego@Sun.COM { 14408334SJose.Borrego@Sun.COM struct { 14418334SJose.Borrego@Sun.COM char *value; 14428334SJose.Borrego@Sun.COM uint32_t flag; 14438334SJose.Borrego@Sun.COM } cscopt[] = { 14448334SJose.Borrego@Sun.COM { "disabled", SMB_SHRF_CSC_DISABLED }, 14458334SJose.Borrego@Sun.COM { "manual", SMB_SHRF_CSC_MANUAL }, 14468334SJose.Borrego@Sun.COM { "auto", SMB_SHRF_CSC_AUTO }, 14478334SJose.Borrego@Sun.COM { "vdo", SMB_SHRF_CSC_VDO } 14488334SJose.Borrego@Sun.COM }; 14498334SJose.Borrego@Sun.COM 14508334SJose.Borrego@Sun.COM int i; 14518334SJose.Borrego@Sun.COM 14528334SJose.Borrego@Sun.COM for (i = 0; i < (sizeof (cscopt) / sizeof (cscopt[0])); ++i) { 14538334SJose.Borrego@Sun.COM if (strcasecmp(value, cscopt[i].value) == 0) { 14548334SJose.Borrego@Sun.COM si->shr_flags |= cscopt[i].flag; 14558334SJose.Borrego@Sun.COM break; 14568334SJose.Borrego@Sun.COM } 14578334SJose.Borrego@Sun.COM } 14588334SJose.Borrego@Sun.COM 14598334SJose.Borrego@Sun.COM switch (si->shr_flags & SMB_SHRF_CSC_MASK) { 14608334SJose.Borrego@Sun.COM case 0: 14618334SJose.Borrego@Sun.COM case SMB_SHRF_CSC_DISABLED: 14628334SJose.Borrego@Sun.COM case SMB_SHRF_CSC_MANUAL: 14638334SJose.Borrego@Sun.COM case SMB_SHRF_CSC_AUTO: 14648334SJose.Borrego@Sun.COM case SMB_SHRF_CSC_VDO: 14658334SJose.Borrego@Sun.COM break; 14668334SJose.Borrego@Sun.COM 14678334SJose.Borrego@Sun.COM default: 14688474SJose.Borrego@Sun.COM syslog(LOG_INFO, "csc option conflict: 0x%08x", 14698474SJose.Borrego@Sun.COM si->shr_flags & SMB_SHRF_CSC_MASK); 14708334SJose.Borrego@Sun.COM break; 14718334SJose.Borrego@Sun.COM } 14728334SJose.Borrego@Sun.COM } 14738334SJose.Borrego@Sun.COM 14748334SJose.Borrego@Sun.COM /* 1475*9231SAfshin.Ardakani@Sun.COM * set SMB_SHRF_CATIA in accordance with catia property value 1476*9231SAfshin.Ardakani@Sun.COM */ 1477*9231SAfshin.Ardakani@Sun.COM void 1478*9231SAfshin.Ardakani@Sun.COM smb_shr_sa_catia_option(const char *value, smb_share_t *si) 1479*9231SAfshin.Ardakani@Sun.COM { 1480*9231SAfshin.Ardakani@Sun.COM if ((strcasecmp(value, "true") == 0) || (strcmp(value, "1") == 0)) { 1481*9231SAfshin.Ardakani@Sun.COM si->shr_flags |= SMB_SHRF_CATIA; 1482*9231SAfshin.Ardakani@Sun.COM } else { 1483*9231SAfshin.Ardakani@Sun.COM si->shr_flags &= ~SMB_SHRF_CATIA; 1484*9231SAfshin.Ardakani@Sun.COM } 1485*9231SAfshin.Ardakani@Sun.COM } 1486*9231SAfshin.Ardakani@Sun.COM 1487*9231SAfshin.Ardakani@Sun.COM /* 14888334SJose.Borrego@Sun.COM * looks up sharemgr for the given share (resource) and loads 14898334SJose.Borrego@Sun.COM * the definition into cache if lookup is successful 14908334SJose.Borrego@Sun.COM */ 14918334SJose.Borrego@Sun.COM static uint32_t 14928334SJose.Borrego@Sun.COM smb_shr_sa_loadbyname(char *sharename) 14938334SJose.Borrego@Sun.COM { 14948334SJose.Borrego@Sun.COM sa_handle_t handle; 14958334SJose.Borrego@Sun.COM sa_share_t share; 14968334SJose.Borrego@Sun.COM sa_resource_t resource; 14978334SJose.Borrego@Sun.COM uint32_t status; 14988334SJose.Borrego@Sun.COM 14998474SJose.Borrego@Sun.COM if ((handle = smb_shr_sa_enter()) == NULL) 15008334SJose.Borrego@Sun.COM return (NERR_InternalError); 15018334SJose.Borrego@Sun.COM 15028334SJose.Borrego@Sun.COM resource = sa_find_resource(handle, sharename); 15038334SJose.Borrego@Sun.COM if (resource == NULL) { 15048474SJose.Borrego@Sun.COM smb_shr_sa_exit(); 15058334SJose.Borrego@Sun.COM return (NERR_NetNameNotFound); 15068334SJose.Borrego@Sun.COM } 15078334SJose.Borrego@Sun.COM 15088334SJose.Borrego@Sun.COM share = sa_get_resource_parent(resource); 15098334SJose.Borrego@Sun.COM if (share == NULL) { 15108474SJose.Borrego@Sun.COM smb_shr_sa_exit(); 15118334SJose.Borrego@Sun.COM return (NERR_InternalError); 15128334SJose.Borrego@Sun.COM } 15138334SJose.Borrego@Sun.COM 15148334SJose.Borrego@Sun.COM status = smb_shr_sa_load(share, resource); 15158334SJose.Borrego@Sun.COM 15168474SJose.Borrego@Sun.COM smb_shr_sa_exit(); 15178334SJose.Borrego@Sun.COM return (status); 15188334SJose.Borrego@Sun.COM } 15198334SJose.Borrego@Sun.COM 15208334SJose.Borrego@Sun.COM /* 15217348SJose.Borrego@Sun.COM * ============================================ 15227348SJose.Borrego@Sun.COM * Share publishing functions 15237961SNatalie.Li@Sun.COM * 15247961SNatalie.Li@Sun.COM * All the functions are private 15257348SJose.Borrego@Sun.COM * ============================================ 15267348SJose.Borrego@Sun.COM */ 15277348SJose.Borrego@Sun.COM 15287961SNatalie.Li@Sun.COM static void 15297961SNatalie.Li@Sun.COM smb_shr_publish(const char *sharename, const char *container) 15307961SNatalie.Li@Sun.COM { 15317961SNatalie.Li@Sun.COM smb_shr_publisher_queue(sharename, container, SMB_SHR_PUBLISH); 15327961SNatalie.Li@Sun.COM } 15337961SNatalie.Li@Sun.COM 15347961SNatalie.Li@Sun.COM static void 15357961SNatalie.Li@Sun.COM smb_shr_unpublish(const char *sharename, const char *container) 15367961SNatalie.Li@Sun.COM { 15377961SNatalie.Li@Sun.COM smb_shr_publisher_queue(sharename, container, SMB_SHR_UNPUBLISH); 15387961SNatalie.Li@Sun.COM } 15397961SNatalie.Li@Sun.COM 15407348SJose.Borrego@Sun.COM /* 15417961SNatalie.Li@Sun.COM * In domain mode, put a share on the publisher queue. 15427961SNatalie.Li@Sun.COM * This is a no-op if the smb service is in Workgroup mode. 15437348SJose.Borrego@Sun.COM */ 15447348SJose.Borrego@Sun.COM static void 15457961SNatalie.Li@Sun.COM smb_shr_publisher_queue(const char *sharename, const char *container, char op) 15467348SJose.Borrego@Sun.COM { 15477348SJose.Borrego@Sun.COM smb_shr_pitem_t *item = NULL; 15487348SJose.Borrego@Sun.COM 15497348SJose.Borrego@Sun.COM if (container == NULL || *container == '\0') 15507348SJose.Borrego@Sun.COM return; 15517348SJose.Borrego@Sun.COM 15527961SNatalie.Li@Sun.COM if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN) 15537961SNatalie.Li@Sun.COM return; 15547961SNatalie.Li@Sun.COM 15557348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 15567348SJose.Borrego@Sun.COM switch (ad_queue.spq_state) { 15577348SJose.Borrego@Sun.COM case SMB_SHR_PQS_READY: 15587348SJose.Borrego@Sun.COM case SMB_SHR_PQS_PUBLISHING: 15597348SJose.Borrego@Sun.COM break; 15607348SJose.Borrego@Sun.COM default: 15617348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 15627348SJose.Borrego@Sun.COM return; 15637348SJose.Borrego@Sun.COM } 15647348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 15657348SJose.Borrego@Sun.COM 15667961SNatalie.Li@Sun.COM if ((item = malloc(sizeof (smb_shr_pitem_t))) == NULL) 15677348SJose.Borrego@Sun.COM return; 15687348SJose.Borrego@Sun.COM 15697348SJose.Borrego@Sun.COM item->spi_op = op; 15707348SJose.Borrego@Sun.COM (void) strlcpy(item->spi_name, sharename, sizeof (item->spi_name)); 15717348SJose.Borrego@Sun.COM (void) strlcpy(item->spi_container, container, 15727348SJose.Borrego@Sun.COM sizeof (item->spi_container)); 15737348SJose.Borrego@Sun.COM 15747348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 15757348SJose.Borrego@Sun.COM list_insert_tail(&ad_queue.spq_list, item); 15767348SJose.Borrego@Sun.COM (void) cond_signal(&ad_queue.spq_cv); 15777348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 15787348SJose.Borrego@Sun.COM } 15797348SJose.Borrego@Sun.COM 15807961SNatalie.Li@Sun.COM /* 15817961SNatalie.Li@Sun.COM * Publishing won't be activated if the smb service is running in 15827961SNatalie.Li@Sun.COM * Workgroup mode. 15837961SNatalie.Li@Sun.COM */ 15847348SJose.Borrego@Sun.COM static int 15857348SJose.Borrego@Sun.COM smb_shr_publisher_start(void) 15867348SJose.Borrego@Sun.COM { 15877961SNatalie.Li@Sun.COM pthread_t publish_thr; 15887348SJose.Borrego@Sun.COM pthread_attr_t tattr; 15897348SJose.Borrego@Sun.COM int rc; 15907348SJose.Borrego@Sun.COM 15917961SNatalie.Li@Sun.COM if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN) 15927961SNatalie.Li@Sun.COM return (0); 15937961SNatalie.Li@Sun.COM 15947348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 15957348SJose.Borrego@Sun.COM if (ad_queue.spq_state != SMB_SHR_PQS_NOQUEUE) { 15967348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 15977348SJose.Borrego@Sun.COM errno = EINVAL; 15987348SJose.Borrego@Sun.COM return (-1); 15997348SJose.Borrego@Sun.COM } 16007348SJose.Borrego@Sun.COM 16017348SJose.Borrego@Sun.COM list_create(&ad_queue.spq_list, sizeof (smb_shr_pitem_t), 16027348SJose.Borrego@Sun.COM offsetof(smb_shr_pitem_t, spi_lnd)); 16037348SJose.Borrego@Sun.COM ad_queue.spq_state = SMB_SHR_PQS_READY; 16047348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 16057348SJose.Borrego@Sun.COM 16067348SJose.Borrego@Sun.COM (void) pthread_attr_init(&tattr); 16077348SJose.Borrego@Sun.COM (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); 16087961SNatalie.Li@Sun.COM rc = pthread_create(&publish_thr, &tattr, smb_shr_publisher, 0); 16097348SJose.Borrego@Sun.COM (void) pthread_attr_destroy(&tattr); 16107348SJose.Borrego@Sun.COM 16117348SJose.Borrego@Sun.COM return (rc); 16127348SJose.Borrego@Sun.COM } 16137348SJose.Borrego@Sun.COM 16147348SJose.Borrego@Sun.COM static void 16157348SJose.Borrego@Sun.COM smb_shr_publisher_stop(void) 16167348SJose.Borrego@Sun.COM { 16177961SNatalie.Li@Sun.COM if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN) 16187961SNatalie.Li@Sun.COM return; 16197961SNatalie.Li@Sun.COM 16207348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 16217348SJose.Borrego@Sun.COM switch (ad_queue.spq_state) { 16227348SJose.Borrego@Sun.COM case SMB_SHR_PQS_READY: 16237348SJose.Borrego@Sun.COM case SMB_SHR_PQS_PUBLISHING: 16247348SJose.Borrego@Sun.COM ad_queue.spq_state = SMB_SHR_PQS_STOPPING; 16257348SJose.Borrego@Sun.COM (void) cond_signal(&ad_queue.spq_cv); 16267348SJose.Borrego@Sun.COM break; 16277348SJose.Borrego@Sun.COM default: 16287348SJose.Borrego@Sun.COM break; 16297348SJose.Borrego@Sun.COM } 16307348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 16317348SJose.Borrego@Sun.COM } 16327348SJose.Borrego@Sun.COM 16337348SJose.Borrego@Sun.COM /* 16347961SNatalie.Li@Sun.COM * This is the publisher daemon thread. While running, the thread waits 16357961SNatalie.Li@Sun.COM * on a conditional variable until notified that a share needs to be 16367961SNatalie.Li@Sun.COM * [un]published or that the thread should be terminated. 16377961SNatalie.Li@Sun.COM * 16387961SNatalie.Li@Sun.COM * Entries may remain in the outgoing queue if the Active Directory 16397961SNatalie.Li@Sun.COM * service is inaccessible, in which case the thread wakes up every 60 16407961SNatalie.Li@Sun.COM * seconds to retry. 16417348SJose.Borrego@Sun.COM */ 16427348SJose.Borrego@Sun.COM /*ARGSUSED*/ 16437348SJose.Borrego@Sun.COM static void * 16447348SJose.Borrego@Sun.COM smb_shr_publisher(void *arg) 16457348SJose.Borrego@Sun.COM { 16467348SJose.Borrego@Sun.COM smb_ads_handle_t *ah; 16477348SJose.Borrego@Sun.COM smb_shr_pitem_t *shr; 16487348SJose.Borrego@Sun.COM list_t publist; 16497961SNatalie.Li@Sun.COM timestruc_t pubretry; 16507348SJose.Borrego@Sun.COM char hostname[MAXHOSTNAMELEN]; 16517348SJose.Borrego@Sun.COM 16527348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 16537961SNatalie.Li@Sun.COM if (ad_queue.spq_state != SMB_SHR_PQS_READY) { 16547348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 16557348SJose.Borrego@Sun.COM return (NULL); 16567348SJose.Borrego@Sun.COM } 16577961SNatalie.Li@Sun.COM ad_queue.spq_state = SMB_SHR_PQS_PUBLISHING; 16587348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 16597348SJose.Borrego@Sun.COM 16607348SJose.Borrego@Sun.COM (void) smb_gethostname(hostname, MAXHOSTNAMELEN, 0); 16617961SNatalie.Li@Sun.COM 16627348SJose.Borrego@Sun.COM list_create(&publist, sizeof (smb_shr_pitem_t), 16637348SJose.Borrego@Sun.COM offsetof(smb_shr_pitem_t, spi_lnd)); 16647348SJose.Borrego@Sun.COM 16657348SJose.Borrego@Sun.COM for (;;) { 16667348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 16677961SNatalie.Li@Sun.COM 16687961SNatalie.Li@Sun.COM while (list_is_empty(&ad_queue.spq_list) && 16697961SNatalie.Li@Sun.COM (ad_queue.spq_state == SMB_SHR_PQS_PUBLISHING)) { 16707961SNatalie.Li@Sun.COM if (list_is_empty(&publist)) { 16717961SNatalie.Li@Sun.COM (void) cond_wait(&ad_queue.spq_cv, 16727961SNatalie.Li@Sun.COM &ad_queue.spq_mtx); 16737961SNatalie.Li@Sun.COM } else { 16747961SNatalie.Li@Sun.COM pubretry.tv_sec = 60; 16757961SNatalie.Li@Sun.COM pubretry.tv_nsec = 0; 16767961SNatalie.Li@Sun.COM (void) cond_reltimedwait(&ad_queue.spq_cv, 16777961SNatalie.Li@Sun.COM &ad_queue.spq_mtx, &pubretry); 16787961SNatalie.Li@Sun.COM break; 16797961SNatalie.Li@Sun.COM } 16807961SNatalie.Li@Sun.COM } 16817348SJose.Borrego@Sun.COM 16827348SJose.Borrego@Sun.COM if (ad_queue.spq_state != SMB_SHR_PQS_PUBLISHING) { 16837348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 16847348SJose.Borrego@Sun.COM break; 16857348SJose.Borrego@Sun.COM } 16867348SJose.Borrego@Sun.COM 16877348SJose.Borrego@Sun.COM /* 16887961SNatalie.Li@Sun.COM * Transfer queued items to the local list so that 16897961SNatalie.Li@Sun.COM * the mutex can be released. 16907348SJose.Borrego@Sun.COM */ 16917348SJose.Borrego@Sun.COM while ((shr = list_head(&ad_queue.spq_list)) != NULL) { 16927348SJose.Borrego@Sun.COM list_remove(&ad_queue.spq_list, shr); 16937348SJose.Borrego@Sun.COM list_insert_tail(&publist, shr); 16947348SJose.Borrego@Sun.COM } 16957961SNatalie.Li@Sun.COM 16967348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 16977348SJose.Borrego@Sun.COM 16987961SNatalie.Li@Sun.COM if ((ah = smb_ads_open()) != NULL) { 16997961SNatalie.Li@Sun.COM smb_shr_publisher_send(ah, &publist, hostname); 17007961SNatalie.Li@Sun.COM smb_ads_close(ah); 17017961SNatalie.Li@Sun.COM } 17027348SJose.Borrego@Sun.COM } 17037348SJose.Borrego@Sun.COM 17047348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 17057961SNatalie.Li@Sun.COM smb_shr_publisher_flush(&ad_queue.spq_list); 17067348SJose.Borrego@Sun.COM list_destroy(&ad_queue.spq_list); 17077348SJose.Borrego@Sun.COM ad_queue.spq_state = SMB_SHR_PQS_NOQUEUE; 17087348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 17097348SJose.Borrego@Sun.COM 17107961SNatalie.Li@Sun.COM smb_shr_publisher_flush(&publist); 17117348SJose.Borrego@Sun.COM list_destroy(&publist); 17127348SJose.Borrego@Sun.COM return (NULL); 17137348SJose.Borrego@Sun.COM } 17147348SJose.Borrego@Sun.COM 17157348SJose.Borrego@Sun.COM /* 17167961SNatalie.Li@Sun.COM * Remove items from the specified queue and [un]publish them. 17177348SJose.Borrego@Sun.COM */ 17187348SJose.Borrego@Sun.COM static void 17197348SJose.Borrego@Sun.COM smb_shr_publisher_send(smb_ads_handle_t *ah, list_t *publist, const char *host) 17207348SJose.Borrego@Sun.COM { 17217348SJose.Borrego@Sun.COM smb_shr_pitem_t *shr; 17227348SJose.Borrego@Sun.COM 17237348SJose.Borrego@Sun.COM while ((shr = list_head(publist)) != NULL) { 17247961SNatalie.Li@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 17257961SNatalie.Li@Sun.COM if (ad_queue.spq_state != SMB_SHR_PQS_PUBLISHING) { 17267348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 17277961SNatalie.Li@Sun.COM return; 17287961SNatalie.Li@Sun.COM } 17297961SNatalie.Li@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 17307348SJose.Borrego@Sun.COM 17317961SNatalie.Li@Sun.COM list_remove(publist, shr); 17327961SNatalie.Li@Sun.COM 17337961SNatalie.Li@Sun.COM if (shr->spi_op == SMB_SHR_PUBLISH) 17347961SNatalie.Li@Sun.COM (void) smb_ads_publish_share(ah, shr->spi_name, 17357961SNatalie.Li@Sun.COM NULL, shr->spi_container, host); 17367961SNatalie.Li@Sun.COM else 17377961SNatalie.Li@Sun.COM (void) smb_ads_remove_share(ah, shr->spi_name, 17387961SNatalie.Li@Sun.COM NULL, shr->spi_container, host); 17397961SNatalie.Li@Sun.COM 17407348SJose.Borrego@Sun.COM free(shr); 17417348SJose.Borrego@Sun.COM } 17427348SJose.Borrego@Sun.COM } 17437961SNatalie.Li@Sun.COM 17447961SNatalie.Li@Sun.COM /* 17457961SNatalie.Li@Sun.COM * Flush all remaining items from the specified list/queue. 17467961SNatalie.Li@Sun.COM */ 17477961SNatalie.Li@Sun.COM static void 17487961SNatalie.Li@Sun.COM smb_shr_publisher_flush(list_t *lst) 17497961SNatalie.Li@Sun.COM { 17507961SNatalie.Li@Sun.COM smb_shr_pitem_t *shr; 17517961SNatalie.Li@Sun.COM 17527961SNatalie.Li@Sun.COM while ((shr = list_head(lst)) != NULL) { 17537961SNatalie.Li@Sun.COM list_remove(lst, shr); 17547961SNatalie.Li@Sun.COM free(shr); 17557961SNatalie.Li@Sun.COM } 17567961SNatalie.Li@Sun.COM } 17578845Samw@Sun.COM 17588845Samw@Sun.COM /* 17598871Samw@Sun.COM * If the share path refers to a ZFS file system, add the 17608845Samw@Sun.COM * .zfs/shares/<share> object. 17618845Samw@Sun.COM */ 17628845Samw@Sun.COM 17638845Samw@Sun.COM static void 17648845Samw@Sun.COM smb_shr_zfs_add(smb_share_t *si) 17658845Samw@Sun.COM { 17668871Samw@Sun.COM libzfs_handle_t *libhd; 17678871Samw@Sun.COM zfs_handle_t *zfshd; 17688871Samw@Sun.COM int ret; 17698845Samw@Sun.COM char dataset[MAXPATHLEN]; 17708845Samw@Sun.COM 17718871Samw@Sun.COM if (smb_getdataset(si->shr_path, dataset, MAXPATHLEN) != 0) 17728871Samw@Sun.COM return; 17738871Samw@Sun.COM 17748871Samw@Sun.COM if ((libhd = libzfs_init()) == NULL) 17758871Samw@Sun.COM return; 17768871Samw@Sun.COM 17778871Samw@Sun.COM if ((zfshd = zfs_open(libhd, dataset, ZFS_TYPE_FILESYSTEM)) == NULL) { 17788871Samw@Sun.COM libzfs_fini(libhd); 17798871Samw@Sun.COM return; 17808845Samw@Sun.COM } 17818871Samw@Sun.COM 17828871Samw@Sun.COM errno = 0; 17838871Samw@Sun.COM ret = zfs_smb_acl_add(libhd, dataset, si->shr_path, si->shr_name); 17848871Samw@Sun.COM if (ret != 0 && errno != EAGAIN && errno != EEXIST) 17858871Samw@Sun.COM syslog(LOG_INFO, "share: failed to add ACL object: %s: %s\n", 17868871Samw@Sun.COM si->shr_name, strerror(errno)); 17878871Samw@Sun.COM 17888871Samw@Sun.COM zfs_close(zfshd); 17898871Samw@Sun.COM libzfs_fini(libhd); 17908845Samw@Sun.COM } 17918845Samw@Sun.COM 17928845Samw@Sun.COM /* 17938871Samw@Sun.COM * If the share path refers to a ZFS file system, remove the 17948845Samw@Sun.COM * .zfs/shares/<share> object. 17958845Samw@Sun.COM */ 17968845Samw@Sun.COM 17978845Samw@Sun.COM static void 17988845Samw@Sun.COM smb_shr_zfs_remove(smb_share_t *si) 17998845Samw@Sun.COM { 18008871Samw@Sun.COM libzfs_handle_t *libhd; 18018871Samw@Sun.COM zfs_handle_t *zfshd; 18028871Samw@Sun.COM int ret; 18038845Samw@Sun.COM char dataset[MAXPATHLEN]; 18048845Samw@Sun.COM 18058871Samw@Sun.COM if (smb_getdataset(si->shr_path, dataset, MAXPATHLEN) != 0) 18068871Samw@Sun.COM return; 18078871Samw@Sun.COM 18088871Samw@Sun.COM if ((libhd = libzfs_init()) == NULL) 18098871Samw@Sun.COM return; 18108871Samw@Sun.COM 18118871Samw@Sun.COM if ((zfshd = zfs_open(libhd, dataset, ZFS_TYPE_FILESYSTEM)) == NULL) { 18128871Samw@Sun.COM libzfs_fini(libhd); 18138871Samw@Sun.COM return; 18148845Samw@Sun.COM } 18158871Samw@Sun.COM 18168871Samw@Sun.COM errno = 0; 18178871Samw@Sun.COM ret = zfs_smb_acl_remove(libhd, dataset, si->shr_path, si->shr_name); 18188871Samw@Sun.COM if (ret != 0 && errno != EAGAIN) 18198871Samw@Sun.COM syslog(LOG_INFO, "share: failed to remove ACL object: %s: %s\n", 18208871Samw@Sun.COM si->shr_name, strerror(errno)); 18218871Samw@Sun.COM 18228871Samw@Sun.COM zfs_close(zfshd); 18238871Samw@Sun.COM libzfs_fini(libhd); 18248845Samw@Sun.COM } 18258845Samw@Sun.COM 18268845Samw@Sun.COM /* 18278871Samw@Sun.COM * If the share path refers to a ZFS file system, rename the 18288845Samw@Sun.COM * .zfs/shares/<share> object. 18298845Samw@Sun.COM */ 18308845Samw@Sun.COM 18318845Samw@Sun.COM static void 18328845Samw@Sun.COM smb_shr_zfs_rename(smb_share_t *from, smb_share_t *to) 18338845Samw@Sun.COM { 18348871Samw@Sun.COM libzfs_handle_t *libhd; 18358871Samw@Sun.COM zfs_handle_t *zfshd; 18368871Samw@Sun.COM int ret; 18378845Samw@Sun.COM char dataset[MAXPATHLEN]; 18388845Samw@Sun.COM 18398871Samw@Sun.COM if (smb_getdataset(from->shr_path, dataset, MAXPATHLEN) != 0) 18408871Samw@Sun.COM return; 18418871Samw@Sun.COM 18428871Samw@Sun.COM if ((libhd = libzfs_init()) == NULL) 18438871Samw@Sun.COM return; 18448871Samw@Sun.COM 18458871Samw@Sun.COM if ((zfshd = zfs_open(libhd, dataset, ZFS_TYPE_FILESYSTEM)) == NULL) { 18468871Samw@Sun.COM libzfs_fini(libhd); 18478871Samw@Sun.COM return; 18488845Samw@Sun.COM } 18498871Samw@Sun.COM 18508871Samw@Sun.COM errno = 0; 18518871Samw@Sun.COM ret = zfs_smb_acl_rename(libhd, dataset, from->shr_path, 18528871Samw@Sun.COM from->shr_name, to->shr_name); 18538871Samw@Sun.COM if (ret != 0 && errno != EAGAIN) 18548871Samw@Sun.COM syslog(LOG_INFO, "share: failed to rename ACL object: %s: %s\n", 18558871Samw@Sun.COM from->shr_name, strerror(errno)); 18568871Samw@Sun.COM 18578871Samw@Sun.COM zfs_close(zfshd); 18588871Samw@Sun.COM libzfs_fini(libhd); 18598845Samw@Sun.COM } 1860