1 /* 2 * CDDL HEADER START 3 * 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. 7 * 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. 12 * 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] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <nss_common.h> 29 #include <dlfcn.h> 30 #include <alloca.h> 31 32 #include <stdlib.h> 33 #include <libscf_priv.h> 34 #include <string.h> 35 #include <assert.h> 36 #include "nscd_switch.h" 37 #include "nscd_log.h" 38 #include "nscd_db.h" 39 40 /* 41 * _nscd_nss_finders is used to replace the nss_default_finders in libc 42 * to allow nscd to have more control over the dl handles when using 43 * dlsym to get the address of the nss backend instance constructors 44 */ 45 static nss_backend_constr_t _nscd_per_src_lookup(void *, 46 const char *, const char *, void **); 47 static void _nscd_per_src_delete(void *, nss_backend_constr_t); 48 49 static nss_backend_finder_t _nscd_per_src = { 50 _nscd_per_src_lookup, 51 _nscd_per_src_delete, 52 0, 53 0 }; 54 55 nss_backend_finder_t *_nscd_nss_finders = &_nscd_per_src; 56 57 /* 58 * nscd database for each source. It contains backend 59 * info (nscd_be_info_t) for each naming database. 60 * Protected by nscd_src_backend_db_lock. 61 */ 62 nscd_db_t ***nscd_src_backend_db; 63 int *nscd_src_backend_db_loaded; 64 static rwlock_t nscd_src_backend_db_lock = DEFAULTRWLOCK; 65 66 /* 67 * nsswitch config monitored by nscd. Protected by 68 * readers/writer lock nscd_nsw_config_lock 69 */ 70 nscd_nsw_config_t ***nscd_nsw_config; 71 static rwlock_t nscd_nsw_config_lock = DEFAULTRWLOCK; 72 73 /* 74 * nsswitch source index/name array 75 * (allow 16 user-defined nsswitch sources/backends) 76 */ 77 #define NSCD_NUM_SRC_UDEF 16 78 nscd_cfg_id_t *_nscd_cfg_nsw_src_all; 79 int _nscd_cfg_num_nsw_src_all; 80 81 static void 82 free_nscd_nsw_config( 83 nscd_acc_data_t *data) 84 { 85 86 nscd_nsw_config_t *nsw_cfg = *(nscd_nsw_config_t **)data; 87 char *me = "free_nscd_nsw_config"; 88 89 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 90 (me, "freeing nscd nsw config %p \n", nsw_cfg); 91 if (nsw_cfg == NULL) 92 return; 93 94 if (nsw_cfg->db_name != NULL) 95 free(nsw_cfg->db_name); 96 if (nsw_cfg->nsw_cfg_str != NULL) 97 free(nsw_cfg->nsw_cfg_str); 98 if (nsw_cfg->nsw_config != NULL) 99 (void) __nsw_freeconfig_v1(nsw_cfg->nsw_config); 100 if (nsw_cfg->src_idx != NULL) 101 free(nsw_cfg->src_idx); 102 103 free(nsw_cfg); 104 } 105 106 107 void 108 _nscd_free_nsw_config( 109 nscd_nsw_config_t *nswcfg) 110 { 111 free_nscd_nsw_config((nscd_acc_data_t *)&nswcfg); 112 } 113 114 void 115 _nscd_free_all_nsw_config() 116 { 117 118 nscd_nsw_config_t **nsw_cfg; 119 int i; 120 char *me = "_nscd_free_all_nsw_config"; 121 122 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 123 (me, "freeing all nscd nsw config \n"); 124 125 (void) rw_wrlock(&nscd_nsw_config_lock); 126 for (i = 0; i < NSCD_NUM_DB; i++) { 127 128 if ((nsw_cfg = nscd_nsw_config[i]) == NULL) 129 continue; 130 131 nscd_nsw_config[i] = (nscd_nsw_config_t **)_nscd_set( 132 (nscd_acc_data_t *)nsw_cfg, NULL); 133 } 134 (void) rw_unlock(&nscd_nsw_config_lock); 135 } 136 137 138 static void 139 free_nsw_backend_info_db(nscd_acc_data_t *data) 140 { 141 142 nscd_db_t *db = *(nscd_db_t **)data; 143 char *me = "free_nsw_backend_info_db"; 144 145 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 146 (me, "freeing nsw backend info db %p\n", db); 147 148 if (db == NULL) 149 return; 150 151 _nscd_free_db(db); 152 153 } 154 155 void 156 _nscd_free_all_nsw_backend_info_db() 157 { 158 159 nscd_db_t **db; 160 int i; 161 char *me = " _nscd_free_all_nsw_backend_info_db"; 162 163 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 164 (me, "freeing all nsw backend info db\n"); 165 166 (void) rw_wrlock(&nscd_src_backend_db_lock); 167 for (i = 0; i < NSCD_NUM_SRC; i++) { 168 169 if ((db = nscd_src_backend_db[i]) == NULL) 170 continue; 171 172 nscd_src_backend_db[i] = (nscd_db_t **)_nscd_set( 173 (nscd_acc_data_t *)db, NULL); 174 nscd_src_backend_db_loaded[i] = 0; 175 } 176 (void) rw_unlock(&nscd_src_backend_db_lock); 177 } 178 179 /* 180 * Populate the backend info db for the 'NSCD_NSW_SRC_NAME(srci)' 181 * source. Create one entry for each source/database pair 182 * (e.g., ldap:passwd, nis:hosts, etc). 183 */ 184 static nscd_rc_t 185 _nscd_populate_nsw_backend_info_db(int srci) 186 { 187 nscd_be_info_t be_info, *bi; 188 nss_backend_finder_t *bf; 189 nscd_nsw_config_t *nsw_cfg; 190 int i, size; 191 nscd_db_entry_t *db_entry; 192 char *src = NSCD_NSW_SRC_NAME(srci); 193 const char *dbn; 194 char *me = "_nscd_populate_nsw_backend_info_db"; 195 void *handle = NULL; 196 197 for (i = 0; i < NSCD_NUM_DB; i++) { 198 199 if (nscd_nsw_config[i] == NULL) 200 continue; 201 202 nsw_cfg = *nscd_nsw_config[i]; 203 dbn = NSCD_NSW_DB_NAME(i); 204 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 205 (me, "adding backend info for <%s : %s>\n", src, dbn); 206 207 (void) memset(&be_info, 0, sizeof (be_info)); 208 209 for (bf = nsw_cfg->fe_params.finders; bf != 0; 210 bf = bf->next) { 211 nss_backend_constr_t c; 212 213 c = (*bf->lookup)(handle, dbn, src, &handle); 214 215 if (c != 0) { 216 be_info.be_constr = c; 217 be_info.finder = bf; 218 be_info.finder_priv = handle; 219 break; 220 } 221 } 222 if (be_info.be_constr == NULL) { 223 /* 224 * Couldn't find the backend anywhere. 225 * This is fine, some backend just don't 226 * support certain databases. 227 */ 228 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 229 (me, "unable to find backend info " 230 "for <%s : %s>\n", src, dbn); 231 } 232 233 size = sizeof (nscd_be_info_t); 234 235 db_entry = _nscd_alloc_db_entry(NSCD_DATA_BACKEND_INFO, 236 dbn, size, 1, 1); 237 238 if (db_entry == NULL) { 239 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 240 (me, "unable to allocate db entry for " 241 "<%s : %s>\n", src, dbn); 242 return (NSCD_NO_MEMORY); 243 } 244 245 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 246 (me, "adding be db entry %p for <%s : %s> to db %p: " 247 "constr = %p\n", db_entry, src, dbn, 248 *nscd_src_backend_db[srci], be_info.be_constr); 249 250 bi = (nscd_be_info_t *)*(db_entry->data_array); 251 *bi = be_info; 252 253 (void) _nscd_wrlock((nscd_acc_data_t *) 254 nscd_src_backend_db[srci]); 255 nscd_src_backend_db_loaded[srci] = 1; 256 (void) _nscd_add_db_entry(*nscd_src_backend_db[srci], 257 dbn, db_entry, NSCD_ADD_DB_ENTRY_LAST); 258 (void) _nscd_rw_unlock((nscd_acc_data_t *) 259 nscd_src_backend_db[srci]); 260 } 261 262 return (NSCD_SUCCESS); 263 } 264 265 /* 266 * create data structures (used by the switch engine) based 267 * on the input switch policy configuration and database 268 * name and indexes 269 */ 270 nscd_rc_t 271 _nscd_create_sw_struct( 272 int dbi, 273 int compat_basei, 274 const char *dbn, 275 const char *cfgstr, 276 void *swcfgv1, 277 nscd_nsw_params_t *params) 278 { 279 char *me = "_nscd_create_sw_struct"; 280 nscd_rc_t rc = NSCD_SUCCESS; 281 nscd_nsw_config_t *nsw_cfg = NULL; 282 nscd_nsw_config_t **nsw_cfg_p = NULL; 283 struct __nsw_switchconfig_v1 *swcfg = NULL; 284 struct __nsw_lookup_v1 *lkp; 285 enum __nsw_parse_err err; 286 int maxsrc; 287 int *src_idx_a = NULL; 288 int j, k; 289 290 /* 291 * if the nsw config string has been parsed into 292 * a struct __nsw_switchconfig_v1, use it. If not, 293 * create the struct. 294 */ 295 if (swcfgv1 != NULL) 296 swcfg = (struct __nsw_switchconfig_v1 *)swcfgv1; 297 else { 298 char *cstr; 299 300 cstr = strdup(cfgstr); 301 if (cstr == NULL) 302 return (NSCD_NO_MEMORY); 303 304 /* 305 * parse the nsw config string and create 306 * a struct __nsw_switchconfig_v1 307 */ 308 swcfg = _nsw_getoneconfig_v1(dbn, cstr, &err); 309 free(cstr); 310 if (swcfg == NULL) { 311 rc = NSCD_CFG_SYNTAX_ERROR; 312 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 313 (me, "error: unable to process nsw config string\n"); 314 goto error_exit; 315 } 316 } 317 318 /* allocate the space for a nscd_nsw_config_t */ 319 nsw_cfg = calloc(1, sizeof (nscd_nsw_config_t)); 320 if (nsw_cfg == NULL) { 321 rc = NSCD_NO_MEMORY; 322 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 323 (me, "error: unable to allocate an nscd_nsw_config_t\n"); 324 goto error_exit; 325 } 326 327 /* need to know how many backends (sources) */ 328 maxsrc = swcfg->num_lookups; 329 nsw_cfg->max_src = maxsrc; 330 331 /* 332 * allocate an array to store the index for each 333 * backend (source) 334 */ 335 src_idx_a = calloc(1, maxsrc * sizeof (int)); 336 if (src_idx_a == NULL) { 337 rc = NSCD_NO_MEMORY; 338 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 339 (me, "error: unable to allocate an array for source index\n"); 340 goto error_exit; 341 } 342 343 /* 344 * set the index for each backend (source) 345 */ 346 lkp = swcfg->lookups; 347 for (j = 0; j < maxsrc; j++) { 348 char *usrc; 349 350 for (k = 0; k < NSCD_NUM_SRC && 351 NSCD_NSW_SRC_NAME(k) != NULL && 352 strcmp(lkp->service_name, 353 NSCD_NSW_SRC_NAME(k)) != 0; k++); 354 355 if (k < NSCD_NUM_SRC && 356 nscd_src_backend_db_loaded[k] == 0) { 357 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 358 (me, "unknown nsw source name %s\n", 359 lkp->service_name); 360 usrc = strdup(lkp->service_name); 361 if (usrc == NULL) { 362 rc = NSCD_NO_MEMORY; 363 _NSCD_LOG(NSCD_LOG_CONFIG, 364 NSCD_LOG_LEVEL_ERROR) 365 (me, "unable to strdup() source name\n"); 366 goto error_exit; 367 } 368 NSCD_NSW_SRC_NAME(k) = usrc; 369 370 rc = _nscd_populate_nsw_backend_info_db(k); 371 if (rc != NSCD_SUCCESS) { 372 free(usrc); 373 NSCD_NSW_SRC_NAME(k) = NULL; 374 goto error_exit; 375 } 376 } else if (NSCD_NSW_SRC_NAME(k) == NULL) { 377 /* 378 * number of user-defined source exceeded 379 */ 380 rc = NSCD_CFG_SYNTAX_ERROR; 381 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 382 (me, "error: number of user_defined source exceeded\n"); 383 384 goto error_exit; 385 } 386 387 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 388 (me, "setting source index array [%d] = %d (%s)\n", 389 j, k, lkp->service_name); 390 391 src_idx_a[j] = k; 392 393 lkp = lkp->next; 394 if (lkp == NULL) break; 395 396 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 397 (me, "number of nsw sources = %d\n", nsw_cfg->max_src); 398 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 399 (me, "next nsw source is %s\n", lkp->service_name); 400 } 401 402 /* set it up to reference count the switch policy config */ 403 nsw_cfg_p = (nscd_nsw_config_t **)_nscd_alloc( 404 NSCD_DATA_NSW_CONFIG, 405 sizeof (nscd_nsw_config_t **), 406 free_nscd_nsw_config, 407 NSCD_ALLOC_RWLOCK); 408 409 if (nsw_cfg_p == NULL) { 410 rc = NSCD_NO_MEMORY; 411 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 412 (me, "unable to allocate a new nsw config DB\n"); 413 goto error_exit; 414 } 415 *nsw_cfg_p = nsw_cfg; 416 417 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 418 (me, "new nsw config DB %p allocated\n", nsw_cfg_p); 419 420 /* save all the data in the new nscd_nsw_config_t */ 421 nsw_cfg->db_name = strdup(dbn); 422 nsw_cfg->nsw_cfg_str = strdup(cfgstr); 423 if (nsw_cfg->db_name == NULL || nsw_cfg->nsw_cfg_str == NULL) { 424 rc = NSCD_NO_MEMORY; 425 goto error_exit; 426 } 427 428 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 429 (me, "switch policy \"%s\" for database is \"%s\"\n", 430 nsw_cfg->db_name, nsw_cfg->nsw_cfg_str); 431 432 nsw_cfg->nsw_config = swcfg; 433 nsw_cfg->src_idx = src_idx_a; 434 435 /* 436 * set default frontend params and if necessary call initf() 437 * to initialize or override 438 */ 439 nsw_cfg->fe_params.max_active_per_src = 10; 440 nsw_cfg->fe_params.max_dormant_per_src = 1; 441 nsw_cfg->fe_params.finders = _nscd_nss_finders; 442 if (params != NULL) { 443 nsw_cfg->fe_params = params->p; 444 445 if (params->p.flags & NSS_USE_DEFAULT_CONFIG) { 446 params->nswcfg = nsw_cfg_p; 447 /* 448 * this nsw_cfg is not meant to last long, no need 449 * to set up the nsw state and getent bases, just 450 * exit with NSCD_SUCCESS 451 */ 452 nsw_cfg->nobase = 1; 453 goto error_exit; 454 } 455 } else 456 (void) (nscd_nss_db_initf[dbi])(&nsw_cfg->fe_params); 457 458 /* 459 * activate the new nscd_nsw_config_t, the old one 460 * will either be deleted or left on the side (and be 461 * deleted eventually) 462 */ 463 nscd_nsw_config[dbi] = (nscd_nsw_config_t **)_nscd_set( 464 (nscd_acc_data_t *)nscd_nsw_config[dbi], 465 (nscd_acc_data_t *)nsw_cfg_p); 466 467 /* 468 * also create a new nsw state base 469 */ 470 if ((rc = _nscd_init_nsw_state_base(dbi, compat_basei, 1)) != 471 NSCD_SUCCESS) { 472 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 473 (me, "unable to initialize a nsw state base(%d)\n", dbi); 474 goto error_exit; 475 } 476 477 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 478 (me, "new nsw state base(%d) %p created\n", dbi, 479 nscd_nsw_state_base[dbi]); 480 481 /* 482 * also create a new getent context base 483 */ 484 if ((rc = _nscd_init_getent_ctx_base(dbi, 1)) != NSCD_SUCCESS) { 485 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 486 (me, "unable to initialize a getent context base(%d)\n", dbi); 487 goto error_exit; 488 } 489 490 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 491 (me, "new getent context base(%d) %p created\n", dbi, 492 nscd_getent_ctx_base[dbi]); 493 494 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 495 (me, "new nsw config created (database = %s, " 496 "config = %s)\n", dbn, cfgstr); 497 498 499 error_exit: 500 501 if (rc != NSCD_SUCCESS) { 502 503 if (swcfgv1 == NULL && swcfg != NULL) 504 (void) __nsw_freeconfig_v1(swcfg); 505 if (src_idx_a != NULL) 506 free(src_idx_a); 507 if (nsw_cfg_p) 508 free(nsw_cfg_p); 509 if (nsw_cfg != NULL) { 510 if (nsw_cfg->db_name != NULL) 511 free(nsw_cfg->db_name); 512 if (nsw_cfg->nsw_cfg_str != NULL) 513 free(nsw_cfg->nsw_cfg_str); 514 free(nsw_cfg); 515 } 516 517 return (rc); 518 } else 519 return (NSCD_SUCCESS); 520 } 521 522 static nscd_rc_t 523 create_nsw_config(int dbi) 524 { 525 526 nscd_nsw_config_t *nsw_cfg = NULL; 527 nscd_nsw_config_t **nsw_cfg_p = NULL; 528 char *me = "create_nsw_config"; 529 530 /* 531 * if pseudo-databases (initf function not defined), 532 * don't bother now 533 */ 534 if (nscd_nss_db_initf[dbi] == NULL) 535 return (NSCD_SUCCESS); 536 537 /* allocate the space for a nscd_nsw_config_t */ 538 nsw_cfg = calloc(1, sizeof (nscd_nsw_config_t)); 539 if (nsw_cfg == NULL) { 540 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 541 (me, "unable to allocate a nsw config structure\n"); 542 return (NSCD_NO_MEMORY); 543 } 544 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 545 (me, "nsw config structure %pallocated\n", nsw_cfg); 546 547 nsw_cfg_p = (nscd_nsw_config_t **)_nscd_alloc( 548 NSCD_DATA_NSW_CONFIG, 549 sizeof (nscd_nsw_config_t **), 550 free_nscd_nsw_config, 551 NSCD_ALLOC_RWLOCK); 552 553 if (nsw_cfg_p == NULL) { 554 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 555 (me, "unable to allocate a pointer to nsw config structure\n"); 556 return (NSCD_NO_MEMORY); 557 } 558 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 559 (me, "nsw config pointer = %p\n", nsw_cfg_p); 560 561 nsw_cfg->db_name = strdup(NSCD_NSW_DB_NAME(dbi)); 562 if (nsw_cfg->db_name == NULL) { 563 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 564 (me, "unable to strdup the db name\n"); 565 return (NSCD_NO_MEMORY); 566 } 567 568 /* 569 * set default frontend params and then call initf() 570 * to initialize or override 571 */ 572 nsw_cfg->fe_params.max_active_per_src = 10; 573 nsw_cfg->fe_params.max_dormant_per_src = 1; 574 nsw_cfg->fe_params.finders = _nscd_nss_finders; 575 (void) (nscd_nss_db_initf[dbi])(&nsw_cfg->fe_params); 576 577 /* 578 * activate the new nscd_nsw_config_t 579 */ 580 *nsw_cfg_p = nsw_cfg; 581 nscd_nsw_config[dbi] = (nscd_nsw_config_t **)_nscd_set( 582 (nscd_acc_data_t *)nscd_nsw_config[dbi], 583 (nscd_acc_data_t *)nsw_cfg_p); 584 585 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 586 (me, "nsw config %p activated\n", nsw_cfg); 587 588 return (NSCD_SUCCESS); 589 } 590 591 nscd_rc_t 592 _nscd_init_all_nsw_config(void) 593 { 594 nscd_rc_t rc; 595 int i; 596 char *me = "_nscd_init_all_nsw_config"; 597 598 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 599 (me, "initializing all nsw config\n"); 600 601 for (i = 0; i < NSCD_NUM_DB; i++) { 602 if ((rc = create_nsw_config(i)) != NSCD_SUCCESS) 603 return (rc); 604 } 605 606 return (NSCD_SUCCESS); 607 } 608 609 static nscd_rc_t 610 init_nsw_be_info_db(int srci) 611 { 612 nscd_db_t *ret, **db_p; 613 char *me = "init_nsw_be_info_db"; 614 615 ret = _nscd_alloc_db(NSCD_DB_SIZE_SMALL); 616 617 if (ret == NULL) { 618 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 619 (me, "unable to allocate a nsw be info database\n"); 620 return (NSCD_NO_MEMORY); 621 } 622 623 /* set up to reference count the backend info db */ 624 db_p = (nscd_db_t **) 625 _nscd_alloc(NSCD_DATA_BACKEND_INFO_DB, 626 sizeof (nscd_db_t **), 627 free_nsw_backend_info_db, 628 NSCD_ALLOC_RWLOCK); 629 630 if (db_p == NULL) { 631 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 632 (me, "unable to allocate the pointer to the nsw " 633 "be info database\n"); 634 return (NSCD_NO_MEMORY); 635 } 636 637 *db_p = ret; 638 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 639 (me, "backend database (db_p = %p, db = %p)\n", db_p, *db_p); 640 641 nscd_src_backend_db[srci] = (nscd_db_t **)_nscd_set( 642 (nscd_acc_data_t *)nscd_src_backend_db[srci], 643 (nscd_acc_data_t *)db_p); 644 645 return (NSCD_SUCCESS); 646 } 647 648 nscd_rc_t 649 _nscd_init_all_nsw_be_info_db(void) 650 { 651 652 int i; 653 nscd_rc_t rc; 654 char *me = "_nscd_init_all_nsw_be_info_db"; 655 656 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 657 (me, "initializing all nsw be info databases\n"); 658 659 for (i = 0; i < NSCD_NUM_SRC; i++) { 660 if ((rc = init_nsw_be_info_db(i)) != NSCD_SUCCESS) 661 return (rc); 662 } 663 664 return (NSCD_SUCCESS); 665 } 666 667 668 nscd_rc_t 669 _nscd_alloc_nsw_config() 670 { 671 nscd_nsw_config = calloc(NSCD_NUM_DB, sizeof (nscd_nsw_config_t **)); 672 if (nscd_nsw_config == NULL) 673 return (NSCD_NO_MEMORY); 674 675 return (NSCD_SUCCESS); 676 } 677 678 nscd_rc_t 679 _nscd_alloc_nsw_be_info_db() 680 { 681 int i; 682 683 _nscd_cfg_num_nsw_src_all = _nscd_cfg_num_nsw_src + NSCD_NUM_SRC_UDEF; 684 nscd_src_backend_db = calloc(NSCD_NUM_SRC, sizeof (nscd_db_t **)); 685 if (nscd_src_backend_db == NULL) 686 return (NSCD_NO_MEMORY); 687 nscd_src_backend_db_loaded = calloc(NSCD_NUM_SRC, sizeof (int)); 688 if (nscd_src_backend_db_loaded == NULL) { 689 free(nscd_src_backend_db); 690 return (NSCD_NO_MEMORY); 691 } 692 693 /* also allocate/init the nsswitch source index/name array */ 694 _nscd_cfg_nsw_src_all = (nscd_cfg_id_t *)calloc( 695 _nscd_cfg_num_nsw_src_all + 1, sizeof (nscd_cfg_id_t)); 696 for (i = 0; i < _nscd_cfg_num_nsw_src_all + 1; i++) 697 (_nscd_cfg_nsw_src_all + i)->index = -1; 698 699 (void) memcpy(_nscd_cfg_nsw_src_all, _nscd_cfg_nsw_src, 700 _nscd_cfg_num_nsw_src * sizeof (nscd_cfg_id_t)); 701 return (NSCD_SUCCESS); 702 } 703 704 nscd_rc_t 705 _nscd_populate_nsw_backend_info() 706 { 707 int i; 708 nscd_rc_t rc; 709 710 for (i = 0; i < NSCD_NUM_SRC; i++) { 711 if (NSCD_NSW_SRC_NAME(i) == NULL) 712 continue; 713 rc = _nscd_populate_nsw_backend_info_db(i); 714 if (rc != NSCD_SUCCESS) 715 return (rc); 716 } 717 718 return (NSCD_SUCCESS); 719 } 720 721 /* 722 * The following defines nscd's own lookup and delete functions 723 * that are to be stored in nss_backend_finder_t which is used 724 * by _nscd_populate_nsw_backend_info_db() to initialize the 725 * various nss backend instances 726 */ 727 728 static const int dlopen_version = 1; 729 #ifndef NSS_DLOPEN_FORMAT 730 #define NSS_DLOPEN_FORMAT "nss_%s.so.%d" 731 #endif 732 #ifndef NSS_DLSYM_FORMAT 733 #define NSS_DLSYM_FORMAT "_nss_%s_%s_constr" 734 #endif 735 static const char dlopen_format[] = NSS_DLOPEN_FORMAT; 736 static const char dlsym_format [] = NSS_DLSYM_FORMAT; 737 static const size_t format_maxlen = sizeof (dlsym_format) - 4; 738 739 /*ARGSUSED*/ 740 static nss_backend_constr_t 741 _nscd_per_src_lookup(void *handle, const char *db_name, const char *src_name, 742 void **delete_privp) 743 { 744 char *name; 745 void *dlhandle; 746 void *sym; 747 size_t len; 748 nss_backend_constr_t res = NULL; 749 750 len = format_maxlen + strlen(db_name) + strlen(src_name); 751 name = alloca(len); 752 dlhandle = handle; 753 if ((dlhandle = handle) == NULL) { 754 (void) sprintf(name, dlopen_format, src_name, dlopen_version); 755 dlhandle = dlopen(name, RTLD_LAZY); 756 } 757 758 if (dlhandle != NULL) { 759 (void) sprintf(name, dlsym_format, src_name, db_name); 760 if ((sym = dlsym(dlhandle, name)) == 0) { 761 if (handle == NULL) 762 (void) dlclose(dlhandle); 763 } else { 764 *delete_privp = dlhandle; 765 res = (nss_backend_constr_t)sym; 766 } 767 } 768 return (res); 769 } 770 771 /*ARGSUSED*/ 772 static void 773 _nscd_per_src_delete(void *delete_priv, nss_backend_constr_t dummy) 774 { 775 (void) dlclose(delete_priv); 776 } 777