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.
24*380acbbeSGordon Ross *
25*380acbbeSGordon Ross * Copyright 2011 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;
7729bd2886SAlan Wright char dc_server[MAXHOSTNAMELEN];
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 *);
9329bd2886SAlan Wright static void smb_dcache_getdc(char *, size_t);
9429bd2886SAlan Wright static void smb_dcache_setdc(char *);
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 {
29629bd2886SAlan Wright boolean_t success;
297da6c28aaSamw
298a0aa776eSAlan Wright success = smb_domain_lookup_type(SMB_DOMAIN_PRIMARY, &dxi->d_primary);
29929bd2886SAlan Wright if (success)
300a0aa776eSAlan Wright smb_dcache_getdc(dxi->d_dc, sizeof (dxi->d_dc));
301da6c28aaSamw
30229bd2886SAlan Wright return (success);
303da6c28aaSamw }
304da6c28aaSamw
30529bd2886SAlan Wright /*
306*380acbbeSGordon Ross * Get the name of the current DC (if any)
307*380acbbeSGordon Ross * Does NOT block.
308*380acbbeSGordon Ross */
309*380acbbeSGordon Ross void
smb_domain_current_dc(char * buf,size_t len)310*380acbbeSGordon Ross smb_domain_current_dc(char *buf, size_t len)
311*380acbbeSGordon Ross {
312*380acbbeSGordon Ross smb_dcache_getdc(buf, len);
313*380acbbeSGordon Ross }
314*380acbbeSGordon Ross
315*380acbbeSGordon Ross /*
31629bd2886SAlan Wright * Transfer the cache to updating state.
31729bd2886SAlan Wright * In this state any request for reading the cache would
31829bd2886SAlan Wright * be blocked until the update is finished.
31929bd2886SAlan Wright */
320a0aa776eSAlan Wright uint32_t
smb_domain_start_update(void)321a0aa776eSAlan Wright smb_domain_start_update(void)
322da6c28aaSamw {
323a0aa776eSAlan Wright return (smb_dcache_updating());
32429bd2886SAlan Wright }
325da6c28aaSamw
32629bd2886SAlan Wright /*
32729bd2886SAlan Wright * Transfer the cache from updating to ready state.
32829bd2886SAlan Wright */
32929bd2886SAlan Wright void
smb_domain_end_update(void)330a0aa776eSAlan Wright smb_domain_end_update(void)
33129bd2886SAlan Wright {
33229bd2886SAlan Wright smb_dcache_ready();
33329bd2886SAlan Wright }
33429bd2886SAlan Wright
33529bd2886SAlan Wright /*
33629bd2886SAlan Wright * Updates the cache with given information for the primary
33729bd2886SAlan Wright * domain, possible trusted domains and the selected domain
33829bd2886SAlan Wright * controller.
33929bd2886SAlan Wright *
34029bd2886SAlan Wright * Before adding the new entries existing entries of type
34129bd2886SAlan Wright * primary and trusted will be removed from cache.
34229bd2886SAlan Wright */
34329bd2886SAlan Wright void
smb_domain_update(smb_domainex_t * dxi)344a0aa776eSAlan Wright smb_domain_update(smb_domainex_t *dxi)
34529bd2886SAlan Wright {
346a0aa776eSAlan Wright smb_domain_t *dcnode;
34729bd2886SAlan Wright int i;
34829bd2886SAlan Wright
34929bd2886SAlan Wright if (smb_dcache_lock(SMB_DCACHE_WRLOCK) != SMB_DOMAIN_SUCCESS)
350da6c28aaSamw return;
35129bd2886SAlan Wright
35229bd2886SAlan Wright dcnode = list_head(&smb_dcache.dc_cache);
35329bd2886SAlan Wright while (dcnode) {
354a0aa776eSAlan Wright if ((dcnode->di_type == SMB_DOMAIN_PRIMARY) ||
355a0aa776eSAlan Wright (dcnode->di_type == SMB_DOMAIN_TRUSTED)) {
35629bd2886SAlan Wright smb_dcache_remove(dcnode);
35729bd2886SAlan Wright dcnode = list_head(&smb_dcache.dc_cache);
35829bd2886SAlan Wright } else {
35929bd2886SAlan Wright dcnode = list_next(&smb_dcache.dc_cache, dcnode);
360da6c28aaSamw }
361da6c28aaSamw }
36229bd2886SAlan Wright
363a0aa776eSAlan Wright if (smb_dcache_add(&dxi->d_primary) == SMB_DOMAIN_SUCCESS) {
364a0aa776eSAlan Wright for (i = 0; i < dxi->d_trusted.td_num; i++)
365a0aa776eSAlan Wright (void) smb_dcache_add(&dxi->d_trusted.td_domains[i]);
36629bd2886SAlan Wright
367a0aa776eSAlan Wright smb_dcache_setdc(dxi->d_dc);
36829bd2886SAlan Wright }
36929bd2886SAlan Wright
37029bd2886SAlan Wright smb_dcache_unlock();
371da6c28aaSamw }
37289dc44ceSjose borrego
37389dc44ceSjose borrego /*
37489dc44ceSjose borrego * Write the list of domains to /var/run/smb/domains.
37589dc44ceSjose borrego */
37689dc44ceSjose borrego void
smb_domain_save(void)377a0aa776eSAlan Wright smb_domain_save(void)
37889dc44ceSjose borrego {
37989dc44ceSjose borrego char fname[MAXPATHLEN];
38089dc44ceSjose borrego char tag;
381a0aa776eSAlan Wright smb_domain_t *domain;
38289dc44ceSjose borrego FILE *fp;
38389dc44ceSjose borrego struct passwd *pwd;
38489dc44ceSjose borrego struct group *grp;
38589dc44ceSjose borrego uid_t uid;
38689dc44ceSjose borrego gid_t gid;
38789dc44ceSjose borrego
38889dc44ceSjose borrego (void) snprintf(fname, MAXPATHLEN, "%s/%s",
38989dc44ceSjose borrego SMB_VARRUN_DIR, SMB_DOMAINS_FILE);
39089dc44ceSjose borrego
39189dc44ceSjose borrego if ((fp = fopen(fname, "w")) == NULL)
39289dc44ceSjose borrego return;
39389dc44ceSjose borrego
39489dc44ceSjose borrego pwd = getpwnam("root");
39589dc44ceSjose borrego grp = getgrnam("sys");
39689dc44ceSjose borrego uid = (pwd == NULL) ? 0 : pwd->pw_uid;
39789dc44ceSjose borrego gid = (grp == NULL) ? 3 : grp->gr_gid;
39889dc44ceSjose borrego
39989dc44ceSjose borrego (void) lockf(fileno(fp), F_LOCK, 0);
40089dc44ceSjose borrego (void) fchmod(fileno(fp), 0600);
40189dc44ceSjose borrego (void) fchown(fileno(fp), uid, gid);
40289dc44ceSjose borrego
40329bd2886SAlan Wright if (smb_dcache_lock(SMB_DCACHE_RDLOCK) != SMB_DOMAIN_SUCCESS)
40429bd2886SAlan Wright return;
40589dc44ceSjose borrego
40629bd2886SAlan Wright domain = list_head(&smb_dcache.dc_cache);
40789dc44ceSjose borrego while (domain) {
40829bd2886SAlan Wright switch (domain->di_type) {
409a0aa776eSAlan Wright case SMB_DOMAIN_PRIMARY:
41089dc44ceSjose borrego tag = '*';
41189dc44ceSjose borrego break;
41289dc44ceSjose borrego
413a0aa776eSAlan Wright case SMB_DOMAIN_TRUSTED:
414a0aa776eSAlan Wright case SMB_DOMAIN_UNTRUSTED:
41589dc44ceSjose borrego tag = '-';
41689dc44ceSjose borrego break;
41789dc44ceSjose borrego
418a0aa776eSAlan Wright case SMB_DOMAIN_LOCAL:
41989dc44ceSjose borrego tag = '.';
42089dc44ceSjose borrego break;
42189dc44ceSjose borrego default:
42229bd2886SAlan Wright domain = list_next(&smb_dcache.dc_cache, domain);
42389dc44ceSjose borrego continue;
42489dc44ceSjose borrego }
42589dc44ceSjose borrego
42689dc44ceSjose borrego (void) fprintf(fp, "[%c] [%s] [%s]\n",
42729bd2886SAlan Wright tag, domain->di_nbname, domain->di_sid);
42889dc44ceSjose borrego
42929bd2886SAlan Wright domain = list_next(&smb_dcache.dc_cache, domain);
43089dc44ceSjose borrego }
43189dc44ceSjose borrego
43229bd2886SAlan Wright smb_dcache_unlock();
43389dc44ceSjose borrego (void) lockf(fileno(fp), F_ULOCK, 0);
43489dc44ceSjose borrego (void) fclose(fp);
43589dc44ceSjose borrego }
43689dc44ceSjose borrego
43789dc44ceSjose borrego /*
43889dc44ceSjose borrego * List the domains in /var/run/smb/domains.
43989dc44ceSjose borrego */
44089dc44ceSjose borrego void
smb_domain_show(void)441a0aa776eSAlan Wright smb_domain_show(void)
44289dc44ceSjose borrego {
44389dc44ceSjose borrego char buf[MAXPATHLEN];
44489dc44ceSjose borrego char *p;
44589dc44ceSjose borrego FILE *fp;
44689dc44ceSjose borrego
44789dc44ceSjose borrego (void) snprintf(buf, MAXPATHLEN, "%s/%s",
44889dc44ceSjose borrego SMB_VARRUN_DIR, SMB_DOMAINS_FILE);
44989dc44ceSjose borrego
45089dc44ceSjose borrego if ((fp = fopen(buf, "r")) != NULL) {
45189dc44ceSjose borrego (void) lockf(fileno(fp), F_LOCK, 0);
45289dc44ceSjose borrego
45389dc44ceSjose borrego while (fgets(buf, MAXPATHLEN, fp) != NULL) {
45489dc44ceSjose borrego if ((p = strchr(buf, '\n')) != NULL)
45589dc44ceSjose borrego *p = '\0';
45689dc44ceSjose borrego (void) printf("%s\n", buf);
45789dc44ceSjose borrego }
45889dc44ceSjose borrego
45989dc44ceSjose borrego (void) lockf(fileno(fp), F_ULOCK, 0);
46089dc44ceSjose borrego (void) fclose(fp);
46189dc44ceSjose borrego }
46289dc44ceSjose borrego }
46389dc44ceSjose borrego
46429bd2886SAlan Wright void
smb_domain_set_basic_info(char * sid,char * nb_domain,char * fq_domain,smb_domain_t * di)465a0aa776eSAlan Wright smb_domain_set_basic_info(char *sid, char *nb_domain, char *fq_domain,
466a0aa776eSAlan Wright smb_domain_t *di)
46729bd2886SAlan Wright {
46829bd2886SAlan Wright if (sid == NULL || nb_domain == NULL || fq_domain == NULL ||
46929bd2886SAlan Wright di == NULL)
47029bd2886SAlan Wright return;
47129bd2886SAlan Wright
47229bd2886SAlan Wright (void) strlcpy(di->di_sid, sid, SMB_SID_STRSZ);
47329bd2886SAlan Wright (void) strlcpy(di->di_nbname, nb_domain, NETBIOS_NAME_SZ);
474bbf6f00cSJordan Brown (void) smb_strupr(di->di_nbname);
47529bd2886SAlan Wright (void) strlcpy(di->di_fqname, fq_domain, MAXHOSTNAMELEN);
47629bd2886SAlan Wright di->di_binsid = NULL;
47729bd2886SAlan Wright }
47829bd2886SAlan Wright
47929bd2886SAlan Wright void
smb_domain_set_dns_info(char * sid,char * nb_domain,char * fq_domain,char * forest,char * guid,smb_domain_t * di)480a0aa776eSAlan Wright smb_domain_set_dns_info(char *sid, char *nb_domain, char *fq_domain,
481a0aa776eSAlan Wright char *forest, char *guid, smb_domain_t *di)
48229bd2886SAlan Wright {
48329bd2886SAlan Wright if (di == NULL || forest == NULL || guid == NULL)
48429bd2886SAlan Wright return;
48529bd2886SAlan Wright
486a0aa776eSAlan Wright smb_domain_set_basic_info(sid, nb_domain, fq_domain, di);
48729bd2886SAlan Wright (void) strlcpy(di->di_u.di_dns.ddi_forest, forest, MAXHOSTNAMELEN);
48829bd2886SAlan Wright (void) strlcpy(di->di_u.di_dns.ddi_guid, guid,
48929bd2886SAlan Wright UUID_PRINTABLE_STRING_LENGTH);
49029bd2886SAlan Wright }
49129bd2886SAlan Wright
49229bd2886SAlan 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)493a0aa776eSAlan Wright smb_domain_set_trust_info(char *sid, char *nb_domain, char *fq_domain,
49429bd2886SAlan Wright uint32_t trust_dir, uint32_t trust_type, uint32_t trust_attrs,
495a0aa776eSAlan Wright smb_domain_t *di)
49629bd2886SAlan Wright {
49729bd2886SAlan Wright smb_domain_trust_t *ti;
49829bd2886SAlan Wright
49929bd2886SAlan Wright if (di == NULL)
50029bd2886SAlan Wright return;
50129bd2886SAlan Wright
502a0aa776eSAlan Wright di->di_type = SMB_DOMAIN_TRUSTED;
50329bd2886SAlan Wright ti = &di->di_u.di_trust;
504a0aa776eSAlan Wright smb_domain_set_basic_info(sid, nb_domain, fq_domain, di);
50529bd2886SAlan Wright ti->dti_trust_direction = trust_dir;
50629bd2886SAlan Wright ti->dti_trust_type = trust_type;
50729bd2886SAlan Wright ti->dti_trust_attrs = trust_attrs;
50829bd2886SAlan Wright }
50929bd2886SAlan Wright
51089dc44ceSjose borrego /*
51189dc44ceSjose borrego * Remove the /var/run/smb/domains file.
51289dc44ceSjose borrego */
51329bd2886SAlan Wright static void
smb_domain_unlink(void)514a0aa776eSAlan Wright smb_domain_unlink(void)
51589dc44ceSjose borrego {
51689dc44ceSjose borrego char fname[MAXPATHLEN];
51789dc44ceSjose borrego
51889dc44ceSjose borrego (void) snprintf(fname, MAXPATHLEN, "%s/%s",
51989dc44ceSjose borrego SMB_VARRUN_DIR, SMB_DOMAINS_FILE);
52089dc44ceSjose borrego (void) unlink(fname);
52189dc44ceSjose borrego }
52229bd2886SAlan Wright
52329bd2886SAlan Wright /*
52429bd2886SAlan Wright * Add an entry for the local domain to the domain cache
52529bd2886SAlan Wright */
52629bd2886SAlan Wright static uint32_t
smb_domain_add_local(void)527a0aa776eSAlan Wright smb_domain_add_local(void)
52829bd2886SAlan Wright {
52929bd2886SAlan Wright char *lsidstr;
53029bd2886SAlan Wright char hostname[NETBIOS_NAME_SZ];
53129bd2886SAlan Wright char fq_name[MAXHOSTNAMELEN];
532a0aa776eSAlan Wright smb_domain_t di;
53329bd2886SAlan Wright
53429bd2886SAlan Wright if ((lsidstr = smb_config_get_localsid()) == NULL)
53529bd2886SAlan Wright return (SMB_DOMAIN_NOMACHINE_SID);
53629bd2886SAlan Wright
53729bd2886SAlan Wright if (smb_getnetbiosname(hostname, NETBIOS_NAME_SZ) != 0) {
53829bd2886SAlan Wright free(lsidstr);
53929bd2886SAlan Wright return (SMB_DOMAIN_NOMACHINE_SID);
54029bd2886SAlan Wright }
54129bd2886SAlan Wright
54229bd2886SAlan Wright *fq_name = '\0';
54329bd2886SAlan Wright (void) smb_getfqhostname(fq_name, MAXHOSTNAMELEN);
544a0aa776eSAlan Wright smb_domain_set_basic_info(lsidstr, hostname, fq_name, &di);
545a0aa776eSAlan Wright (void) smb_domain_add(SMB_DOMAIN_LOCAL, &di);
54629bd2886SAlan Wright
54729bd2886SAlan Wright free(lsidstr);
54829bd2886SAlan Wright return (SMB_DOMAIN_SUCCESS);
54929bd2886SAlan Wright }
55029bd2886SAlan Wright
55129bd2886SAlan Wright /*
55229bd2886SAlan Wright * Add an entry for the primary domain to the domain cache
55329bd2886SAlan Wright */
55429bd2886SAlan Wright static uint32_t
smb_domain_add_primary(uint32_t secmode)555a0aa776eSAlan Wright smb_domain_add_primary(uint32_t secmode)
55629bd2886SAlan Wright {
55729bd2886SAlan Wright char sidstr[SMB_SID_STRSZ];
55829bd2886SAlan Wright char fq_name[MAXHOSTNAMELEN];
55929bd2886SAlan Wright char nb_name[NETBIOS_NAME_SZ];
560a0aa776eSAlan Wright smb_domain_t di;
56129bd2886SAlan Wright int rc;
56229bd2886SAlan Wright
56329bd2886SAlan Wright if (secmode != SMB_SECMODE_DOMAIN)
56429bd2886SAlan Wright return (SMB_DOMAIN_SUCCESS);
56529bd2886SAlan Wright
56629bd2886SAlan Wright rc = smb_config_getstr(SMB_CI_DOMAIN_SID, sidstr, sizeof (sidstr));
56729bd2886SAlan Wright if (rc != SMBD_SMF_OK)
56829bd2886SAlan Wright return (SMB_DOMAIN_NODOMAIN_SID);
56929bd2886SAlan Wright
57029bd2886SAlan Wright rc = smb_config_getstr(SMB_CI_DOMAIN_NAME, nb_name, NETBIOS_NAME_SZ);
57129bd2886SAlan Wright if ((rc != SMBD_SMF_OK) || (*nb_name == '\0'))
57229bd2886SAlan Wright return (SMB_DOMAIN_NODOMAIN_NAME);
57329bd2886SAlan Wright
57429bd2886SAlan Wright (void) smb_getfqdomainname(fq_name, MAXHOSTNAMELEN);
575a0aa776eSAlan Wright smb_domain_set_basic_info(sidstr, nb_name, fq_name, &di);
576a0aa776eSAlan Wright (void) smb_domain_add(SMB_DOMAIN_PRIMARY, &di);
57729bd2886SAlan Wright return (SMB_DOMAIN_SUCCESS);
57829bd2886SAlan Wright }
57929bd2886SAlan Wright
58029bd2886SAlan Wright /*
58129bd2886SAlan Wright * Initialize the domain cache.
58229bd2886SAlan Wright * This function does not populate the cache.
58329bd2886SAlan Wright */
58429bd2886SAlan Wright static void
smb_dcache_create(void)58529bd2886SAlan Wright smb_dcache_create(void)
58629bd2886SAlan Wright {
58729bd2886SAlan Wright (void) mutex_lock(&smb_dcache.dc_mtx);
58829bd2886SAlan Wright if (smb_dcache.dc_state != SMB_DCACHE_STATE_NONE) {
58929bd2886SAlan Wright (void) mutex_unlock(&smb_dcache.dc_mtx);
59029bd2886SAlan Wright return;
59129bd2886SAlan Wright }
59229bd2886SAlan Wright
593a0aa776eSAlan Wright list_create(&smb_dcache.dc_cache, sizeof (smb_domain_t),
594a0aa776eSAlan Wright offsetof(smb_domain_t, di_lnd));
59529bd2886SAlan Wright
59629bd2886SAlan Wright smb_dcache.dc_nops = 0;
59729bd2886SAlan Wright *smb_dcache.dc_server = '\0';
59829bd2886SAlan Wright smb_dcache.dc_state = SMB_DCACHE_STATE_READY;
59929bd2886SAlan Wright (void) mutex_unlock(&smb_dcache.dc_mtx);
60029bd2886SAlan Wright }
60129bd2886SAlan Wright
60229bd2886SAlan Wright /*
60329bd2886SAlan Wright * Removes and frees all the cache entries
60429bd2886SAlan Wright */
60529bd2886SAlan Wright static void
smb_dcache_flush(void)60629bd2886SAlan Wright smb_dcache_flush(void)
60729bd2886SAlan Wright {
608a0aa776eSAlan Wright smb_domain_t *di;
60929bd2886SAlan Wright
61029bd2886SAlan Wright (void) rw_wrlock(&smb_dcache.dc_cache_lck);
61129bd2886SAlan Wright while ((di = list_head(&smb_dcache.dc_cache)) != NULL)
61229bd2886SAlan Wright smb_dcache_remove(di);
61329bd2886SAlan Wright (void) rw_unlock(&smb_dcache.dc_cache_lck);
61429bd2886SAlan Wright }
61529bd2886SAlan Wright
61629bd2886SAlan Wright /*
61729bd2886SAlan Wright * Destroys the cache.
61829bd2886SAlan Wright */
61929bd2886SAlan Wright static void
smb_dcache_destroy(void)62029bd2886SAlan Wright smb_dcache_destroy(void)
62129bd2886SAlan Wright {
62229bd2886SAlan Wright (void) mutex_lock(&smb_dcache.dc_mtx);
62329bd2886SAlan Wright if ((smb_dcache.dc_state == SMB_DCACHE_STATE_READY) ||
62429bd2886SAlan Wright (smb_dcache.dc_state == SMB_DCACHE_STATE_UPDATING)) {
62529bd2886SAlan Wright smb_dcache.dc_state = SMB_DCACHE_STATE_DESTROYING;
62629bd2886SAlan Wright while (smb_dcache.dc_nops > 0)
62729bd2886SAlan Wright (void) cond_wait(&smb_dcache.dc_cv,
62829bd2886SAlan Wright &smb_dcache.dc_mtx);
62929bd2886SAlan Wright
63029bd2886SAlan Wright smb_dcache_flush();
63129bd2886SAlan Wright list_destroy(&smb_dcache.dc_cache);
63229bd2886SAlan Wright
63329bd2886SAlan Wright smb_dcache.dc_state = SMB_DCACHE_STATE_NONE;
63429bd2886SAlan Wright }
63529bd2886SAlan Wright (void) mutex_unlock(&smb_dcache.dc_mtx);
63629bd2886SAlan Wright }
63729bd2886SAlan Wright
63829bd2886SAlan Wright /*
63929bd2886SAlan Wright * Lock the cache with the specified mode.
64029bd2886SAlan Wright * If the cache is in updating state and a read lock is
64129bd2886SAlan Wright * requested, the lock won't be granted until either the
64229bd2886SAlan Wright * update is finished or SMB_DCACHE_UPDATE_WAIT has passed.
64329bd2886SAlan Wright *
64429bd2886SAlan Wright * Whenever a lock is granted, the number of inflight cache
64529bd2886SAlan Wright * operations is incremented.
64629bd2886SAlan Wright */
64729bd2886SAlan Wright static uint32_t
smb_dcache_lock(int mode)64829bd2886SAlan Wright smb_dcache_lock(int mode)
64929bd2886SAlan Wright {
65029bd2886SAlan Wright (void) mutex_lock(&smb_dcache.dc_mtx);
65129bd2886SAlan Wright switch (smb_dcache.dc_state) {
65229bd2886SAlan Wright case SMB_DCACHE_STATE_NONE:
65329bd2886SAlan Wright case SMB_DCACHE_STATE_DESTROYING:
65429bd2886SAlan Wright (void) mutex_unlock(&smb_dcache.dc_mtx);
65529bd2886SAlan Wright return (SMB_DOMAIN_INTERNAL_ERR);
65629bd2886SAlan Wright
65729bd2886SAlan Wright case SMB_DCACHE_STATE_UPDATING:
65829bd2886SAlan Wright if (mode == SMB_DCACHE_RDLOCK) {
65929bd2886SAlan Wright /*
66029bd2886SAlan Wright * Read operations should wait until the update
66129bd2886SAlan Wright * is completed.
66229bd2886SAlan Wright */
66329bd2886SAlan Wright if (!smb_dcache_wait()) {
66429bd2886SAlan Wright (void) mutex_unlock(&smb_dcache.dc_mtx);
66529bd2886SAlan Wright return (SMB_DOMAIN_INTERNAL_ERR);
66629bd2886SAlan Wright }
66729bd2886SAlan Wright }
66829bd2886SAlan Wright
66929bd2886SAlan Wright default:
67029bd2886SAlan Wright smb_dcache.dc_nops++;
67129bd2886SAlan Wright break;
67229bd2886SAlan Wright }
67329bd2886SAlan Wright (void) mutex_unlock(&smb_dcache.dc_mtx);
67429bd2886SAlan Wright
67529bd2886SAlan Wright /*
67629bd2886SAlan Wright * Lock has to be taken outside the mutex otherwise
67729bd2886SAlan Wright * there could be a deadlock
67829bd2886SAlan Wright */
67929bd2886SAlan Wright if (mode == SMB_DCACHE_RDLOCK)
68029bd2886SAlan Wright (void) rw_rdlock(&smb_dcache.dc_cache_lck);
68129bd2886SAlan Wright else
68229bd2886SAlan Wright (void) rw_wrlock(&smb_dcache.dc_cache_lck);
68329bd2886SAlan Wright
68429bd2886SAlan Wright return (SMB_DOMAIN_SUCCESS);
68529bd2886SAlan Wright }
68629bd2886SAlan Wright
68729bd2886SAlan Wright /*
68829bd2886SAlan Wright * Decrement the number of inflight operations and then unlock.
68929bd2886SAlan Wright */
69029bd2886SAlan Wright static void
smb_dcache_unlock(void)69129bd2886SAlan Wright smb_dcache_unlock(void)
69229bd2886SAlan Wright {
69329bd2886SAlan Wright (void) mutex_lock(&smb_dcache.dc_mtx);
69429bd2886SAlan Wright assert(smb_dcache.dc_nops > 0);
69529bd2886SAlan Wright smb_dcache.dc_nops--;
69629bd2886SAlan Wright (void) cond_broadcast(&smb_dcache.dc_cv);
69729bd2886SAlan Wright (void) mutex_unlock(&smb_dcache.dc_mtx);
69829bd2886SAlan Wright
69929bd2886SAlan Wright (void) rw_unlock(&smb_dcache.dc_cache_lck);
70029bd2886SAlan Wright }
70129bd2886SAlan Wright
70229bd2886SAlan Wright static uint32_t
smb_dcache_add(smb_domain_t * di)703a0aa776eSAlan Wright smb_dcache_add(smb_domain_t *di)
70429bd2886SAlan Wright {
705a0aa776eSAlan Wright smb_domain_t *dcnode;
70629bd2886SAlan Wright
707a0aa776eSAlan Wright if ((dcnode = malloc(sizeof (smb_domain_t))) == NULL)
70829bd2886SAlan Wright return (SMB_DOMAIN_NO_MEMORY);
70929bd2886SAlan Wright
71029bd2886SAlan Wright *dcnode = *di;
71129bd2886SAlan Wright dcnode->di_binsid = smb_sid_fromstr(dcnode->di_sid);
71229bd2886SAlan Wright if (dcnode->di_binsid == NULL) {
71329bd2886SAlan Wright free(dcnode);
71429bd2886SAlan Wright return (SMB_DOMAIN_NO_MEMORY);
71529bd2886SAlan Wright }
71629bd2886SAlan Wright
71729bd2886SAlan Wright list_insert_tail(&smb_dcache.dc_cache, dcnode);
71829bd2886SAlan Wright return (SMB_DOMAIN_SUCCESS);
71929bd2886SAlan Wright }
72029bd2886SAlan Wright
72129bd2886SAlan Wright static void
smb_dcache_remove(smb_domain_t * di)722a0aa776eSAlan Wright smb_dcache_remove(smb_domain_t *di)
72329bd2886SAlan Wright {
72429bd2886SAlan Wright list_remove(&smb_dcache.dc_cache, di);
72529bd2886SAlan Wright smb_sid_free(di->di_binsid);
72629bd2886SAlan Wright free(di);
72729bd2886SAlan Wright }
72829bd2886SAlan Wright
72929bd2886SAlan Wright static void
smb_dcache_setdc(char * dc)73029bd2886SAlan Wright smb_dcache_setdc(char *dc)
73129bd2886SAlan Wright {
73229bd2886SAlan Wright (void) mutex_lock(&smb_dcache.dc_mtx);
73329bd2886SAlan Wright (void) strlcpy(smb_dcache.dc_server, dc, sizeof (smb_dcache.dc_server));
73429bd2886SAlan Wright (void) mutex_unlock(&smb_dcache.dc_mtx);
73529bd2886SAlan Wright }
73629bd2886SAlan Wright
73729bd2886SAlan Wright static void
smb_dcache_getdc(char * buf,size_t buflen)73829bd2886SAlan Wright smb_dcache_getdc(char *buf, size_t buflen)
73929bd2886SAlan Wright {
74029bd2886SAlan Wright (void) mutex_lock(&smb_dcache.dc_mtx);
74129bd2886SAlan Wright (void) strlcpy(buf, smb_dcache.dc_server, buflen);
74229bd2886SAlan Wright (void) mutex_unlock(&smb_dcache.dc_mtx);
74329bd2886SAlan Wright }
74429bd2886SAlan Wright
745a0aa776eSAlan Wright /*
746a0aa776eSAlan Wright * Waits for SMB_DCACHE_UPDATE_WAIT seconds if cache is in
747a0aa776eSAlan Wright * UPDATING state. Upon wake up returns true if cache is
748a0aa776eSAlan Wright * ready to be used, otherwise it returns false.
749a0aa776eSAlan Wright */
75029bd2886SAlan Wright static boolean_t
smb_dcache_wait(void)75129bd2886SAlan Wright smb_dcache_wait(void)
75229bd2886SAlan Wright {
75329bd2886SAlan Wright timestruc_t to;
75429bd2886SAlan Wright int err;
75529bd2886SAlan Wright
75629bd2886SAlan Wright to.tv_sec = SMB_DCACHE_UPDATE_WAIT;
75729bd2886SAlan Wright to.tv_nsec = 0;
75829bd2886SAlan Wright while (smb_dcache.dc_state == SMB_DCACHE_STATE_UPDATING) {
75929bd2886SAlan Wright err = cond_reltimedwait(&smb_dcache.dc_cv,
76029bd2886SAlan Wright &smb_dcache.dc_mtx, &to);
76129bd2886SAlan Wright if (err == ETIME)
76229bd2886SAlan Wright break;
76329bd2886SAlan Wright }
76429bd2886SAlan Wright
76529bd2886SAlan Wright return (smb_dcache.dc_state == SMB_DCACHE_STATE_READY);
76629bd2886SAlan Wright }
76729bd2886SAlan Wright
768a0aa776eSAlan Wright /*
769a0aa776eSAlan Wright * Transfers the cache into UPDATING state, this will ensure
770a0aa776eSAlan Wright * any read access to the cache will be stalled until the
771a0aa776eSAlan Wright * update is finished. This is to avoid providing incomplete,
772a0aa776eSAlan Wright * inconsistent or stale information.
773a0aa776eSAlan Wright *
774a0aa776eSAlan Wright * If another thread is already updating the cache, other
775a0aa776eSAlan Wright * callers will wait until cache is no longer in UPDATING
776a0aa776eSAlan Wright * state. The return code is decided based on the new
777a0aa776eSAlan Wright * state of the cache.
778a0aa776eSAlan Wright */
779a0aa776eSAlan Wright static uint32_t
smb_dcache_updating(void)78029bd2886SAlan Wright smb_dcache_updating(void)
78129bd2886SAlan Wright {
782a0aa776eSAlan Wright uint32_t rc;
783a0aa776eSAlan Wright
78429bd2886SAlan Wright (void) mutex_lock(&smb_dcache.dc_mtx);
785a0aa776eSAlan Wright switch (smb_dcache.dc_state) {
786a0aa776eSAlan Wright case SMB_DCACHE_STATE_READY:
78729bd2886SAlan Wright smb_dcache.dc_state = SMB_DCACHE_STATE_UPDATING;
788a0aa776eSAlan Wright rc = SMB_DOMAIN_SUCCESS;
789a0aa776eSAlan Wright break;
790a0aa776eSAlan Wright
791a0aa776eSAlan Wright case SMB_DCACHE_STATE_UPDATING:
792a0aa776eSAlan Wright while (smb_dcache.dc_state == SMB_DCACHE_STATE_UPDATING)
793a0aa776eSAlan Wright (void) cond_wait(&smb_dcache.dc_cv,
794a0aa776eSAlan Wright &smb_dcache.dc_mtx);
795a0aa776eSAlan Wright
796a0aa776eSAlan Wright if (smb_dcache.dc_state == SMB_DCACHE_STATE_READY) {
797a0aa776eSAlan Wright smb_dcache.dc_state = SMB_DCACHE_STATE_UPDATING;
798a0aa776eSAlan Wright rc = SMB_DOMAIN_SUCCESS;
799a0aa776eSAlan Wright } else {
800a0aa776eSAlan Wright rc = SMB_DOMAIN_NO_CACHE;
801a0aa776eSAlan Wright }
802a0aa776eSAlan Wright break;
803a0aa776eSAlan Wright
804a0aa776eSAlan Wright case SMB_DCACHE_STATE_NONE:
805a0aa776eSAlan Wright case SMB_DCACHE_STATE_DESTROYING:
806a0aa776eSAlan Wright rc = SMB_DOMAIN_NO_CACHE;
807a0aa776eSAlan Wright break;
808a0aa776eSAlan Wright
809a0aa776eSAlan Wright default:
810a0aa776eSAlan Wright break;
81129bd2886SAlan Wright }
81229bd2886SAlan Wright
813a0aa776eSAlan Wright (void) mutex_unlock(&smb_dcache.dc_mtx);
814a0aa776eSAlan Wright return (rc);
815a0aa776eSAlan Wright }
816a0aa776eSAlan Wright
817a0aa776eSAlan Wright /*
818a0aa776eSAlan Wright * Transfers the cache from UPDATING to READY state.
819a0aa776eSAlan Wright *
820a0aa776eSAlan Wright * Nothing will happen if the cache is no longer available
821a0aa776eSAlan Wright * or it is being destroyed.
822a0aa776eSAlan Wright */
82329bd2886SAlan Wright static void
smb_dcache_ready(void)82429bd2886SAlan Wright smb_dcache_ready(void)
82529bd2886SAlan Wright {
82629bd2886SAlan Wright (void) mutex_lock(&smb_dcache.dc_mtx);
827a0aa776eSAlan Wright switch (smb_dcache.dc_state) {
828a0aa776eSAlan Wright case SMB_DCACHE_STATE_UPDATING:
82929bd2886SAlan Wright smb_dcache.dc_state = SMB_DCACHE_STATE_READY;
830a0aa776eSAlan Wright (void) cond_broadcast(&smb_dcache.dc_cv);
831a0aa776eSAlan Wright break;
832a0aa776eSAlan Wright
833a0aa776eSAlan Wright case SMB_DCACHE_STATE_NONE:
834a0aa776eSAlan Wright case SMB_DCACHE_STATE_DESTROYING:
835a0aa776eSAlan Wright break;
836a0aa776eSAlan Wright
837a0aa776eSAlan Wright default:
83829bd2886SAlan Wright assert(0);
839a0aa776eSAlan Wright }
84029bd2886SAlan Wright (void) mutex_unlock(&smb_dcache.dc_mtx);
84129bd2886SAlan Wright }
842