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
smb_domain_init(uint32_t secmode)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
smb_domain_fini(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
smb_domain_add(smb_domain_type_t type,smb_domain_t * di)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
smb_domain_lookup_name(char * name,smb_domain_t * di)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
smb_domain_lookup_sid(smb_sid_t * sid,smb_domain_t * di)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
smb_domain_lookup_type(smb_domain_type_t type,smb_domain_t * di)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
smb_domain_getinfo(smb_domainex_t * dxi)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
smb_domain_current_dc(smb_dcinfo_t * dci)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
smb_domain_start_update(void)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
smb_domain_end_update(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
smb_domain_update(smb_domainex_t * dxi)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
smb_domain_save(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
smb_domain_show(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
smb_domain_set_basic_info(char * sid,char * nb_domain,char * fq_domain,smb_domain_t * di)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
smb_domain_set_dns_info(char * sid,char * nb_domain,char * fq_domain,char * forest,char * guid,smb_domain_t * di)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
smb_domain_set_trust_info(char * sid,char * nb_domain,char * fq_domain,uint32_t trust_dir,uint32_t trust_type,uint32_t trust_attrs,smb_domain_t * di)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
smb_domain_unlink(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
smb_domain_add_local(void)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
smb_domain_add_primary(uint32_t secmode)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
smb_dcache_create(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
smb_dcache_flush(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
smb_dcache_destroy(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
smb_dcache_lock(int mode)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
smb_dcache_unlock(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
smb_dcache_add(smb_domain_t * di)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
smb_dcache_remove(smb_domain_t * di)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
smb_dcache_setdc(const smb_dcinfo_t * dci)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
smb_dcache_getdc(smb_dcinfo_t * dci)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
smb_dcache_wait(void)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
smb_dcache_updating(void)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
smb_dcache_ready(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