17052Samw /* 27052Samw * CDDL HEADER START 37052Samw * 47052Samw * The contents of this file are subject to the terms of the 57052Samw * Common Development and Distribution License (the "License"). 67052Samw * You may not use this file except in compliance with the License. 77052Samw * 87052Samw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97052Samw * or http://www.opensolaris.org/os/licensing. 107052Samw * See the License for the specific language governing permissions 117052Samw * and limitations under the License. 127052Samw * 137052Samw * When distributing Covered Code, include this CDDL HEADER in each 147052Samw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157052Samw * If applicable, add the following below this CDDL HEADER, with the 167052Samw * fields enclosed by brackets "[]" replaced with your own identifying 177052Samw * information: Portions Copyright [yyyy] [name of copyright owner] 187052Samw * 197052Samw * CDDL HEADER END 207052Samw */ 217052Samw /* 227052Samw * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 237052Samw * Use is subject to license terms. 247052Samw */ 257052Samw 26*7348SJose.Borrego@Sun.COM #pragma ident "@(#)smb_share.c 1.7 08/08/07 SMI" 277052Samw 287052Samw /* 297052Samw * Lan Manager (SMB/CIFS) share interface implementation. This interface 307052Samw * returns Win32 error codes, usually network error values (lmerr.h). 317052Samw */ 327052Samw 337052Samw #include <errno.h> 347052Samw #include <synch.h> 357052Samw #include <stdio.h> 367052Samw #include <stdlib.h> 377052Samw #include <strings.h> 387052Samw #include <syslog.h> 397052Samw #include <thread.h> 407052Samw #include <fcntl.h> 417052Samw #include <unistd.h> 427052Samw #include <netdb.h> 437052Samw #include <synch.h> 447052Samw #include <pthread.h> 45*7348SJose.Borrego@Sun.COM #include <ctype.h> 46*7348SJose.Borrego@Sun.COM #include <assert.h> 477052Samw #include <sys/mnttab.h> 487052Samw #include <sys/stat.h> 497052Samw #include <sys/types.h> 507052Samw 517052Samw #include <smbsrv/libsmb.h> 527052Samw #include <smbsrv/libsmbns.h> 537052Samw 547052Samw #include <libshare.h> 557052Samw 567052Samw #include <smbsrv/lm.h> 577052Samw #include <smbsrv/smb_share.h> 587052Samw #include <smbsrv/cifs.h> 597052Samw 607052Samw #include <smbsrv/ctype.h> 617052Samw #include <smbsrv/smb_vops.h> 62*7348SJose.Borrego@Sun.COM #include <smbsrv/nterror.h> 637052Samw 64*7348SJose.Borrego@Sun.COM /* 65*7348SJose.Borrego@Sun.COM * Cache functions and vars 66*7348SJose.Borrego@Sun.COM */ 677052Samw #define SMB_SHARE_HTAB_SZ 1024 687052Samw 697052Samw static HT_HANDLE *smb_shr_handle = NULL; 707052Samw static rwlock_t smb_shr_lock; 71*7348SJose.Borrego@Sun.COM static pthread_t smb_shr_populate_thr; 727052Samw 737052Samw static uint32_t smb_shr_cache_create(void); 74*7348SJose.Borrego@Sun.COM static void smb_shr_cache_destroy(void); 757052Samw static void *smb_shr_cache_populate(void *); 76*7348SJose.Borrego@Sun.COM static uint32_t smb_shr_cache_addent(smb_share_t *); 77*7348SJose.Borrego@Sun.COM static void smb_shr_cache_delent(char *); 78*7348SJose.Borrego@Sun.COM static uint32_t smb_shr_cache_chgent(smb_share_t *); 79*7348SJose.Borrego@Sun.COM static void smb_shr_cache_freent(HT_ITEM *); 80*7348SJose.Borrego@Sun.COM static uint32_t smb_shr_cache_loadent(sa_share_t, sa_resource_t); 81*7348SJose.Borrego@Sun.COM static void smb_shr_cache_loadgrp(sa_group_t); 827052Samw 83*7348SJose.Borrego@Sun.COM static void smb_shr_set_ahcnt(char *, int); 84*7348SJose.Borrego@Sun.COM static void smb_shr_set_oemname(smb_share_t *); 85*7348SJose.Borrego@Sun.COM static uint32_t smb_shr_create_autohome(smb_share_t *); 86*7348SJose.Borrego@Sun.COM static uint32_t smb_shr_create_ipc(void); 877052Samw 88*7348SJose.Borrego@Sun.COM /* 89*7348SJose.Borrego@Sun.COM * sharemgr functions 90*7348SJose.Borrego@Sun.COM */ 91*7348SJose.Borrego@Sun.COM static uint32_t smb_shr_sa_delent(smb_share_t *); 92*7348SJose.Borrego@Sun.COM static uint32_t smb_shr_sa_addent(smb_share_t *); 93*7348SJose.Borrego@Sun.COM static uint32_t smb_shr_sa_getent(sa_share_t, sa_resource_t, smb_share_t *); 94*7348SJose.Borrego@Sun.COM static sa_group_t smb_shr_sa_getdefgrp(sa_handle_t); 957052Samw 967052Samw /* 97*7348SJose.Borrego@Sun.COM * share publishing 98*7348SJose.Borrego@Sun.COM */ 99*7348SJose.Borrego@Sun.COM #define SMB_SHR_PUBLISH 0 100*7348SJose.Borrego@Sun.COM #define SMB_SHR_UNPUBLISH 1 101*7348SJose.Borrego@Sun.COM 102*7348SJose.Borrego@Sun.COM typedef struct smb_shr_pitem { 103*7348SJose.Borrego@Sun.COM list_node_t spi_lnd; 104*7348SJose.Borrego@Sun.COM char spi_name[MAXNAMELEN]; 105*7348SJose.Borrego@Sun.COM char spi_container[MAXPATHLEN]; 106*7348SJose.Borrego@Sun.COM char spi_op; 107*7348SJose.Borrego@Sun.COM } smb_shr_pitem_t; 108*7348SJose.Borrego@Sun.COM 109*7348SJose.Borrego@Sun.COM /* 110*7348SJose.Borrego@Sun.COM * publish queue states 111*7348SJose.Borrego@Sun.COM */ 112*7348SJose.Borrego@Sun.COM #define SMB_SHR_PQS_NOQUEUE 0 113*7348SJose.Borrego@Sun.COM #define SMB_SHR_PQS_READY 1 /* the queue is ready */ 114*7348SJose.Borrego@Sun.COM #define SMB_SHR_PQS_PUBLISHING 2 /* publisher thread is running */ 115*7348SJose.Borrego@Sun.COM #define SMB_SHR_PQS_STOPPING 3 116*7348SJose.Borrego@Sun.COM 117*7348SJose.Borrego@Sun.COM /* 118*7348SJose.Borrego@Sun.COM * share publishing queue 119*7348SJose.Borrego@Sun.COM */ 120*7348SJose.Borrego@Sun.COM typedef struct smb_shr_pqueue { 121*7348SJose.Borrego@Sun.COM int spq_cnt; 122*7348SJose.Borrego@Sun.COM list_t spq_list; 123*7348SJose.Borrego@Sun.COM mutex_t spq_mtx; 124*7348SJose.Borrego@Sun.COM cond_t spq_cv; 125*7348SJose.Borrego@Sun.COM uint32_t spq_state; 126*7348SJose.Borrego@Sun.COM } smb_shr_pqueue_t; 127*7348SJose.Borrego@Sun.COM 128*7348SJose.Borrego@Sun.COM static smb_shr_pqueue_t ad_queue; 129*7348SJose.Borrego@Sun.COM static pthread_t smb_shr_publish_thr; 130*7348SJose.Borrego@Sun.COM 131*7348SJose.Borrego@Sun.COM static int smb_shr_publisher_start(void); 132*7348SJose.Borrego@Sun.COM static void smb_shr_publisher_stop(void); 133*7348SJose.Borrego@Sun.COM static void smb_shr_publisher_send(smb_ads_handle_t *, list_t *, const char *); 134*7348SJose.Borrego@Sun.COM static void *smb_shr_publisher(void *); 135*7348SJose.Borrego@Sun.COM static void smb_shr_publish(const char *, const char *, char); 136*7348SJose.Borrego@Sun.COM 137*7348SJose.Borrego@Sun.COM 138*7348SJose.Borrego@Sun.COM /* 139*7348SJose.Borrego@Sun.COM * smb_shr_start 140*7348SJose.Borrego@Sun.COM * 141*7348SJose.Borrego@Sun.COM * Starts the publisher thread and another thread which 142*7348SJose.Borrego@Sun.COM * populates the share cache by share information stored 143*7348SJose.Borrego@Sun.COM * by sharemgr 1447052Samw */ 1457052Samw int 1467052Samw smb_shr_start(void) 1477052Samw { 148*7348SJose.Borrego@Sun.COM pthread_attr_t tattr; 1497052Samw int rc; 1507052Samw 151*7348SJose.Borrego@Sun.COM if ((rc = smb_shr_publisher_start()) != 0) 152*7348SJose.Borrego@Sun.COM return (rc); 1537052Samw 154*7348SJose.Borrego@Sun.COM (void) pthread_attr_init(&tattr); 155*7348SJose.Borrego@Sun.COM (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); 156*7348SJose.Borrego@Sun.COM rc = pthread_create(&smb_shr_populate_thr, &tattr, 1577052Samw smb_shr_cache_populate, 0); 158*7348SJose.Borrego@Sun.COM (void) pthread_attr_destroy(&tattr); 1597052Samw 1607052Samw return (rc); 1617052Samw } 1627052Samw 1637052Samw void 1647052Samw smb_shr_stop(void) 1657052Samw { 166*7348SJose.Borrego@Sun.COM smb_shr_cache_destroy(); 167*7348SJose.Borrego@Sun.COM smb_shr_publisher_stop(); 1687052Samw } 1697052Samw 1707052Samw /* 1717052Samw * smb_shr_count 1727052Samw * 173*7348SJose.Borrego@Sun.COM * Return the total number of shares 1747052Samw */ 1757052Samw int 1767052Samw smb_shr_count(void) 1777052Samw { 1787052Samw int n_shares; 1797052Samw 180*7348SJose.Borrego@Sun.COM (void) rw_rdlock(&smb_shr_lock); 1817052Samw n_shares = ht_get_total_items(smb_shr_handle); 182*7348SJose.Borrego@Sun.COM (void) rw_unlock(&smb_shr_lock); 1837052Samw 1847052Samw return (n_shares); 1857052Samw } 1867052Samw 1877052Samw /* 1887052Samw * smb_shr_iterinit 1897052Samw * 190*7348SJose.Borrego@Sun.COM * Initialize given iterator for traversing hash table. 1917052Samw */ 1927052Samw void 193*7348SJose.Borrego@Sun.COM smb_shr_iterinit(smb_shriter_t *shi) 1947052Samw { 1957052Samw bzero(shi, sizeof (smb_shriter_t)); 196*7348SJose.Borrego@Sun.COM shi->si_first = B_TRUE; 1977052Samw } 1987052Samw 1997052Samw /* 2007052Samw * smb_shr_iterate 2017052Samw * 2027052Samw * Iterate on the shares in the hash table. The iterator must be initialized 2037052Samw * before the first iteration. On subsequent calls, the iterator must be 2047052Samw * passed unchanged. 2057052Samw * 2067052Samw * Returns NULL on failure or when all shares are visited, otherwise 2077052Samw * returns information of visited share. 2087052Samw */ 2097052Samw smb_share_t * 2107052Samw smb_shr_iterate(smb_shriter_t *shi) 2117052Samw { 2127052Samw HT_ITEM *item; 213*7348SJose.Borrego@Sun.COM smb_share_t *share = NULL; 2147052Samw 2157052Samw if (smb_shr_handle == NULL || shi == NULL) 2167052Samw return (NULL); 2177052Samw 218*7348SJose.Borrego@Sun.COM (void) rw_rdlock(&smb_shr_lock); 219*7348SJose.Borrego@Sun.COM if (shi->si_first) { 220*7348SJose.Borrego@Sun.COM item = ht_findfirst(smb_shr_handle, &shi->si_hashiter); 221*7348SJose.Borrego@Sun.COM shi->si_first = B_FALSE; 222*7348SJose.Borrego@Sun.COM } else { 223*7348SJose.Borrego@Sun.COM item = ht_findnext(&shi->si_hashiter); 2247052Samw } 2257052Samw 226*7348SJose.Borrego@Sun.COM if (item && item->hi_data) { 227*7348SJose.Borrego@Sun.COM share = &shi->si_share; 228*7348SJose.Borrego@Sun.COM bcopy(item->hi_data, share, sizeof (smb_share_t)); 229*7348SJose.Borrego@Sun.COM } 230*7348SJose.Borrego@Sun.COM (void) rw_unlock(&smb_shr_lock); 2317052Samw 232*7348SJose.Borrego@Sun.COM return (share); 2337052Samw } 2347052Samw 2357052Samw /* 236*7348SJose.Borrego@Sun.COM * smb_shr_create 2377052Samw * 238*7348SJose.Borrego@Sun.COM * Adds the given to cache and if 'store' is B_TRUE it's also 239*7348SJose.Borrego@Sun.COM * added to sharemgr 2407052Samw */ 2417052Samw uint32_t 242*7348SJose.Borrego@Sun.COM smb_shr_create(smb_share_t *si, boolean_t store) 2437052Samw { 2447052Samw uint32_t status = NERR_Success; 245*7348SJose.Borrego@Sun.COM int rc; 2467052Samw 247*7348SJose.Borrego@Sun.COM assert(si != NULL); 2487052Samw 249*7348SJose.Borrego@Sun.COM if (!smb_shr_chkname(si->shr_name)) 250*7348SJose.Borrego@Sun.COM return (ERROR_INVALID_NAME); 2517052Samw 252*7348SJose.Borrego@Sun.COM if (si->shr_flags & SMB_SHRF_AUTOHOME) 253*7348SJose.Borrego@Sun.COM return (smb_shr_create_autohome(si)); 2547052Samw 255*7348SJose.Borrego@Sun.COM if (smb_shr_exists(si->shr_name)) 256*7348SJose.Borrego@Sun.COM return (NERR_DuplicateShare); 2577052Samw 258*7348SJose.Borrego@Sun.COM if ((status = smb_shr_cache_addent(si)) != NERR_Success) 2597052Samw return (status); 2607052Samw 261*7348SJose.Borrego@Sun.COM if (store && (si->shr_flags & SMB_SHRF_PERM)) { 262*7348SJose.Borrego@Sun.COM if ((status = smb_shr_sa_addent(si)) != NERR_Success) { 263*7348SJose.Borrego@Sun.COM (void) smb_shr_cache_delent(si->shr_name); 2647052Samw return (status); 2657052Samw } 2667052Samw } 2677052Samw 268*7348SJose.Borrego@Sun.COM rc = smb_dwncall_share(SMB_SHROP_ADD, si->shr_path, si->shr_name); 269*7348SJose.Borrego@Sun.COM 270*7348SJose.Borrego@Sun.COM if (rc == 0) { 271*7348SJose.Borrego@Sun.COM smb_shr_publish(si->shr_name, si->shr_container, 272*7348SJose.Borrego@Sun.COM SMB_SHR_PUBLISH); 273*7348SJose.Borrego@Sun.COM return (status); 2747052Samw } 2757052Samw 276*7348SJose.Borrego@Sun.COM smb_shr_cache_delent(si->shr_name); 277*7348SJose.Borrego@Sun.COM if (store && (si->shr_flags & SMB_SHRF_PERM)) 278*7348SJose.Borrego@Sun.COM (void) smb_shr_sa_delent(si); 2797052Samw 2807052Samw /* 281*7348SJose.Borrego@Sun.COM * rc == ENOENT means the shared directory doesn't exist 2827052Samw */ 283*7348SJose.Borrego@Sun.COM return ((rc == ENOENT) ? NERR_UnknownDevDir : NERR_InternalError); 2847052Samw } 2857052Samw 2867052Samw /* 287*7348SJose.Borrego@Sun.COM * smb_shr_delete 2887052Samw * 289*7348SJose.Borrego@Sun.COM * Removes the specified share. 2907052Samw */ 291*7348SJose.Borrego@Sun.COM uint32_t 292*7348SJose.Borrego@Sun.COM smb_shr_delete(char *sharename, boolean_t store) 2937052Samw { 294*7348SJose.Borrego@Sun.COM smb_share_t si; 295*7348SJose.Borrego@Sun.COM uint32_t status = NERR_Success; 296*7348SJose.Borrego@Sun.COM 297*7348SJose.Borrego@Sun.COM assert(sharename != NULL); 298*7348SJose.Borrego@Sun.COM 299*7348SJose.Borrego@Sun.COM if ((status = smb_shr_get(sharename, &si)) != NERR_Success) 300*7348SJose.Borrego@Sun.COM return (status); 3017052Samw 302*7348SJose.Borrego@Sun.COM if (si.shr_type & STYPE_IPC) 303*7348SJose.Borrego@Sun.COM return (ERROR_ACCESS_DENIED); 304*7348SJose.Borrego@Sun.COM 305*7348SJose.Borrego@Sun.COM if (si.shr_flags & SMB_SHRF_AUTOHOME) { 306*7348SJose.Borrego@Sun.COM si.shr_refcnt--; 307*7348SJose.Borrego@Sun.COM if (si.shr_refcnt > 0) { 308*7348SJose.Borrego@Sun.COM smb_shr_set_ahcnt(si.shr_name, si.shr_refcnt); 309*7348SJose.Borrego@Sun.COM return (status); 310*7348SJose.Borrego@Sun.COM } 3117052Samw } 3127052Samw 313*7348SJose.Borrego@Sun.COM if (store && (si.shr_flags & SMB_SHRF_PERM)) { 314*7348SJose.Borrego@Sun.COM if (smb_shr_sa_delent(&si) != NERR_Success) 315*7348SJose.Borrego@Sun.COM return (NERR_InternalError); 3167052Samw } 317*7348SJose.Borrego@Sun.COM 318*7348SJose.Borrego@Sun.COM smb_shr_cache_delent(si.shr_name); 319*7348SJose.Borrego@Sun.COM smb_shr_publish(si.shr_name, si.shr_container, SMB_SHR_UNPUBLISH); 320*7348SJose.Borrego@Sun.COM (void) smb_dwncall_share(SMB_SHROP_DELETE, si.shr_path, si.shr_name); 321*7348SJose.Borrego@Sun.COM 3227052Samw return (NERR_Success); 3237052Samw } 3247052Samw 3257052Samw /* 326*7348SJose.Borrego@Sun.COM * smb_shr_rename 3277052Samw * 3287052Samw * Rename a share. Check that the current name exists and the new name 3297052Samw * doesn't exist. The rename is performed by deleting the current share 3307052Samw * definition and creating a new share with the new name. 3317052Samw */ 3327052Samw uint32_t 333*7348SJose.Borrego@Sun.COM smb_shr_rename(char *from_name, char *to_name) 3347052Samw { 3357052Samw smb_share_t si; 336*7348SJose.Borrego@Sun.COM uint32_t status; 337*7348SJose.Borrego@Sun.COM 338*7348SJose.Borrego@Sun.COM assert((from_name != NULL) && (to_name != NULL)); 3397052Samw 340*7348SJose.Borrego@Sun.COM if (!smb_shr_chkname(from_name) || !smb_shr_chkname(to_name)) 341*7348SJose.Borrego@Sun.COM return (ERROR_INVALID_NAME); 3427052Samw 343*7348SJose.Borrego@Sun.COM if (!smb_shr_exists(from_name)) 3447052Samw return (NERR_NetNameNotFound); 3457052Samw 3467052Samw if (smb_shr_exists(to_name)) 3477052Samw return (NERR_DuplicateShare); 3487052Samw 349*7348SJose.Borrego@Sun.COM if ((status = smb_shr_get(from_name, &si)) != NERR_Success) 350*7348SJose.Borrego@Sun.COM return (status); 351*7348SJose.Borrego@Sun.COM 352*7348SJose.Borrego@Sun.COM if (si.shr_type & STYPE_IPC) 353*7348SJose.Borrego@Sun.COM return (ERROR_ACCESS_DENIED); 354*7348SJose.Borrego@Sun.COM 355*7348SJose.Borrego@Sun.COM (void) strlcpy(si.shr_name, to_name, sizeof (si.shr_name)); 356*7348SJose.Borrego@Sun.COM if ((status = smb_shr_cache_addent(&si)) != NERR_Success) 357*7348SJose.Borrego@Sun.COM return (status); 358*7348SJose.Borrego@Sun.COM 359*7348SJose.Borrego@Sun.COM smb_shr_cache_delent(from_name); 360*7348SJose.Borrego@Sun.COM smb_shr_publish(from_name, si.shr_container, SMB_SHR_UNPUBLISH); 361*7348SJose.Borrego@Sun.COM smb_shr_publish(to_name, si.shr_container, SMB_SHR_PUBLISH); 362*7348SJose.Borrego@Sun.COM 363*7348SJose.Borrego@Sun.COM return (NERR_Success); 364*7348SJose.Borrego@Sun.COM } 365*7348SJose.Borrego@Sun.COM 366*7348SJose.Borrego@Sun.COM /* 367*7348SJose.Borrego@Sun.COM * smb_shr_get 368*7348SJose.Borrego@Sun.COM * 369*7348SJose.Borrego@Sun.COM * Load the information for the specified share into the supplied share 370*7348SJose.Borrego@Sun.COM * info structure. 371*7348SJose.Borrego@Sun.COM */ 372*7348SJose.Borrego@Sun.COM uint32_t 373*7348SJose.Borrego@Sun.COM smb_shr_get(char *sharename, smb_share_t *si) 374*7348SJose.Borrego@Sun.COM { 375*7348SJose.Borrego@Sun.COM HT_ITEM *item; 376*7348SJose.Borrego@Sun.COM 377*7348SJose.Borrego@Sun.COM (void) utf8_strlwr(sharename); 378*7348SJose.Borrego@Sun.COM 379*7348SJose.Borrego@Sun.COM (void) rw_rdlock(&smb_shr_lock); 380*7348SJose.Borrego@Sun.COM item = ht_find_item(smb_shr_handle, sharename); 381*7348SJose.Borrego@Sun.COM if (item == NULL || item->hi_data == NULL) { 382*7348SJose.Borrego@Sun.COM (void) rw_unlock(&smb_shr_lock); 383*7348SJose.Borrego@Sun.COM return (NERR_NetNameNotFound); 384*7348SJose.Borrego@Sun.COM } 385*7348SJose.Borrego@Sun.COM 386*7348SJose.Borrego@Sun.COM bcopy(item->hi_data, si, sizeof (smb_share_t)); 387*7348SJose.Borrego@Sun.COM (void) rw_unlock(&smb_shr_lock); 388*7348SJose.Borrego@Sun.COM 389*7348SJose.Borrego@Sun.COM return (NERR_Success); 390*7348SJose.Borrego@Sun.COM } 391*7348SJose.Borrego@Sun.COM 392*7348SJose.Borrego@Sun.COM /* 393*7348SJose.Borrego@Sun.COM * smb_shr_modify 394*7348SJose.Borrego@Sun.COM * 395*7348SJose.Borrego@Sun.COM * Modifies an existing share. Properties that can be modified are: 396*7348SJose.Borrego@Sun.COM * 397*7348SJose.Borrego@Sun.COM * o comment 398*7348SJose.Borrego@Sun.COM * o AD container 399*7348SJose.Borrego@Sun.COM */ 400*7348SJose.Borrego@Sun.COM uint32_t 401*7348SJose.Borrego@Sun.COM smb_shr_modify(char *sharename, const char *cmnt, 402*7348SJose.Borrego@Sun.COM const char *ad_container, boolean_t store) 403*7348SJose.Borrego@Sun.COM { 404*7348SJose.Borrego@Sun.COM smb_share_t si; 405*7348SJose.Borrego@Sun.COM uint32_t status; 406*7348SJose.Borrego@Sun.COM boolean_t cmnt_changed = B_FALSE; 407*7348SJose.Borrego@Sun.COM boolean_t adc_changed = B_FALSE; 408*7348SJose.Borrego@Sun.COM char shr_container[MAXPATHLEN]; 409*7348SJose.Borrego@Sun.COM 410*7348SJose.Borrego@Sun.COM assert(sharename != NULL); 411*7348SJose.Borrego@Sun.COM 412*7348SJose.Borrego@Sun.COM if ((cmnt == NULL) && (ad_container == NULL)) 413*7348SJose.Borrego@Sun.COM /* no changes */ 414*7348SJose.Borrego@Sun.COM return (NERR_Success); 4157052Samw 416*7348SJose.Borrego@Sun.COM if ((status = smb_shr_get(sharename, &si)) != NERR_Success) 417*7348SJose.Borrego@Sun.COM return (status); 418*7348SJose.Borrego@Sun.COM 419*7348SJose.Borrego@Sun.COM if (si.shr_type & STYPE_IPC) 420*7348SJose.Borrego@Sun.COM return (ERROR_ACCESS_DENIED); 421*7348SJose.Borrego@Sun.COM 422*7348SJose.Borrego@Sun.COM if (cmnt) { 423*7348SJose.Borrego@Sun.COM cmnt_changed = (strcmp(cmnt, si.shr_cmnt) != 0); 424*7348SJose.Borrego@Sun.COM if (cmnt_changed) 425*7348SJose.Borrego@Sun.COM (void) strlcpy(si.shr_cmnt, cmnt, sizeof (si.shr_cmnt)); 426*7348SJose.Borrego@Sun.COM } 427*7348SJose.Borrego@Sun.COM 428*7348SJose.Borrego@Sun.COM if (ad_container) { 429*7348SJose.Borrego@Sun.COM adc_changed = (strcmp(ad_container, si.shr_container) != 0); 430*7348SJose.Borrego@Sun.COM if (adc_changed) { 431*7348SJose.Borrego@Sun.COM /* save current container needed for unpublishing */ 432*7348SJose.Borrego@Sun.COM (void) strlcpy(shr_container, si.shr_container, 433*7348SJose.Borrego@Sun.COM sizeof (shr_container)); 434*7348SJose.Borrego@Sun.COM (void) strlcpy(si.shr_container, ad_container, 435*7348SJose.Borrego@Sun.COM sizeof (si.shr_container)); 436*7348SJose.Borrego@Sun.COM } 437*7348SJose.Borrego@Sun.COM } 438*7348SJose.Borrego@Sun.COM 439*7348SJose.Borrego@Sun.COM if (!cmnt_changed && !adc_changed) 440*7348SJose.Borrego@Sun.COM /* no changes */ 441*7348SJose.Borrego@Sun.COM return (NERR_Success); 442*7348SJose.Borrego@Sun.COM 443*7348SJose.Borrego@Sun.COM if (store && (si.shr_flags & SMB_SHRF_PERM)) { 444*7348SJose.Borrego@Sun.COM if (smb_shr_sa_addent(&si) != NERR_Success) 445*7348SJose.Borrego@Sun.COM return (NERR_InternalError); 446*7348SJose.Borrego@Sun.COM } 447*7348SJose.Borrego@Sun.COM 448*7348SJose.Borrego@Sun.COM (void) smb_shr_cache_chgent(&si); 4497052Samw 450*7348SJose.Borrego@Sun.COM if (adc_changed) { 451*7348SJose.Borrego@Sun.COM smb_shr_publish(si.shr_name, shr_container, 452*7348SJose.Borrego@Sun.COM SMB_SHR_UNPUBLISH); 453*7348SJose.Borrego@Sun.COM smb_shr_publish(si.shr_name, si.shr_container, 454*7348SJose.Borrego@Sun.COM SMB_SHR_PUBLISH); 455*7348SJose.Borrego@Sun.COM } 456*7348SJose.Borrego@Sun.COM 457*7348SJose.Borrego@Sun.COM return (NERR_Success); 4587052Samw } 4597052Samw 460*7348SJose.Borrego@Sun.COM void 461*7348SJose.Borrego@Sun.COM smb_shr_list(int offset, smb_shrlist_t *list) 462*7348SJose.Borrego@Sun.COM { 463*7348SJose.Borrego@Sun.COM smb_shriter_t iterator; 464*7348SJose.Borrego@Sun.COM smb_share_t *si; 465*7348SJose.Borrego@Sun.COM int n = 0; 466*7348SJose.Borrego@Sun.COM 467*7348SJose.Borrego@Sun.COM bzero(list, sizeof (smb_shrlist_t)); 468*7348SJose.Borrego@Sun.COM smb_shr_iterinit(&iterator); 469*7348SJose.Borrego@Sun.COM 470*7348SJose.Borrego@Sun.COM while ((si = smb_shr_iterate(&iterator)) != NULL) { 471*7348SJose.Borrego@Sun.COM if (--offset > 0) 472*7348SJose.Borrego@Sun.COM continue; 473*7348SJose.Borrego@Sun.COM 474*7348SJose.Borrego@Sun.COM if ((si->shr_flags & SMB_SHRF_TRANS) && 475*7348SJose.Borrego@Sun.COM ((si->shr_type & STYPE_IPC) == 0)) { 476*7348SJose.Borrego@Sun.COM bcopy(si, &list->sl_shares[n], sizeof (smb_share_t)); 477*7348SJose.Borrego@Sun.COM if (++n == LMSHARES_PER_REQUEST) 478*7348SJose.Borrego@Sun.COM break; 479*7348SJose.Borrego@Sun.COM } 480*7348SJose.Borrego@Sun.COM } 481*7348SJose.Borrego@Sun.COM 482*7348SJose.Borrego@Sun.COM list->sl_cnt = n; 483*7348SJose.Borrego@Sun.COM } 484*7348SJose.Borrego@Sun.COM 485*7348SJose.Borrego@Sun.COM 4867052Samw /* 4877052Samw * smb_shr_exists 4887052Samw * 489*7348SJose.Borrego@Sun.COM * Returns B_TRUE if the share exists. Otherwise returns B_FALSE 4907052Samw */ 491*7348SJose.Borrego@Sun.COM boolean_t 492*7348SJose.Borrego@Sun.COM smb_shr_exists(char *sharename) 4937052Samw { 494*7348SJose.Borrego@Sun.COM boolean_t exists; 495*7348SJose.Borrego@Sun.COM 496*7348SJose.Borrego@Sun.COM if (sharename == NULL || *sharename == '\0') 497*7348SJose.Borrego@Sun.COM return (B_FALSE); 4987052Samw 499*7348SJose.Borrego@Sun.COM (void) utf8_strlwr(sharename); 500*7348SJose.Borrego@Sun.COM 501*7348SJose.Borrego@Sun.COM (void) rw_rdlock(&smb_shr_lock); 502*7348SJose.Borrego@Sun.COM exists = (ht_find_item(smb_shr_handle, sharename) != NULL); 503*7348SJose.Borrego@Sun.COM (void) rw_unlock(&smb_shr_lock); 504*7348SJose.Borrego@Sun.COM 505*7348SJose.Borrego@Sun.COM return (exists); 5067052Samw } 5077052Samw 5087052Samw /* 5097052Samw * smb_shr_is_special 5107052Samw * 511*7348SJose.Borrego@Sun.COM * Special share reserved for interprocess communication (IPC$) or 512*7348SJose.Borrego@Sun.COM * remote administration of the server (ADMIN$). Can also refer to 513*7348SJose.Borrego@Sun.COM * administrative shares such as C$, D$, E$, and so forth. 5147052Samw */ 5157052Samw int 516*7348SJose.Borrego@Sun.COM smb_shr_is_special(char *sharename) 5177052Samw { 5187052Samw int len; 5197052Samw 520*7348SJose.Borrego@Sun.COM if (sharename == NULL) 5217052Samw return (0); 5227052Samw 523*7348SJose.Borrego@Sun.COM if ((len = strlen(sharename)) == 0) 5247052Samw return (0); 5257052Samw 526*7348SJose.Borrego@Sun.COM if (sharename[len - 1] == '$') 5277052Samw return (STYPE_SPECIAL); 528*7348SJose.Borrego@Sun.COM 529*7348SJose.Borrego@Sun.COM return (0); 5307052Samw } 5317052Samw 5327052Samw /* 5337052Samw * smb_shr_is_restricted 5347052Samw * 5357052Samw * Check whether or not there is a restriction on a share. Restricted 5367052Samw * shares are generally STYPE_SPECIAL, for example, IPC$. All the 537*7348SJose.Borrego@Sun.COM * administration share names are restricted: C$, D$ etc. Returns B_TRUE 538*7348SJose.Borrego@Sun.COM * if the share is restricted. Otherwise B_FALSE is returned to indicate 5397052Samw * that there are no restrictions. 5407052Samw */ 541*7348SJose.Borrego@Sun.COM boolean_t 542*7348SJose.Borrego@Sun.COM smb_shr_is_restricted(char *sharename) 5437052Samw { 5447052Samw static char *restricted[] = { 5457052Samw "IPC$" 5467052Samw }; 5477052Samw 5487052Samw int i; 5497052Samw 550*7348SJose.Borrego@Sun.COM if (sharename == NULL) 551*7348SJose.Borrego@Sun.COM return (B_FALSE); 552*7348SJose.Borrego@Sun.COM 5537052Samw for (i = 0; i < sizeof (restricted)/sizeof (restricted[0]); i++) { 554*7348SJose.Borrego@Sun.COM if (utf8_strcasecmp(restricted[i], sharename) == 0) 555*7348SJose.Borrego@Sun.COM return (B_TRUE); 5567052Samw } 5577052Samw 558*7348SJose.Borrego@Sun.COM return (smb_shr_is_admin(sharename)); 5597052Samw } 5607052Samw 5617052Samw /* 5627052Samw * smb_shr_is_admin 5637052Samw * 5647052Samw * Check whether or not access to the share should be restricted to 5657052Samw * administrators. This is a bit of a hack because what we're doing 5667052Samw * is checking for the default admin shares: C$, D$ etc.. There are 5677052Samw * other shares that have restrictions: see smb_shr_is_restricted(). 5687052Samw * 569*7348SJose.Borrego@Sun.COM * Returns B_TRUE if the shares is an admin share. Otherwise B_FALSE 570*7348SJose.Borrego@Sun.COM * is returned to indicate that there are no restrictions. 5717052Samw */ 572*7348SJose.Borrego@Sun.COM boolean_t 573*7348SJose.Borrego@Sun.COM smb_shr_is_admin(char *sharename) 5747052Samw { 575*7348SJose.Borrego@Sun.COM if (sharename == NULL) 576*7348SJose.Borrego@Sun.COM return (B_FALSE); 5777052Samw 578*7348SJose.Borrego@Sun.COM if (strlen(sharename) == 2 && 579*7348SJose.Borrego@Sun.COM mts_isalpha(sharename[0]) && sharename[1] == '$') { 580*7348SJose.Borrego@Sun.COM return (B_TRUE); 5817052Samw } 5827052Samw 583*7348SJose.Borrego@Sun.COM return (B_FALSE); 5847052Samw } 5857052Samw 5867052Samw /* 587*7348SJose.Borrego@Sun.COM * smb_shr_chkname 5887052Samw * 5897052Samw * Check if any invalid char is present in share name. According to 5907052Samw * MSDN article #236388: "Err Msg: The Share Name Contains Invalid 5917052Samw * Characters", the list of invalid character is: 5927052Samw * 5937052Samw * " / \ [ ] : | < > + ; , ? * = 5947052Samw * 5957052Samw * Also rejects if control characters are embedded. 5967052Samw */ 597*7348SJose.Borrego@Sun.COM boolean_t 598*7348SJose.Borrego@Sun.COM smb_shr_chkname(char *sharename) 5997052Samw { 6007052Samw char *invalid = "\"/\\[]:|<>+;,?*="; 6017052Samw char *cp; 6027052Samw 603*7348SJose.Borrego@Sun.COM if (sharename == NULL) 604*7348SJose.Borrego@Sun.COM return (B_FALSE); 6057052Samw 606*7348SJose.Borrego@Sun.COM if (strpbrk(sharename, invalid)) 607*7348SJose.Borrego@Sun.COM return (B_FALSE); 6087052Samw 609*7348SJose.Borrego@Sun.COM for (cp = sharename; *cp != '\0'; cp++) { 610*7348SJose.Borrego@Sun.COM if (iscntrl(*cp)) 611*7348SJose.Borrego@Sun.COM return (B_FALSE); 6127052Samw } 6137052Samw 614*7348SJose.Borrego@Sun.COM return (B_TRUE); 6157052Samw } 6167052Samw 6177052Samw /* 6187052Samw * smb_shr_get_realpath 6197052Samw * 6207052Samw * Derive the real path of a share from the path provided by a 6217052Samw * Windows client application during the share addition. 6227052Samw * 6237052Samw * For instance, the real path of C:\ is /cvol and the 6247052Samw * real path of F:\home is /vol1/home. 6257052Samw * 6267052Samw * clipath - path provided by the Windows client is in the 6277052Samw * format of <drive letter>:\<dir> 6287052Samw * realpath - path that will be stored as the directory field of 6297052Samw * the smb_share_t structure of the share. 6307052Samw * maxlen - maximum length fo the realpath buffer 6317052Samw * 6327052Samw * Return LAN Manager network error code. 6337052Samw */ 6347052Samw /*ARGSUSED*/ 6357052Samw uint32_t 6367052Samw smb_shr_get_realpath(const char *clipath, char *realpath, int maxlen) 6377052Samw { 6387052Samw /* XXX do this translation */ 6397052Samw return (NERR_Success); 6407052Samw } 6417052Samw 6427052Samw /* 643*7348SJose.Borrego@Sun.COM * ============================================ 644*7348SJose.Borrego@Sun.COM * Cache management functions 645*7348SJose.Borrego@Sun.COM * ============================================ 646*7348SJose.Borrego@Sun.COM */ 647*7348SJose.Borrego@Sun.COM 648*7348SJose.Borrego@Sun.COM /* 649*7348SJose.Borrego@Sun.COM * smb_shr_cache_create 650*7348SJose.Borrego@Sun.COM * 651*7348SJose.Borrego@Sun.COM * Create the share hash table. 652*7348SJose.Borrego@Sun.COM */ 653*7348SJose.Borrego@Sun.COM static uint32_t 654*7348SJose.Borrego@Sun.COM smb_shr_cache_create(void) 655*7348SJose.Borrego@Sun.COM { 656*7348SJose.Borrego@Sun.COM if (smb_shr_handle == NULL) { 657*7348SJose.Borrego@Sun.COM (void) rwlock_init(&smb_shr_lock, USYNC_THREAD, 0); 658*7348SJose.Borrego@Sun.COM (void) rw_wrlock(&smb_shr_lock); 659*7348SJose.Borrego@Sun.COM 660*7348SJose.Borrego@Sun.COM smb_shr_handle = ht_create_table(SMB_SHARE_HTAB_SZ, 661*7348SJose.Borrego@Sun.COM MAXNAMELEN, 0); 662*7348SJose.Borrego@Sun.COM if (smb_shr_handle == NULL) { 663*7348SJose.Borrego@Sun.COM (void) rw_unlock(&smb_shr_lock); 664*7348SJose.Borrego@Sun.COM return (NERR_InternalError); 665*7348SJose.Borrego@Sun.COM } 666*7348SJose.Borrego@Sun.COM 667*7348SJose.Borrego@Sun.COM (void) ht_register_callback(smb_shr_handle, 668*7348SJose.Borrego@Sun.COM smb_shr_cache_freent); 669*7348SJose.Borrego@Sun.COM (void) rw_unlock(&smb_shr_lock); 670*7348SJose.Borrego@Sun.COM } 671*7348SJose.Borrego@Sun.COM 672*7348SJose.Borrego@Sun.COM return (NERR_Success); 673*7348SJose.Borrego@Sun.COM } 674*7348SJose.Borrego@Sun.COM 675*7348SJose.Borrego@Sun.COM /* 676*7348SJose.Borrego@Sun.COM * smb_shr_cache_destroy 677*7348SJose.Borrego@Sun.COM * 678*7348SJose.Borrego@Sun.COM * Destroys the share hash table. 679*7348SJose.Borrego@Sun.COM */ 680*7348SJose.Borrego@Sun.COM static void 681*7348SJose.Borrego@Sun.COM smb_shr_cache_destroy(void) 682*7348SJose.Borrego@Sun.COM { 683*7348SJose.Borrego@Sun.COM if (smb_shr_handle) { 684*7348SJose.Borrego@Sun.COM (void) rw_wrlock(&smb_shr_lock); 685*7348SJose.Borrego@Sun.COM ht_destroy_table(smb_shr_handle); 686*7348SJose.Borrego@Sun.COM (void) rw_unlock(&smb_shr_lock); 687*7348SJose.Borrego@Sun.COM (void) rwlock_destroy(&smb_shr_lock); 688*7348SJose.Borrego@Sun.COM smb_shr_handle = NULL; 689*7348SJose.Borrego@Sun.COM } 690*7348SJose.Borrego@Sun.COM } 691*7348SJose.Borrego@Sun.COM 692*7348SJose.Borrego@Sun.COM /* 693*7348SJose.Borrego@Sun.COM * smb_shr_cache_populate 694*7348SJose.Borrego@Sun.COM * 695*7348SJose.Borrego@Sun.COM * Load shares from sharemgr 696*7348SJose.Borrego@Sun.COM */ 697*7348SJose.Borrego@Sun.COM /*ARGSUSED*/ 698*7348SJose.Borrego@Sun.COM static void * 699*7348SJose.Borrego@Sun.COM smb_shr_cache_populate(void *args) 700*7348SJose.Borrego@Sun.COM { 701*7348SJose.Borrego@Sun.COM sa_handle_t handle; 702*7348SJose.Borrego@Sun.COM sa_group_t group, subgroup; 703*7348SJose.Borrego@Sun.COM char *gstate; 704*7348SJose.Borrego@Sun.COM boolean_t gdisabled; 705*7348SJose.Borrego@Sun.COM 706*7348SJose.Borrego@Sun.COM if (smb_shr_cache_create() != NERR_Success) { 707*7348SJose.Borrego@Sun.COM syslog(LOG_ERR, "share: failed creating the cache"); 708*7348SJose.Borrego@Sun.COM return (NULL); 709*7348SJose.Borrego@Sun.COM } 710*7348SJose.Borrego@Sun.COM 711*7348SJose.Borrego@Sun.COM if (smb_shr_create_ipc() != NERR_Success) { 712*7348SJose.Borrego@Sun.COM syslog(LOG_ERR, "share: failed creating IPC$"); 713*7348SJose.Borrego@Sun.COM return (NULL); 714*7348SJose.Borrego@Sun.COM } 715*7348SJose.Borrego@Sun.COM 716*7348SJose.Borrego@Sun.COM if ((handle = sa_init(SA_INIT_SHARE_API)) == NULL) { 717*7348SJose.Borrego@Sun.COM syslog(LOG_ERR, "share: failed connecting to backend"); 718*7348SJose.Borrego@Sun.COM return (NULL); 719*7348SJose.Borrego@Sun.COM } 720*7348SJose.Borrego@Sun.COM 721*7348SJose.Borrego@Sun.COM for (group = sa_get_group(handle, NULL); 722*7348SJose.Borrego@Sun.COM group != NULL; group = sa_get_next_group(group)) { 723*7348SJose.Borrego@Sun.COM gstate = sa_get_group_attr(group, "state"); 724*7348SJose.Borrego@Sun.COM if (gstate == NULL) 725*7348SJose.Borrego@Sun.COM continue; 726*7348SJose.Borrego@Sun.COM 727*7348SJose.Borrego@Sun.COM gdisabled = (strcasecmp(gstate, "disabled") == 0); 728*7348SJose.Borrego@Sun.COM sa_free_attr_string(gstate); 729*7348SJose.Borrego@Sun.COM if (gdisabled) 730*7348SJose.Borrego@Sun.COM continue; 731*7348SJose.Borrego@Sun.COM 732*7348SJose.Borrego@Sun.COM smb_shr_cache_loadgrp(group); 733*7348SJose.Borrego@Sun.COM for (subgroup = sa_get_sub_group(group); 734*7348SJose.Borrego@Sun.COM subgroup != NULL; 735*7348SJose.Borrego@Sun.COM subgroup = sa_get_next_group(subgroup)) { 736*7348SJose.Borrego@Sun.COM smb_shr_cache_loadgrp(subgroup); 737*7348SJose.Borrego@Sun.COM } 738*7348SJose.Borrego@Sun.COM 739*7348SJose.Borrego@Sun.COM } 740*7348SJose.Borrego@Sun.COM 741*7348SJose.Borrego@Sun.COM sa_fini(handle); 742*7348SJose.Borrego@Sun.COM return (NULL); 743*7348SJose.Borrego@Sun.COM } 744*7348SJose.Borrego@Sun.COM 745*7348SJose.Borrego@Sun.COM static uint32_t 746*7348SJose.Borrego@Sun.COM smb_shr_cache_addent(smb_share_t *si) 747*7348SJose.Borrego@Sun.COM { 748*7348SJose.Borrego@Sun.COM smb_share_t *cache_ent; 749*7348SJose.Borrego@Sun.COM uint32_t status = NERR_Success; 750*7348SJose.Borrego@Sun.COM 751*7348SJose.Borrego@Sun.COM /* 752*7348SJose.Borrego@Sun.COM * allocate memory for the entry that needs to be cached. 753*7348SJose.Borrego@Sun.COM */ 754*7348SJose.Borrego@Sun.COM if ((cache_ent = malloc(sizeof (smb_share_t))) == NULL) 755*7348SJose.Borrego@Sun.COM return (ERROR_NOT_ENOUGH_MEMORY); 756*7348SJose.Borrego@Sun.COM 757*7348SJose.Borrego@Sun.COM bcopy(si, cache_ent, sizeof (smb_share_t)); 758*7348SJose.Borrego@Sun.COM 759*7348SJose.Borrego@Sun.COM (void) utf8_strlwr(cache_ent->shr_name); 760*7348SJose.Borrego@Sun.COM smb_shr_set_oemname(cache_ent); 761*7348SJose.Borrego@Sun.COM if ((si->shr_type & STYPE_IPC) == 0) 762*7348SJose.Borrego@Sun.COM cache_ent->shr_type = STYPE_DISKTREE; 763*7348SJose.Borrego@Sun.COM cache_ent->shr_type |= smb_shr_is_special(cache_ent->shr_name); 764*7348SJose.Borrego@Sun.COM 765*7348SJose.Borrego@Sun.COM (void) rw_wrlock(&smb_shr_lock); 766*7348SJose.Borrego@Sun.COM if (ht_add_item(smb_shr_handle, cache_ent->shr_name, cache_ent) 767*7348SJose.Borrego@Sun.COM == NULL) { 768*7348SJose.Borrego@Sun.COM syslog(LOG_DEBUG, "share: failed adding %s to cache", 769*7348SJose.Borrego@Sun.COM cache_ent->shr_name); 770*7348SJose.Borrego@Sun.COM free(cache_ent); 771*7348SJose.Borrego@Sun.COM status = NERR_InternalError; 772*7348SJose.Borrego@Sun.COM } 773*7348SJose.Borrego@Sun.COM (void) rw_unlock(&smb_shr_lock); 774*7348SJose.Borrego@Sun.COM 775*7348SJose.Borrego@Sun.COM return (status); 776*7348SJose.Borrego@Sun.COM } 777*7348SJose.Borrego@Sun.COM 778*7348SJose.Borrego@Sun.COM static void 779*7348SJose.Borrego@Sun.COM smb_shr_cache_delent(char *sharename) 780*7348SJose.Borrego@Sun.COM { 781*7348SJose.Borrego@Sun.COM (void) utf8_strlwr(sharename); 782*7348SJose.Borrego@Sun.COM (void) rw_wrlock(&smb_shr_lock); 783*7348SJose.Borrego@Sun.COM (void) ht_remove_item(smb_shr_handle, sharename); 784*7348SJose.Borrego@Sun.COM (void) rw_unlock(&smb_shr_lock); 785*7348SJose.Borrego@Sun.COM } 786*7348SJose.Borrego@Sun.COM 787*7348SJose.Borrego@Sun.COM static uint32_t 788*7348SJose.Borrego@Sun.COM smb_shr_cache_chgent(smb_share_t *si) 789*7348SJose.Borrego@Sun.COM { 790*7348SJose.Borrego@Sun.COM smb_share_t *cache_ent; 791*7348SJose.Borrego@Sun.COM uint32_t status = NERR_Success; 792*7348SJose.Borrego@Sun.COM 793*7348SJose.Borrego@Sun.COM /* 794*7348SJose.Borrego@Sun.COM * allocate memory for the entry that needs to be cached. 795*7348SJose.Borrego@Sun.COM */ 796*7348SJose.Borrego@Sun.COM if ((cache_ent = malloc(sizeof (smb_share_t))) == NULL) 797*7348SJose.Borrego@Sun.COM return (ERROR_NOT_ENOUGH_MEMORY); 798*7348SJose.Borrego@Sun.COM 799*7348SJose.Borrego@Sun.COM bcopy(si, cache_ent, sizeof (smb_share_t)); 800*7348SJose.Borrego@Sun.COM (void) utf8_strlwr(cache_ent->shr_name); 801*7348SJose.Borrego@Sun.COM 802*7348SJose.Borrego@Sun.COM (void) rw_wrlock(&smb_shr_lock); 803*7348SJose.Borrego@Sun.COM if (ht_replace_item(smb_shr_handle, cache_ent->shr_name, cache_ent) 804*7348SJose.Borrego@Sun.COM == NULL) { 805*7348SJose.Borrego@Sun.COM syslog(LOG_DEBUG, "share: failed modifying %s", 806*7348SJose.Borrego@Sun.COM cache_ent->shr_name); 807*7348SJose.Borrego@Sun.COM free(cache_ent); 808*7348SJose.Borrego@Sun.COM status = NERR_InternalError; 809*7348SJose.Borrego@Sun.COM } 810*7348SJose.Borrego@Sun.COM (void) rw_unlock(&smb_shr_lock); 811*7348SJose.Borrego@Sun.COM 812*7348SJose.Borrego@Sun.COM return (status); 813*7348SJose.Borrego@Sun.COM } 814*7348SJose.Borrego@Sun.COM 815*7348SJose.Borrego@Sun.COM static uint32_t 816*7348SJose.Borrego@Sun.COM smb_shr_create_autohome(smb_share_t *si) 817*7348SJose.Borrego@Sun.COM { 818*7348SJose.Borrego@Sun.COM uint32_t status = NERR_Success; 819*7348SJose.Borrego@Sun.COM int rc; 820*7348SJose.Borrego@Sun.COM 821*7348SJose.Borrego@Sun.COM if (si->shr_refcnt == 0) { 822*7348SJose.Borrego@Sun.COM if ((status = smb_shr_cache_addent(si)) != NERR_Success) 823*7348SJose.Borrego@Sun.COM return (status); 824*7348SJose.Borrego@Sun.COM 825*7348SJose.Borrego@Sun.COM rc = smb_dwncall_share(SMB_SHROP_ADD, si->shr_path, 826*7348SJose.Borrego@Sun.COM si->shr_name); 827*7348SJose.Borrego@Sun.COM 828*7348SJose.Borrego@Sun.COM if (rc != 0) { 829*7348SJose.Borrego@Sun.COM smb_shr_cache_delent(si->shr_name); 830*7348SJose.Borrego@Sun.COM return ((rc == ENOENT) 831*7348SJose.Borrego@Sun.COM ? NERR_UnknownDevDir : NERR_InternalError); 832*7348SJose.Borrego@Sun.COM } 833*7348SJose.Borrego@Sun.COM 834*7348SJose.Borrego@Sun.COM smb_shr_publish(si->shr_name, si->shr_container, 835*7348SJose.Borrego@Sun.COM SMB_SHR_PUBLISH); 836*7348SJose.Borrego@Sun.COM } 837*7348SJose.Borrego@Sun.COM 838*7348SJose.Borrego@Sun.COM si->shr_refcnt++; 839*7348SJose.Borrego@Sun.COM smb_shr_set_ahcnt(si->shr_name, si->shr_refcnt); 840*7348SJose.Borrego@Sun.COM return (status); 841*7348SJose.Borrego@Sun.COM } 842*7348SJose.Borrego@Sun.COM 843*7348SJose.Borrego@Sun.COM static uint32_t 844*7348SJose.Borrego@Sun.COM smb_shr_create_ipc(void) 845*7348SJose.Borrego@Sun.COM { 846*7348SJose.Borrego@Sun.COM smb_share_t ipc; 847*7348SJose.Borrego@Sun.COM 848*7348SJose.Borrego@Sun.COM bzero(&ipc, sizeof (smb_share_t)); 849*7348SJose.Borrego@Sun.COM (void) strcpy(ipc.shr_name, "IPC$"); 850*7348SJose.Borrego@Sun.COM (void) strcpy(ipc.shr_cmnt, "Remote IPC"); 851*7348SJose.Borrego@Sun.COM ipc.shr_flags = SMB_SHRF_TRANS; 852*7348SJose.Borrego@Sun.COM ipc.shr_type = STYPE_IPC; 853*7348SJose.Borrego@Sun.COM return (smb_shr_cache_addent(&ipc)); 854*7348SJose.Borrego@Sun.COM } 855*7348SJose.Borrego@Sun.COM 856*7348SJose.Borrego@Sun.COM /* 857*7348SJose.Borrego@Sun.COM * loads the given resource 858*7348SJose.Borrego@Sun.COM */ 859*7348SJose.Borrego@Sun.COM static uint32_t 860*7348SJose.Borrego@Sun.COM smb_shr_cache_loadent(sa_share_t share, sa_resource_t resource) 861*7348SJose.Borrego@Sun.COM { 862*7348SJose.Borrego@Sun.COM smb_share_t si; 863*7348SJose.Borrego@Sun.COM uint32_t status; 864*7348SJose.Borrego@Sun.COM 865*7348SJose.Borrego@Sun.COM if ((status = smb_shr_sa_getent(share, resource, &si)) != NERR_Success) 866*7348SJose.Borrego@Sun.COM return (status); 867*7348SJose.Borrego@Sun.COM 868*7348SJose.Borrego@Sun.COM if ((status = smb_shr_cache_addent(&si)) == NERR_Success) 869*7348SJose.Borrego@Sun.COM smb_shr_publish(si.shr_name, si.shr_container, SMB_SHR_PUBLISH); 870*7348SJose.Borrego@Sun.COM 871*7348SJose.Borrego@Sun.COM if (status != NERR_Success) { 872*7348SJose.Borrego@Sun.COM syslog(LOG_ERR, "share: failed loading %s (%d)", si.shr_name, 873*7348SJose.Borrego@Sun.COM status); 874*7348SJose.Borrego@Sun.COM } 875*7348SJose.Borrego@Sun.COM 876*7348SJose.Borrego@Sun.COM return (status); 877*7348SJose.Borrego@Sun.COM } 878*7348SJose.Borrego@Sun.COM 879*7348SJose.Borrego@Sun.COM /* 880*7348SJose.Borrego@Sun.COM * smb_shr_cache_loadgrp 881*7348SJose.Borrego@Sun.COM * 882*7348SJose.Borrego@Sun.COM * Helper function for smb_shr_cache_populate. 883*7348SJose.Borrego@Sun.COM * It attempts to load the shares contained in the given group. 884*7348SJose.Borrego@Sun.COM * It will check to see if "smb" protocol is enabled or 885*7348SJose.Borrego@Sun.COM * not on the given group. This is needed in the ZFS case where 886*7348SJose.Borrego@Sun.COM * the top level ZFS group won't have "smb" protocol 887*7348SJose.Borrego@Sun.COM * enabled but the sub-groups will. 888*7348SJose.Borrego@Sun.COM */ 889*7348SJose.Borrego@Sun.COM static void 890*7348SJose.Borrego@Sun.COM smb_shr_cache_loadgrp(sa_group_t group) 891*7348SJose.Borrego@Sun.COM { 892*7348SJose.Borrego@Sun.COM sa_share_t share; 893*7348SJose.Borrego@Sun.COM sa_resource_t resource; 894*7348SJose.Borrego@Sun.COM 895*7348SJose.Borrego@Sun.COM /* Don't bother if "smb" isn't set on the group */ 896*7348SJose.Borrego@Sun.COM if (sa_get_optionset(group, SMB_PROTOCOL_NAME) == NULL) 897*7348SJose.Borrego@Sun.COM return; 898*7348SJose.Borrego@Sun.COM 899*7348SJose.Borrego@Sun.COM for (share = sa_get_share(group, NULL); 900*7348SJose.Borrego@Sun.COM share != NULL; share = sa_get_next_share(share)) { 901*7348SJose.Borrego@Sun.COM for (resource = sa_get_share_resource(share, NULL); 902*7348SJose.Borrego@Sun.COM resource != NULL; 903*7348SJose.Borrego@Sun.COM resource = sa_get_next_resource(resource)) { 904*7348SJose.Borrego@Sun.COM (void) smb_shr_cache_loadent(share, resource); 905*7348SJose.Borrego@Sun.COM } 906*7348SJose.Borrego@Sun.COM } 907*7348SJose.Borrego@Sun.COM } 908*7348SJose.Borrego@Sun.COM 909*7348SJose.Borrego@Sun.COM /* 910*7348SJose.Borrego@Sun.COM * smb_shr_cache_freent 911*7348SJose.Borrego@Sun.COM * 912*7348SJose.Borrego@Sun.COM * Call back to free given cache entry 913*7348SJose.Borrego@Sun.COM */ 914*7348SJose.Borrego@Sun.COM static void 915*7348SJose.Borrego@Sun.COM smb_shr_cache_freent(HT_ITEM *item) 916*7348SJose.Borrego@Sun.COM { 917*7348SJose.Borrego@Sun.COM if (item && item->hi_data) 918*7348SJose.Borrego@Sun.COM free(item->hi_data); 919*7348SJose.Borrego@Sun.COM } 920*7348SJose.Borrego@Sun.COM 921*7348SJose.Borrego@Sun.COM /* 922*7348SJose.Borrego@Sun.COM * smb_shr_set_ahcnt 923*7348SJose.Borrego@Sun.COM * 924*7348SJose.Borrego@Sun.COM * sets the autohome reference count for the given share 925*7348SJose.Borrego@Sun.COM */ 926*7348SJose.Borrego@Sun.COM static void 927*7348SJose.Borrego@Sun.COM smb_shr_set_ahcnt(char *sharename, int refcnt) 928*7348SJose.Borrego@Sun.COM { 929*7348SJose.Borrego@Sun.COM smb_share_t *si; 930*7348SJose.Borrego@Sun.COM HT_ITEM *item; 931*7348SJose.Borrego@Sun.COM 932*7348SJose.Borrego@Sun.COM (void) rw_wrlock(&smb_shr_lock); 933*7348SJose.Borrego@Sun.COM item = ht_find_item(smb_shr_handle, sharename); 934*7348SJose.Borrego@Sun.COM if (item == NULL || item->hi_data == NULL) { 935*7348SJose.Borrego@Sun.COM (void) rw_unlock(&smb_shr_lock); 936*7348SJose.Borrego@Sun.COM return; 937*7348SJose.Borrego@Sun.COM } 938*7348SJose.Borrego@Sun.COM 939*7348SJose.Borrego@Sun.COM si = (smb_share_t *)item->hi_data; 940*7348SJose.Borrego@Sun.COM si->shr_refcnt = refcnt; 941*7348SJose.Borrego@Sun.COM (void) rw_unlock(&smb_shr_lock); 942*7348SJose.Borrego@Sun.COM } 943*7348SJose.Borrego@Sun.COM 944*7348SJose.Borrego@Sun.COM /* 9457052Samw * smb_shr_set_oemname 9467052Samw * 9477052Samw * Generates the OEM name of the given share. If it's 9487052Samw * shorter than 13 chars it'll be saved in si->shr_oemname. 9497052Samw * Otherwise si->shr_oemname will be empty and SMB_SHRF_LONGNAME 9507052Samw * will be set in si->shr_flags. 9517052Samw */ 9527052Samw static void 9537052Samw smb_shr_set_oemname(smb_share_t *si) 9547052Samw { 9557052Samw unsigned int cpid = oem_get_smb_cpid(); 9567052Samw mts_wchar_t *unibuf; 9577052Samw char *oem_name; 9587052Samw int length; 9597052Samw 9607052Samw length = strlen(si->shr_name) + 1; 9617052Samw 9627052Samw oem_name = malloc(length); 9637052Samw unibuf = malloc(length * sizeof (mts_wchar_t)); 9647052Samw if ((oem_name == NULL) || (unibuf == NULL)) { 9657052Samw free(oem_name); 9667052Samw free(unibuf); 9677052Samw return; 9687052Samw } 9697052Samw 9707052Samw (void) mts_mbstowcs(unibuf, si->shr_name, length); 9717052Samw 9727052Samw if (unicodestooems(oem_name, unibuf, length, cpid) == 0) 9737052Samw (void) strcpy(oem_name, si->shr_name); 9747052Samw 9757052Samw free(unibuf); 9767052Samw 9777052Samw if (strlen(oem_name) + 1 > SMB_SHARE_OEMNAME_MAX) { 9787052Samw si->shr_flags |= SMB_SHRF_LONGNAME; 9797052Samw *si->shr_oemname = '\0'; 9807052Samw } else { 9817052Samw si->shr_flags &= ~SMB_SHRF_LONGNAME; 9827052Samw (void) strlcpy(si->shr_oemname, oem_name, 9837052Samw SMB_SHARE_OEMNAME_MAX); 9847052Samw } 9857052Samw 9867052Samw free(oem_name); 9877052Samw } 988*7348SJose.Borrego@Sun.COM 989*7348SJose.Borrego@Sun.COM /* 990*7348SJose.Borrego@Sun.COM * ============================================ 991*7348SJose.Borrego@Sun.COM * Interfaces to sharemgr 992*7348SJose.Borrego@Sun.COM * ============================================ 993*7348SJose.Borrego@Sun.COM */ 994*7348SJose.Borrego@Sun.COM 995*7348SJose.Borrego@Sun.COM /* 996*7348SJose.Borrego@Sun.COM * Stores the given share in sharemgr 997*7348SJose.Borrego@Sun.COM */ 998*7348SJose.Borrego@Sun.COM static uint32_t 999*7348SJose.Borrego@Sun.COM smb_shr_sa_addent(smb_share_t *si) 1000*7348SJose.Borrego@Sun.COM { 1001*7348SJose.Borrego@Sun.COM sa_handle_t handle; 1002*7348SJose.Borrego@Sun.COM sa_share_t share; 1003*7348SJose.Borrego@Sun.COM sa_group_t group; 1004*7348SJose.Borrego@Sun.COM sa_resource_t resource; 1005*7348SJose.Borrego@Sun.COM boolean_t share_created = B_FALSE; 1006*7348SJose.Borrego@Sun.COM int err; 1007*7348SJose.Borrego@Sun.COM 1008*7348SJose.Borrego@Sun.COM if ((handle = sa_init(SA_INIT_SHARE_API)) == NULL) 1009*7348SJose.Borrego@Sun.COM return (NERR_InternalError); 1010*7348SJose.Borrego@Sun.COM 1011*7348SJose.Borrego@Sun.COM share = sa_find_share(handle, si->shr_path); 1012*7348SJose.Borrego@Sun.COM if (share == NULL) { 1013*7348SJose.Borrego@Sun.COM group = smb_shr_sa_getdefgrp(handle); 1014*7348SJose.Borrego@Sun.COM if (group == NULL) { 1015*7348SJose.Borrego@Sun.COM sa_fini(handle); 1016*7348SJose.Borrego@Sun.COM return (NERR_InternalError); 1017*7348SJose.Borrego@Sun.COM } 1018*7348SJose.Borrego@Sun.COM 1019*7348SJose.Borrego@Sun.COM share = sa_add_share(group, si->shr_path, SA_SHARE_PERMANENT, 1020*7348SJose.Borrego@Sun.COM &err); 1021*7348SJose.Borrego@Sun.COM if (share == NULL) { 1022*7348SJose.Borrego@Sun.COM sa_fini(handle); 1023*7348SJose.Borrego@Sun.COM return (NERR_InternalError); 1024*7348SJose.Borrego@Sun.COM } 1025*7348SJose.Borrego@Sun.COM share_created = B_TRUE; 1026*7348SJose.Borrego@Sun.COM } 1027*7348SJose.Borrego@Sun.COM 1028*7348SJose.Borrego@Sun.COM resource = sa_get_share_resource(share, si->shr_name); 1029*7348SJose.Borrego@Sun.COM if (resource == NULL) { 1030*7348SJose.Borrego@Sun.COM resource = sa_add_resource(share, si->shr_name, 1031*7348SJose.Borrego@Sun.COM SA_SHARE_PERMANENT, &err); 1032*7348SJose.Borrego@Sun.COM if (resource == NULL) 1033*7348SJose.Borrego@Sun.COM goto failure; 1034*7348SJose.Borrego@Sun.COM } 1035*7348SJose.Borrego@Sun.COM 1036*7348SJose.Borrego@Sun.COM if (sa_set_resource_attr(resource, "description", si->shr_cmnt) 1037*7348SJose.Borrego@Sun.COM != SA_OK) { 1038*7348SJose.Borrego@Sun.COM goto failure; 1039*7348SJose.Borrego@Sun.COM } 1040*7348SJose.Borrego@Sun.COM 1041*7348SJose.Borrego@Sun.COM if (sa_set_resource_attr(resource, SMB_SHROPT_AD_CONTAINER, 1042*7348SJose.Borrego@Sun.COM si->shr_container) != SA_OK) { 1043*7348SJose.Borrego@Sun.COM goto failure; 1044*7348SJose.Borrego@Sun.COM } 1045*7348SJose.Borrego@Sun.COM 1046*7348SJose.Borrego@Sun.COM sa_fini(handle); 1047*7348SJose.Borrego@Sun.COM return (NERR_Success); 1048*7348SJose.Borrego@Sun.COM 1049*7348SJose.Borrego@Sun.COM failure: 1050*7348SJose.Borrego@Sun.COM if (share_created && (share != NULL)) 1051*7348SJose.Borrego@Sun.COM (void) sa_remove_share(share); 1052*7348SJose.Borrego@Sun.COM 1053*7348SJose.Borrego@Sun.COM if (resource != NULL) 1054*7348SJose.Borrego@Sun.COM (void) sa_remove_resource(resource); 1055*7348SJose.Borrego@Sun.COM 1056*7348SJose.Borrego@Sun.COM sa_fini(handle); 1057*7348SJose.Borrego@Sun.COM return (NERR_InternalError); 1058*7348SJose.Borrego@Sun.COM } 1059*7348SJose.Borrego@Sun.COM 1060*7348SJose.Borrego@Sun.COM static uint32_t 1061*7348SJose.Borrego@Sun.COM smb_shr_sa_getent(sa_share_t share, sa_resource_t resource, smb_share_t *si) 1062*7348SJose.Borrego@Sun.COM { 1063*7348SJose.Borrego@Sun.COM sa_property_t prop; 1064*7348SJose.Borrego@Sun.COM sa_optionset_t opts; 1065*7348SJose.Borrego@Sun.COM char *val = NULL; 1066*7348SJose.Borrego@Sun.COM char *path; 1067*7348SJose.Borrego@Sun.COM char *rname; 1068*7348SJose.Borrego@Sun.COM 1069*7348SJose.Borrego@Sun.COM if ((path = sa_get_share_attr(share, "path")) == NULL) 1070*7348SJose.Borrego@Sun.COM return (NERR_InternalError); 1071*7348SJose.Borrego@Sun.COM 1072*7348SJose.Borrego@Sun.COM if ((rname = sa_get_resource_attr(resource, "name")) == NULL) { 1073*7348SJose.Borrego@Sun.COM sa_free_attr_string(path); 1074*7348SJose.Borrego@Sun.COM return (NERR_InternalError); 1075*7348SJose.Borrego@Sun.COM } 1076*7348SJose.Borrego@Sun.COM 1077*7348SJose.Borrego@Sun.COM bzero(si, sizeof (smb_share_t)); 1078*7348SJose.Borrego@Sun.COM /* Share is read from SMF so it should be permanent */ 1079*7348SJose.Borrego@Sun.COM si->shr_flags = SMB_SHRF_PERM; 1080*7348SJose.Borrego@Sun.COM 1081*7348SJose.Borrego@Sun.COM (void) strlcpy(si->shr_path, path, sizeof (si->shr_path)); 1082*7348SJose.Borrego@Sun.COM (void) strlcpy(si->shr_name, rname, sizeof (si->shr_name)); 1083*7348SJose.Borrego@Sun.COM 1084*7348SJose.Borrego@Sun.COM sa_free_attr_string(path); 1085*7348SJose.Borrego@Sun.COM sa_free_attr_string(rname); 1086*7348SJose.Borrego@Sun.COM 1087*7348SJose.Borrego@Sun.COM val = sa_get_resource_description(resource); 1088*7348SJose.Borrego@Sun.COM if (val == NULL) 1089*7348SJose.Borrego@Sun.COM val = sa_get_share_description(share); 1090*7348SJose.Borrego@Sun.COM 1091*7348SJose.Borrego@Sun.COM if (val != NULL) { 1092*7348SJose.Borrego@Sun.COM (void) strlcpy(si->shr_cmnt, val, sizeof (si->shr_cmnt)); 1093*7348SJose.Borrego@Sun.COM sa_free_share_description(val); 1094*7348SJose.Borrego@Sun.COM } 1095*7348SJose.Borrego@Sun.COM 1096*7348SJose.Borrego@Sun.COM opts = sa_get_derived_optionset(resource, SMB_PROTOCOL_NAME, 1); 1097*7348SJose.Borrego@Sun.COM if (opts == NULL) 1098*7348SJose.Borrego@Sun.COM return (NERR_Success); 1099*7348SJose.Borrego@Sun.COM 1100*7348SJose.Borrego@Sun.COM prop = (sa_property_t)sa_get_property(opts, SMB_SHROPT_AD_CONTAINER); 1101*7348SJose.Borrego@Sun.COM if (prop != NULL) { 1102*7348SJose.Borrego@Sun.COM if ((val = sa_get_property_attr(prop, "value")) != NULL) { 1103*7348SJose.Borrego@Sun.COM (void) strlcpy(si->shr_container, val, 1104*7348SJose.Borrego@Sun.COM sizeof (si->shr_container)); 1105*7348SJose.Borrego@Sun.COM free(val); 1106*7348SJose.Borrego@Sun.COM } 1107*7348SJose.Borrego@Sun.COM } 1108*7348SJose.Borrego@Sun.COM sa_free_derived_optionset(opts); 1109*7348SJose.Borrego@Sun.COM 1110*7348SJose.Borrego@Sun.COM return (NERR_Success); 1111*7348SJose.Borrego@Sun.COM } 1112*7348SJose.Borrego@Sun.COM 1113*7348SJose.Borrego@Sun.COM /* 1114*7348SJose.Borrego@Sun.COM * Removes the share from sharemgr 1115*7348SJose.Borrego@Sun.COM */ 1116*7348SJose.Borrego@Sun.COM static uint32_t 1117*7348SJose.Borrego@Sun.COM smb_shr_sa_delent(smb_share_t *si) 1118*7348SJose.Borrego@Sun.COM { 1119*7348SJose.Borrego@Sun.COM sa_handle_t handle; 1120*7348SJose.Borrego@Sun.COM sa_share_t share; 1121*7348SJose.Borrego@Sun.COM sa_resource_t resource; 1122*7348SJose.Borrego@Sun.COM 1123*7348SJose.Borrego@Sun.COM if ((handle = sa_init(SA_INIT_SHARE_API)) == NULL) 1124*7348SJose.Borrego@Sun.COM return (NERR_InternalError); 1125*7348SJose.Borrego@Sun.COM 1126*7348SJose.Borrego@Sun.COM if ((share = sa_find_share(handle, si->shr_path)) == NULL) { 1127*7348SJose.Borrego@Sun.COM sa_fini(handle); 1128*7348SJose.Borrego@Sun.COM return (NERR_InternalError); 1129*7348SJose.Borrego@Sun.COM } 1130*7348SJose.Borrego@Sun.COM 1131*7348SJose.Borrego@Sun.COM if ((resource = sa_get_share_resource(share, si->shr_name)) == NULL) { 1132*7348SJose.Borrego@Sun.COM sa_fini(handle); 1133*7348SJose.Borrego@Sun.COM return (NERR_InternalError); 1134*7348SJose.Borrego@Sun.COM } 1135*7348SJose.Borrego@Sun.COM 1136*7348SJose.Borrego@Sun.COM if (sa_remove_resource(resource) != SA_OK) { 1137*7348SJose.Borrego@Sun.COM sa_fini(handle); 1138*7348SJose.Borrego@Sun.COM return (NERR_InternalError); 1139*7348SJose.Borrego@Sun.COM } 1140*7348SJose.Borrego@Sun.COM 1141*7348SJose.Borrego@Sun.COM sa_fini(handle); 1142*7348SJose.Borrego@Sun.COM return (NERR_Success); 1143*7348SJose.Borrego@Sun.COM } 1144*7348SJose.Borrego@Sun.COM 1145*7348SJose.Borrego@Sun.COM /* 1146*7348SJose.Borrego@Sun.COM * smb_shr_sa_getdefgrp 1147*7348SJose.Borrego@Sun.COM * 1148*7348SJose.Borrego@Sun.COM * If default group for CIFS shares (i.e. "smb") exists 1149*7348SJose.Borrego@Sun.COM * then it will return the group handle, otherwise it will 1150*7348SJose.Borrego@Sun.COM * create the group and return the handle. 1151*7348SJose.Borrego@Sun.COM * 1152*7348SJose.Borrego@Sun.COM * All the shares created by CIFS clients (this is only possible 1153*7348SJose.Borrego@Sun.COM * via RPC) will be added to "smb" groups. 1154*7348SJose.Borrego@Sun.COM */ 1155*7348SJose.Borrego@Sun.COM static sa_group_t 1156*7348SJose.Borrego@Sun.COM smb_shr_sa_getdefgrp(sa_handle_t handle) 1157*7348SJose.Borrego@Sun.COM { 1158*7348SJose.Borrego@Sun.COM sa_group_t group = NULL; 1159*7348SJose.Borrego@Sun.COM int err; 1160*7348SJose.Borrego@Sun.COM 1161*7348SJose.Borrego@Sun.COM group = sa_get_group(handle, SMB_DEFAULT_SHARE_GROUP); 1162*7348SJose.Borrego@Sun.COM if (group != NULL) 1163*7348SJose.Borrego@Sun.COM return (group); 1164*7348SJose.Borrego@Sun.COM 1165*7348SJose.Borrego@Sun.COM group = sa_create_group(handle, SMB_DEFAULT_SHARE_GROUP, &err); 1166*7348SJose.Borrego@Sun.COM if (group == NULL) 1167*7348SJose.Borrego@Sun.COM return (NULL); 1168*7348SJose.Borrego@Sun.COM 1169*7348SJose.Borrego@Sun.COM if (sa_create_optionset(group, SMB_DEFAULT_SHARE_GROUP) == NULL) { 1170*7348SJose.Borrego@Sun.COM (void) sa_remove_group(group); 1171*7348SJose.Borrego@Sun.COM group = NULL; 1172*7348SJose.Borrego@Sun.COM } 1173*7348SJose.Borrego@Sun.COM 1174*7348SJose.Borrego@Sun.COM return (group); 1175*7348SJose.Borrego@Sun.COM } 1176*7348SJose.Borrego@Sun.COM 1177*7348SJose.Borrego@Sun.COM /* 1178*7348SJose.Borrego@Sun.COM * ============================================ 1179*7348SJose.Borrego@Sun.COM * Share publishing functions 1180*7348SJose.Borrego@Sun.COM * ============================================ 1181*7348SJose.Borrego@Sun.COM */ 1182*7348SJose.Borrego@Sun.COM 1183*7348SJose.Borrego@Sun.COM /* 1184*7348SJose.Borrego@Sun.COM * Put the share on publish queue. 1185*7348SJose.Borrego@Sun.COM */ 1186*7348SJose.Borrego@Sun.COM static void 1187*7348SJose.Borrego@Sun.COM smb_shr_publish(const char *sharename, const char *container, char op) 1188*7348SJose.Borrego@Sun.COM { 1189*7348SJose.Borrego@Sun.COM smb_shr_pitem_t *item = NULL; 1190*7348SJose.Borrego@Sun.COM 1191*7348SJose.Borrego@Sun.COM if (container == NULL || *container == '\0') 1192*7348SJose.Borrego@Sun.COM return; 1193*7348SJose.Borrego@Sun.COM 1194*7348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 1195*7348SJose.Borrego@Sun.COM switch (ad_queue.spq_state) { 1196*7348SJose.Borrego@Sun.COM case SMB_SHR_PQS_READY: 1197*7348SJose.Borrego@Sun.COM case SMB_SHR_PQS_PUBLISHING: 1198*7348SJose.Borrego@Sun.COM break; 1199*7348SJose.Borrego@Sun.COM default: 1200*7348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 1201*7348SJose.Borrego@Sun.COM return; 1202*7348SJose.Borrego@Sun.COM } 1203*7348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 1204*7348SJose.Borrego@Sun.COM 1205*7348SJose.Borrego@Sun.COM if ((item = malloc(sizeof (smb_shr_pitem_t))) == NULL) { 1206*7348SJose.Borrego@Sun.COM syslog(LOG_DEBUG, "failed allocating share publish item"); 1207*7348SJose.Borrego@Sun.COM return; 1208*7348SJose.Borrego@Sun.COM } 1209*7348SJose.Borrego@Sun.COM 1210*7348SJose.Borrego@Sun.COM item->spi_op = op; 1211*7348SJose.Borrego@Sun.COM (void) strlcpy(item->spi_name, sharename, sizeof (item->spi_name)); 1212*7348SJose.Borrego@Sun.COM (void) strlcpy(item->spi_container, container, 1213*7348SJose.Borrego@Sun.COM sizeof (item->spi_container)); 1214*7348SJose.Borrego@Sun.COM 1215*7348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 1216*7348SJose.Borrego@Sun.COM list_insert_tail(&ad_queue.spq_list, item); 1217*7348SJose.Borrego@Sun.COM ad_queue.spq_cnt++; 1218*7348SJose.Borrego@Sun.COM (void) cond_signal(&ad_queue.spq_cv); 1219*7348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 1220*7348SJose.Borrego@Sun.COM } 1221*7348SJose.Borrego@Sun.COM 1222*7348SJose.Borrego@Sun.COM static int 1223*7348SJose.Borrego@Sun.COM smb_shr_publisher_start(void) 1224*7348SJose.Borrego@Sun.COM { 1225*7348SJose.Borrego@Sun.COM pthread_attr_t tattr; 1226*7348SJose.Borrego@Sun.COM int rc; 1227*7348SJose.Borrego@Sun.COM 1228*7348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 1229*7348SJose.Borrego@Sun.COM if (ad_queue.spq_state != SMB_SHR_PQS_NOQUEUE) { 1230*7348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 1231*7348SJose.Borrego@Sun.COM errno = EINVAL; 1232*7348SJose.Borrego@Sun.COM return (-1); 1233*7348SJose.Borrego@Sun.COM } 1234*7348SJose.Borrego@Sun.COM 1235*7348SJose.Borrego@Sun.COM list_create(&ad_queue.spq_list, sizeof (smb_shr_pitem_t), 1236*7348SJose.Borrego@Sun.COM offsetof(smb_shr_pitem_t, spi_lnd)); 1237*7348SJose.Borrego@Sun.COM ad_queue.spq_state = SMB_SHR_PQS_READY; 1238*7348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 1239*7348SJose.Borrego@Sun.COM 1240*7348SJose.Borrego@Sun.COM (void) pthread_attr_init(&tattr); 1241*7348SJose.Borrego@Sun.COM (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); 1242*7348SJose.Borrego@Sun.COM rc = pthread_create(&smb_shr_publish_thr, &tattr, 1243*7348SJose.Borrego@Sun.COM smb_shr_publisher, 0); 1244*7348SJose.Borrego@Sun.COM (void) pthread_attr_destroy(&tattr); 1245*7348SJose.Borrego@Sun.COM 1246*7348SJose.Borrego@Sun.COM return (rc); 1247*7348SJose.Borrego@Sun.COM } 1248*7348SJose.Borrego@Sun.COM 1249*7348SJose.Borrego@Sun.COM static void 1250*7348SJose.Borrego@Sun.COM smb_shr_publisher_stop(void) 1251*7348SJose.Borrego@Sun.COM { 1252*7348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 1253*7348SJose.Borrego@Sun.COM switch (ad_queue.spq_state) { 1254*7348SJose.Borrego@Sun.COM case SMB_SHR_PQS_READY: 1255*7348SJose.Borrego@Sun.COM case SMB_SHR_PQS_PUBLISHING: 1256*7348SJose.Borrego@Sun.COM ad_queue.spq_state = SMB_SHR_PQS_STOPPING; 1257*7348SJose.Borrego@Sun.COM (void) cond_signal(&ad_queue.spq_cv); 1258*7348SJose.Borrego@Sun.COM break; 1259*7348SJose.Borrego@Sun.COM default: 1260*7348SJose.Borrego@Sun.COM break; 1261*7348SJose.Borrego@Sun.COM } 1262*7348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 1263*7348SJose.Borrego@Sun.COM } 1264*7348SJose.Borrego@Sun.COM 1265*7348SJose.Borrego@Sun.COM /* 1266*7348SJose.Borrego@Sun.COM * This functions waits to be signaled and once running 1267*7348SJose.Borrego@Sun.COM * will publish/unpublish any items in the ad_queue 1268*7348SJose.Borrego@Sun.COM */ 1269*7348SJose.Borrego@Sun.COM /*ARGSUSED*/ 1270*7348SJose.Borrego@Sun.COM static void * 1271*7348SJose.Borrego@Sun.COM smb_shr_publisher(void *arg) 1272*7348SJose.Borrego@Sun.COM { 1273*7348SJose.Borrego@Sun.COM smb_ads_handle_t *ah; 1274*7348SJose.Borrego@Sun.COM smb_shr_pitem_t *shr; 1275*7348SJose.Borrego@Sun.COM list_t publist; 1276*7348SJose.Borrego@Sun.COM char hostname[MAXHOSTNAMELEN]; 1277*7348SJose.Borrego@Sun.COM 1278*7348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 1279*7348SJose.Borrego@Sun.COM if (ad_queue.spq_state == SMB_SHR_PQS_READY) { 1280*7348SJose.Borrego@Sun.COM ad_queue.spq_state = SMB_SHR_PQS_PUBLISHING; 1281*7348SJose.Borrego@Sun.COM } else { 1282*7348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 1283*7348SJose.Borrego@Sun.COM return (NULL); 1284*7348SJose.Borrego@Sun.COM } 1285*7348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 1286*7348SJose.Borrego@Sun.COM 1287*7348SJose.Borrego@Sun.COM (void) smb_gethostname(hostname, MAXHOSTNAMELEN, 0); 1288*7348SJose.Borrego@Sun.COM list_create(&publist, sizeof (smb_shr_pitem_t), 1289*7348SJose.Borrego@Sun.COM offsetof(smb_shr_pitem_t, spi_lnd)); 1290*7348SJose.Borrego@Sun.COM 1291*7348SJose.Borrego@Sun.COM for (;;) { 1292*7348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 1293*7348SJose.Borrego@Sun.COM while ((ad_queue.spq_cnt == 0) && 1294*7348SJose.Borrego@Sun.COM (ad_queue.spq_state == SMB_SHR_PQS_PUBLISHING)) 1295*7348SJose.Borrego@Sun.COM (void) cond_wait(&ad_queue.spq_cv, &ad_queue.spq_mtx); 1296*7348SJose.Borrego@Sun.COM 1297*7348SJose.Borrego@Sun.COM if (ad_queue.spq_state != SMB_SHR_PQS_PUBLISHING) { 1298*7348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 1299*7348SJose.Borrego@Sun.COM break; 1300*7348SJose.Borrego@Sun.COM } 1301*7348SJose.Borrego@Sun.COM 1302*7348SJose.Borrego@Sun.COM if ((ah = smb_ads_open()) == NULL) { 1303*7348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 1304*7348SJose.Borrego@Sun.COM continue; 1305*7348SJose.Borrego@Sun.COM } 1306*7348SJose.Borrego@Sun.COM 1307*7348SJose.Borrego@Sun.COM /* 1308*7348SJose.Borrego@Sun.COM * Transfer queued items to the local list so the mutex 1309*7348SJose.Borrego@Sun.COM * can be quickly released 1310*7348SJose.Borrego@Sun.COM */ 1311*7348SJose.Borrego@Sun.COM while ((shr = list_head(&ad_queue.spq_list)) != NULL) { 1312*7348SJose.Borrego@Sun.COM list_remove(&ad_queue.spq_list, shr); 1313*7348SJose.Borrego@Sun.COM ad_queue.spq_cnt--; 1314*7348SJose.Borrego@Sun.COM list_insert_tail(&publist, shr); 1315*7348SJose.Borrego@Sun.COM } 1316*7348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 1317*7348SJose.Borrego@Sun.COM 1318*7348SJose.Borrego@Sun.COM smb_shr_publisher_send(ah, &publist, hostname); 1319*7348SJose.Borrego@Sun.COM smb_ads_close(ah); 1320*7348SJose.Borrego@Sun.COM } 1321*7348SJose.Borrego@Sun.COM 1322*7348SJose.Borrego@Sun.COM /* Remove any leftover items from publishing queue */ 1323*7348SJose.Borrego@Sun.COM (void) mutex_lock(&ad_queue.spq_mtx); 1324*7348SJose.Borrego@Sun.COM while ((shr = list_head(&ad_queue.spq_list)) != NULL) { 1325*7348SJose.Borrego@Sun.COM list_remove(&ad_queue.spq_list, shr); 1326*7348SJose.Borrego@Sun.COM free(shr); 1327*7348SJose.Borrego@Sun.COM } 1328*7348SJose.Borrego@Sun.COM ad_queue.spq_cnt = 0; 1329*7348SJose.Borrego@Sun.COM list_destroy(&ad_queue.spq_list); 1330*7348SJose.Borrego@Sun.COM ad_queue.spq_state = SMB_SHR_PQS_NOQUEUE; 1331*7348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 1332*7348SJose.Borrego@Sun.COM 1333*7348SJose.Borrego@Sun.COM list_destroy(&publist); 1334*7348SJose.Borrego@Sun.COM return (NULL); 1335*7348SJose.Borrego@Sun.COM } 1336*7348SJose.Borrego@Sun.COM 1337*7348SJose.Borrego@Sun.COM /* 1338*7348SJose.Borrego@Sun.COM * Takes item from the given list and [un]publish them one by one. 1339*7348SJose.Borrego@Sun.COM * In each iteration it checks the status of the publisher thread 1340*7348SJose.Borrego@Sun.COM * and if it's been stopped then it continues to just empty the list 1341*7348SJose.Borrego@Sun.COM */ 1342*7348SJose.Borrego@Sun.COM static void 1343*7348SJose.Borrego@Sun.COM smb_shr_publisher_send(smb_ads_handle_t *ah, list_t *publist, const char *host) 1344*7348SJose.Borrego@Sun.COM { 1345*7348SJose.Borrego@Sun.COM smb_shr_pitem_t *shr; 1346*7348SJose.Borrego@Sun.COM boolean_t publish = B_TRUE; 1347*7348SJose.Borrego@Sun.COM 1348*7348SJose.Borrego@Sun.COM while ((shr = list_head(publist)) != NULL) { 1349*7348SJose.Borrego@Sun.COM list_remove(publist, shr); 1350*7348SJose.Borrego@Sun.COM if (publish) { 1351*7348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 1352*7348SJose.Borrego@Sun.COM if (ad_queue.spq_state != SMB_SHR_PQS_PUBLISHING) 1353*7348SJose.Borrego@Sun.COM publish = B_FALSE; 1354*7348SJose.Borrego@Sun.COM (void) mutex_unlock(&ad_queue.spq_mtx); 1355*7348SJose.Borrego@Sun.COM 1356*7348SJose.Borrego@Sun.COM if (shr->spi_op == SMB_SHR_PUBLISH) 1357*7348SJose.Borrego@Sun.COM (void) smb_ads_publish_share(ah, shr->spi_name, 1358*7348SJose.Borrego@Sun.COM NULL, shr->spi_container, host); 1359*7348SJose.Borrego@Sun.COM else 1360*7348SJose.Borrego@Sun.COM (void) smb_ads_remove_share(ah, shr->spi_name, 1361*7348SJose.Borrego@Sun.COM NULL, shr->spi_container, host); 1362*7348SJose.Borrego@Sun.COM } 1363*7348SJose.Borrego@Sun.COM free(shr); 1364*7348SJose.Borrego@Sun.COM } 1365*7348SJose.Borrego@Sun.COM } 1366