Print this page
NEX-15558 SMB logon fails during 1st second after service start
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-15558 SMB logon fails during 1st second after service start
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-2225 Unable to join NexentaStor to 2008 AD
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/lib/smbsrv/libsmb/common/smb_domain.c
+++ new/usr/src/lib/smbsrv/libsmb/common/smb_domain.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 *
25 - * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
25 + * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
26 26 */
27 27
28 28 /*
29 29 * This file defines the domain environment values and the domain
30 30 * database interface. The database is a single linked list of
31 31 * structures containing domain type, name and SID information.
32 32 */
33 33
34 34 #include <sys/types.h>
35 35 #include <sys/stat.h>
36 36 #include <sys/list.h>
37 37 #include <stdio.h>
38 38 #include <strings.h>
39 39 #include <string.h>
40 +#include <syslog.h>
40 41 #include <unistd.h>
41 42 #include <stdlib.h>
42 43 #include <synch.h>
43 44 #include <pwd.h>
44 45 #include <grp.h>
45 46 #include <assert.h>
46 47
47 48 #include <smbsrv/smbinfo.h>
48 49 #include <smbsrv/string.h>
49 50 #include <smbsrv/smb_sid.h>
50 51 #include <smbsrv/libsmb.h>
51 52
52 53 #define SMB_DOMAINS_FILE "domains"
53 54
54 55 #define SMB_DCACHE_UPDATE_WAIT 45 /* seconds */
55 56
56 57 /*
57 58 * Domain cache states
58 59 */
59 60 #define SMB_DCACHE_STATE_NONE 0
60 61 #define SMB_DCACHE_STATE_READY 1
61 62 #define SMB_DCACHE_STATE_UPDATING 2
62 63 #define SMB_DCACHE_STATE_DESTROYING 3
|
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
63 64
64 65 /*
65 66 * Cache lock modes
66 67 */
67 68 #define SMB_DCACHE_RDLOCK 0
68 69 #define SMB_DCACHE_WRLOCK 1
69 70
70 71 typedef struct smb_domain_cache {
71 72 list_t dc_cache;
72 73 rwlock_t dc_cache_lck;
73 - mutex_t dc_mtx;
74 - cond_t dc_cv;
75 74 uint32_t dc_state;
76 75 uint32_t dc_nops;
76 + mutex_t dc_mtx;
77 + cond_t dc_cv;
78 + /* domain controller information */
79 + cond_t dc_dci_cv;
80 + boolean_t dc_dci_valid;
77 81 smb_dcinfo_t dc_dci;
78 82 } smb_domain_cache_t;
79 83
80 84 static smb_domain_cache_t smb_dcache;
81 85
82 86 static uint32_t smb_domain_add(smb_domain_type_t, smb_domain_t *);
83 87 static uint32_t smb_domain_add_local(void);
84 88 static uint32_t smb_domain_add_primary(uint32_t);
85 89 static void smb_domain_unlink(void);
86 90
87 91 static void smb_dcache_create(void);
88 92 static void smb_dcache_destroy(void);
89 93 static uint32_t smb_dcache_lock(int);
90 94 static void smb_dcache_unlock(void);
91 95 static void smb_dcache_remove(smb_domain_t *);
92 96 static uint32_t smb_dcache_add(smb_domain_t *);
93 -static boolean_t smb_dcache_getdc(smb_dcinfo_t *);
97 +static boolean_t smb_dcache_getdc(smb_dcinfo_t *, boolean_t);
94 98 static void smb_dcache_setdc(const smb_dcinfo_t *);
95 99 static boolean_t smb_dcache_wait(void);
96 100 static uint32_t smb_dcache_updating(void);
97 101 static void smb_dcache_ready(void);
98 102
99 103 /*
100 104 * domain cache one time initialization. This function should
101 105 * only be called during service startup.
102 106 *
103 107 * Returns 0 on success and an error code on failure.
104 108 */
105 109 int
|
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
106 110 smb_domain_init(uint32_t secmode)
107 111 {
108 112 smb_domain_t di;
109 113 int rc;
110 114
111 115 smb_dcache_create();
112 116
113 117 if ((rc = smb_domain_add_local()) != 0)
114 118 return (rc);
115 119
120 + bzero(&di, sizeof (di));
116 121 smb_domain_set_basic_info(NT_BUILTIN_DOMAIN_SIDSTR, "BUILTIN", "", &di);
117 122 (void) smb_domain_add(SMB_DOMAIN_BUILTIN, &di);
118 123
119 124 return (smb_domain_add_primary(secmode));
120 125 }
121 126
122 127 /*
123 128 * Destroys the cache upon service termination
124 129 */
125 130 void
126 131 smb_domain_fini(void)
127 132 {
128 133 smb_dcache_destroy();
129 134 smb_domain_unlink();
130 135 }
131 136
132 137 /*
133 138 * Add a domain structure to domain cache. There is no checking
134 139 * for duplicates.
135 140 */
136 141 static uint32_t
137 142 smb_domain_add(smb_domain_type_t type, smb_domain_t *di)
138 143 {
139 144 uint32_t res;
140 145
141 146 if ((di == NULL) || (di->di_sid == NULL))
142 147 return (SMB_DOMAIN_INVALID_ARG);
143 148
144 149 if ((res = smb_dcache_lock(SMB_DCACHE_WRLOCK)) == SMB_DOMAIN_SUCCESS) {
145 150 di->di_type = type;
146 151 res = smb_dcache_add(di);
147 152 smb_dcache_unlock();
148 153 }
149 154
150 155 return (res);
151 156 }
152 157
153 158 /*
154 159 * Lookup a domain by its name. The passed name is the NETBIOS or fully
155 160 * qualified DNS name or non-qualified DNS name.
156 161 *
157 162 * If the requested domain is found and given 'di' pointer is not NULL
158 163 * it'll be filled with the domain information and B_TRUE is returned.
159 164 * If the caller only needs to check a domain existence it can pass
160 165 * NULL for 'di' and just check the return value.
161 166 *
162 167 * If the domain is not in the cache B_FALSE is returned.
163 168 */
164 169 boolean_t
165 170 smb_domain_lookup_name(char *name, smb_domain_t *di)
166 171 {
167 172 boolean_t found = B_FALSE;
168 173 smb_domain_t *dcnode;
169 174 char *p;
170 175
171 176 bzero(di, sizeof (smb_domain_t));
172 177
173 178 if (name == NULL || *name == '\0')
174 179 return (B_FALSE);
175 180
176 181 if (smb_dcache_lock(SMB_DCACHE_RDLOCK) != SMB_DOMAIN_SUCCESS)
177 182 return (B_FALSE);
178 183
179 184 dcnode = list_head(&smb_dcache.dc_cache);
180 185 while (dcnode) {
181 186 found = (smb_strcasecmp(dcnode->di_nbname, name, 0) == 0) ||
182 187 (smb_strcasecmp(dcnode->di_fqname, name, 0) == 0);
183 188
184 189 if (found) {
185 190 if (di)
186 191 *di = *dcnode;
187 192 break;
188 193 }
189 194
190 195 if ((p = strchr(dcnode->di_fqname, '.')) != NULL) {
191 196 *p = '\0';
192 197 found = (smb_strcasecmp(dcnode->di_fqname, name,
193 198 0) == 0);
194 199 *p = '.';
195 200 if (found) {
196 201 if (di)
197 202 *di = *dcnode;
198 203 break;
199 204 }
200 205 }
201 206
202 207 dcnode = list_next(&smb_dcache.dc_cache, dcnode);
203 208 }
204 209
205 210 smb_dcache_unlock();
206 211 return (found);
207 212 }
208 213
209 214 /*
210 215 * Lookup a domain by its SID.
211 216 *
212 217 * If the requested domain is found and given 'di' pointer is not NULL
213 218 * it'll be filled with the domain information and B_TRUE is returned.
214 219 * If the caller only needs to check a domain existence it can pass
215 220 * NULL for 'di' and just check the return value.
216 221 *
217 222 * If the domain is not in the cache B_FALSE is returned.
218 223 */
219 224 boolean_t
220 225 smb_domain_lookup_sid(smb_sid_t *sid, smb_domain_t *di)
221 226 {
222 227 boolean_t found = B_FALSE;
223 228 smb_domain_t *dcnode;
224 229 char sidstr[SMB_SID_STRSZ];
225 230
226 231 bzero(di, sizeof (smb_domain_t));
227 232
228 233 if (sid == NULL)
229 234 return (B_FALSE);
230 235
231 236 smb_sid_tostr(sid, sidstr);
232 237
233 238 if (smb_dcache_lock(SMB_DCACHE_RDLOCK) != SMB_DOMAIN_SUCCESS)
234 239 return (B_FALSE);
235 240
236 241 dcnode = list_head(&smb_dcache.dc_cache);
237 242 while (dcnode) {
238 243 found = (strcmp(dcnode->di_sid, sidstr) == 0);
239 244 if (found) {
240 245 if (di)
241 246 *di = *dcnode;
242 247 break;
243 248 }
244 249
245 250 dcnode = list_next(&smb_dcache.dc_cache, dcnode);
246 251 }
247 252
248 253 smb_dcache_unlock();
249 254 return (found);
250 255 }
251 256
252 257 /*
253 258 * Lookup a domain by its type.
254 259 *
255 260 * If the requested domain is found and given 'di' pointer is not NULL
256 261 * it'll be filled with the domain information and B_TRUE is returned.
257 262 * If the caller only needs to check a domain existence it can pass
258 263 * NULL for 'di' and just check the return value.
259 264 *
260 265 * If the domain is not in the cache B_FALSE is returned.
261 266 */
262 267 boolean_t
263 268 smb_domain_lookup_type(smb_domain_type_t type, smb_domain_t *di)
264 269 {
265 270 boolean_t found = B_FALSE;
266 271 smb_domain_t *dcnode;
267 272
268 273 bzero(di, sizeof (smb_domain_t));
269 274
270 275 if (smb_dcache_lock(SMB_DCACHE_RDLOCK) != SMB_DOMAIN_SUCCESS)
271 276 return (B_FALSE);
272 277
273 278 dcnode = list_head(&smb_dcache.dc_cache);
274 279 while (dcnode) {
275 280 if (dcnode->di_type == type) {
276 281 found = B_TRUE;
277 282 if (di)
278 283 *di = *dcnode;
279 284 break;
280 285 }
281 286
|
↓ open down ↓ |
156 lines elided |
↑ open up ↑ |
282 287 dcnode = list_next(&smb_dcache.dc_cache, dcnode);
283 288 }
284 289
285 290 smb_dcache_unlock();
286 291 return (found);
287 292 }
288 293
289 294 /*
290 295 * Returns primary domain information plus the name of
291 296 * the selected domain controller.
297 + *
298 + * Returns TRUE on success.
292 299 */
293 300 boolean_t
294 301 smb_domain_getinfo(smb_domainex_t *dxi)
295 302 {
296 303 boolean_t rv;
297 304
298 305 /* Note: this waits for the dcache lock. */
299 306 rv = smb_domain_lookup_type(SMB_DOMAIN_PRIMARY, &dxi->d_primary);
300 - if (rv)
301 - rv = smb_dcache_getdc(&dxi->d_dci);
307 + if (!rv) {
308 + syslog(LOG_ERR, "smb_domain_getinfo: no primary domain");
309 + return (B_FALSE);
310 + }
302 311
303 - return (rv);
312 + /*
313 + * The 2nd arg TRUE means this will wait for DC info.
314 + *
315 + * Note that we do NOT hold the dcache rwlock here
316 + * (not even as reader) because we already have what we
317 + * need from the dcache (our primary domain) and we don't
318 + * want to interfere with the DC locator which will take
319 + * the dcache lock as write to update the domain info.
320 + */
321 + rv = smb_dcache_getdc(&dxi->d_dci, B_TRUE);
322 + if (!rv) {
323 + syslog(LOG_ERR, "smb_domain_getinfo: no DC info");
324 + return (B_FALSE);
325 + }
326 +
327 + return (B_TRUE);
304 328 }
305 329
306 330 /*
307 331 * Get the name of the current DC (if any)
308 332 * Does NOT block.
309 333 */
310 334 void
311 335 smb_domain_current_dc(smb_dcinfo_t *dci)
312 336 {
313 - (void) smb_dcache_getdc(dci);
337 + (void) smb_dcache_getdc(dci, B_FALSE);
314 338 }
315 339
316 340 /*
317 341 * Transfer the cache to updating state.
318 342 * In this state any request for reading the cache would
319 343 * be blocked until the update is finished.
320 344 */
321 345 uint32_t
322 346 smb_domain_start_update(void)
323 347 {
324 348 return (smb_dcache_updating());
325 349 }
326 350
|
↓ open down ↓ |
3 lines elided |
↑ open up ↑ |
327 351 /*
328 352 * Transfer the cache from updating to ready state.
329 353 */
330 354 void
331 355 smb_domain_end_update(void)
332 356 {
333 357 smb_dcache_ready();
334 358 }
335 359
336 360 /*
361 + * Mark the current domain controller (DC) info invalid
362 + * until the DC locator call smb_domain_update().
363 + */
364 +void
365 +smb_domain_bad_dc(void)
366 +{
367 + (void) mutex_lock(&smb_dcache.dc_mtx);
368 + smb_dcache.dc_dci_valid = B_FALSE;
369 + (void) mutex_unlock(&smb_dcache.dc_mtx);
370 +}
371 +
372 +/*
337 373 * Updates the cache with given information for the primary
338 374 * domain, possible trusted domains and the selected domain
339 375 * controller.
340 376 *
341 377 * Before adding the new entries existing entries of type
342 378 * primary and trusted will be removed from cache.
343 379 */
344 380 void
345 381 smb_domain_update(smb_domainex_t *dxi)
346 382 {
347 383 smb_domain_t *dcnode;
348 384 int i;
349 385
350 386 if (smb_dcache_lock(SMB_DCACHE_WRLOCK) != SMB_DOMAIN_SUCCESS)
351 387 return;
352 388
353 389 dcnode = list_head(&smb_dcache.dc_cache);
354 390 while (dcnode) {
355 391 if ((dcnode->di_type == SMB_DOMAIN_PRIMARY) ||
356 392 (dcnode->di_type == SMB_DOMAIN_TRUSTED)) {
357 393 smb_dcache_remove(dcnode);
358 394 dcnode = list_head(&smb_dcache.dc_cache);
359 395 } else {
360 396 dcnode = list_next(&smb_dcache.dc_cache, dcnode);
361 397 }
362 398 }
363 399
364 400 if (smb_dcache_add(&dxi->d_primary) == SMB_DOMAIN_SUCCESS) {
365 401 for (i = 0; i < dxi->d_trusted.td_num; i++)
366 402 (void) smb_dcache_add(&dxi->d_trusted.td_domains[i]);
367 403
368 404 smb_dcache_setdc(&dxi->d_dci);
369 405 }
370 406
371 407 smb_dcache_unlock();
372 408 }
373 409
374 410 /*
375 411 * Write the list of domains to /var/run/smb/domains.
376 412 */
377 413 void
378 414 smb_domain_save(void)
379 415 {
380 416 char fname[MAXPATHLEN];
381 417 char tag;
382 418 smb_domain_t *domain;
383 419 FILE *fp;
384 420 struct passwd *pwd;
385 421 struct group *grp;
386 422 uid_t uid;
387 423 gid_t gid;
388 424
389 425 (void) snprintf(fname, MAXPATHLEN, "%s/%s",
390 426 SMB_VARRUN_DIR, SMB_DOMAINS_FILE);
391 427
392 428 if ((fp = fopen(fname, "w")) == NULL)
393 429 return;
394 430
395 431 pwd = getpwnam("root");
396 432 grp = getgrnam("sys");
397 433 uid = (pwd == NULL) ? 0 : pwd->pw_uid;
398 434 gid = (grp == NULL) ? 3 : grp->gr_gid;
399 435
400 436 (void) lockf(fileno(fp), F_LOCK, 0);
401 437 (void) fchmod(fileno(fp), 0600);
402 438 (void) fchown(fileno(fp), uid, gid);
403 439
404 440 if (smb_dcache_lock(SMB_DCACHE_RDLOCK) != SMB_DOMAIN_SUCCESS)
405 441 return;
406 442
407 443 domain = list_head(&smb_dcache.dc_cache);
408 444 while (domain) {
409 445 switch (domain->di_type) {
410 446 case SMB_DOMAIN_PRIMARY:
411 447 tag = '*';
412 448 break;
413 449
414 450 case SMB_DOMAIN_TRUSTED:
415 451 case SMB_DOMAIN_UNTRUSTED:
416 452 tag = '-';
417 453 break;
418 454
419 455 case SMB_DOMAIN_LOCAL:
420 456 tag = '.';
421 457 break;
422 458 default:
423 459 domain = list_next(&smb_dcache.dc_cache, domain);
424 460 continue;
425 461 }
426 462
427 463 (void) fprintf(fp, "[%c] [%s] [%s]\n",
428 464 tag, domain->di_nbname, domain->di_sid);
429 465
430 466 domain = list_next(&smb_dcache.dc_cache, domain);
431 467 }
432 468
433 469 smb_dcache_unlock();
434 470 (void) lockf(fileno(fp), F_ULOCK, 0);
435 471 (void) fclose(fp);
436 472 }
437 473
438 474 /*
439 475 * List the domains in /var/run/smb/domains.
440 476 */
441 477 void
442 478 smb_domain_show(void)
443 479 {
444 480 char buf[MAXPATHLEN];
445 481 char *p;
446 482 FILE *fp;
447 483
448 484 (void) snprintf(buf, MAXPATHLEN, "%s/%s",
449 485 SMB_VARRUN_DIR, SMB_DOMAINS_FILE);
450 486
451 487 if ((fp = fopen(buf, "r")) != NULL) {
452 488 (void) lockf(fileno(fp), F_LOCK, 0);
453 489
454 490 while (fgets(buf, MAXPATHLEN, fp) != NULL) {
455 491 if ((p = strchr(buf, '\n')) != NULL)
456 492 *p = '\0';
457 493 (void) printf("%s\n", buf);
458 494 }
459 495
460 496 (void) lockf(fileno(fp), F_ULOCK, 0);
461 497 (void) fclose(fp);
462 498 }
463 499 }
464 500
465 501 void
466 502 smb_domain_set_basic_info(char *sid, char *nb_domain, char *fq_domain,
467 503 smb_domain_t *di)
468 504 {
469 505 if (sid == NULL || nb_domain == NULL || fq_domain == NULL ||
470 506 di == NULL)
471 507 return;
472 508
473 509 (void) strlcpy(di->di_sid, sid, SMB_SID_STRSZ);
474 510 (void) strlcpy(di->di_nbname, nb_domain, NETBIOS_NAME_SZ);
475 511 (void) smb_strupr(di->di_nbname);
476 512 (void) strlcpy(di->di_fqname, fq_domain, MAXHOSTNAMELEN);
|
↓ open down ↓ |
130 lines elided |
↑ open up ↑ |
477 513 di->di_binsid = NULL;
478 514 }
479 515
480 516 void
481 517 smb_domain_set_dns_info(char *sid, char *nb_domain, char *fq_domain,
482 518 char *forest, char *guid, smb_domain_t *di)
483 519 {
484 520 if (di == NULL || forest == NULL || guid == NULL)
485 521 return;
486 522
523 + /* Caller zeros out *di before this. */
487 524 smb_domain_set_basic_info(sid, nb_domain, fq_domain, di);
488 525 (void) strlcpy(di->di_u.di_dns.ddi_forest, forest, MAXHOSTNAMELEN);
489 526 (void) strlcpy(di->di_u.di_dns.ddi_guid, guid,
490 527 UUID_PRINTABLE_STRING_LENGTH);
491 528 }
492 529
493 530 void
494 531 smb_domain_set_trust_info(char *sid, char *nb_domain, char *fq_domain,
495 532 uint32_t trust_dir, uint32_t trust_type, uint32_t trust_attrs,
496 533 smb_domain_t *di)
497 534 {
498 535 smb_domain_trust_t *ti;
499 536
500 537 if (di == NULL)
501 538 return;
502 539
540 + /* Caller zeros out *di before this. */
503 541 di->di_type = SMB_DOMAIN_TRUSTED;
504 542 ti = &di->di_u.di_trust;
505 543 smb_domain_set_basic_info(sid, nb_domain, fq_domain, di);
506 544 ti->dti_trust_direction = trust_dir;
507 545 ti->dti_trust_type = trust_type;
508 546 ti->dti_trust_attrs = trust_attrs;
509 547 }
510 548
511 549 /*
512 550 * Remove the /var/run/smb/domains file.
513 551 */
514 552 static void
515 553 smb_domain_unlink(void)
516 554 {
517 555 char fname[MAXPATHLEN];
518 556
519 557 (void) snprintf(fname, MAXPATHLEN, "%s/%s",
520 558 SMB_VARRUN_DIR, SMB_DOMAINS_FILE);
521 559 (void) unlink(fname);
522 560 }
523 561
524 562 /*
525 563 * Add an entry for the local domain to the domain cache
526 564 */
527 565 static uint32_t
528 566 smb_domain_add_local(void)
529 567 {
530 568 char *lsidstr;
531 569 char hostname[NETBIOS_NAME_SZ];
532 570 char fq_name[MAXHOSTNAMELEN];
|
↓ open down ↓ |
20 lines elided |
↑ open up ↑ |
533 571 smb_domain_t di;
534 572
535 573 if ((lsidstr = smb_config_get_localsid()) == NULL)
536 574 return (SMB_DOMAIN_NOMACHINE_SID);
537 575
538 576 if (smb_getnetbiosname(hostname, NETBIOS_NAME_SZ) != 0) {
539 577 free(lsidstr);
540 578 return (SMB_DOMAIN_NOMACHINE_SID);
541 579 }
542 580
581 + bzero(&di, sizeof (di));
543 582 *fq_name = '\0';
544 583 (void) smb_getfqhostname(fq_name, MAXHOSTNAMELEN);
545 584 smb_domain_set_basic_info(lsidstr, hostname, fq_name, &di);
546 585 (void) smb_domain_add(SMB_DOMAIN_LOCAL, &di);
547 586
548 587 free(lsidstr);
549 588 return (SMB_DOMAIN_SUCCESS);
550 589 }
551 590
552 591 /*
553 592 * Add an entry for the primary domain to the domain cache
554 593 */
555 594 static uint32_t
556 595 smb_domain_add_primary(uint32_t secmode)
557 596 {
558 597 char sidstr[SMB_SID_STRSZ];
559 598 char fq_name[MAXHOSTNAMELEN];
560 599 char nb_name[NETBIOS_NAME_SZ];
561 600 smb_domain_t di;
562 601 int rc;
563 602
564 603 if (secmode != SMB_SECMODE_DOMAIN)
|
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
565 604 return (SMB_DOMAIN_SUCCESS);
566 605
567 606 rc = smb_config_getstr(SMB_CI_DOMAIN_SID, sidstr, sizeof (sidstr));
568 607 if (rc != SMBD_SMF_OK)
569 608 return (SMB_DOMAIN_NODOMAIN_SID);
570 609
571 610 rc = smb_config_getstr(SMB_CI_DOMAIN_NAME, nb_name, NETBIOS_NAME_SZ);
572 611 if ((rc != SMBD_SMF_OK) || (*nb_name == '\0'))
573 612 return (SMB_DOMAIN_NODOMAIN_NAME);
574 613
614 + bzero(&di, sizeof (di));
575 615 (void) smb_getfqdomainname(fq_name, MAXHOSTNAMELEN);
576 616 smb_domain_set_basic_info(sidstr, nb_name, fq_name, &di);
577 617 (void) smb_domain_add(SMB_DOMAIN_PRIMARY, &di);
578 618 return (SMB_DOMAIN_SUCCESS);
579 619 }
580 620
581 621 /*
582 622 * Initialize the domain cache.
583 623 * This function does not populate the cache.
584 624 */
585 625 static void
586 626 smb_dcache_create(void)
587 627 {
588 628 (void) mutex_lock(&smb_dcache.dc_mtx);
|
↓ open down ↓ |
4 lines elided |
↑ open up ↑ |
589 629 if (smb_dcache.dc_state != SMB_DCACHE_STATE_NONE) {
590 630 (void) mutex_unlock(&smb_dcache.dc_mtx);
591 631 return;
592 632 }
593 633
594 634 list_create(&smb_dcache.dc_cache, sizeof (smb_domain_t),
595 635 offsetof(smb_domain_t, di_lnd));
596 636
597 637 smb_dcache.dc_nops = 0;
598 638 bzero(&smb_dcache.dc_dci, sizeof (smb_dcache.dc_dci));
639 + smb_dcache.dc_dci_valid = B_FALSE;
599 640 smb_dcache.dc_state = SMB_DCACHE_STATE_READY;
600 641 (void) mutex_unlock(&smb_dcache.dc_mtx);
601 642 }
602 643
603 644 /*
604 645 * Removes and frees all the cache entries
605 646 */
606 647 static void
607 648 smb_dcache_flush(void)
608 649 {
609 650 smb_domain_t *di;
610 651
611 652 (void) rw_wrlock(&smb_dcache.dc_cache_lck);
612 653 while ((di = list_head(&smb_dcache.dc_cache)) != NULL)
613 654 smb_dcache_remove(di);
614 655 (void) rw_unlock(&smb_dcache.dc_cache_lck);
615 656 }
616 657
617 658 /*
618 659 * Destroys the cache.
619 660 */
620 661 static void
621 662 smb_dcache_destroy(void)
622 663 {
623 664 (void) mutex_lock(&smb_dcache.dc_mtx);
624 665 if ((smb_dcache.dc_state == SMB_DCACHE_STATE_READY) ||
625 666 (smb_dcache.dc_state == SMB_DCACHE_STATE_UPDATING)) {
626 667 smb_dcache.dc_state = SMB_DCACHE_STATE_DESTROYING;
627 668 while (smb_dcache.dc_nops > 0)
628 669 (void) cond_wait(&smb_dcache.dc_cv,
629 670 &smb_dcache.dc_mtx);
630 671
631 672 smb_dcache_flush();
632 673 list_destroy(&smb_dcache.dc_cache);
633 674
634 675 smb_dcache.dc_state = SMB_DCACHE_STATE_NONE;
635 676 }
636 677 (void) mutex_unlock(&smb_dcache.dc_mtx);
637 678 }
638 679
639 680 /*
640 681 * Lock the cache with the specified mode.
641 682 * If the cache is in updating state and a read lock is
642 683 * requested, the lock won't be granted until either the
643 684 * update is finished or SMB_DCACHE_UPDATE_WAIT has passed.
644 685 *
|
↓ open down ↓ |
36 lines elided |
↑ open up ↑ |
645 686 * Whenever a lock is granted, the number of inflight cache
646 687 * operations is incremented.
647 688 */
648 689 static uint32_t
649 690 smb_dcache_lock(int mode)
650 691 {
651 692 (void) mutex_lock(&smb_dcache.dc_mtx);
652 693 switch (smb_dcache.dc_state) {
653 694 case SMB_DCACHE_STATE_NONE:
654 695 case SMB_DCACHE_STATE_DESTROYING:
696 + default:
655 697 (void) mutex_unlock(&smb_dcache.dc_mtx);
656 698 return (SMB_DOMAIN_INTERNAL_ERR);
657 699
658 700 case SMB_DCACHE_STATE_UPDATING:
659 701 if (mode == SMB_DCACHE_RDLOCK) {
660 702 /*
661 703 * Read operations should wait until the update
662 704 * is completed.
663 705 */
664 706 if (!smb_dcache_wait()) {
665 707 (void) mutex_unlock(&smb_dcache.dc_mtx);
666 708 return (SMB_DOMAIN_INTERNAL_ERR);
667 709 }
668 710 }
711 + /* FALLTHROUGH */
669 712
670 - default:
713 + case SMB_DCACHE_STATE_READY:
671 714 smb_dcache.dc_nops++;
672 715 break;
673 716 }
674 717 (void) mutex_unlock(&smb_dcache.dc_mtx);
675 718
676 719 /*
677 720 * Lock has to be taken outside the mutex otherwise
678 721 * there could be a deadlock
679 722 */
680 723 if (mode == SMB_DCACHE_RDLOCK)
681 724 (void) rw_rdlock(&smb_dcache.dc_cache_lck);
682 725 else
683 726 (void) rw_wrlock(&smb_dcache.dc_cache_lck);
684 727
685 728 return (SMB_DOMAIN_SUCCESS);
686 729 }
687 730
688 731 /*
689 732 * Decrement the number of inflight operations and then unlock.
690 733 */
691 734 static void
692 735 smb_dcache_unlock(void)
693 736 {
694 737 (void) mutex_lock(&smb_dcache.dc_mtx);
695 738 assert(smb_dcache.dc_nops > 0);
696 739 smb_dcache.dc_nops--;
697 740 (void) cond_broadcast(&smb_dcache.dc_cv);
698 741 (void) mutex_unlock(&smb_dcache.dc_mtx);
699 742
700 743 (void) rw_unlock(&smb_dcache.dc_cache_lck);
701 744 }
702 745
703 746 static uint32_t
704 747 smb_dcache_add(smb_domain_t *di)
705 748 {
706 749 smb_domain_t *dcnode;
707 750
708 751 if ((dcnode = malloc(sizeof (smb_domain_t))) == NULL)
709 752 return (SMB_DOMAIN_NO_MEMORY);
710 753
711 754 *dcnode = *di;
712 755 dcnode->di_binsid = smb_sid_fromstr(dcnode->di_sid);
713 756 if (dcnode->di_binsid == NULL) {
714 757 free(dcnode);
715 758 return (SMB_DOMAIN_NO_MEMORY);
716 759 }
717 760
718 761 list_insert_tail(&smb_dcache.dc_cache, dcnode);
719 762 return (SMB_DOMAIN_SUCCESS);
720 763 }
721 764
722 765 static void
723 766 smb_dcache_remove(smb_domain_t *di)
724 767 {
|
↓ open down ↓ |
44 lines elided |
↑ open up ↑ |
725 768 list_remove(&smb_dcache.dc_cache, di);
726 769 smb_sid_free(di->di_binsid);
727 770 free(di);
728 771 }
729 772
730 773 static void
731 774 smb_dcache_setdc(const smb_dcinfo_t *dci)
732 775 {
733 776 (void) mutex_lock(&smb_dcache.dc_mtx);
734 777 smb_dcache.dc_dci = *dci; /* struct assignment! */
778 + smb_dcache.dc_dci_valid = B_TRUE;
779 + (void) cond_broadcast(&smb_dcache.dc_dci_cv);
735 780 (void) mutex_unlock(&smb_dcache.dc_mtx);
736 781 }
737 782
738 783 /*
739 - * Return B_TRUE if we have DC information.
784 + * Get information about our domain controller. If the wait arg
785 + * is true, wait for the DC locator to finish before copying.
786 + * Returns TRUE on success (have DC info).
740 787 */
741 788 static boolean_t
742 -smb_dcache_getdc(smb_dcinfo_t *dci)
789 +smb_dcache_getdc(smb_dcinfo_t *dci, boolean_t wait)
743 790 {
791 + timestruc_t to;
792 + boolean_t rv;
793 + int err;
794 +
795 + to.tv_sec = time(NULL) + SMB_DCACHE_UPDATE_WAIT;
796 + to.tv_nsec = 0;
797 +
744 798 (void) mutex_lock(&smb_dcache.dc_mtx);
799 +
800 + while (wait && !smb_dcache.dc_dci_valid) {
801 + err = cond_timedwait(&smb_dcache.dc_dci_cv,
802 + &smb_dcache.dc_mtx, &to);
803 + if (err == ETIME)
804 + break;
805 + }
745 806 *dci = smb_dcache.dc_dci; /* struct assignment! */
807 + rv = smb_dcache.dc_dci_valid;
808 +
746 809 (void) mutex_unlock(&smb_dcache.dc_mtx);
747 - return (dci->dc_name[0] != '\0');
810 +
811 + return (rv);
748 812 }
749 813
750 814 /*
751 815 * Waits for SMB_DCACHE_UPDATE_WAIT seconds if cache is in
752 816 * UPDATING state. Upon wake up returns true if cache is
753 817 * ready to be used, otherwise it returns false.
754 818 */
755 819 static boolean_t
756 820 smb_dcache_wait(void)
757 821 {
758 822 timestruc_t to;
759 823 int err;
760 824
761 - to.tv_sec = SMB_DCACHE_UPDATE_WAIT;
825 + assert(MUTEX_HELD(&smb_dcache.dc_mtx));
826 +
827 + to.tv_sec = time(NULL) + SMB_DCACHE_UPDATE_WAIT;
762 828 to.tv_nsec = 0;
763 829 while (smb_dcache.dc_state == SMB_DCACHE_STATE_UPDATING) {
764 - err = cond_reltimedwait(&smb_dcache.dc_cv,
830 + err = cond_timedwait(&smb_dcache.dc_cv,
765 831 &smb_dcache.dc_mtx, &to);
766 832 if (err == ETIME)
767 833 break;
768 834 }
769 835
770 836 return (smb_dcache.dc_state == SMB_DCACHE_STATE_READY);
771 837 }
772 838
773 839 /*
774 840 * Transfers the cache into UPDATING state, this will ensure
775 841 * any read access to the cache will be stalled until the
776 842 * update is finished. This is to avoid providing incomplete,
777 843 * inconsistent or stale information.
778 844 *
779 845 * If another thread is already updating the cache, other
780 846 * callers will wait until cache is no longer in UPDATING
781 847 * state. The return code is decided based on the new
782 848 * state of the cache.
783 849 */
784 850 static uint32_t
785 851 smb_dcache_updating(void)
786 852 {
787 853 uint32_t rc;
788 854
789 855 (void) mutex_lock(&smb_dcache.dc_mtx);
790 856 switch (smb_dcache.dc_state) {
791 857 case SMB_DCACHE_STATE_READY:
792 858 smb_dcache.dc_state = SMB_DCACHE_STATE_UPDATING;
793 859 rc = SMB_DOMAIN_SUCCESS;
794 860 break;
795 861
796 862 case SMB_DCACHE_STATE_UPDATING:
797 863 while (smb_dcache.dc_state == SMB_DCACHE_STATE_UPDATING)
798 864 (void) cond_wait(&smb_dcache.dc_cv,
799 865 &smb_dcache.dc_mtx);
800 866
801 867 if (smb_dcache.dc_state == SMB_DCACHE_STATE_READY) {
802 868 smb_dcache.dc_state = SMB_DCACHE_STATE_UPDATING;
803 869 rc = SMB_DOMAIN_SUCCESS;
804 870 } else {
805 871 rc = SMB_DOMAIN_NO_CACHE;
806 872 }
807 873 break;
808 874
809 875 case SMB_DCACHE_STATE_NONE:
810 876 case SMB_DCACHE_STATE_DESTROYING:
811 877 rc = SMB_DOMAIN_NO_CACHE;
812 878 break;
813 879
814 880 default:
815 881 break;
816 882 }
817 883
818 884 (void) mutex_unlock(&smb_dcache.dc_mtx);
819 885 return (rc);
820 886 }
821 887
822 888 /*
823 889 * Transfers the cache from UPDATING to READY state.
824 890 *
825 891 * Nothing will happen if the cache is no longer available
826 892 * or it is being destroyed.
827 893 */
828 894 static void
829 895 smb_dcache_ready(void)
830 896 {
831 897 (void) mutex_lock(&smb_dcache.dc_mtx);
832 898 switch (smb_dcache.dc_state) {
833 899 case SMB_DCACHE_STATE_UPDATING:
834 900 smb_dcache.dc_state = SMB_DCACHE_STATE_READY;
835 901 (void) cond_broadcast(&smb_dcache.dc_cv);
836 902 break;
837 903
838 904 case SMB_DCACHE_STATE_NONE:
839 905 case SMB_DCACHE_STATE_DESTROYING:
840 906 break;
841 907
842 908 default:
843 909 assert(0);
844 910 }
845 911 (void) mutex_unlock(&smb_dcache.dc_mtx);
846 912 }
|
↓ open down ↓ |
72 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX