8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / smbsrv / libsmb / common / smb_domain.c
blob3d673d2d4cd6f53dbddb02d946fe7970a6ca3efe
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
25 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
29 * This file defines the domain environment values and the domain
30 * database interface. The database is a single linked list of
31 * structures containing domain type, name and SID information.
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <sys/list.h>
37 #include <stdio.h>
38 #include <strings.h>
39 #include <string.h>
40 #include <unistd.h>
41 #include <stdlib.h>
42 #include <synch.h>
43 #include <pwd.h>
44 #include <grp.h>
45 #include <assert.h>
47 #include <smbsrv/smbinfo.h>
48 #include <smbsrv/string.h>
49 #include <smbsrv/smb_sid.h>
50 #include <smbsrv/libsmb.h>
52 #define SMB_DOMAINS_FILE "domains"
54 #define SMB_DCACHE_UPDATE_WAIT 45 /* seconds */
57 * Domain cache states
59 #define SMB_DCACHE_STATE_NONE 0
60 #define SMB_DCACHE_STATE_READY 1
61 #define SMB_DCACHE_STATE_UPDATING 2
62 #define SMB_DCACHE_STATE_DESTROYING 3
65 * Cache lock modes
67 #define SMB_DCACHE_RDLOCK 0
68 #define SMB_DCACHE_WRLOCK 1
70 typedef struct smb_domain_cache {
71 list_t dc_cache;
72 rwlock_t dc_cache_lck;
73 mutex_t dc_mtx;
74 cond_t dc_cv;
75 uint32_t dc_state;
76 uint32_t dc_nops;
77 smb_dcinfo_t dc_dci;
78 } smb_domain_cache_t;
80 static smb_domain_cache_t smb_dcache;
82 static uint32_t smb_domain_add(smb_domain_type_t, smb_domain_t *);
83 static uint32_t smb_domain_add_local(void);
84 static uint32_t smb_domain_add_primary(uint32_t);
85 static void smb_domain_unlink(void);
87 static void smb_dcache_create(void);
88 static void smb_dcache_destroy(void);
89 static uint32_t smb_dcache_lock(int);
90 static void smb_dcache_unlock(void);
91 static void smb_dcache_remove(smb_domain_t *);
92 static uint32_t smb_dcache_add(smb_domain_t *);
93 static boolean_t smb_dcache_getdc(smb_dcinfo_t *);
94 static void smb_dcache_setdc(const smb_dcinfo_t *);
95 static boolean_t smb_dcache_wait(void);
96 static uint32_t smb_dcache_updating(void);
97 static void smb_dcache_ready(void);
100 * domain cache one time initialization. This function should
101 * only be called during service startup.
103 * Returns 0 on success and an error code on failure.
106 smb_domain_init(uint32_t secmode)
108 smb_domain_t di;
109 int rc;
111 smb_dcache_create();
113 if ((rc = smb_domain_add_local()) != 0)
114 return (rc);
116 smb_domain_set_basic_info(NT_BUILTIN_DOMAIN_SIDSTR, "BUILTIN", "", &di);
117 (void) smb_domain_add(SMB_DOMAIN_BUILTIN, &di);
119 return (smb_domain_add_primary(secmode));
123 * Destroys the cache upon service termination
125 void
126 smb_domain_fini(void)
128 smb_dcache_destroy();
129 smb_domain_unlink();
133 * Add a domain structure to domain cache. There is no checking
134 * for duplicates.
136 static uint32_t
137 smb_domain_add(smb_domain_type_t type, smb_domain_t *di)
139 uint32_t res;
141 if ((di == NULL) || (di->di_sid == NULL))
142 return (SMB_DOMAIN_INVALID_ARG);
144 if ((res = smb_dcache_lock(SMB_DCACHE_WRLOCK)) == SMB_DOMAIN_SUCCESS) {
145 di->di_type = type;
146 res = smb_dcache_add(di);
147 smb_dcache_unlock();
150 return (res);
154 * Lookup a domain by its name. The passed name is the NETBIOS or fully
155 * qualified DNS name or non-qualified DNS name.
157 * If the requested domain is found and given 'di' pointer is not NULL
158 * it'll be filled with the domain information and B_TRUE is returned.
159 * If the caller only needs to check a domain existence it can pass
160 * NULL for 'di' and just check the return value.
162 * If the domain is not in the cache B_FALSE is returned.
164 boolean_t
165 smb_domain_lookup_name(char *name, smb_domain_t *di)
167 boolean_t found = B_FALSE;
168 smb_domain_t *dcnode;
169 char *p;
171 bzero(di, sizeof (smb_domain_t));
173 if (name == NULL || *name == '\0')
174 return (B_FALSE);
176 if (smb_dcache_lock(SMB_DCACHE_RDLOCK) != SMB_DOMAIN_SUCCESS)
177 return (B_FALSE);
179 dcnode = list_head(&smb_dcache.dc_cache);
180 while (dcnode) {
181 found = (smb_strcasecmp(dcnode->di_nbname, name, 0) == 0) ||
182 (smb_strcasecmp(dcnode->di_fqname, name, 0) == 0);
184 if (found) {
185 if (di)
186 *di = *dcnode;
187 break;
190 if ((p = strchr(dcnode->di_fqname, '.')) != NULL) {
191 *p = '\0';
192 found = (smb_strcasecmp(dcnode->di_fqname, name,
193 0) == 0);
194 *p = '.';
195 if (found) {
196 if (di)
197 *di = *dcnode;
198 break;
202 dcnode = list_next(&smb_dcache.dc_cache, dcnode);
205 smb_dcache_unlock();
206 return (found);
210 * Lookup a domain by its SID.
212 * If the requested domain is found and given 'di' pointer is not NULL
213 * it'll be filled with the domain information and B_TRUE is returned.
214 * If the caller only needs to check a domain existence it can pass
215 * NULL for 'di' and just check the return value.
217 * If the domain is not in the cache B_FALSE is returned.
219 boolean_t
220 smb_domain_lookup_sid(smb_sid_t *sid, smb_domain_t *di)
222 boolean_t found = B_FALSE;
223 smb_domain_t *dcnode;
224 char sidstr[SMB_SID_STRSZ];
226 bzero(di, sizeof (smb_domain_t));
228 if (sid == NULL)
229 return (B_FALSE);
231 smb_sid_tostr(sid, sidstr);
233 if (smb_dcache_lock(SMB_DCACHE_RDLOCK) != SMB_DOMAIN_SUCCESS)
234 return (B_FALSE);
236 dcnode = list_head(&smb_dcache.dc_cache);
237 while (dcnode) {
238 found = (strcmp(dcnode->di_sid, sidstr) == 0);
239 if (found) {
240 if (di)
241 *di = *dcnode;
242 break;
245 dcnode = list_next(&smb_dcache.dc_cache, dcnode);
248 smb_dcache_unlock();
249 return (found);
253 * Lookup a domain by its type.
255 * If the requested domain is found and given 'di' pointer is not NULL
256 * it'll be filled with the domain information and B_TRUE is returned.
257 * If the caller only needs to check a domain existence it can pass
258 * NULL for 'di' and just check the return value.
260 * If the domain is not in the cache B_FALSE is returned.
262 boolean_t
263 smb_domain_lookup_type(smb_domain_type_t type, smb_domain_t *di)
265 boolean_t found = B_FALSE;
266 smb_domain_t *dcnode;
268 bzero(di, sizeof (smb_domain_t));
270 if (smb_dcache_lock(SMB_DCACHE_RDLOCK) != SMB_DOMAIN_SUCCESS)
271 return (B_FALSE);
273 dcnode = list_head(&smb_dcache.dc_cache);
274 while (dcnode) {
275 if (dcnode->di_type == type) {
276 found = B_TRUE;
277 if (di)
278 *di = *dcnode;
279 break;
282 dcnode = list_next(&smb_dcache.dc_cache, dcnode);
285 smb_dcache_unlock();
286 return (found);
290 * Returns primary domain information plus the name of
291 * the selected domain controller.
293 boolean_t
294 smb_domain_getinfo(smb_domainex_t *dxi)
296 boolean_t rv;
298 /* Note: this waits for the dcache lock. */
299 rv = smb_domain_lookup_type(SMB_DOMAIN_PRIMARY, &dxi->d_primary);
300 if (rv)
301 rv = smb_dcache_getdc(&dxi->d_dci);
303 return (rv);
307 * Get the name of the current DC (if any)
308 * Does NOT block.
310 void
311 smb_domain_current_dc(smb_dcinfo_t *dci)
313 (void) smb_dcache_getdc(dci);
317 * Transfer the cache to updating state.
318 * In this state any request for reading the cache would
319 * be blocked until the update is finished.
321 uint32_t
322 smb_domain_start_update(void)
324 return (smb_dcache_updating());
328 * Transfer the cache from updating to ready state.
330 void
331 smb_domain_end_update(void)
333 smb_dcache_ready();
337 * Updates the cache with given information for the primary
338 * domain, possible trusted domains and the selected domain
339 * controller.
341 * Before adding the new entries existing entries of type
342 * primary and trusted will be removed from cache.
344 void
345 smb_domain_update(smb_domainex_t *dxi)
347 smb_domain_t *dcnode;
348 int i;
350 if (smb_dcache_lock(SMB_DCACHE_WRLOCK) != SMB_DOMAIN_SUCCESS)
351 return;
353 dcnode = list_head(&smb_dcache.dc_cache);
354 while (dcnode) {
355 if ((dcnode->di_type == SMB_DOMAIN_PRIMARY) ||
356 (dcnode->di_type == SMB_DOMAIN_TRUSTED)) {
357 smb_dcache_remove(dcnode);
358 dcnode = list_head(&smb_dcache.dc_cache);
359 } else {
360 dcnode = list_next(&smb_dcache.dc_cache, dcnode);
364 if (smb_dcache_add(&dxi->d_primary) == SMB_DOMAIN_SUCCESS) {
365 for (i = 0; i < dxi->d_trusted.td_num; i++)
366 (void) smb_dcache_add(&dxi->d_trusted.td_domains[i]);
368 smb_dcache_setdc(&dxi->d_dci);
371 smb_dcache_unlock();
375 * Write the list of domains to /var/run/smb/domains.
377 void
378 smb_domain_save(void)
380 char fname[MAXPATHLEN];
381 char tag;
382 smb_domain_t *domain;
383 FILE *fp;
384 struct passwd *pwd;
385 struct group *grp;
386 uid_t uid;
387 gid_t gid;
389 (void) snprintf(fname, MAXPATHLEN, "%s/%s",
390 SMB_VARRUN_DIR, SMB_DOMAINS_FILE);
392 if ((fp = fopen(fname, "w")) == NULL)
393 return;
395 pwd = getpwnam("root");
396 grp = getgrnam("sys");
397 uid = (pwd == NULL) ? 0 : pwd->pw_uid;
398 gid = (grp == NULL) ? 3 : grp->gr_gid;
400 (void) lockf(fileno(fp), F_LOCK, 0);
401 (void) fchmod(fileno(fp), 0600);
402 (void) fchown(fileno(fp), uid, gid);
404 if (smb_dcache_lock(SMB_DCACHE_RDLOCK) != SMB_DOMAIN_SUCCESS)
405 return;
407 domain = list_head(&smb_dcache.dc_cache);
408 while (domain) {
409 switch (domain->di_type) {
410 case SMB_DOMAIN_PRIMARY:
411 tag = '*';
412 break;
414 case SMB_DOMAIN_TRUSTED:
415 case SMB_DOMAIN_UNTRUSTED:
416 tag = '-';
417 break;
419 case SMB_DOMAIN_LOCAL:
420 tag = '.';
421 break;
422 default:
423 domain = list_next(&smb_dcache.dc_cache, domain);
424 continue;
427 (void) fprintf(fp, "[%c] [%s] [%s]\n",
428 tag, domain->di_nbname, domain->di_sid);
430 domain = list_next(&smb_dcache.dc_cache, domain);
433 smb_dcache_unlock();
434 (void) lockf(fileno(fp), F_ULOCK, 0);
435 (void) fclose(fp);
439 * List the domains in /var/run/smb/domains.
441 void
442 smb_domain_show(void)
444 char buf[MAXPATHLEN];
445 char *p;
446 FILE *fp;
448 (void) snprintf(buf, MAXPATHLEN, "%s/%s",
449 SMB_VARRUN_DIR, SMB_DOMAINS_FILE);
451 if ((fp = fopen(buf, "r")) != NULL) {
452 (void) lockf(fileno(fp), F_LOCK, 0);
454 while (fgets(buf, MAXPATHLEN, fp) != NULL) {
455 if ((p = strchr(buf, '\n')) != NULL)
456 *p = '\0';
457 (void) printf("%s\n", buf);
460 (void) lockf(fileno(fp), F_ULOCK, 0);
461 (void) fclose(fp);
465 void
466 smb_domain_set_basic_info(char *sid, char *nb_domain, char *fq_domain,
467 smb_domain_t *di)
469 if (sid == NULL || nb_domain == NULL || fq_domain == NULL ||
470 di == NULL)
471 return;
473 (void) strlcpy(di->di_sid, sid, SMB_SID_STRSZ);
474 (void) strlcpy(di->di_nbname, nb_domain, NETBIOS_NAME_SZ);
475 (void) smb_strupr(di->di_nbname);
476 (void) strlcpy(di->di_fqname, fq_domain, MAXHOSTNAMELEN);
477 di->di_binsid = NULL;
480 void
481 smb_domain_set_dns_info(char *sid, char *nb_domain, char *fq_domain,
482 char *forest, char *guid, smb_domain_t *di)
484 if (di == NULL || forest == NULL || guid == NULL)
485 return;
487 smb_domain_set_basic_info(sid, nb_domain, fq_domain, di);
488 (void) strlcpy(di->di_u.di_dns.ddi_forest, forest, MAXHOSTNAMELEN);
489 (void) strlcpy(di->di_u.di_dns.ddi_guid, guid,
490 UUID_PRINTABLE_STRING_LENGTH);
493 void
494 smb_domain_set_trust_info(char *sid, char *nb_domain, char *fq_domain,
495 uint32_t trust_dir, uint32_t trust_type, uint32_t trust_attrs,
496 smb_domain_t *di)
498 smb_domain_trust_t *ti;
500 if (di == NULL)
501 return;
503 di->di_type = SMB_DOMAIN_TRUSTED;
504 ti = &di->di_u.di_trust;
505 smb_domain_set_basic_info(sid, nb_domain, fq_domain, di);
506 ti->dti_trust_direction = trust_dir;
507 ti->dti_trust_type = trust_type;
508 ti->dti_trust_attrs = trust_attrs;
512 * Remove the /var/run/smb/domains file.
514 static void
515 smb_domain_unlink(void)
517 char fname[MAXPATHLEN];
519 (void) snprintf(fname, MAXPATHLEN, "%s/%s",
520 SMB_VARRUN_DIR, SMB_DOMAINS_FILE);
521 (void) unlink(fname);
525 * Add an entry for the local domain to the domain cache
527 static uint32_t
528 smb_domain_add_local(void)
530 char *lsidstr;
531 char hostname[NETBIOS_NAME_SZ];
532 char fq_name[MAXHOSTNAMELEN];
533 smb_domain_t di;
535 if ((lsidstr = smb_config_get_localsid()) == NULL)
536 return (SMB_DOMAIN_NOMACHINE_SID);
538 if (smb_getnetbiosname(hostname, NETBIOS_NAME_SZ) != 0) {
539 free(lsidstr);
540 return (SMB_DOMAIN_NOMACHINE_SID);
543 *fq_name = '\0';
544 (void) smb_getfqhostname(fq_name, MAXHOSTNAMELEN);
545 smb_domain_set_basic_info(lsidstr, hostname, fq_name, &di);
546 (void) smb_domain_add(SMB_DOMAIN_LOCAL, &di);
548 free(lsidstr);
549 return (SMB_DOMAIN_SUCCESS);
553 * Add an entry for the primary domain to the domain cache
555 static uint32_t
556 smb_domain_add_primary(uint32_t secmode)
558 char sidstr[SMB_SID_STRSZ];
559 char fq_name[MAXHOSTNAMELEN];
560 char nb_name[NETBIOS_NAME_SZ];
561 smb_domain_t di;
562 int rc;
564 if (secmode != SMB_SECMODE_DOMAIN)
565 return (SMB_DOMAIN_SUCCESS);
567 rc = smb_config_getstr(SMB_CI_DOMAIN_SID, sidstr, sizeof (sidstr));
568 if (rc != SMBD_SMF_OK)
569 return (SMB_DOMAIN_NODOMAIN_SID);
571 rc = smb_config_getstr(SMB_CI_DOMAIN_NAME, nb_name, NETBIOS_NAME_SZ);
572 if ((rc != SMBD_SMF_OK) || (*nb_name == '\0'))
573 return (SMB_DOMAIN_NODOMAIN_NAME);
575 (void) smb_getfqdomainname(fq_name, MAXHOSTNAMELEN);
576 smb_domain_set_basic_info(sidstr, nb_name, fq_name, &di);
577 (void) smb_domain_add(SMB_DOMAIN_PRIMARY, &di);
578 return (SMB_DOMAIN_SUCCESS);
582 * Initialize the domain cache.
583 * This function does not populate the cache.
585 static void
586 smb_dcache_create(void)
588 (void) mutex_lock(&smb_dcache.dc_mtx);
589 if (smb_dcache.dc_state != SMB_DCACHE_STATE_NONE) {
590 (void) mutex_unlock(&smb_dcache.dc_mtx);
591 return;
594 list_create(&smb_dcache.dc_cache, sizeof (smb_domain_t),
595 offsetof(smb_domain_t, di_lnd));
597 smb_dcache.dc_nops = 0;
598 bzero(&smb_dcache.dc_dci, sizeof (smb_dcache.dc_dci));
599 smb_dcache.dc_state = SMB_DCACHE_STATE_READY;
600 (void) mutex_unlock(&smb_dcache.dc_mtx);
604 * Removes and frees all the cache entries
606 static void
607 smb_dcache_flush(void)
609 smb_domain_t *di;
611 (void) rw_wrlock(&smb_dcache.dc_cache_lck);
612 while ((di = list_head(&smb_dcache.dc_cache)) != NULL)
613 smb_dcache_remove(di);
614 (void) rw_unlock(&smb_dcache.dc_cache_lck);
618 * Destroys the cache.
620 static void
621 smb_dcache_destroy(void)
623 (void) mutex_lock(&smb_dcache.dc_mtx);
624 if ((smb_dcache.dc_state == SMB_DCACHE_STATE_READY) ||
625 (smb_dcache.dc_state == SMB_DCACHE_STATE_UPDATING)) {
626 smb_dcache.dc_state = SMB_DCACHE_STATE_DESTROYING;
627 while (smb_dcache.dc_nops > 0)
628 (void) cond_wait(&smb_dcache.dc_cv,
629 &smb_dcache.dc_mtx);
631 smb_dcache_flush();
632 list_destroy(&smb_dcache.dc_cache);
634 smb_dcache.dc_state = SMB_DCACHE_STATE_NONE;
636 (void) mutex_unlock(&smb_dcache.dc_mtx);
640 * Lock the cache with the specified mode.
641 * If the cache is in updating state and a read lock is
642 * requested, the lock won't be granted until either the
643 * update is finished or SMB_DCACHE_UPDATE_WAIT has passed.
645 * Whenever a lock is granted, the number of inflight cache
646 * operations is incremented.
648 static uint32_t
649 smb_dcache_lock(int mode)
651 (void) mutex_lock(&smb_dcache.dc_mtx);
652 switch (smb_dcache.dc_state) {
653 case SMB_DCACHE_STATE_NONE:
654 case SMB_DCACHE_STATE_DESTROYING:
655 (void) mutex_unlock(&smb_dcache.dc_mtx);
656 return (SMB_DOMAIN_INTERNAL_ERR);
658 case SMB_DCACHE_STATE_UPDATING:
659 if (mode == SMB_DCACHE_RDLOCK) {
661 * Read operations should wait until the update
662 * is completed.
664 if (!smb_dcache_wait()) {
665 (void) mutex_unlock(&smb_dcache.dc_mtx);
666 return (SMB_DOMAIN_INTERNAL_ERR);
670 default:
671 smb_dcache.dc_nops++;
672 break;
674 (void) mutex_unlock(&smb_dcache.dc_mtx);
677 * Lock has to be taken outside the mutex otherwise
678 * there could be a deadlock
680 if (mode == SMB_DCACHE_RDLOCK)
681 (void) rw_rdlock(&smb_dcache.dc_cache_lck);
682 else
683 (void) rw_wrlock(&smb_dcache.dc_cache_lck);
685 return (SMB_DOMAIN_SUCCESS);
689 * Decrement the number of inflight operations and then unlock.
691 static void
692 smb_dcache_unlock(void)
694 (void) mutex_lock(&smb_dcache.dc_mtx);
695 assert(smb_dcache.dc_nops > 0);
696 smb_dcache.dc_nops--;
697 (void) cond_broadcast(&smb_dcache.dc_cv);
698 (void) mutex_unlock(&smb_dcache.dc_mtx);
700 (void) rw_unlock(&smb_dcache.dc_cache_lck);
703 static uint32_t
704 smb_dcache_add(smb_domain_t *di)
706 smb_domain_t *dcnode;
708 if ((dcnode = malloc(sizeof (smb_domain_t))) == NULL)
709 return (SMB_DOMAIN_NO_MEMORY);
711 *dcnode = *di;
712 dcnode->di_binsid = smb_sid_fromstr(dcnode->di_sid);
713 if (dcnode->di_binsid == NULL) {
714 free(dcnode);
715 return (SMB_DOMAIN_NO_MEMORY);
718 list_insert_tail(&smb_dcache.dc_cache, dcnode);
719 return (SMB_DOMAIN_SUCCESS);
722 static void
723 smb_dcache_remove(smb_domain_t *di)
725 list_remove(&smb_dcache.dc_cache, di);
726 smb_sid_free(di->di_binsid);
727 free(di);
730 static void
731 smb_dcache_setdc(const smb_dcinfo_t *dci)
733 (void) mutex_lock(&smb_dcache.dc_mtx);
734 smb_dcache.dc_dci = *dci; /* struct assignment! */
735 (void) mutex_unlock(&smb_dcache.dc_mtx);
739 * Return B_TRUE if we have DC information.
741 static boolean_t
742 smb_dcache_getdc(smb_dcinfo_t *dci)
744 (void) mutex_lock(&smb_dcache.dc_mtx);
745 *dci = smb_dcache.dc_dci; /* struct assignment! */
746 (void) mutex_unlock(&smb_dcache.dc_mtx);
747 return (dci->dc_name[0] != '\0');
751 * Waits for SMB_DCACHE_UPDATE_WAIT seconds if cache is in
752 * UPDATING state. Upon wake up returns true if cache is
753 * ready to be used, otherwise it returns false.
755 static boolean_t
756 smb_dcache_wait(void)
758 timestruc_t to;
759 int err;
761 to.tv_sec = SMB_DCACHE_UPDATE_WAIT;
762 to.tv_nsec = 0;
763 while (smb_dcache.dc_state == SMB_DCACHE_STATE_UPDATING) {
764 err = cond_reltimedwait(&smb_dcache.dc_cv,
765 &smb_dcache.dc_mtx, &to);
766 if (err == ETIME)
767 break;
770 return (smb_dcache.dc_state == SMB_DCACHE_STATE_READY);
774 * Transfers the cache into UPDATING state, this will ensure
775 * any read access to the cache will be stalled until the
776 * update is finished. This is to avoid providing incomplete,
777 * inconsistent or stale information.
779 * If another thread is already updating the cache, other
780 * callers will wait until cache is no longer in UPDATING
781 * state. The return code is decided based on the new
782 * state of the cache.
784 static uint32_t
785 smb_dcache_updating(void)
787 uint32_t rc;
789 (void) mutex_lock(&smb_dcache.dc_mtx);
790 switch (smb_dcache.dc_state) {
791 case SMB_DCACHE_STATE_READY:
792 smb_dcache.dc_state = SMB_DCACHE_STATE_UPDATING;
793 rc = SMB_DOMAIN_SUCCESS;
794 break;
796 case SMB_DCACHE_STATE_UPDATING:
797 while (smb_dcache.dc_state == SMB_DCACHE_STATE_UPDATING)
798 (void) cond_wait(&smb_dcache.dc_cv,
799 &smb_dcache.dc_mtx);
801 if (smb_dcache.dc_state == SMB_DCACHE_STATE_READY) {
802 smb_dcache.dc_state = SMB_DCACHE_STATE_UPDATING;
803 rc = SMB_DOMAIN_SUCCESS;
804 } else {
805 rc = SMB_DOMAIN_NO_CACHE;
807 break;
809 case SMB_DCACHE_STATE_NONE:
810 case SMB_DCACHE_STATE_DESTROYING:
811 rc = SMB_DOMAIN_NO_CACHE;
812 break;
814 default:
815 break;
818 (void) mutex_unlock(&smb_dcache.dc_mtx);
819 return (rc);
823 * Transfers the cache from UPDATING to READY state.
825 * Nothing will happen if the cache is no longer available
826 * or it is being destroyed.
828 static void
829 smb_dcache_ready(void)
831 (void) mutex_lock(&smb_dcache.dc_mtx);
832 switch (smb_dcache.dc_state) {
833 case SMB_DCACHE_STATE_UPDATING:
834 smb_dcache.dc_state = SMB_DCACHE_STATE_READY;
835 (void) cond_broadcast(&smb_dcache.dc_cv);
836 break;
838 case SMB_DCACHE_STATE_NONE:
839 case SMB_DCACHE_STATE_DESTROYING:
840 break;
842 default:
843 assert(0);
845 (void) mutex_unlock(&smb_dcache.dc_mtx);