1da6c28aaSamw /* 2da6c28aaSamw * CDDL HEADER START 3da6c28aaSamw * 4da6c28aaSamw * The contents of this file are subject to the terms of the 5da6c28aaSamw * Common Development and Distribution License (the "License"). 6da6c28aaSamw * You may not use this file except in compliance with the License. 7da6c28aaSamw * 8da6c28aaSamw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9da6c28aaSamw * or http://www.opensolaris.org/os/licensing. 10da6c28aaSamw * See the License for the specific language governing permissions 11da6c28aaSamw * and limitations under the License. 12da6c28aaSamw * 13da6c28aaSamw * When distributing Covered Code, include this CDDL HEADER in each 14da6c28aaSamw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15da6c28aaSamw * If applicable, add the following below this CDDL HEADER, with the 16da6c28aaSamw * fields enclosed by brackets "[]" replaced with your own identifying 17da6c28aaSamw * information: Portions Copyright [yyyy] [name of copyright owner] 18da6c28aaSamw * 19da6c28aaSamw * CDDL HEADER END 20da6c28aaSamw */ 21da6c28aaSamw /* 2289dc44ceSjose borrego * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23da6c28aaSamw * Use is subject to license terms. 24380acbbeSGordon Ross * 25*b3700b07SGordon Ross * Copyright 2014 Nexenta Systems, Inc. All rights reserved. 26da6c28aaSamw */ 27da6c28aaSamw 28da6c28aaSamw /* 2929bd2886SAlan Wright * This file defines the domain environment values and the domain 30da6c28aaSamw * database interface. The database is a single linked list of 31da6c28aaSamw * structures containing domain type, name and SID information. 32da6c28aaSamw */ 33da6c28aaSamw 3489dc44ceSjose borrego #include <sys/types.h> 3589dc44ceSjose borrego #include <sys/stat.h> 3629bd2886SAlan Wright #include <sys/list.h> 3789dc44ceSjose borrego #include <stdio.h> 38da6c28aaSamw #include <strings.h> 3989dc44ceSjose borrego #include <string.h> 40da6c28aaSamw #include <unistd.h> 4189dc44ceSjose borrego #include <stdlib.h> 42da6c28aaSamw #include <synch.h> 4389dc44ceSjose borrego #include <pwd.h> 4489dc44ceSjose borrego #include <grp.h> 4529bd2886SAlan Wright #include <assert.h> 46da6c28aaSamw 47da6c28aaSamw #include <smbsrv/smbinfo.h> 48da6c28aaSamw #include <smbsrv/string.h> 496537f381Sas200622 #include <smbsrv/smb_sid.h> 50da6c28aaSamw #include <smbsrv/libsmb.h> 51da6c28aaSamw 5289dc44ceSjose borrego #define SMB_DOMAINS_FILE "domains" 53da6c28aaSamw 5429bd2886SAlan Wright #define SMB_DCACHE_UPDATE_WAIT 45 /* seconds */ 55da6c28aaSamw 56da6c28aaSamw /* 5729bd2886SAlan Wright * Domain cache states 58da6c28aaSamw */ 5929bd2886SAlan Wright #define SMB_DCACHE_STATE_NONE 0 6029bd2886SAlan Wright #define SMB_DCACHE_STATE_READY 1 6129bd2886SAlan Wright #define SMB_DCACHE_STATE_UPDATING 2 6229bd2886SAlan Wright #define SMB_DCACHE_STATE_DESTROYING 3 63da6c28aaSamw 64da6c28aaSamw /* 6529bd2886SAlan Wright * Cache lock modes 6629bd2886SAlan Wright */ 6729bd2886SAlan Wright #define SMB_DCACHE_RDLOCK 0 6829bd2886SAlan Wright #define SMB_DCACHE_WRLOCK 1 6929bd2886SAlan Wright 7029bd2886SAlan Wright typedef struct smb_domain_cache { 7129bd2886SAlan Wright list_t dc_cache; 7229bd2886SAlan Wright rwlock_t dc_cache_lck; 7329bd2886SAlan Wright mutex_t dc_mtx; 7429bd2886SAlan Wright cond_t dc_cv; 7529bd2886SAlan Wright uint32_t dc_state; 7629bd2886SAlan Wright uint32_t dc_nops; 77*b3700b07SGordon Ross smb_dcinfo_t dc_dci; 7829bd2886SAlan Wright } smb_domain_cache_t; 7929bd2886SAlan Wright 8029bd2886SAlan Wright static smb_domain_cache_t smb_dcache; 8129bd2886SAlan Wright 82a0aa776eSAlan Wright static uint32_t smb_domain_add(smb_domain_type_t, smb_domain_t *); 83a0aa776eSAlan Wright static uint32_t smb_domain_add_local(void); 84a0aa776eSAlan Wright static uint32_t smb_domain_add_primary(uint32_t); 85a0aa776eSAlan Wright static void smb_domain_unlink(void); 8629bd2886SAlan Wright 8729bd2886SAlan Wright static void smb_dcache_create(void); 8829bd2886SAlan Wright static void smb_dcache_destroy(void); 8929bd2886SAlan Wright static uint32_t smb_dcache_lock(int); 9029bd2886SAlan Wright static void smb_dcache_unlock(void); 91a0aa776eSAlan Wright static void smb_dcache_remove(smb_domain_t *); 92a0aa776eSAlan Wright static uint32_t smb_dcache_add(smb_domain_t *); 93*b3700b07SGordon Ross static boolean_t smb_dcache_getdc(smb_dcinfo_t *); 94*b3700b07SGordon Ross static void smb_dcache_setdc(const smb_dcinfo_t *); 9529bd2886SAlan Wright static boolean_t smb_dcache_wait(void); 96a0aa776eSAlan Wright static uint32_t smb_dcache_updating(void); 9729bd2886SAlan Wright static void smb_dcache_ready(void); 9829bd2886SAlan Wright 9929bd2886SAlan Wright /* 10029bd2886SAlan Wright * domain cache one time initialization. This function should 10129bd2886SAlan Wright * only be called during service startup. 102da6c28aaSamw * 10329bd2886SAlan Wright * Returns 0 on success and an error code on failure. 104da6c28aaSamw */ 105da6c28aaSamw int 106a0aa776eSAlan Wright smb_domain_init(uint32_t secmode) 107da6c28aaSamw { 108a0aa776eSAlan Wright smb_domain_t di; 109dc20a302Sas200622 int rc; 110da6c28aaSamw 11129bd2886SAlan Wright smb_dcache_create(); 112da6c28aaSamw 113a0aa776eSAlan Wright if ((rc = smb_domain_add_local()) != 0) 11429bd2886SAlan Wright return (rc); 115da6c28aaSamw 116a0aa776eSAlan Wright smb_domain_set_basic_info(NT_BUILTIN_DOMAIN_SIDSTR, "BUILTIN", "", &di); 117a0aa776eSAlan Wright (void) smb_domain_add(SMB_DOMAIN_BUILTIN, &di); 118da6c28aaSamw 119a0aa776eSAlan Wright return (smb_domain_add_primary(secmode)); 120da6c28aaSamw } 121da6c28aaSamw 122da6c28aaSamw /* 12329bd2886SAlan Wright * Destroys the cache upon service termination 124da6c28aaSamw */ 125da6c28aaSamw void 126a0aa776eSAlan Wright smb_domain_fini(void) 127da6c28aaSamw { 12829bd2886SAlan Wright smb_dcache_destroy(); 129a0aa776eSAlan Wright smb_domain_unlink(); 130da6c28aaSamw } 131da6c28aaSamw 132da6c28aaSamw /* 13329bd2886SAlan Wright * Add a domain structure to domain cache. There is no checking 13429bd2886SAlan Wright * for duplicates. 135da6c28aaSamw */ 13629bd2886SAlan Wright static uint32_t 137a0aa776eSAlan Wright smb_domain_add(smb_domain_type_t type, smb_domain_t *di) 138da6c28aaSamw { 13929bd2886SAlan Wright uint32_t res; 14029bd2886SAlan Wright 14129bd2886SAlan Wright if ((di == NULL) || (di->di_sid == NULL)) 14229bd2886SAlan Wright return (SMB_DOMAIN_INVALID_ARG); 14329bd2886SAlan Wright 14429bd2886SAlan Wright if ((res = smb_dcache_lock(SMB_DCACHE_WRLOCK)) == SMB_DOMAIN_SUCCESS) { 14529bd2886SAlan Wright di->di_type = type; 14629bd2886SAlan Wright res = smb_dcache_add(di); 14729bd2886SAlan Wright smb_dcache_unlock(); 148da6c28aaSamw } 149da6c28aaSamw 15029bd2886SAlan Wright return (res); 151da6c28aaSamw } 152da6c28aaSamw 153da6c28aaSamw /* 15429bd2886SAlan Wright * Lookup a domain by its name. The passed name is the NETBIOS or fully 15529bd2886SAlan Wright * qualified DNS name or non-qualified DNS name. 156da6c28aaSamw * 15729bd2886SAlan Wright * If the requested domain is found and given 'di' pointer is not NULL 15829bd2886SAlan Wright * it'll be filled with the domain information and B_TRUE is returned. 15929bd2886SAlan Wright * If the caller only needs to check a domain existence it can pass 16029bd2886SAlan Wright * NULL for 'di' and just check the return value. 16129bd2886SAlan Wright * 16229bd2886SAlan Wright * If the domain is not in the cache B_FALSE is returned. 163da6c28aaSamw */ 16429bd2886SAlan Wright boolean_t 165a0aa776eSAlan Wright smb_domain_lookup_name(char *name, smb_domain_t *di) 166da6c28aaSamw { 16729bd2886SAlan Wright boolean_t found = B_FALSE; 168a0aa776eSAlan Wright smb_domain_t *dcnode; 1697f667e74Sjose borrego char *p; 1707f667e74Sjose borrego 171a0aa776eSAlan Wright bzero(di, sizeof (smb_domain_t)); 1727f667e74Sjose borrego 17329bd2886SAlan Wright if (name == NULL || *name == '\0') 17429bd2886SAlan Wright return (B_FALSE); 17529bd2886SAlan Wright 17629bd2886SAlan Wright if (smb_dcache_lock(SMB_DCACHE_RDLOCK) != SMB_DOMAIN_SUCCESS) 17729bd2886SAlan Wright return (B_FALSE); 17829bd2886SAlan Wright 17929bd2886SAlan Wright dcnode = list_head(&smb_dcache.dc_cache); 18029bd2886SAlan Wright while (dcnode) { 181bbf6f00cSJordan Brown found = (smb_strcasecmp(dcnode->di_nbname, name, 0) == 0) || 182bbf6f00cSJordan Brown (smb_strcasecmp(dcnode->di_fqname, name, 0) == 0); 18329bd2886SAlan Wright 18429bd2886SAlan Wright if (found) { 18529bd2886SAlan Wright if (di) 18629bd2886SAlan Wright *di = *dcnode; 18729bd2886SAlan Wright break; 18829bd2886SAlan Wright } 18929bd2886SAlan Wright 19029bd2886SAlan Wright if ((p = strchr(dcnode->di_fqname, '.')) != NULL) { 1917f667e74Sjose borrego *p = '\0'; 192bbf6f00cSJordan Brown found = (smb_strcasecmp(dcnode->di_fqname, name, 193bbf6f00cSJordan Brown 0) == 0); 19429bd2886SAlan Wright *p = '.'; 19529bd2886SAlan Wright if (found) { 19629bd2886SAlan Wright if (di) 19729bd2886SAlan Wright *di = *dcnode; 198da6c28aaSamw break; 199da6c28aaSamw } 200da6c28aaSamw } 201da6c28aaSamw 20229bd2886SAlan Wright dcnode = list_next(&smb_dcache.dc_cache, dcnode); 20329bd2886SAlan Wright } 20429bd2886SAlan Wright 20529bd2886SAlan Wright smb_dcache_unlock(); 20629bd2886SAlan Wright return (found); 20729bd2886SAlan Wright } 208da6c28aaSamw 209da6c28aaSamw /* 21029bd2886SAlan Wright * Lookup a domain by its SID. 211da6c28aaSamw * 21229bd2886SAlan Wright * If the requested domain is found and given 'di' pointer is not NULL 21329bd2886SAlan Wright * it'll be filled with the domain information and B_TRUE is returned. 21429bd2886SAlan Wright * If the caller only needs to check a domain existence it can pass 21529bd2886SAlan Wright * NULL for 'di' and just check the return value. 21629bd2886SAlan Wright * 21729bd2886SAlan Wright * If the domain is not in the cache B_FALSE is returned. 218da6c28aaSamw */ 21929bd2886SAlan Wright boolean_t 220a0aa776eSAlan Wright smb_domain_lookup_sid(smb_sid_t *sid, smb_domain_t *di) 221da6c28aaSamw { 22229bd2886SAlan Wright boolean_t found = B_FALSE; 223a0aa776eSAlan Wright smb_domain_t *dcnode; 22429bd2886SAlan Wright char sidstr[SMB_SID_STRSZ]; 225da6c28aaSamw 226a0aa776eSAlan Wright bzero(di, sizeof (smb_domain_t)); 22729bd2886SAlan Wright 22829bd2886SAlan Wright if (sid == NULL) 22929bd2886SAlan Wright return (B_FALSE); 23029bd2886SAlan Wright 23129bd2886SAlan Wright smb_sid_tostr(sid, sidstr); 23229bd2886SAlan Wright 23329bd2886SAlan Wright if (smb_dcache_lock(SMB_DCACHE_RDLOCK) != SMB_DOMAIN_SUCCESS) 23429bd2886SAlan Wright return (B_FALSE); 23529bd2886SAlan Wright 23629bd2886SAlan Wright dcnode = list_head(&smb_dcache.dc_cache); 23729bd2886SAlan Wright while (dcnode) { 23829bd2886SAlan Wright found = (strcmp(dcnode->di_sid, sidstr) == 0); 23929bd2886SAlan Wright if (found) { 24029bd2886SAlan Wright if (di) 24129bd2886SAlan Wright *di = *dcnode; 242da6c28aaSamw break; 243da6c28aaSamw } 244da6c28aaSamw 24529bd2886SAlan Wright dcnode = list_next(&smb_dcache.dc_cache, dcnode); 24629bd2886SAlan Wright } 24729bd2886SAlan Wright 24829bd2886SAlan Wright smb_dcache_unlock(); 24929bd2886SAlan Wright return (found); 25029bd2886SAlan Wright } 251da6c28aaSamw 252da6c28aaSamw /* 25329bd2886SAlan Wright * Lookup a domain by its type. 254da6c28aaSamw * 25529bd2886SAlan Wright * If the requested domain is found and given 'di' pointer is not NULL 25629bd2886SAlan Wright * it'll be filled with the domain information and B_TRUE is returned. 25729bd2886SAlan Wright * If the caller only needs to check a domain existence it can pass 25829bd2886SAlan Wright * NULL for 'di' and just check the return value. 25929bd2886SAlan Wright * 26029bd2886SAlan Wright * If the domain is not in the cache B_FALSE is returned. 261da6c28aaSamw */ 26229bd2886SAlan Wright boolean_t 263a0aa776eSAlan Wright smb_domain_lookup_type(smb_domain_type_t type, smb_domain_t *di) 264da6c28aaSamw { 26529bd2886SAlan Wright boolean_t found = B_FALSE; 266a0aa776eSAlan Wright smb_domain_t *dcnode; 267da6c28aaSamw 268a0aa776eSAlan Wright bzero(di, sizeof (smb_domain_t)); 26929bd2886SAlan Wright 27029bd2886SAlan Wright if (smb_dcache_lock(SMB_DCACHE_RDLOCK) != SMB_DOMAIN_SUCCESS) 27129bd2886SAlan Wright return (B_FALSE); 27229bd2886SAlan Wright 27329bd2886SAlan Wright dcnode = list_head(&smb_dcache.dc_cache); 27429bd2886SAlan Wright while (dcnode) { 27529bd2886SAlan Wright if (dcnode->di_type == type) { 27629bd2886SAlan Wright found = B_TRUE; 27729bd2886SAlan Wright if (di) 27829bd2886SAlan Wright *di = *dcnode; 279da6c28aaSamw break; 280da6c28aaSamw } 281da6c28aaSamw 28229bd2886SAlan Wright dcnode = list_next(&smb_dcache.dc_cache, dcnode); 28329bd2886SAlan Wright } 28429bd2886SAlan Wright 28529bd2886SAlan Wright smb_dcache_unlock(); 28629bd2886SAlan Wright return (found); 28729bd2886SAlan Wright } 288da6c28aaSamw 289da6c28aaSamw /* 29029bd2886SAlan Wright * Returns primary domain information plus the name of 29129bd2886SAlan Wright * the selected domain controller. 292da6c28aaSamw */ 29329bd2886SAlan Wright boolean_t 294a0aa776eSAlan Wright smb_domain_getinfo(smb_domainex_t *dxi) 295da6c28aaSamw { 296*b3700b07SGordon Ross boolean_t rv; 297da6c28aaSamw 298*b3700b07SGordon Ross /* Note: this waits for the dcache lock. */ 299*b3700b07SGordon Ross rv = smb_domain_lookup_type(SMB_DOMAIN_PRIMARY, &dxi->d_primary); 300*b3700b07SGordon Ross if (rv) 301*b3700b07SGordon Ross rv = smb_dcache_getdc(&dxi->d_dci); 302da6c28aaSamw 303*b3700b07SGordon Ross return (rv); 304da6c28aaSamw } 305da6c28aaSamw 30629bd2886SAlan Wright /* 307380acbbeSGordon Ross * Get the name of the current DC (if any) 308380acbbeSGordon Ross * Does NOT block. 309380acbbeSGordon Ross */ 310380acbbeSGordon Ross void 311*b3700b07SGordon Ross smb_domain_current_dc(smb_dcinfo_t *dci) 312380acbbeSGordon Ross { 313*b3700b07SGordon Ross (void) smb_dcache_getdc(dci); 314380acbbeSGordon Ross } 315380acbbeSGordon Ross 316380acbbeSGordon Ross /* 31729bd2886SAlan Wright * Transfer the cache to updating state. 31829bd2886SAlan Wright * In this state any request for reading the cache would 31929bd2886SAlan Wright * be blocked until the update is finished. 32029bd2886SAlan Wright */ 321a0aa776eSAlan Wright uint32_t 322a0aa776eSAlan Wright smb_domain_start_update(void) 323da6c28aaSamw { 324a0aa776eSAlan Wright return (smb_dcache_updating()); 32529bd2886SAlan Wright } 326da6c28aaSamw 32729bd2886SAlan Wright /* 32829bd2886SAlan Wright * Transfer the cache from updating to ready state. 32929bd2886SAlan Wright */ 33029bd2886SAlan Wright void 331a0aa776eSAlan Wright smb_domain_end_update(void) 33229bd2886SAlan Wright { 33329bd2886SAlan Wright smb_dcache_ready(); 33429bd2886SAlan Wright } 33529bd2886SAlan Wright 33629bd2886SAlan Wright /* 33729bd2886SAlan Wright * Updates the cache with given information for the primary 33829bd2886SAlan Wright * domain, possible trusted domains and the selected domain 33929bd2886SAlan Wright * controller. 34029bd2886SAlan Wright * 34129bd2886SAlan Wright * Before adding the new entries existing entries of type 34229bd2886SAlan Wright * primary and trusted will be removed from cache. 34329bd2886SAlan Wright */ 34429bd2886SAlan Wright void 345a0aa776eSAlan Wright smb_domain_update(smb_domainex_t *dxi) 34629bd2886SAlan Wright { 347a0aa776eSAlan Wright smb_domain_t *dcnode; 34829bd2886SAlan Wright int i; 34929bd2886SAlan Wright 35029bd2886SAlan Wright if (smb_dcache_lock(SMB_DCACHE_WRLOCK) != SMB_DOMAIN_SUCCESS) 351da6c28aaSamw return; 35229bd2886SAlan Wright 35329bd2886SAlan Wright dcnode = list_head(&smb_dcache.dc_cache); 35429bd2886SAlan Wright while (dcnode) { 355a0aa776eSAlan Wright if ((dcnode->di_type == SMB_DOMAIN_PRIMARY) || 356a0aa776eSAlan Wright (dcnode->di_type == SMB_DOMAIN_TRUSTED)) { 35729bd2886SAlan Wright smb_dcache_remove(dcnode); 35829bd2886SAlan Wright dcnode = list_head(&smb_dcache.dc_cache); 35929bd2886SAlan Wright } else { 36029bd2886SAlan Wright dcnode = list_next(&smb_dcache.dc_cache, dcnode); 361da6c28aaSamw } 362da6c28aaSamw } 36329bd2886SAlan Wright 364a0aa776eSAlan Wright if (smb_dcache_add(&dxi->d_primary) == SMB_DOMAIN_SUCCESS) { 365a0aa776eSAlan Wright for (i = 0; i < dxi->d_trusted.td_num; i++) 366a0aa776eSAlan Wright (void) smb_dcache_add(&dxi->d_trusted.td_domains[i]); 36729bd2886SAlan Wright 368*b3700b07SGordon Ross smb_dcache_setdc(&dxi->d_dci); 36929bd2886SAlan Wright } 37029bd2886SAlan Wright 37129bd2886SAlan Wright smb_dcache_unlock(); 372da6c28aaSamw } 37389dc44ceSjose borrego 37489dc44ceSjose borrego /* 37589dc44ceSjose borrego * Write the list of domains to /var/run/smb/domains. 37689dc44ceSjose borrego */ 37789dc44ceSjose borrego void 378a0aa776eSAlan Wright smb_domain_save(void) 37989dc44ceSjose borrego { 38089dc44ceSjose borrego char fname[MAXPATHLEN]; 38189dc44ceSjose borrego char tag; 382a0aa776eSAlan Wright smb_domain_t *domain; 38389dc44ceSjose borrego FILE *fp; 38489dc44ceSjose borrego struct passwd *pwd; 38589dc44ceSjose borrego struct group *grp; 38689dc44ceSjose borrego uid_t uid; 38789dc44ceSjose borrego gid_t gid; 38889dc44ceSjose borrego 38989dc44ceSjose borrego (void) snprintf(fname, MAXPATHLEN, "%s/%s", 39089dc44ceSjose borrego SMB_VARRUN_DIR, SMB_DOMAINS_FILE); 39189dc44ceSjose borrego 39289dc44ceSjose borrego if ((fp = fopen(fname, "w")) == NULL) 39389dc44ceSjose borrego return; 39489dc44ceSjose borrego 39589dc44ceSjose borrego pwd = getpwnam("root"); 39689dc44ceSjose borrego grp = getgrnam("sys"); 39789dc44ceSjose borrego uid = (pwd == NULL) ? 0 : pwd->pw_uid; 39889dc44ceSjose borrego gid = (grp == NULL) ? 3 : grp->gr_gid; 39989dc44ceSjose borrego 40089dc44ceSjose borrego (void) lockf(fileno(fp), F_LOCK, 0); 40189dc44ceSjose borrego (void) fchmod(fileno(fp), 0600); 40289dc44ceSjose borrego (void) fchown(fileno(fp), uid, gid); 40389dc44ceSjose borrego 40429bd2886SAlan Wright if (smb_dcache_lock(SMB_DCACHE_RDLOCK) != SMB_DOMAIN_SUCCESS) 40529bd2886SAlan Wright return; 40689dc44ceSjose borrego 40729bd2886SAlan Wright domain = list_head(&smb_dcache.dc_cache); 40889dc44ceSjose borrego while (domain) { 40929bd2886SAlan Wright switch (domain->di_type) { 410a0aa776eSAlan Wright case SMB_DOMAIN_PRIMARY: 41189dc44ceSjose borrego tag = '*'; 41289dc44ceSjose borrego break; 41389dc44ceSjose borrego 414a0aa776eSAlan Wright case SMB_DOMAIN_TRUSTED: 415a0aa776eSAlan Wright case SMB_DOMAIN_UNTRUSTED: 41689dc44ceSjose borrego tag = '-'; 41789dc44ceSjose borrego break; 41889dc44ceSjose borrego 419a0aa776eSAlan Wright case SMB_DOMAIN_LOCAL: 42089dc44ceSjose borrego tag = '.'; 42189dc44ceSjose borrego break; 42289dc44ceSjose borrego default: 42329bd2886SAlan Wright domain = list_next(&smb_dcache.dc_cache, domain); 42489dc44ceSjose borrego continue; 42589dc44ceSjose borrego } 42689dc44ceSjose borrego 42789dc44ceSjose borrego (void) fprintf(fp, "[%c] [%s] [%s]\n", 42829bd2886SAlan Wright tag, domain->di_nbname, domain->di_sid); 42989dc44ceSjose borrego 43029bd2886SAlan Wright domain = list_next(&smb_dcache.dc_cache, domain); 43189dc44ceSjose borrego } 43289dc44ceSjose borrego 43329bd2886SAlan Wright smb_dcache_unlock(); 43489dc44ceSjose borrego (void) lockf(fileno(fp), F_ULOCK, 0); 43589dc44ceSjose borrego (void) fclose(fp); 43689dc44ceSjose borrego } 43789dc44ceSjose borrego 43889dc44ceSjose borrego /* 43989dc44ceSjose borrego * List the domains in /var/run/smb/domains. 44089dc44ceSjose borrego */ 44189dc44ceSjose borrego void 442a0aa776eSAlan Wright smb_domain_show(void) 44389dc44ceSjose borrego { 44489dc44ceSjose borrego char buf[MAXPATHLEN]; 44589dc44ceSjose borrego char *p; 44689dc44ceSjose borrego FILE *fp; 44789dc44ceSjose borrego 44889dc44ceSjose borrego (void) snprintf(buf, MAXPATHLEN, "%s/%s", 44989dc44ceSjose borrego SMB_VARRUN_DIR, SMB_DOMAINS_FILE); 45089dc44ceSjose borrego 45189dc44ceSjose borrego if ((fp = fopen(buf, "r")) != NULL) { 45289dc44ceSjose borrego (void) lockf(fileno(fp), F_LOCK, 0); 45389dc44ceSjose borrego 45489dc44ceSjose borrego while (fgets(buf, MAXPATHLEN, fp) != NULL) { 45589dc44ceSjose borrego if ((p = strchr(buf, '\n')) != NULL) 45689dc44ceSjose borrego *p = '\0'; 45789dc44ceSjose borrego (void) printf("%s\n", buf); 45889dc44ceSjose borrego } 45989dc44ceSjose borrego 46089dc44ceSjose borrego (void) lockf(fileno(fp), F_ULOCK, 0); 46189dc44ceSjose borrego (void) fclose(fp); 46289dc44ceSjose borrego } 46389dc44ceSjose borrego } 46489dc44ceSjose borrego 46529bd2886SAlan Wright void 466a0aa776eSAlan Wright smb_domain_set_basic_info(char *sid, char *nb_domain, char *fq_domain, 467a0aa776eSAlan Wright smb_domain_t *di) 46829bd2886SAlan Wright { 46929bd2886SAlan Wright if (sid == NULL || nb_domain == NULL || fq_domain == NULL || 47029bd2886SAlan Wright di == NULL) 47129bd2886SAlan Wright return; 47229bd2886SAlan Wright 47329bd2886SAlan Wright (void) strlcpy(di->di_sid, sid, SMB_SID_STRSZ); 47429bd2886SAlan Wright (void) strlcpy(di->di_nbname, nb_domain, NETBIOS_NAME_SZ); 475bbf6f00cSJordan Brown (void) smb_strupr(di->di_nbname); 47629bd2886SAlan Wright (void) strlcpy(di->di_fqname, fq_domain, MAXHOSTNAMELEN); 47729bd2886SAlan Wright di->di_binsid = NULL; 47829bd2886SAlan Wright } 47929bd2886SAlan Wright 48029bd2886SAlan Wright void 481a0aa776eSAlan Wright smb_domain_set_dns_info(char *sid, char *nb_domain, char *fq_domain, 482a0aa776eSAlan Wright char *forest, char *guid, smb_domain_t *di) 48329bd2886SAlan Wright { 48429bd2886SAlan Wright if (di == NULL || forest == NULL || guid == NULL) 48529bd2886SAlan Wright return; 48629bd2886SAlan Wright 487a0aa776eSAlan Wright smb_domain_set_basic_info(sid, nb_domain, fq_domain, di); 48829bd2886SAlan Wright (void) strlcpy(di->di_u.di_dns.ddi_forest, forest, MAXHOSTNAMELEN); 48929bd2886SAlan Wright (void) strlcpy(di->di_u.di_dns.ddi_guid, guid, 49029bd2886SAlan Wright UUID_PRINTABLE_STRING_LENGTH); 49129bd2886SAlan Wright } 49229bd2886SAlan Wright 49329bd2886SAlan Wright void 494a0aa776eSAlan Wright smb_domain_set_trust_info(char *sid, char *nb_domain, char *fq_domain, 49529bd2886SAlan Wright uint32_t trust_dir, uint32_t trust_type, uint32_t trust_attrs, 496a0aa776eSAlan Wright smb_domain_t *di) 49729bd2886SAlan Wright { 49829bd2886SAlan Wright smb_domain_trust_t *ti; 49929bd2886SAlan Wright 50029bd2886SAlan Wright if (di == NULL) 50129bd2886SAlan Wright return; 50229bd2886SAlan Wright 503a0aa776eSAlan Wright di->di_type = SMB_DOMAIN_TRUSTED; 50429bd2886SAlan Wright ti = &di->di_u.di_trust; 505a0aa776eSAlan Wright smb_domain_set_basic_info(sid, nb_domain, fq_domain, di); 50629bd2886SAlan Wright ti->dti_trust_direction = trust_dir; 50729bd2886SAlan Wright ti->dti_trust_type = trust_type; 50829bd2886SAlan Wright ti->dti_trust_attrs = trust_attrs; 50929bd2886SAlan Wright } 51029bd2886SAlan Wright 51189dc44ceSjose borrego /* 51289dc44ceSjose borrego * Remove the /var/run/smb/domains file. 51389dc44ceSjose borrego */ 51429bd2886SAlan Wright static void 515a0aa776eSAlan Wright smb_domain_unlink(void) 51689dc44ceSjose borrego { 51789dc44ceSjose borrego char fname[MAXPATHLEN]; 51889dc44ceSjose borrego 51989dc44ceSjose borrego (void) snprintf(fname, MAXPATHLEN, "%s/%s", 52089dc44ceSjose borrego SMB_VARRUN_DIR, SMB_DOMAINS_FILE); 52189dc44ceSjose borrego (void) unlink(fname); 52289dc44ceSjose borrego } 52329bd2886SAlan Wright 52429bd2886SAlan Wright /* 52529bd2886SAlan Wright * Add an entry for the local domain to the domain cache 52629bd2886SAlan Wright */ 52729bd2886SAlan Wright static uint32_t 528a0aa776eSAlan Wright smb_domain_add_local(void) 52929bd2886SAlan Wright { 53029bd2886SAlan Wright char *lsidstr; 53129bd2886SAlan Wright char hostname[NETBIOS_NAME_SZ]; 53229bd2886SAlan Wright char fq_name[MAXHOSTNAMELEN]; 533a0aa776eSAlan Wright smb_domain_t di; 53429bd2886SAlan Wright 53529bd2886SAlan Wright if ((lsidstr = smb_config_get_localsid()) == NULL) 53629bd2886SAlan Wright return (SMB_DOMAIN_NOMACHINE_SID); 53729bd2886SAlan Wright 53829bd2886SAlan Wright if (smb_getnetbiosname(hostname, NETBIOS_NAME_SZ) != 0) { 53929bd2886SAlan Wright free(lsidstr); 54029bd2886SAlan Wright return (SMB_DOMAIN_NOMACHINE_SID); 54129bd2886SAlan Wright } 54229bd2886SAlan Wright 54329bd2886SAlan Wright *fq_name = '\0'; 54429bd2886SAlan Wright (void) smb_getfqhostname(fq_name, MAXHOSTNAMELEN); 545a0aa776eSAlan Wright smb_domain_set_basic_info(lsidstr, hostname, fq_name, &di); 546a0aa776eSAlan Wright (void) smb_domain_add(SMB_DOMAIN_LOCAL, &di); 54729bd2886SAlan Wright 54829bd2886SAlan Wright free(lsidstr); 54929bd2886SAlan Wright return (SMB_DOMAIN_SUCCESS); 55029bd2886SAlan Wright } 55129bd2886SAlan Wright 55229bd2886SAlan Wright /* 55329bd2886SAlan Wright * Add an entry for the primary domain to the domain cache 55429bd2886SAlan Wright */ 55529bd2886SAlan Wright static uint32_t 556a0aa776eSAlan Wright smb_domain_add_primary(uint32_t secmode) 55729bd2886SAlan Wright { 55829bd2886SAlan Wright char sidstr[SMB_SID_STRSZ]; 55929bd2886SAlan Wright char fq_name[MAXHOSTNAMELEN]; 56029bd2886SAlan Wright char nb_name[NETBIOS_NAME_SZ]; 561a0aa776eSAlan Wright smb_domain_t di; 56229bd2886SAlan Wright int rc; 56329bd2886SAlan Wright 56429bd2886SAlan Wright if (secmode != SMB_SECMODE_DOMAIN) 56529bd2886SAlan Wright return (SMB_DOMAIN_SUCCESS); 56629bd2886SAlan Wright 56729bd2886SAlan Wright rc = smb_config_getstr(SMB_CI_DOMAIN_SID, sidstr, sizeof (sidstr)); 56829bd2886SAlan Wright if (rc != SMBD_SMF_OK) 56929bd2886SAlan Wright return (SMB_DOMAIN_NODOMAIN_SID); 57029bd2886SAlan Wright 57129bd2886SAlan Wright rc = smb_config_getstr(SMB_CI_DOMAIN_NAME, nb_name, NETBIOS_NAME_SZ); 57229bd2886SAlan Wright if ((rc != SMBD_SMF_OK) || (*nb_name == '\0')) 57329bd2886SAlan Wright return (SMB_DOMAIN_NODOMAIN_NAME); 57429bd2886SAlan Wright 57529bd2886SAlan Wright (void) smb_getfqdomainname(fq_name, MAXHOSTNAMELEN); 576a0aa776eSAlan Wright smb_domain_set_basic_info(sidstr, nb_name, fq_name, &di); 577a0aa776eSAlan Wright (void) smb_domain_add(SMB_DOMAIN_PRIMARY, &di); 57829bd2886SAlan Wright return (SMB_DOMAIN_SUCCESS); 57929bd2886SAlan Wright } 58029bd2886SAlan Wright 58129bd2886SAlan Wright /* 58229bd2886SAlan Wright * Initialize the domain cache. 58329bd2886SAlan Wright * This function does not populate the cache. 58429bd2886SAlan Wright */ 58529bd2886SAlan Wright static void 58629bd2886SAlan Wright smb_dcache_create(void) 58729bd2886SAlan Wright { 58829bd2886SAlan Wright (void) mutex_lock(&smb_dcache.dc_mtx); 58929bd2886SAlan Wright if (smb_dcache.dc_state != SMB_DCACHE_STATE_NONE) { 59029bd2886SAlan Wright (void) mutex_unlock(&smb_dcache.dc_mtx); 59129bd2886SAlan Wright return; 59229bd2886SAlan Wright } 59329bd2886SAlan Wright 594a0aa776eSAlan Wright list_create(&smb_dcache.dc_cache, sizeof (smb_domain_t), 595a0aa776eSAlan Wright offsetof(smb_domain_t, di_lnd)); 59629bd2886SAlan Wright 59729bd2886SAlan Wright smb_dcache.dc_nops = 0; 598*b3700b07SGordon Ross bzero(&smb_dcache.dc_dci, sizeof (smb_dcache.dc_dci)); 59929bd2886SAlan Wright smb_dcache.dc_state = SMB_DCACHE_STATE_READY; 60029bd2886SAlan Wright (void) mutex_unlock(&smb_dcache.dc_mtx); 60129bd2886SAlan Wright } 60229bd2886SAlan Wright 60329bd2886SAlan Wright /* 60429bd2886SAlan Wright * Removes and frees all the cache entries 60529bd2886SAlan Wright */ 60629bd2886SAlan Wright static void 60729bd2886SAlan Wright smb_dcache_flush(void) 60829bd2886SAlan Wright { 609a0aa776eSAlan Wright smb_domain_t *di; 61029bd2886SAlan Wright 61129bd2886SAlan Wright (void) rw_wrlock(&smb_dcache.dc_cache_lck); 61229bd2886SAlan Wright while ((di = list_head(&smb_dcache.dc_cache)) != NULL) 61329bd2886SAlan Wright smb_dcache_remove(di); 61429bd2886SAlan Wright (void) rw_unlock(&smb_dcache.dc_cache_lck); 61529bd2886SAlan Wright } 61629bd2886SAlan Wright 61729bd2886SAlan Wright /* 61829bd2886SAlan Wright * Destroys the cache. 61929bd2886SAlan Wright */ 62029bd2886SAlan Wright static void 62129bd2886SAlan Wright smb_dcache_destroy(void) 62229bd2886SAlan Wright { 62329bd2886SAlan Wright (void) mutex_lock(&smb_dcache.dc_mtx); 62429bd2886SAlan Wright if ((smb_dcache.dc_state == SMB_DCACHE_STATE_READY) || 62529bd2886SAlan Wright (smb_dcache.dc_state == SMB_DCACHE_STATE_UPDATING)) { 62629bd2886SAlan Wright smb_dcache.dc_state = SMB_DCACHE_STATE_DESTROYING; 62729bd2886SAlan Wright while (smb_dcache.dc_nops > 0) 62829bd2886SAlan Wright (void) cond_wait(&smb_dcache.dc_cv, 62929bd2886SAlan Wright &smb_dcache.dc_mtx); 63029bd2886SAlan Wright 63129bd2886SAlan Wright smb_dcache_flush(); 63229bd2886SAlan Wright list_destroy(&smb_dcache.dc_cache); 63329bd2886SAlan Wright 63429bd2886SAlan Wright smb_dcache.dc_state = SMB_DCACHE_STATE_NONE; 63529bd2886SAlan Wright } 63629bd2886SAlan Wright (void) mutex_unlock(&smb_dcache.dc_mtx); 63729bd2886SAlan Wright } 63829bd2886SAlan Wright 63929bd2886SAlan Wright /* 64029bd2886SAlan Wright * Lock the cache with the specified mode. 64129bd2886SAlan Wright * If the cache is in updating state and a read lock is 64229bd2886SAlan Wright * requested, the lock won't be granted until either the 64329bd2886SAlan Wright * update is finished or SMB_DCACHE_UPDATE_WAIT has passed. 64429bd2886SAlan Wright * 64529bd2886SAlan Wright * Whenever a lock is granted, the number of inflight cache 64629bd2886SAlan Wright * operations is incremented. 64729bd2886SAlan Wright */ 64829bd2886SAlan Wright static uint32_t 64929bd2886SAlan Wright smb_dcache_lock(int mode) 65029bd2886SAlan Wright { 65129bd2886SAlan Wright (void) mutex_lock(&smb_dcache.dc_mtx); 65229bd2886SAlan Wright switch (smb_dcache.dc_state) { 65329bd2886SAlan Wright case SMB_DCACHE_STATE_NONE: 65429bd2886SAlan Wright case SMB_DCACHE_STATE_DESTROYING: 65529bd2886SAlan Wright (void) mutex_unlock(&smb_dcache.dc_mtx); 65629bd2886SAlan Wright return (SMB_DOMAIN_INTERNAL_ERR); 65729bd2886SAlan Wright 65829bd2886SAlan Wright case SMB_DCACHE_STATE_UPDATING: 65929bd2886SAlan Wright if (mode == SMB_DCACHE_RDLOCK) { 66029bd2886SAlan Wright /* 66129bd2886SAlan Wright * Read operations should wait until the update 66229bd2886SAlan Wright * is completed. 66329bd2886SAlan Wright */ 66429bd2886SAlan Wright if (!smb_dcache_wait()) { 66529bd2886SAlan Wright (void) mutex_unlock(&smb_dcache.dc_mtx); 66629bd2886SAlan Wright return (SMB_DOMAIN_INTERNAL_ERR); 66729bd2886SAlan Wright } 66829bd2886SAlan Wright } 66929bd2886SAlan Wright 67029bd2886SAlan Wright default: 67129bd2886SAlan Wright smb_dcache.dc_nops++; 67229bd2886SAlan Wright break; 67329bd2886SAlan Wright } 67429bd2886SAlan Wright (void) mutex_unlock(&smb_dcache.dc_mtx); 67529bd2886SAlan Wright 67629bd2886SAlan Wright /* 67729bd2886SAlan Wright * Lock has to be taken outside the mutex otherwise 67829bd2886SAlan Wright * there could be a deadlock 67929bd2886SAlan Wright */ 68029bd2886SAlan Wright if (mode == SMB_DCACHE_RDLOCK) 68129bd2886SAlan Wright (void) rw_rdlock(&smb_dcache.dc_cache_lck); 68229bd2886SAlan Wright else 68329bd2886SAlan Wright (void) rw_wrlock(&smb_dcache.dc_cache_lck); 68429bd2886SAlan Wright 68529bd2886SAlan Wright return (SMB_DOMAIN_SUCCESS); 68629bd2886SAlan Wright } 68729bd2886SAlan Wright 68829bd2886SAlan Wright /* 68929bd2886SAlan Wright * Decrement the number of inflight operations and then unlock. 69029bd2886SAlan Wright */ 69129bd2886SAlan Wright static void 69229bd2886SAlan Wright smb_dcache_unlock(void) 69329bd2886SAlan Wright { 69429bd2886SAlan Wright (void) mutex_lock(&smb_dcache.dc_mtx); 69529bd2886SAlan Wright assert(smb_dcache.dc_nops > 0); 69629bd2886SAlan Wright smb_dcache.dc_nops--; 69729bd2886SAlan Wright (void) cond_broadcast(&smb_dcache.dc_cv); 69829bd2886SAlan Wright (void) mutex_unlock(&smb_dcache.dc_mtx); 69929bd2886SAlan Wright 70029bd2886SAlan Wright (void) rw_unlock(&smb_dcache.dc_cache_lck); 70129bd2886SAlan Wright } 70229bd2886SAlan Wright 70329bd2886SAlan Wright static uint32_t 704a0aa776eSAlan Wright smb_dcache_add(smb_domain_t *di) 70529bd2886SAlan Wright { 706a0aa776eSAlan Wright smb_domain_t *dcnode; 70729bd2886SAlan Wright 708a0aa776eSAlan Wright if ((dcnode = malloc(sizeof (smb_domain_t))) == NULL) 70929bd2886SAlan Wright return (SMB_DOMAIN_NO_MEMORY); 71029bd2886SAlan Wright 71129bd2886SAlan Wright *dcnode = *di; 71229bd2886SAlan Wright dcnode->di_binsid = smb_sid_fromstr(dcnode->di_sid); 71329bd2886SAlan Wright if (dcnode->di_binsid == NULL) { 71429bd2886SAlan Wright free(dcnode); 71529bd2886SAlan Wright return (SMB_DOMAIN_NO_MEMORY); 71629bd2886SAlan Wright } 71729bd2886SAlan Wright 71829bd2886SAlan Wright list_insert_tail(&smb_dcache.dc_cache, dcnode); 71929bd2886SAlan Wright return (SMB_DOMAIN_SUCCESS); 72029bd2886SAlan Wright } 72129bd2886SAlan Wright 72229bd2886SAlan Wright static void 723a0aa776eSAlan Wright smb_dcache_remove(smb_domain_t *di) 72429bd2886SAlan Wright { 72529bd2886SAlan Wright list_remove(&smb_dcache.dc_cache, di); 72629bd2886SAlan Wright smb_sid_free(di->di_binsid); 72729bd2886SAlan Wright free(di); 72829bd2886SAlan Wright } 72929bd2886SAlan Wright 73029bd2886SAlan Wright static void 731*b3700b07SGordon Ross smb_dcache_setdc(const smb_dcinfo_t *dci) 73229bd2886SAlan Wright { 73329bd2886SAlan Wright (void) mutex_lock(&smb_dcache.dc_mtx); 734*b3700b07SGordon Ross smb_dcache.dc_dci = *dci; /* struct assignment! */ 73529bd2886SAlan Wright (void) mutex_unlock(&smb_dcache.dc_mtx); 73629bd2886SAlan Wright } 73729bd2886SAlan Wright 738*b3700b07SGordon Ross /* 739*b3700b07SGordon Ross * Return B_TRUE if we have DC information. 740*b3700b07SGordon Ross */ 741*b3700b07SGordon Ross static boolean_t 742*b3700b07SGordon Ross smb_dcache_getdc(smb_dcinfo_t *dci) 74329bd2886SAlan Wright { 74429bd2886SAlan Wright (void) mutex_lock(&smb_dcache.dc_mtx); 745*b3700b07SGordon Ross *dci = smb_dcache.dc_dci; /* struct assignment! */ 74629bd2886SAlan Wright (void) mutex_unlock(&smb_dcache.dc_mtx); 747*b3700b07SGordon Ross return (dci->dc_name[0] != '\0'); 74829bd2886SAlan Wright } 74929bd2886SAlan Wright 750a0aa776eSAlan Wright /* 751a0aa776eSAlan Wright * Waits for SMB_DCACHE_UPDATE_WAIT seconds if cache is in 752a0aa776eSAlan Wright * UPDATING state. Upon wake up returns true if cache is 753a0aa776eSAlan Wright * ready to be used, otherwise it returns false. 754a0aa776eSAlan Wright */ 75529bd2886SAlan Wright static boolean_t 75629bd2886SAlan Wright smb_dcache_wait(void) 75729bd2886SAlan Wright { 75829bd2886SAlan Wright timestruc_t to; 75929bd2886SAlan Wright int err; 76029bd2886SAlan Wright 76129bd2886SAlan Wright to.tv_sec = SMB_DCACHE_UPDATE_WAIT; 76229bd2886SAlan Wright to.tv_nsec = 0; 76329bd2886SAlan Wright while (smb_dcache.dc_state == SMB_DCACHE_STATE_UPDATING) { 76429bd2886SAlan Wright err = cond_reltimedwait(&smb_dcache.dc_cv, 76529bd2886SAlan Wright &smb_dcache.dc_mtx, &to); 76629bd2886SAlan Wright if (err == ETIME) 76729bd2886SAlan Wright break; 76829bd2886SAlan Wright } 76929bd2886SAlan Wright 77029bd2886SAlan Wright return (smb_dcache.dc_state == SMB_DCACHE_STATE_READY); 77129bd2886SAlan Wright } 77229bd2886SAlan Wright 773a0aa776eSAlan Wright /* 774a0aa776eSAlan Wright * Transfers the cache into UPDATING state, this will ensure 775a0aa776eSAlan Wright * any read access to the cache will be stalled until the 776a0aa776eSAlan Wright * update is finished. This is to avoid providing incomplete, 777a0aa776eSAlan Wright * inconsistent or stale information. 778a0aa776eSAlan Wright * 779a0aa776eSAlan Wright * If another thread is already updating the cache, other 780a0aa776eSAlan Wright * callers will wait until cache is no longer in UPDATING 781a0aa776eSAlan Wright * state. The return code is decided based on the new 782a0aa776eSAlan Wright * state of the cache. 783a0aa776eSAlan Wright */ 784a0aa776eSAlan Wright static uint32_t 78529bd2886SAlan Wright smb_dcache_updating(void) 78629bd2886SAlan Wright { 787a0aa776eSAlan Wright uint32_t rc; 788a0aa776eSAlan Wright 78929bd2886SAlan Wright (void) mutex_lock(&smb_dcache.dc_mtx); 790a0aa776eSAlan Wright switch (smb_dcache.dc_state) { 791a0aa776eSAlan Wright case SMB_DCACHE_STATE_READY: 79229bd2886SAlan Wright smb_dcache.dc_state = SMB_DCACHE_STATE_UPDATING; 793a0aa776eSAlan Wright rc = SMB_DOMAIN_SUCCESS; 794a0aa776eSAlan Wright break; 795a0aa776eSAlan Wright 796a0aa776eSAlan Wright case SMB_DCACHE_STATE_UPDATING: 797a0aa776eSAlan Wright while (smb_dcache.dc_state == SMB_DCACHE_STATE_UPDATING) 798a0aa776eSAlan Wright (void) cond_wait(&smb_dcache.dc_cv, 799a0aa776eSAlan Wright &smb_dcache.dc_mtx); 800a0aa776eSAlan Wright 801a0aa776eSAlan Wright if (smb_dcache.dc_state == SMB_DCACHE_STATE_READY) { 802a0aa776eSAlan Wright smb_dcache.dc_state = SMB_DCACHE_STATE_UPDATING; 803a0aa776eSAlan Wright rc = SMB_DOMAIN_SUCCESS; 804a0aa776eSAlan Wright } else { 805a0aa776eSAlan Wright rc = SMB_DOMAIN_NO_CACHE; 806a0aa776eSAlan Wright } 807a0aa776eSAlan Wright break; 808a0aa776eSAlan Wright 809a0aa776eSAlan Wright case SMB_DCACHE_STATE_NONE: 810a0aa776eSAlan Wright case SMB_DCACHE_STATE_DESTROYING: 811a0aa776eSAlan Wright rc = SMB_DOMAIN_NO_CACHE; 812a0aa776eSAlan Wright break; 813a0aa776eSAlan Wright 814a0aa776eSAlan Wright default: 815a0aa776eSAlan Wright break; 81629bd2886SAlan Wright } 81729bd2886SAlan Wright 818a0aa776eSAlan Wright (void) mutex_unlock(&smb_dcache.dc_mtx); 819a0aa776eSAlan Wright return (rc); 820a0aa776eSAlan Wright } 821a0aa776eSAlan Wright 822a0aa776eSAlan Wright /* 823a0aa776eSAlan Wright * Transfers the cache from UPDATING to READY state. 824a0aa776eSAlan Wright * 825a0aa776eSAlan Wright * Nothing will happen if the cache is no longer available 826a0aa776eSAlan Wright * or it is being destroyed. 827a0aa776eSAlan Wright */ 82829bd2886SAlan Wright static void 82929bd2886SAlan Wright smb_dcache_ready(void) 83029bd2886SAlan Wright { 83129bd2886SAlan Wright (void) mutex_lock(&smb_dcache.dc_mtx); 832a0aa776eSAlan Wright switch (smb_dcache.dc_state) { 833a0aa776eSAlan Wright case SMB_DCACHE_STATE_UPDATING: 83429bd2886SAlan Wright smb_dcache.dc_state = SMB_DCACHE_STATE_READY; 835a0aa776eSAlan Wright (void) cond_broadcast(&smb_dcache.dc_cv); 836a0aa776eSAlan Wright break; 837a0aa776eSAlan Wright 838a0aa776eSAlan Wright case SMB_DCACHE_STATE_NONE: 839a0aa776eSAlan Wright case SMB_DCACHE_STATE_DESTROYING: 840a0aa776eSAlan Wright break; 841a0aa776eSAlan Wright 842a0aa776eSAlan Wright default: 84329bd2886SAlan Wright assert(0); 844a0aa776eSAlan Wright } 84529bd2886SAlan Wright (void) mutex_unlock(&smb_dcache.dc_mtx); 84629bd2886SAlan Wright } 847