1*7052Samw /* 2*7052Samw * CDDL HEADER START 3*7052Samw * 4*7052Samw * The contents of this file are subject to the terms of the 5*7052Samw * Common Development and Distribution License (the "License"). 6*7052Samw * You may not use this file except in compliance with the License. 7*7052Samw * 8*7052Samw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*7052Samw * or http://www.opensolaris.org/os/licensing. 10*7052Samw * See the License for the specific language governing permissions 11*7052Samw * and limitations under the License. 12*7052Samw * 13*7052Samw * When distributing Covered Code, include this CDDL HEADER in each 14*7052Samw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*7052Samw * If applicable, add the following below this CDDL HEADER, with the 16*7052Samw * fields enclosed by brackets "[]" replaced with your own identifying 17*7052Samw * information: Portions Copyright [yyyy] [name of copyright owner] 18*7052Samw * 19*7052Samw * CDDL HEADER END 20*7052Samw */ 21*7052Samw /* 22*7052Samw * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23*7052Samw * Use is subject to license terms. 24*7052Samw */ 25*7052Samw 26*7052Samw #pragma ident "%Z%%M% %I% %E% SMI" 27*7052Samw 28*7052Samw /* 29*7052Samw * Lan Manager (SMB/CIFS) share interface implementation. This interface 30*7052Samw * returns Win32 error codes, usually network error values (lmerr.h). 31*7052Samw */ 32*7052Samw 33*7052Samw #include <errno.h> 34*7052Samw #include <synch.h> 35*7052Samw #include <stdio.h> 36*7052Samw #include <stdlib.h> 37*7052Samw #include <strings.h> 38*7052Samw #include <syslog.h> 39*7052Samw #include <thread.h> 40*7052Samw #include <fcntl.h> 41*7052Samw #include <unistd.h> 42*7052Samw #include <netdb.h> 43*7052Samw #include <synch.h> 44*7052Samw #include <pthread.h> 45*7052Samw #include <sys/mnttab.h> 46*7052Samw #include <sys/stat.h> 47*7052Samw #include <sys/types.h> 48*7052Samw #include <sys/queue.h> 49*7052Samw #include <ctype.h> 50*7052Samw 51*7052Samw #include <smbsrv/libsmb.h> 52*7052Samw #include <smbsrv/libsmbns.h> 53*7052Samw 54*7052Samw #include <libshare.h> 55*7052Samw 56*7052Samw #include <smbsrv/lm.h> 57*7052Samw #include <smbsrv/smb_share.h> 58*7052Samw #include <smbsrv/cifs.h> 59*7052Samw 60*7052Samw #include <smbsrv/ctype.h> 61*7052Samw #include <smbsrv/smb_vops.h> 62*7052Samw #include <smbsrv/smb_fsd.h> 63*7052Samw 64*7052Samw #define SMB_SHARE_HTAB_SZ 1024 65*7052Samw 66*7052Samw #define SMB_SHARE_PUBLISH 0 67*7052Samw #define SMB_SHARE_UNPUBLISH 1 68*7052Samw 69*7052Samw static HT_HANDLE *smb_shr_handle = NULL; 70*7052Samw static rwlock_t smb_shr_lock; 71*7052Samw static pthread_t smb_shr_cache_populatethr; 72*7052Samw 73*7052Samw static uint32_t smb_shr_cache_create(void); 74*7052Samw static void *smb_shr_cache_populate(void *); 75*7052Samw static int smb_shr_del_shmgr(smb_share_t *); 76*7052Samw static int smb_shr_set_shmgr(smb_share_t *); 77*7052Samw static uint32_t smb_shr_set_refcnt(char *, int); 78*7052Samw static void smb_shr_set_oemname(smb_share_t *); 79*7052Samw 80*7052Samw typedef struct smb_shr_adinfo { 81*7052Samw TAILQ_ENTRY(smb_shr_adinfo) next; 82*7052Samw char name[MAXNAMELEN]; 83*7052Samw char container[MAXPATHLEN]; 84*7052Samw char flag; 85*7052Samw } smb_shr_adinfo_t; 86*7052Samw 87*7052Samw typedef struct smb_shr_adqueue { 88*7052Samw int nentries; 89*7052Samw TAILQ_HEAD(adqueue, smb_shr_adinfo) adlist; 90*7052Samw } smb_shr_adqueue_t; 91*7052Samw 92*7052Samw static smb_shr_adqueue_t ad_queue; 93*7052Samw static int publish_on = 0; 94*7052Samw 95*7052Samw static pthread_t smb_shr_publish_thr; 96*7052Samw static mutex_t smb_shr_publish_mtx = PTHREAD_MUTEX_INITIALIZER; 97*7052Samw static cond_t smb_shr_publish_cv = DEFAULTCV; 98*7052Samw 99*7052Samw static void *smb_shr_publisher(void *); 100*7052Samw static void smb_shr_stop_publish(void); 101*7052Samw static void smb_shr_publish(smb_share_t *, char, int); 102*7052Samw 103*7052Samw /* 104*7052Samw * Start loading lmshare information from sharemanager 105*7052Samw * and create the cache. 106*7052Samw */ 107*7052Samw int 108*7052Samw smb_shr_start(void) 109*7052Samw { 110*7052Samw int rc; 111*7052Samw 112*7052Samw rc = pthread_create(&smb_shr_publish_thr, NULL, 113*7052Samw smb_shr_publisher, 0); 114*7052Samw if (rc != 0) { 115*7052Samw syslog(LOG_ERR, "Failed to start publisher thread, " 116*7052Samw "share publishing is disabled"); 117*7052Samw } 118*7052Samw 119*7052Samw rc = pthread_create(&smb_shr_cache_populatethr, NULL, 120*7052Samw smb_shr_cache_populate, 0); 121*7052Samw if (rc != 0) { 122*7052Samw syslog(LOG_ERR, "Failed to start share loading, " 123*7052Samw "existing shares will not be available"); 124*7052Samw } 125*7052Samw 126*7052Samw return (rc); 127*7052Samw } 128*7052Samw 129*7052Samw void 130*7052Samw smb_shr_stop(void) 131*7052Samw { 132*7052Samw smb_shr_stop_publish(); 133*7052Samw } 134*7052Samw 135*7052Samw /* 136*7052Samw * lmshare_load_shares 137*7052Samw * 138*7052Samw * Helper function for smb_shr_cache_populate. It attempts to load the shares 139*7052Samw * contained in the group. 140*7052Samw */ 141*7052Samw 142*7052Samw static void 143*7052Samw lmshare_load_shares(sa_group_t group) 144*7052Samw { 145*7052Samw sa_share_t share; 146*7052Samw sa_resource_t resource; 147*7052Samw smb_share_t si; 148*7052Samw char *path, *rname; 149*7052Samw 150*7052Samw /* Don't bother if "smb" isn't set on the group */ 151*7052Samw if (sa_get_optionset(group, SMB_PROTOCOL_NAME) == NULL) 152*7052Samw return; 153*7052Samw 154*7052Samw for (share = sa_get_share(group, NULL); 155*7052Samw share != NULL; share = sa_get_next_share(share)) { 156*7052Samw path = sa_get_share_attr(share, "path"); 157*7052Samw if (path == NULL) { 158*7052Samw continue; 159*7052Samw } 160*7052Samw for (resource = sa_get_share_resource(share, NULL); 161*7052Samw resource != NULL; 162*7052Samw resource = sa_get_next_resource(resource)) { 163*7052Samw rname = sa_get_resource_attr(resource, "name"); 164*7052Samw if (rname == NULL) { 165*7052Samw syslog(LOG_ERR, "Invalid share " 166*7052Samw "resource for path: %s", path); 167*7052Samw continue; 168*7052Samw } 169*7052Samw smb_build_lmshare_info(rname, path, resource, &si); 170*7052Samw sa_free_attr_string(rname); 171*7052Samw if (smb_shr_add(&si, 0) != NERR_Success) { 172*7052Samw syslog(LOG_ERR, "Failed to load " 173*7052Samw "share %s", si.shr_name); 174*7052Samw } 175*7052Samw } 176*7052Samw /* We are done with all shares for same path */ 177*7052Samw sa_free_attr_string(path); 178*7052Samw } 179*7052Samw } 180*7052Samw 181*7052Samw /* 182*7052Samw * smb_shr_cache_populate 183*7052Samw * 184*7052Samw * Load shares from sharemanager. The args argument is currently not 185*7052Samw * used. The function walks through all the groups in libshare and 186*7052Samw * calls lmshare_load_shares for each group found. It also looks for 187*7052Samw * sub-groups and calls lmshare_load_shares for each sub-group found. 188*7052Samw */ 189*7052Samw 190*7052Samw /*ARGSUSED*/ 191*7052Samw static void * 192*7052Samw smb_shr_cache_populate(void *args) 193*7052Samw { 194*7052Samw sa_handle_t handle; 195*7052Samw sa_group_t group, subgroup; 196*7052Samw char *gstate; 197*7052Samw 198*7052Samw if (smb_shr_cache_create() != NERR_Success) { 199*7052Samw syslog(LOG_ERR, "Failed to create share hash table"); 200*7052Samw return (NULL); 201*7052Samw } 202*7052Samw 203*7052Samw handle = sa_init(SA_INIT_SHARE_API); 204*7052Samw if (handle == NULL) { 205*7052Samw syslog(LOG_ERR, "Failed to load share " 206*7052Samw "information: no libshare handle"); 207*7052Samw return (NULL); 208*7052Samw } 209*7052Samw 210*7052Samw for (group = sa_get_group(handle, NULL); 211*7052Samw group != NULL; group = sa_get_next_group(group)) { 212*7052Samw gstate = sa_get_group_attr(group, "state"); 213*7052Samw if (gstate == NULL) 214*7052Samw continue; 215*7052Samw if (strcasecmp(gstate, "disabled") == 0) { 216*7052Samw /* Skip disabled or unknown state group */ 217*7052Samw sa_free_attr_string(gstate); 218*7052Samw continue; 219*7052Samw } 220*7052Samw sa_free_attr_string(gstate); 221*7052Samw 222*7052Samw /* 223*7052Samw * Attempt to load the shares. lmshare_load_shares 224*7052Samw * will check to see if the protocol is enabled or 225*7052Samw * not. We then want to check for any sub-groups on 226*7052Samw * this group. This is needed in the ZFS case where 227*7052Samw * the top level ZFS group won't have "smb" protocol 228*7052Samw * enabled but the sub-groups will. 229*7052Samw */ 230*7052Samw lmshare_load_shares(group); 231*7052Samw for (subgroup = sa_get_sub_group(group); 232*7052Samw subgroup != NULL; 233*7052Samw subgroup = sa_get_next_group(subgroup)) { 234*7052Samw lmshare_load_shares(subgroup); 235*7052Samw } 236*7052Samw 237*7052Samw } 238*7052Samw 239*7052Samw sa_fini(handle); 240*7052Samw 241*7052Samw return (NULL); 242*7052Samw } 243*7052Samw 244*7052Samw /* 245*7052Samw * lmshare_callback 246*7052Samw * 247*7052Samw * Call back to free share structures stored 248*7052Samw * in shares' hash table. 249*7052Samw */ 250*7052Samw static void 251*7052Samw lmshare_callback(HT_ITEM *item) 252*7052Samw { 253*7052Samw if (item && item->hi_data) 254*7052Samw free(item->hi_data); 255*7052Samw } 256*7052Samw 257*7052Samw /* 258*7052Samw * smb_shr_cache_create 259*7052Samw * 260*7052Samw * Create the share hash table. 261*7052Samw */ 262*7052Samw static uint32_t 263*7052Samw smb_shr_cache_create(void) 264*7052Samw { 265*7052Samw if (smb_shr_handle == NULL) { 266*7052Samw (void) rwlock_init(&smb_shr_lock, USYNC_THREAD, 0); 267*7052Samw (void) rw_wrlock(&smb_shr_lock); 268*7052Samw 269*7052Samw smb_shr_handle = ht_create_table(SMB_SHARE_HTAB_SZ, 270*7052Samw MAXNAMELEN, 0); 271*7052Samw if (smb_shr_handle == NULL) { 272*7052Samw syslog(LOG_ERR, "smb_shr_cache_create:" 273*7052Samw " unable to create share table"); 274*7052Samw (void) rw_unlock(&smb_shr_lock); 275*7052Samw return (NERR_InternalError); 276*7052Samw } 277*7052Samw (void) ht_register_callback(smb_shr_handle, lmshare_callback); 278*7052Samw (void) rw_unlock(&smb_shr_lock); 279*7052Samw } 280*7052Samw 281*7052Samw return (NERR_Success); 282*7052Samw } 283*7052Samw 284*7052Samw /* 285*7052Samw * smb_shr_add_adminshare 286*7052Samw * 287*7052Samw * add the admin share for the volume when the share database 288*7052Samw * for that volume is going to be loaded. 289*7052Samw */ 290*7052Samw uint32_t 291*7052Samw smb_shr_add_adminshare(char *volname, unsigned char drive) 292*7052Samw { 293*7052Samw smb_share_t si; 294*7052Samw uint32_t rc; 295*7052Samw 296*7052Samw if (drive == 0) 297*7052Samw return (NERR_InvalidDevice); 298*7052Samw 299*7052Samw bzero(&si, sizeof (smb_share_t)); 300*7052Samw (void) strcpy(si.shr_path, volname); 301*7052Samw si.shr_flags = SMB_SHRF_TRANS | SMB_SHRF_ADMIN; 302*7052Samw (void) snprintf(si.shr_name, sizeof (si.shr_name), "%c$", drive); 303*7052Samw rc = smb_shr_add(&si, 0); 304*7052Samw 305*7052Samw return (rc); 306*7052Samw } 307*7052Samw 308*7052Samw /* 309*7052Samw * smb_shr_count 310*7052Samw * 311*7052Samw * Return the total number of shares, which should be the same value 312*7052Samw * that would be returned from a share enum request. 313*7052Samw */ 314*7052Samw int 315*7052Samw smb_shr_count(void) 316*7052Samw { 317*7052Samw int n_shares; 318*7052Samw 319*7052Samw n_shares = ht_get_total_items(smb_shr_handle); 320*7052Samw 321*7052Samw /* If we don't store IPC$ in hash table we should do this */ 322*7052Samw n_shares++; 323*7052Samw 324*7052Samw return (n_shares); 325*7052Samw } 326*7052Samw 327*7052Samw /* 328*7052Samw * smb_shr_iterinit 329*7052Samw * 330*7052Samw * Initialize an iterator for traversing hash table. 331*7052Samw * 'mode' is used for filtering shares when iterating. 332*7052Samw */ 333*7052Samw void 334*7052Samw smb_shr_iterinit(smb_shriter_t *shi, uint32_t mode) 335*7052Samw { 336*7052Samw bzero(shi, sizeof (smb_shriter_t)); 337*7052Samw shi->si_mode = mode; 338*7052Samw } 339*7052Samw 340*7052Samw /* 341*7052Samw * smb_shr_iterate 342*7052Samw * 343*7052Samw * Iterate on the shares in the hash table. The iterator must be initialized 344*7052Samw * before the first iteration. On subsequent calls, the iterator must be 345*7052Samw * passed unchanged. 346*7052Samw * 347*7052Samw * Returns NULL on failure or when all shares are visited, otherwise 348*7052Samw * returns information of visited share. 349*7052Samw * 350*7052Samw * Note that there are some special shares, i.e. IPC$, that must also 351*7052Samw * be processed. 352*7052Samw */ 353*7052Samw smb_share_t * 354*7052Samw smb_shr_iterate(smb_shriter_t *shi) 355*7052Samw { 356*7052Samw HT_ITEM *item; 357*7052Samw smb_share_t *si; 358*7052Samw 359*7052Samw if (smb_shr_handle == NULL || shi == NULL) 360*7052Samw return (NULL); 361*7052Samw 362*7052Samw if (shi->si_counter == 0) { 363*7052Samw /* 364*7052Samw * IPC$ is always first. 365*7052Samw */ 366*7052Samw (void) strcpy(shi->si_share.shr_name, "IPC$"); 367*7052Samw smb_shr_set_oemname(&shi->si_share); 368*7052Samw shi->si_share.shr_flags = SMB_SHRF_TRANS; 369*7052Samw shi->si_share.shr_type = (int)(STYPE_IPC | STYPE_SPECIAL); 370*7052Samw shi->si_counter = 1; 371*7052Samw return (&(shi->si_share)); 372*7052Samw } 373*7052Samw 374*7052Samw if (shi->si_counter == 1) { 375*7052Samw if ((item = ht_findfirst( 376*7052Samw smb_shr_handle, &shi->si_hashiter)) == NULL) { 377*7052Samw return (NULL); 378*7052Samw } 379*7052Samw 380*7052Samw si = (smb_share_t *)(item->hi_data); 381*7052Samw ++shi->si_counter; 382*7052Samw 383*7052Samw if (si->shr_flags & shi->si_mode) { 384*7052Samw bcopy(si, &(shi->si_share), sizeof (smb_share_t)); 385*7052Samw return (&(shi->si_share)); 386*7052Samw } 387*7052Samw } 388*7052Samw 389*7052Samw while ((item = ht_findnext(&shi->si_hashiter)) != NULL) { 390*7052Samw si = (smb_share_t *)(item->hi_data); 391*7052Samw ++shi->si_counter; 392*7052Samw if (si->shr_flags & shi->si_mode) { 393*7052Samw bcopy(si, &(shi->si_share), sizeof (smb_share_t)); 394*7052Samw return (&(shi->si_share)); 395*7052Samw } 396*7052Samw } 397*7052Samw 398*7052Samw return (NULL); 399*7052Samw } 400*7052Samw 401*7052Samw /* 402*7052Samw * smb_shr_add 403*7052Samw * 404*7052Samw * Add a share. This is a wrapper round smb_shr_set that checks 405*7052Samw * whether or not the share already exists. If the share exists, an 406*7052Samw * error is returned. 407*7052Samw * 408*7052Samw * Don't check smb_shr_is_dir here: it causes rootfs to recurse. 409*7052Samw */ 410*7052Samw uint32_t 411*7052Samw smb_shr_add(smb_share_t *si, int doshm) 412*7052Samw { 413*7052Samw uint32_t status = NERR_Success; 414*7052Samw 415*7052Samw if (si == 0 || smb_shr_is_valid(si->shr_name) == 0) 416*7052Samw return (NERR_InvalidDevice); 417*7052Samw 418*7052Samw (void) utf8_strlwr(si->shr_name); 419*7052Samw 420*7052Samw if (smb_shr_exists(si->shr_name)) { 421*7052Samw /* 422*7052Samw * Only autohome shares can be added multiple times 423*7052Samw */ 424*7052Samw if ((si->shr_flags & SMB_SHRF_AUTOHOME) == 0) 425*7052Samw return (NERR_DuplicateShare); 426*7052Samw } 427*7052Samw 428*7052Samw if (si->shr_refcnt == 0) { 429*7052Samw status = smb_shr_set(si, doshm); 430*7052Samw smb_shr_publish(si, SMB_SHARE_PUBLISH, 1); 431*7052Samw } 432*7052Samw 433*7052Samw if ((si->shr_flags & SMB_SHRF_AUTOHOME) && (status == NERR_Success)) { 434*7052Samw si->shr_refcnt++; 435*7052Samw status = smb_shr_set_refcnt(si->shr_name, si->shr_refcnt); 436*7052Samw } 437*7052Samw 438*7052Samw if (status) 439*7052Samw return (status); 440*7052Samw 441*7052Samw return (smb_dwncall_share(SMB_SHROP_ADD, si->shr_path, si->shr_name)); 442*7052Samw } 443*7052Samw 444*7052Samw /* 445*7052Samw * smb_shr_del 446*7052Samw * 447*7052Samw * Remove a share. Ensure that all SMB trees associated with this share 448*7052Samw * are disconnected. If the share does not exist, an error is returned. 449*7052Samw */ 450*7052Samw uint32_t 451*7052Samw smb_shr_del(char *share_name, int doshm) 452*7052Samw { 453*7052Samw smb_share_t *si; 454*7052Samw HT_ITEM *item; 455*7052Samw uint32_t status; 456*7052Samw char path[MAXPATHLEN]; 457*7052Samw 458*7052Samw if (share_name) 459*7052Samw (void) utf8_strlwr(share_name); 460*7052Samw 461*7052Samw if (smb_shr_is_valid(share_name) == 0 || 462*7052Samw smb_shr_exists(share_name) == 0) { 463*7052Samw return (NERR_NetNameNotFound); 464*7052Samw } 465*7052Samw 466*7052Samw (void) rw_wrlock(&smb_shr_lock); 467*7052Samw item = ht_find_item(smb_shr_handle, share_name); 468*7052Samw 469*7052Samw if (item == NULL) { 470*7052Samw (void) rw_unlock(&smb_shr_lock); 471*7052Samw return (NERR_ItemNotFound); 472*7052Samw } 473*7052Samw 474*7052Samw si = (smb_share_t *)item->hi_data; 475*7052Samw if (si == NULL) { 476*7052Samw (void) rw_unlock(&smb_shr_lock); 477*7052Samw return (NERR_InternalError); 478*7052Samw } 479*7052Samw 480*7052Samw if ((si->shr_flags & SMB_SHRF_AUTOHOME) == SMB_SHRF_AUTOHOME) { 481*7052Samw si->shr_refcnt--; 482*7052Samw if (si->shr_refcnt > 0) { 483*7052Samw status = smb_shr_set_refcnt(si->shr_name, 484*7052Samw si->shr_refcnt); 485*7052Samw (void) rw_unlock(&smb_shr_lock); 486*7052Samw return (status); 487*7052Samw } 488*7052Samw } 489*7052Samw 490*7052Samw if (doshm && (smb_shr_del_shmgr(si) != 0)) { 491*7052Samw (void) rw_unlock(&smb_shr_lock); 492*7052Samw return (NERR_InternalError); 493*7052Samw } 494*7052Samw 495*7052Samw smb_shr_publish(si, SMB_SHARE_UNPUBLISH, 1); 496*7052Samw 497*7052Samw /* 498*7052Samw * Copy the path before the entry is removed from the hash table 499*7052Samw */ 500*7052Samw 501*7052Samw (void) strlcpy(path, si->shr_path, MAXPATHLEN); 502*7052Samw 503*7052Samw /* Delete from hash table */ 504*7052Samw 505*7052Samw (void) ht_remove_item(smb_shr_handle, share_name); 506*7052Samw (void) rw_unlock(&smb_shr_lock); 507*7052Samw 508*7052Samw return (smb_dwncall_share(SMB_SHROP_DELETE, path, share_name)); 509*7052Samw } 510*7052Samw 511*7052Samw /* 512*7052Samw * smb_shr_set_refcnt 513*7052Samw * 514*7052Samw * sets the autohome shr_refcnt for a share 515*7052Samw */ 516*7052Samw static uint32_t 517*7052Samw smb_shr_set_refcnt(char *share_name, int refcnt) 518*7052Samw { 519*7052Samw smb_share_t *si; 520*7052Samw HT_ITEM *item; 521*7052Samw 522*7052Samw if (share_name) { 523*7052Samw (void) utf8_strlwr(share_name); 524*7052Samw } 525*7052Samw (void) rw_wrlock(&smb_shr_lock); 526*7052Samw item = ht_find_item(smb_shr_handle, share_name); 527*7052Samw if (item == NULL) { 528*7052Samw (void) rw_unlock(&smb_shr_lock); 529*7052Samw return (NERR_ItemNotFound); 530*7052Samw } 531*7052Samw 532*7052Samw si = (smb_share_t *)item->hi_data; 533*7052Samw if (si == NULL) { 534*7052Samw (void) rw_unlock(&smb_shr_lock); 535*7052Samw return (NERR_InternalError); 536*7052Samw } 537*7052Samw si->shr_refcnt = refcnt; 538*7052Samw (void) rw_unlock(&smb_shr_lock); 539*7052Samw return (NERR_Success); 540*7052Samw } 541*7052Samw 542*7052Samw /* 543*7052Samw * smb_shr_ren 544*7052Samw * 545*7052Samw * Rename a share. Check that the current name exists and the new name 546*7052Samw * doesn't exist. The rename is performed by deleting the current share 547*7052Samw * definition and creating a new share with the new name. 548*7052Samw */ 549*7052Samw uint32_t 550*7052Samw smb_shr_ren(char *from_name, char *to_name, int doshm) 551*7052Samw { 552*7052Samw smb_share_t si; 553*7052Samw uint32_t nerr; 554*7052Samw 555*7052Samw if (smb_shr_is_valid(from_name) == 0 || 556*7052Samw smb_shr_is_valid(to_name) == 0) 557*7052Samw return (NERR_InvalidDevice); 558*7052Samw 559*7052Samw (void) utf8_strlwr(from_name); 560*7052Samw (void) utf8_strlwr(to_name); 561*7052Samw 562*7052Samw if (smb_shr_exists(from_name) == 0) 563*7052Samw return (NERR_NetNameNotFound); 564*7052Samw 565*7052Samw if (smb_shr_exists(to_name)) 566*7052Samw return (NERR_DuplicateShare); 567*7052Samw 568*7052Samw if ((nerr = smb_shr_get(from_name, &si)) != NERR_Success) 569*7052Samw return (nerr); 570*7052Samw 571*7052Samw if ((nerr = smb_shr_del(from_name, doshm)) != NERR_Success) 572*7052Samw return (nerr); 573*7052Samw 574*7052Samw (void) strlcpy(si.shr_name, to_name, MAXNAMELEN); 575*7052Samw return (smb_shr_add(&si, 1)); 576*7052Samw } 577*7052Samw 578*7052Samw /* 579*7052Samw * smb_shr_exists 580*7052Samw * 581*7052Samw * Returns 1 if the share exists. Otherwise returns 0. 582*7052Samw */ 583*7052Samw int 584*7052Samw smb_shr_exists(char *share_name) 585*7052Samw { 586*7052Samw if (share_name == 0 || *share_name == 0) 587*7052Samw return (0); 588*7052Samw 589*7052Samw if (ht_find_item(smb_shr_handle, share_name) == NULL) 590*7052Samw return (0); 591*7052Samw else 592*7052Samw return (1); 593*7052Samw } 594*7052Samw 595*7052Samw /* 596*7052Samw * smb_shr_is_special 597*7052Samw * 598*7052Samw * Simple check to determine if share name represents a special share, 599*7052Samw * i.e. the last character of the name is a '$'. Returns STYPE_SPECIAL 600*7052Samw * if the name is special. Otherwise returns 0. 601*7052Samw */ 602*7052Samw int 603*7052Samw smb_shr_is_special(char *share_name) 604*7052Samw { 605*7052Samw int len; 606*7052Samw 607*7052Samw if (share_name == 0) 608*7052Samw return (0); 609*7052Samw 610*7052Samw if ((len = strlen(share_name)) == 0) 611*7052Samw return (0); 612*7052Samw 613*7052Samw if (share_name[len - 1] == '$') 614*7052Samw return (STYPE_SPECIAL); 615*7052Samw else 616*7052Samw return (0); 617*7052Samw } 618*7052Samw 619*7052Samw 620*7052Samw /* 621*7052Samw * smb_shr_is_restricted 622*7052Samw * 623*7052Samw * Check whether or not there is a restriction on a share. Restricted 624*7052Samw * shares are generally STYPE_SPECIAL, for example, IPC$. All the 625*7052Samw * administration share names are restricted: C$, D$ etc. Returns 1 626*7052Samw * if the share is restricted. Otherwise 0 is returned to indicate 627*7052Samw * that there are no restrictions. 628*7052Samw */ 629*7052Samw int 630*7052Samw smb_shr_is_restricted(char *share_name) 631*7052Samw { 632*7052Samw static char *restricted[] = { 633*7052Samw "IPC$" 634*7052Samw }; 635*7052Samw 636*7052Samw int i; 637*7052Samw 638*7052Samw for (i = 0; i < sizeof (restricted)/sizeof (restricted[0]); i++) { 639*7052Samw if (strcasecmp(restricted[i], share_name) == 0) 640*7052Samw return (1); 641*7052Samw } 642*7052Samw 643*7052Samw if (smb_shr_is_admin(share_name)) 644*7052Samw return (1); 645*7052Samw 646*7052Samw return (0); 647*7052Samw } 648*7052Samw 649*7052Samw 650*7052Samw /* 651*7052Samw * smb_shr_is_admin 652*7052Samw * 653*7052Samw * Check whether or not access to the share should be restricted to 654*7052Samw * administrators. This is a bit of a hack because what we're doing 655*7052Samw * is checking for the default admin shares: C$, D$ etc.. There are 656*7052Samw * other shares that have restrictions: see smb_shr_is_restricted(). 657*7052Samw * 658*7052Samw * Returns 1 if the shares is an admin share. Otherwise 0 is returned 659*7052Samw * to indicate that there are no restrictions. 660*7052Samw */ 661*7052Samw int 662*7052Samw smb_shr_is_admin(char *share_name) 663*7052Samw { 664*7052Samw if (share_name == 0) 665*7052Samw return (0); 666*7052Samw 667*7052Samw if (strlen(share_name) == 2 && 668*7052Samw mts_isalpha(share_name[0]) && share_name[1] == '$') { 669*7052Samw return (1); 670*7052Samw } 671*7052Samw 672*7052Samw return (0); 673*7052Samw } 674*7052Samw 675*7052Samw 676*7052Samw /* 677*7052Samw * smb_shr_is_valid 678*7052Samw * 679*7052Samw * Check if any invalid char is present in share name. According to 680*7052Samw * MSDN article #236388: "Err Msg: The Share Name Contains Invalid 681*7052Samw * Characters", the list of invalid character is: 682*7052Samw * 683*7052Samw * " / \ [ ] : | < > + ; , ? * = 684*7052Samw * 685*7052Samw * Also rejects if control characters are embedded. 686*7052Samw * 687*7052Samw * If the sharename is valid, return (1). Otherwise return (0). 688*7052Samw */ 689*7052Samw int 690*7052Samw smb_shr_is_valid(char *share_name) 691*7052Samw { 692*7052Samw char *invalid = "\"/\\[]:|<>+;,?*="; 693*7052Samw char *cp; 694*7052Samw 695*7052Samw if (share_name == 0) 696*7052Samw return (0); 697*7052Samw 698*7052Samw if (strpbrk(share_name, invalid)) 699*7052Samw return (0); 700*7052Samw 701*7052Samw for (cp = share_name; *cp != '\0'; cp++) 702*7052Samw if (iscntrl(*cp)) 703*7052Samw return (0); 704*7052Samw 705*7052Samw return (1); 706*7052Samw } 707*7052Samw 708*7052Samw /* 709*7052Samw * smb_shr_is_dir 710*7052Samw * 711*7052Samw * Check to determine if a share object represents a directory. 712*7052Samw * 713*7052Samw * Returns 1 if the path leads to a directory. Otherwise returns 0. 714*7052Samw */ 715*7052Samw int 716*7052Samw smb_shr_is_dir(char *path) 717*7052Samw { 718*7052Samw struct stat stat_info; 719*7052Samw 720*7052Samw if (stat(path, &stat_info) == 0) 721*7052Samw if (S_ISDIR(stat_info.st_mode)) 722*7052Samw return (1); 723*7052Samw 724*7052Samw return (0); 725*7052Samw 726*7052Samw } 727*7052Samw 728*7052Samw /* 729*7052Samw * smb_shr_get 730*7052Samw * 731*7052Samw * Load the information for the specified share into the supplied share 732*7052Samw * info structure. If the shared directory does not begin with a /, one 733*7052Samw * will be inserted as a prefix. 734*7052Samw */ 735*7052Samw uint32_t 736*7052Samw smb_shr_get(char *share_name, smb_share_t *si) 737*7052Samw { 738*7052Samw int i, endidx; 739*7052Samw int dirlen; 740*7052Samw HT_ITEM *item; 741*7052Samw 742*7052Samw (void) rw_rdlock(&smb_shr_lock); 743*7052Samw 744*7052Samw (void) utf8_strlwr(share_name); 745*7052Samw if ((item = ht_find_item(smb_shr_handle, share_name)) == NULL) { 746*7052Samw bzero(si, sizeof (smb_share_t)); 747*7052Samw (void) rw_unlock(&smb_shr_lock); 748*7052Samw return (NERR_NetNameNotFound); 749*7052Samw } 750*7052Samw 751*7052Samw (void) memcpy(si, item->hi_data, sizeof (smb_share_t)); 752*7052Samw (void) rw_unlock(&smb_shr_lock); 753*7052Samw 754*7052Samw if (si->shr_path[0] == '\0') 755*7052Samw return (NERR_NetNameNotFound); 756*7052Samw 757*7052Samw if (si->shr_path[0] != '/') { 758*7052Samw dirlen = strlen(si->shr_path) + 1; 759*7052Samw endidx = (dirlen < MAXPATHLEN-1) ? 760*7052Samw dirlen : MAXPATHLEN - 2; 761*7052Samw for (i = endidx; i >= 0; i--) 762*7052Samw si->shr_path[i+1] = si->shr_path[i]; 763*7052Samw si->shr_path[MAXPATHLEN-1] = '\0'; 764*7052Samw si->shr_path[0] = '/'; 765*7052Samw } 766*7052Samw 767*7052Samw return (NERR_Success); 768*7052Samw } 769*7052Samw 770*7052Samw /* 771*7052Samw * Remove share from sharemanager repository. 772*7052Samw */ 773*7052Samw static int 774*7052Samw smb_shr_del_shmgr(smb_share_t *si) 775*7052Samw { 776*7052Samw sa_handle_t handle; 777*7052Samw sa_share_t share; 778*7052Samw sa_resource_t resource; 779*7052Samw 780*7052Samw handle = sa_init(SA_INIT_SHARE_API); 781*7052Samw if (handle == NULL) { 782*7052Samw syslog(LOG_ERR, "Failed to get handle to " 783*7052Samw "share lib"); 784*7052Samw return (1); 785*7052Samw } 786*7052Samw share = sa_find_share(handle, si->shr_path); 787*7052Samw if (share == NULL) { 788*7052Samw syslog(LOG_ERR, "Failed to get share to delete"); 789*7052Samw sa_fini(handle); 790*7052Samw return (1); 791*7052Samw } 792*7052Samw resource = sa_get_share_resource(share, si->shr_name); 793*7052Samw if (resource == NULL) { 794*7052Samw syslog(LOG_ERR, "Failed to get share resource to delete"); 795*7052Samw sa_fini(handle); 796*7052Samw return (1); 797*7052Samw } 798*7052Samw if (sa_remove_resource(resource) != SA_OK) { 799*7052Samw syslog(LOG_ERR, "Failed to remove resource"); 800*7052Samw sa_fini(handle); 801*7052Samw return (1); 802*7052Samw } 803*7052Samw sa_fini(handle); 804*7052Samw return (0); 805*7052Samw } 806*7052Samw 807*7052Samw static int 808*7052Samw smb_shr_set_shmgr(smb_share_t *si) 809*7052Samw { 810*7052Samw sa_handle_t handle; 811*7052Samw sa_share_t share; 812*7052Samw sa_group_t group; 813*7052Samw sa_resource_t resource; 814*7052Samw int share_created = 0; 815*7052Samw int err; 816*7052Samw 817*7052Samw /* Add share to sharemanager */ 818*7052Samw handle = sa_init(SA_INIT_SHARE_API); 819*7052Samw if (handle == NULL) { 820*7052Samw syslog(LOG_ERR, "Failed to get handle to share lib"); 821*7052Samw return (1); 822*7052Samw } 823*7052Samw share = sa_find_share(handle, si->shr_path); 824*7052Samw if (share == NULL) { 825*7052Samw group = smb_get_smb_share_group(handle); 826*7052Samw if (group == NULL) { 827*7052Samw sa_fini(handle); 828*7052Samw return (1); 829*7052Samw } 830*7052Samw share = sa_add_share(group, si->shr_path, 0, &err); 831*7052Samw if (share == NULL) { 832*7052Samw sa_fini(handle); 833*7052Samw return (1); 834*7052Samw } 835*7052Samw share_created = 1; 836*7052Samw } 837*7052Samw resource = sa_get_share_resource(share, si->shr_name); 838*7052Samw if (resource == NULL) { 839*7052Samw resource = sa_add_resource(share, si->shr_name, 840*7052Samw SA_SHARE_PERMANENT, &err); 841*7052Samw if (resource == NULL) { 842*7052Samw goto failure; 843*7052Samw } 844*7052Samw } 845*7052Samw if (sa_set_resource_attr(resource, 846*7052Samw "description", si->shr_cmnt) != SA_OK) { 847*7052Samw syslog(LOG_ERR, "Falied to set resource " 848*7052Samw "description in sharemgr"); 849*7052Samw goto failure; 850*7052Samw } 851*7052Samw if (sa_set_resource_attr(resource, 852*7052Samw SMB_SHROPT_AD_CONTAINER, si->shr_container) != SA_OK) { 853*7052Samw syslog(LOG_ERR, "Falied to set ad-container in sharemgr"); 854*7052Samw goto failure; 855*7052Samw } 856*7052Samw 857*7052Samw sa_fini(handle); 858*7052Samw return (0); 859*7052Samw failure: 860*7052Samw if (share_created && (share != NULL)) { 861*7052Samw if (sa_remove_share(share) != SA_OK) { 862*7052Samw syslog(LOG_ERR, "Failed to cleanup share"); 863*7052Samw } 864*7052Samw } 865*7052Samw if (resource != NULL) { 866*7052Samw if (sa_remove_resource(resource) != SA_OK) { 867*7052Samw syslog(LOG_ERR, "Failed to cleanup share resource"); 868*7052Samw } 869*7052Samw } 870*7052Samw sa_fini(handle); 871*7052Samw return (1); 872*7052Samw } 873*7052Samw 874*7052Samw /* 875*7052Samw * smb_shr_cache_delshare 876*7052Samw * 877*7052Samw * Delete the given share only from hash table 878*7052Samw */ 879*7052Samw static uint32_t 880*7052Samw smb_shr_cache_delshare(char *share_name) 881*7052Samw { 882*7052Samw if (share_name == 0) 883*7052Samw return (NERR_NetNameNotFound); 884*7052Samw 885*7052Samw (void) utf8_strlwr(share_name); 886*7052Samw 887*7052Samw if (smb_shr_is_valid(share_name) == 0 || 888*7052Samw smb_shr_exists(share_name) == 0) { 889*7052Samw return (NERR_NetNameNotFound); 890*7052Samw } 891*7052Samw 892*7052Samw (void) rw_wrlock(&smb_shr_lock); 893*7052Samw (void) ht_remove_item(smb_shr_handle, share_name); 894*7052Samw (void) rw_unlock(&smb_shr_lock); 895*7052Samw 896*7052Samw return (NERR_Success); 897*7052Samw } 898*7052Samw 899*7052Samw /* 900*7052Samw * smb_shr_set 901*7052Samw * 902*7052Samw * Adds the specified share into the system hash table 903*7052Samw * and also store its info in the corresponding disk 904*7052Samw * structure if it is not a temporary (SMB_SHRF_TRANS) share. 905*7052Samw * when the first share is going to be added, create shares 906*7052Samw * hash table if it is not already created. 907*7052Samw * If the share already exists, it will be replaced. If the 908*7052Samw * new share directory name does not begin with a /, one will be 909*7052Samw * inserted as a prefix. 910*7052Samw */ 911*7052Samw uint32_t 912*7052Samw smb_shr_set(smb_share_t *si, int doshm) 913*7052Samw { 914*7052Samw int i, endidx; 915*7052Samw int dirlen; 916*7052Samw smb_share_t *add_si; 917*7052Samw int res = NERR_Success; 918*7052Samw smb_share_t old_si; 919*7052Samw 920*7052Samw if (si->shr_path[0] != '/') { 921*7052Samw dirlen = strlen(si->shr_path) + 1; 922*7052Samw endidx = (dirlen < MAXPATHLEN - 1) ? 923*7052Samw dirlen : MAXPATHLEN - 2; 924*7052Samw for (i = endidx; i >= 0; i--) 925*7052Samw si->shr_path[i+1] = si->shr_path[i]; 926*7052Samw si->shr_path[MAXPATHLEN-1] = '\0'; 927*7052Samw si->shr_path[0] = '/'; 928*7052Samw } 929*7052Samw 930*7052Samw /* XXX Do we need to translate the directory here? to real path */ 931*7052Samw if (smb_shr_is_dir(si->shr_path) == 0) 932*7052Samw return (NERR_UnknownDevDir); 933*7052Samw 934*7052Samw /* 935*7052Samw * We should allocate memory for new entry because we 936*7052Samw * don't know anything about the passed pointer i.e. 937*7052Samw * it maybe destroyed by caller of this function while 938*7052Samw * we only store a pointer to the data in hash table. 939*7052Samw * Hash table doesn't do any allocation for the data that 940*7052Samw * is being added. 941*7052Samw */ 942*7052Samw add_si = malloc(sizeof (smb_share_t)); 943*7052Samw if (add_si == NULL) { 944*7052Samw syslog(LOG_ERR, "LmshareSetinfo: resource shortage"); 945*7052Samw return (NERR_NoRoom); 946*7052Samw } 947*7052Samw 948*7052Samw (void) memcpy(add_si, si, sizeof (smb_share_t)); 949*7052Samw 950*7052Samw /* 951*7052Samw * If we can't find it, use the new one to get things in sync, 952*7052Samw * but if there is an existing one, that is the one to 953*7052Samw * unpublish. 954*7052Samw */ 955*7052Samw if (smb_shr_get(si->shr_name, &old_si) != NERR_Success) 956*7052Samw (void) memcpy(&old_si, si, sizeof (smb_share_t)); 957*7052Samw 958*7052Samw if (doshm) { 959*7052Samw res = smb_shr_del(si->shr_name, doshm); 960*7052Samw if (res != NERR_Success) { 961*7052Samw free(add_si); 962*7052Samw syslog(LOG_ERR, "LmshareSetinfo: delete failed", res); 963*7052Samw return (res); 964*7052Samw } 965*7052Samw } else { 966*7052Samw /* Unpublish old share from AD */ 967*7052Samw if ((add_si->shr_flags & SMB_SHRF_PERM) == SMB_SHRF_PERM) 968*7052Samw smb_shr_publish(&old_si, SMB_SHARE_UNPUBLISH, 1); 969*7052Samw (void) smb_shr_cache_delshare(si->shr_name); 970*7052Samw } 971*7052Samw 972*7052Samw smb_shr_set_oemname(add_si); 973*7052Samw 974*7052Samw /* if it's not transient it should be permanent */ 975*7052Samw if ((add_si->shr_flags & SMB_SHRF_TRANS) == 0) 976*7052Samw add_si->shr_flags |= SMB_SHRF_PERM; 977*7052Samw 978*7052Samw 979*7052Samw add_si->shr_type = STYPE_DISKTREE; 980*7052Samw add_si->shr_type |= smb_shr_is_special(add_si->shr_name); 981*7052Samw 982*7052Samw (void) rw_wrlock(&smb_shr_lock); 983*7052Samw if (ht_add_item(smb_shr_handle, add_si->shr_name, add_si) == NULL) { 984*7052Samw syslog(LOG_ERR, "smb_shr_set[%s]: error in adding share", 985*7052Samw add_si->shr_name); 986*7052Samw (void) rw_unlock(&smb_shr_lock); 987*7052Samw free(add_si); 988*7052Samw return (NERR_InternalError); 989*7052Samw } 990*7052Samw (void) rw_unlock(&smb_shr_lock); 991*7052Samw 992*7052Samw if ((add_si->shr_flags & SMB_SHRF_PERM) == SMB_SHRF_PERM) { 993*7052Samw if (doshm && (smb_shr_set_shmgr(add_si) != 0)) { 994*7052Samw syslog(LOG_ERR, "Update share %s in sharemgr failed", 995*7052Samw add_si->shr_name); 996*7052Samw return (NERR_InternalError); 997*7052Samw } 998*7052Samw smb_shr_publish(add_si, SMB_SHARE_PUBLISH, 1); 999*7052Samw } 1000*7052Samw 1001*7052Samw return (res); 1002*7052Samw } 1003*7052Samw 1004*7052Samw void 1005*7052Samw smb_shr_list(int offset, smb_shrlist_t *list) 1006*7052Samw { 1007*7052Samw smb_shriter_t iterator; 1008*7052Samw smb_share_t *si; 1009*7052Samw int list_idx = 0; 1010*7052Samw int i = 0; 1011*7052Samw 1012*7052Samw bzero(list, sizeof (smb_shrlist_t)); 1013*7052Samw smb_shr_iterinit(&iterator, SMB_SHRF_ALL); 1014*7052Samw 1015*7052Samw (void) smb_shr_iterate(&iterator); /* To skip IPC$ */ 1016*7052Samw 1017*7052Samw while ((si = smb_shr_iterate(&iterator)) != NULL) { 1018*7052Samw if (smb_shr_is_special(si->shr_name)) { 1019*7052Samw /* 1020*7052Samw * Don't return restricted shares. 1021*7052Samw */ 1022*7052Samw if (smb_shr_is_restricted(si->shr_name)) 1023*7052Samw continue; 1024*7052Samw } 1025*7052Samw 1026*7052Samw if (i++ < offset) 1027*7052Samw continue; 1028*7052Samw 1029*7052Samw (void) memcpy(&list->smbshr[list_idx], si, 1030*7052Samw sizeof (smb_share_t)); 1031*7052Samw if (++list_idx == LMSHARES_PER_REQUEST) 1032*7052Samw break; 1033*7052Samw } 1034*7052Samw 1035*7052Samw list->no = list_idx; 1036*7052Samw } 1037*7052Samw 1038*7052Samw /* 1039*7052Samw * Put the share on publish queue. 1040*7052Samw */ 1041*7052Samw static void 1042*7052Samw smb_shr_publish(smb_share_t *si, char flag, int poke) 1043*7052Samw { 1044*7052Samw smb_shr_adinfo_t *item = NULL; 1045*7052Samw 1046*7052Samw if (publish_on == 0) 1047*7052Samw return; 1048*7052Samw 1049*7052Samw if ((si == NULL) || (si->shr_container[0] == '\0')) 1050*7052Samw return; 1051*7052Samw 1052*7052Samw (void) mutex_lock(&smb_shr_publish_mtx); 1053*7052Samw item = (smb_shr_adinfo_t *)malloc(sizeof (smb_shr_adinfo_t)); 1054*7052Samw if (item == NULL) { 1055*7052Samw syslog(LOG_ERR, "Failed to allocate share publish item"); 1056*7052Samw (void) mutex_unlock(&smb_shr_publish_mtx); 1057*7052Samw return; 1058*7052Samw } 1059*7052Samw item->flag = flag; 1060*7052Samw (void) strlcpy(item->name, si->shr_name, sizeof (item->name)); 1061*7052Samw (void) strlcpy(item->container, si->shr_container, 1062*7052Samw sizeof (item->container)); 1063*7052Samw /*LINTED - E_CONSTANT_CONDITION*/ 1064*7052Samw TAILQ_INSERT_TAIL(&ad_queue.adlist, item, next); 1065*7052Samw ad_queue.nentries++; 1066*7052Samw if (poke) 1067*7052Samw (void) cond_signal(&smb_shr_publish_cv); 1068*7052Samw (void) mutex_unlock(&smb_shr_publish_mtx); 1069*7052Samw } 1070*7052Samw 1071*7052Samw void 1072*7052Samw smb_shr_stop_publish() 1073*7052Samw { 1074*7052Samw (void) mutex_lock(&smb_shr_publish_mtx); 1075*7052Samw publish_on = 0; 1076*7052Samw (void) cond_signal(&smb_shr_publish_cv); 1077*7052Samw (void) mutex_unlock(&smb_shr_publish_mtx); 1078*7052Samw } 1079*7052Samw 1080*7052Samw /* 1081*7052Samw * This functions waits to be signaled and once running 1082*7052Samw * will publish/unpublish any items on list. 1083*7052Samw * smb_shr_stop_publish when called will exit this thread. 1084*7052Samw */ 1085*7052Samw /*ARGSUSED*/ 1086*7052Samw static void * 1087*7052Samw smb_shr_publisher(void *arg) 1088*7052Samw { 1089*7052Samw smb_ads_handle_t *ah; 1090*7052Samw smb_shr_adinfo_t *item; 1091*7052Samw char hostname[MAXHOSTNAMELEN]; 1092*7052Samw char name[MAXNAMELEN]; 1093*7052Samw char container[MAXPATHLEN]; 1094*7052Samw char flag; 1095*7052Samw 1096*7052Samw /*LINTED - E_CONSTANT_CONDITION*/ 1097*7052Samw TAILQ_INIT(&ad_queue.adlist); 1098*7052Samw ad_queue.nentries = 0; 1099*7052Samw publish_on = 1; 1100*7052Samw hostname[0] = '\0'; 1101*7052Samw 1102*7052Samw for (;;) { 1103*7052Samw (void) cond_wait(&smb_shr_publish_cv, 1104*7052Samw &smb_shr_publish_mtx); 1105*7052Samw 1106*7052Samw if (hostname[0] == '\0') { 1107*7052Samw if (smb_gethostname(hostname, MAXHOSTNAMELEN, 0) != 0) 1108*7052Samw continue; 1109*7052Samw } 1110*7052Samw 1111*7052Samw if (publish_on == 0) { 1112*7052Samw syslog(LOG_DEBUG, "lmshare: publisher exit"); 1113*7052Samw if (ad_queue.nentries == 0) { 1114*7052Samw (void) mutex_unlock(&smb_shr_publish_mtx); 1115*7052Samw break; 1116*7052Samw } 1117*7052Samw for (item = TAILQ_FIRST(&ad_queue.adlist); item; 1118*7052Samw item = TAILQ_FIRST(&ad_queue.adlist)) { 1119*7052Samw /*LINTED - E_CONSTANT_CONDITION*/ 1120*7052Samw TAILQ_REMOVE(&ad_queue.adlist, item, next); 1121*7052Samw (void) free(item); 1122*7052Samw } 1123*7052Samw ad_queue.nentries = 0; 1124*7052Samw (void) mutex_unlock(&smb_shr_publish_mtx); 1125*7052Samw break; 1126*7052Samw } 1127*7052Samw if (ad_queue.nentries == 0) 1128*7052Samw continue; 1129*7052Samw ah = smb_ads_open(); 1130*7052Samw if (ah == NULL) { 1131*7052Samw /* We mostly have no AD config so just clear the list */ 1132*7052Samw for (item = TAILQ_FIRST(&ad_queue.adlist); item; 1133*7052Samw item = TAILQ_FIRST(&ad_queue.adlist)) { 1134*7052Samw /*LINTED - E_CONSTANT_CONDITION*/ 1135*7052Samw TAILQ_REMOVE(&ad_queue.adlist, item, next); 1136*7052Samw (void) free(item); 1137*7052Samw } 1138*7052Samw ad_queue.nentries = 0; 1139*7052Samw continue; 1140*7052Samw } 1141*7052Samw TAILQ_FOREACH(item, &ad_queue.adlist, next) { 1142*7052Samw (void) strlcpy(name, item->name, sizeof (name)); 1143*7052Samw (void) strlcpy(container, item->container, 1144*7052Samw sizeof (container)); 1145*7052Samw flag = item->flag; 1146*7052Samw 1147*7052Samw if (flag == SMB_SHARE_UNPUBLISH) 1148*7052Samw (void) smb_ads_remove_share(ah, name, NULL, 1149*7052Samw container, hostname); 1150*7052Samw else 1151*7052Samw (void) smb_ads_publish_share(ah, name, NULL, 1152*7052Samw container, hostname); 1153*7052Samw } 1154*7052Samw for (item = TAILQ_FIRST(&ad_queue.adlist); item; 1155*7052Samw item = TAILQ_FIRST(&ad_queue.adlist)) { 1156*7052Samw /*LINTED - E_CONSTANT_CONDITION*/ 1157*7052Samw TAILQ_REMOVE(&ad_queue.adlist, item, next); 1158*7052Samw (void) free(item); 1159*7052Samw } 1160*7052Samw ad_queue.nentries = 0; 1161*7052Samw if (ah != NULL) { 1162*7052Samw smb_ads_close(ah); 1163*7052Samw ah = NULL; 1164*7052Samw } 1165*7052Samw } 1166*7052Samw 1167*7052Samw syslog(LOG_DEBUG, "lmshare: Stopping publisher"); 1168*7052Samw return (NULL); 1169*7052Samw } 1170*7052Samw 1171*7052Samw /* 1172*7052Samw * smb_shr_get_realpath 1173*7052Samw * 1174*7052Samw * Derive the real path of a share from the path provided by a 1175*7052Samw * Windows client application during the share addition. 1176*7052Samw * 1177*7052Samw * For instance, the real path of C:\ is /cvol and the 1178*7052Samw * real path of F:\home is /vol1/home. 1179*7052Samw * 1180*7052Samw * clipath - path provided by the Windows client is in the 1181*7052Samw * format of <drive letter>:\<dir> 1182*7052Samw * realpath - path that will be stored as the directory field of 1183*7052Samw * the smb_share_t structure of the share. 1184*7052Samw * maxlen - maximum length fo the realpath buffer 1185*7052Samw * 1186*7052Samw * Return LAN Manager network error code. 1187*7052Samw */ 1188*7052Samw /*ARGSUSED*/ 1189*7052Samw uint32_t 1190*7052Samw smb_shr_get_realpath(const char *clipath, char *realpath, int maxlen) 1191*7052Samw { 1192*7052Samw /* XXX do this translation */ 1193*7052Samw return (NERR_Success); 1194*7052Samw } 1195*7052Samw 1196*7052Samw /* 1197*7052Samw * smb_shr_set_oemname 1198*7052Samw * 1199*7052Samw * Generates the OEM name of the given share. If it's 1200*7052Samw * shorter than 13 chars it'll be saved in si->shr_oemname. 1201*7052Samw * Otherwise si->shr_oemname will be empty and SMB_SHRF_LONGNAME 1202*7052Samw * will be set in si->shr_flags. 1203*7052Samw */ 1204*7052Samw static void 1205*7052Samw smb_shr_set_oemname(smb_share_t *si) 1206*7052Samw { 1207*7052Samw unsigned int cpid = oem_get_smb_cpid(); 1208*7052Samw mts_wchar_t *unibuf; 1209*7052Samw char *oem_name; 1210*7052Samw int length; 1211*7052Samw 1212*7052Samw length = strlen(si->shr_name) + 1; 1213*7052Samw 1214*7052Samw oem_name = malloc(length); 1215*7052Samw unibuf = malloc(length * sizeof (mts_wchar_t)); 1216*7052Samw if ((oem_name == NULL) || (unibuf == NULL)) { 1217*7052Samw free(oem_name); 1218*7052Samw free(unibuf); 1219*7052Samw return; 1220*7052Samw } 1221*7052Samw 1222*7052Samw (void) mts_mbstowcs(unibuf, si->shr_name, length); 1223*7052Samw 1224*7052Samw if (unicodestooems(oem_name, unibuf, length, cpid) == 0) 1225*7052Samw (void) strcpy(oem_name, si->shr_name); 1226*7052Samw 1227*7052Samw free(unibuf); 1228*7052Samw 1229*7052Samw if (strlen(oem_name) + 1 > SMB_SHARE_OEMNAME_MAX) { 1230*7052Samw si->shr_flags |= SMB_SHRF_LONGNAME; 1231*7052Samw *si->shr_oemname = '\0'; 1232*7052Samw } else { 1233*7052Samw si->shr_flags &= ~SMB_SHRF_LONGNAME; 1234*7052Samw (void) strlcpy(si->shr_oemname, oem_name, 1235*7052Samw SMB_SHARE_OEMNAME_MAX); 1236*7052Samw } 1237*7052Samw 1238*7052Samw free(oem_name); 1239*7052Samw } 1240