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 2008 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 32 foreign nsswitch sources/backends) 76 */ 77 #define NSCD_NUM_SRC_FOREIGN 32 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 nss_backend_constr_t c; 197 void *be_version = &_nscd_be_version; 198 199 /* get the version number of the backend (if available) */ 200 if (srci >= _nscd_cfg_num_nsw_src) { /* a foreign backend */ 201 c = _nscd_per_src_lookup(handle, NULL, src, &handle); 202 if (c == NULL) 203 be_version = NULL; 204 else 205 be_version = (void *)c; 206 207 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 208 (me, "foreign backend: _nss_%s_version = %p ", src, be_version); 209 } 210 211 for (i = 0; i < NSCD_NUM_DB; i++) { 212 213 if (nscd_nsw_config[i] == NULL) 214 continue; 215 216 nsw_cfg = *nscd_nsw_config[i]; 217 dbn = NSCD_NSW_DB_NAME(i); 218 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 219 (me, "adding backend info for <%s : %s>\n", src, dbn); 220 221 (void) memset(&be_info, 0, sizeof (be_info)); 222 223 for (bf = nsw_cfg->fe_params.finders; bf != 0; bf = bf->next) { 224 225 c = (*bf->lookup)(handle, dbn, src, &handle); 226 227 if (c != 0) { 228 be_info.be_constr = c; 229 be_info.finder = bf; 230 be_info.finder_priv = handle; 231 be_info.be_version = be_version; 232 break; 233 } 234 } 235 if (be_info.be_constr == NULL) { 236 /* 237 * Couldn't find the backend anywhere. 238 * This is fine, some backend just don't 239 * support certain databases. 240 */ 241 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 242 (me, "unable to find backend info " 243 "for <%s : %s>\n", src, dbn); 244 } 245 246 size = sizeof (nscd_be_info_t); 247 248 db_entry = _nscd_alloc_db_entry(NSCD_DATA_BACKEND_INFO, 249 dbn, size, 1, 1); 250 251 if (db_entry == NULL) { 252 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 253 (me, "unable to allocate db entry for " 254 "<%s : %s>\n", src, dbn); 255 return (NSCD_NO_MEMORY); 256 } 257 258 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 259 (me, "adding be db entry %p for <%s : %s> to db %p: " 260 "constr = %p\n", db_entry, src, dbn, 261 *nscd_src_backend_db[srci], be_info.be_constr); 262 263 bi = (nscd_be_info_t *)*(db_entry->data_array); 264 *bi = be_info; 265 266 (void) _nscd_wrlock((nscd_acc_data_t *) 267 nscd_src_backend_db[srci]); 268 nscd_src_backend_db_loaded[srci] = 1; 269 (void) _nscd_add_db_entry(*nscd_src_backend_db[srci], 270 dbn, db_entry, NSCD_ADD_DB_ENTRY_LAST); 271 (void) _nscd_rw_unlock((nscd_acc_data_t *) 272 nscd_src_backend_db[srci]); 273 } 274 275 return (NSCD_SUCCESS); 276 } 277 278 /* 279 * create data structures (used by the switch engine) based 280 * on the input switch policy configuration and database 281 * name and indexes 282 */ 283 nscd_rc_t 284 _nscd_create_sw_struct( 285 int dbi, 286 int compat_basei, 287 const char *dbn, 288 const char *cfgstr, 289 void *swcfgv1, 290 nscd_nsw_params_t *params) 291 { 292 char *me = "_nscd_create_sw_struct"; 293 nscd_rc_t rc = NSCD_SUCCESS; 294 nscd_nsw_config_t *nsw_cfg = NULL; 295 nscd_nsw_config_t **nsw_cfg_p = NULL; 296 struct __nsw_switchconfig_v1 *swcfg = NULL; 297 struct __nsw_lookup_v1 *lkp; 298 enum __nsw_parse_err err; 299 int maxsrc; 300 int *src_idx_a = NULL; 301 int j, k; 302 303 /* 304 * if the nsw config string has been parsed into 305 * a struct __nsw_switchconfig_v1, use it. If not, 306 * create the struct. 307 */ 308 if (swcfgv1 != NULL) 309 swcfg = (struct __nsw_switchconfig_v1 *)swcfgv1; 310 else { 311 char *cstr; 312 313 cstr = strdup(cfgstr); 314 if (cstr == NULL) 315 return (NSCD_NO_MEMORY); 316 317 /* 318 * parse the nsw config string and create 319 * a struct __nsw_switchconfig_v1 320 */ 321 swcfg = _nsw_getoneconfig_v1(dbn, cstr, &err); 322 free(cstr); 323 if (swcfg == NULL) { 324 rc = NSCD_CFG_SYNTAX_ERROR; 325 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 326 (me, "error: unable to process nsw config string\n"); 327 goto error_exit; 328 } 329 } 330 331 /* allocate the space for a nscd_nsw_config_t */ 332 nsw_cfg = calloc(1, sizeof (nscd_nsw_config_t)); 333 if (nsw_cfg == NULL) { 334 rc = NSCD_NO_MEMORY; 335 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 336 (me, "error: unable to allocate an nscd_nsw_config_t\n"); 337 goto error_exit; 338 } 339 340 /* need to know how many backends (sources) */ 341 maxsrc = swcfg->num_lookups; 342 nsw_cfg->max_src = maxsrc; 343 344 /* 345 * allocate an array to store the index for each 346 * backend (source) 347 */ 348 src_idx_a = calloc(1, maxsrc * sizeof (int)); 349 if (src_idx_a == NULL) { 350 rc = NSCD_NO_MEMORY; 351 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 352 (me, "error: unable to allocate an array for source index\n"); 353 goto error_exit; 354 } 355 356 /* 357 * set the index for each backend (source) 358 */ 359 lkp = swcfg->lookups; 360 for (j = 0; j < maxsrc; j++) { 361 char *usrc; 362 363 for (k = 0; k < NSCD_NUM_SRC && NSCD_NSW_SRC_NAME(k) != NULL && 364 strcmp(lkp->service_name, NSCD_NSW_SRC_NAME(k)) != 0; 365 k++) { 366 /* empty */ 367 } 368 369 if (k < NSCD_NUM_SRC && nscd_src_backend_db_loaded[k] == 0) { 370 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 371 (me, "unknown nsw source name %s\n", lkp->service_name); 372 usrc = strdup(lkp->service_name); 373 if (usrc == NULL) { 374 rc = NSCD_NO_MEMORY; 375 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 376 (me, "unable to strdup() source name\n"); 377 goto error_exit; 378 } 379 NSCD_NSW_SRC_NAME(k) = usrc; 380 381 rc = _nscd_populate_nsw_backend_info_db(k); 382 if (rc != NSCD_SUCCESS) { 383 free(usrc); 384 NSCD_NSW_SRC_NAME(k) = NULL; 385 goto error_exit; 386 } 387 } else if (NSCD_NSW_SRC_NAME(k) == NULL) { 388 /* 389 * number of user-defined source exceeded 390 */ 391 rc = NSCD_CFG_SYNTAX_ERROR; 392 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 393 (me, "error: number of user_defined source exceeded\n"); 394 395 goto error_exit; 396 } 397 398 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 399 (me, "setting source index array [%d] = %d (%s)\n", 400 j, k, lkp->service_name); 401 402 src_idx_a[j] = k; 403 404 lkp = lkp->next; 405 if (lkp == NULL) break; 406 407 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 408 (me, "number of nsw sources = %d\n", nsw_cfg->max_src); 409 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 410 (me, "next nsw source is %s\n", lkp->service_name); 411 } 412 413 /* set it up to reference count the switch policy config */ 414 nsw_cfg_p = (nscd_nsw_config_t **)_nscd_alloc(NSCD_DATA_NSW_CONFIG, 415 sizeof (nscd_nsw_config_t **), free_nscd_nsw_config, 416 NSCD_ALLOC_RWLOCK); 417 418 if (nsw_cfg_p == NULL) { 419 rc = NSCD_NO_MEMORY; 420 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 421 (me, "unable to allocate a new nsw config DB\n"); 422 goto error_exit; 423 } 424 *nsw_cfg_p = nsw_cfg; 425 426 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 427 (me, "new nsw config DB %p allocated\n", nsw_cfg_p); 428 429 /* save all the data in the new nscd_nsw_config_t */ 430 nsw_cfg->db_name = strdup(dbn); 431 nsw_cfg->nsw_cfg_str = strdup(cfgstr); 432 if (nsw_cfg->db_name == NULL || nsw_cfg->nsw_cfg_str == NULL) { 433 rc = NSCD_NO_MEMORY; 434 goto error_exit; 435 } 436 437 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 438 (me, "switch policy \"%s\" for database is \"%s\"\n", 439 nsw_cfg->db_name, nsw_cfg->nsw_cfg_str); 440 441 nsw_cfg->nsw_config = swcfg; 442 nsw_cfg->src_idx = src_idx_a; 443 444 /* 445 * set default frontend params and if necessary call initf() 446 * to initialize or override 447 */ 448 nsw_cfg->fe_params.max_active_per_src = 10; 449 nsw_cfg->fe_params.max_dormant_per_src = 1; 450 nsw_cfg->fe_params.finders = _nscd_nss_finders; 451 if (params != NULL) { 452 nsw_cfg->fe_params = params->p; 453 454 if (params->p.flags & NSS_USE_DEFAULT_CONFIG) { 455 params->nswcfg = nsw_cfg_p; 456 /* 457 * this nsw_cfg is not meant to last long, no need 458 * to set up the nsw state and getent bases, just 459 * exit with NSCD_SUCCESS 460 */ 461 nsw_cfg->nobase = 1; 462 goto error_exit; 463 } 464 } else 465 (void) (nscd_nss_db_initf[dbi])(&nsw_cfg->fe_params); 466 467 /* 468 * activate the new nscd_nsw_config_t, the old one 469 * will either be deleted or left on the side (and be 470 * deleted eventually) 471 */ 472 nscd_nsw_config[dbi] = (nscd_nsw_config_t **)_nscd_set( 473 (nscd_acc_data_t *)nscd_nsw_config[dbi], 474 (nscd_acc_data_t *)nsw_cfg_p); 475 476 /* 477 * also create a new nsw state base 478 */ 479 if ((rc = _nscd_init_nsw_state_base(dbi, compat_basei, 1)) != 480 NSCD_SUCCESS) { 481 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 482 (me, "unable to initialize a nsw state base(%d)\n", dbi); 483 goto error_exit; 484 } 485 486 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 487 (me, "new nsw state base(%d) %p created\n", dbi, 488 nscd_nsw_state_base[dbi]); 489 490 /* 491 * also create a new getent context base 492 */ 493 if ((rc = _nscd_init_getent_ctx_base(dbi, 1)) != NSCD_SUCCESS) { 494 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 495 (me, "unable to initialize a getent context base(%d)\n", dbi); 496 goto error_exit; 497 } 498 499 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 500 (me, "new getent context base(%d) %p created\n", dbi, 501 nscd_getent_ctx_base[dbi]); 502 503 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 504 (me, "new nsw config created (database = %s, " 505 "config = %s)\n", dbn, cfgstr); 506 507 508 error_exit: 509 510 if (rc != NSCD_SUCCESS) { 511 512 if (swcfgv1 == NULL && swcfg != NULL) 513 (void) __nsw_freeconfig_v1(swcfg); 514 if (src_idx_a != NULL) 515 free(src_idx_a); 516 if (nsw_cfg_p) 517 free(nsw_cfg_p); 518 if (nsw_cfg != NULL) { 519 if (nsw_cfg->db_name != NULL) 520 free(nsw_cfg->db_name); 521 if (nsw_cfg->nsw_cfg_str != NULL) 522 free(nsw_cfg->nsw_cfg_str); 523 free(nsw_cfg); 524 } 525 526 return (rc); 527 } else 528 return (NSCD_SUCCESS); 529 } 530 531 static nscd_rc_t 532 create_nsw_config(int dbi) 533 { 534 535 nscd_nsw_config_t *nsw_cfg = NULL; 536 nscd_nsw_config_t **nsw_cfg_p = NULL; 537 char *me = "create_nsw_config"; 538 539 /* 540 * if pseudo-databases (initf function not defined), 541 * don't bother now 542 */ 543 if (nscd_nss_db_initf[dbi] == NULL) 544 return (NSCD_SUCCESS); 545 546 /* allocate the space for a nscd_nsw_config_t */ 547 nsw_cfg = calloc(1, sizeof (nscd_nsw_config_t)); 548 if (nsw_cfg == NULL) { 549 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 550 (me, "unable to allocate a nsw config structure\n"); 551 return (NSCD_NO_MEMORY); 552 } 553 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 554 (me, "nsw config structure %pallocated\n", nsw_cfg); 555 556 nsw_cfg_p = (nscd_nsw_config_t **)_nscd_alloc(NSCD_DATA_NSW_CONFIG, 557 sizeof (nscd_nsw_config_t **), free_nscd_nsw_config, 558 NSCD_ALLOC_RWLOCK); 559 560 if (nsw_cfg_p == NULL) { 561 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 562 (me, "unable to allocate a pointer to nsw config structure\n"); 563 return (NSCD_NO_MEMORY); 564 } 565 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 566 (me, "nsw config pointer = %p\n", nsw_cfg_p); 567 568 nsw_cfg->db_name = strdup(NSCD_NSW_DB_NAME(dbi)); 569 if (nsw_cfg->db_name == NULL) { 570 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 571 (me, "unable to strdup the db name\n"); 572 return (NSCD_NO_MEMORY); 573 } 574 575 /* 576 * set default frontend params and then call initf() 577 * to initialize or override 578 */ 579 nsw_cfg->fe_params.max_active_per_src = 10; 580 nsw_cfg->fe_params.max_dormant_per_src = 1; 581 nsw_cfg->fe_params.finders = _nscd_nss_finders; 582 (void) (nscd_nss_db_initf[dbi])(&nsw_cfg->fe_params); 583 584 /* 585 * activate the new nscd_nsw_config_t 586 */ 587 *nsw_cfg_p = nsw_cfg; 588 nscd_nsw_config[dbi] = (nscd_nsw_config_t **)_nscd_set( 589 (nscd_acc_data_t *)nscd_nsw_config[dbi], 590 (nscd_acc_data_t *)nsw_cfg_p); 591 592 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 593 (me, "nsw config %p activated\n", nsw_cfg); 594 595 return (NSCD_SUCCESS); 596 } 597 598 nscd_rc_t 599 _nscd_init_all_nsw_config(void) 600 { 601 nscd_rc_t rc; 602 int i; 603 char *me = "_nscd_init_all_nsw_config"; 604 605 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 606 (me, "initializing all nsw config\n"); 607 608 for (i = 0; i < NSCD_NUM_DB; i++) { 609 if ((rc = create_nsw_config(i)) != NSCD_SUCCESS) 610 return (rc); 611 } 612 613 return (NSCD_SUCCESS); 614 } 615 616 static nscd_rc_t 617 init_nsw_be_info_db(int srci) 618 { 619 nscd_db_t *ret, **db_p; 620 char *me = "init_nsw_be_info_db"; 621 622 ret = _nscd_alloc_db(NSCD_DB_SIZE_SMALL); 623 624 if (ret == NULL) { 625 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 626 (me, "unable to allocate a nsw be info database\n"); 627 return (NSCD_NO_MEMORY); 628 } 629 630 /* set up to reference count the backend info db */ 631 db_p = (nscd_db_t **)_nscd_alloc(NSCD_DATA_BACKEND_INFO_DB, 632 sizeof (nscd_db_t **), free_nsw_backend_info_db, 633 NSCD_ALLOC_RWLOCK); 634 635 if (db_p == NULL) { 636 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 637 (me, "unable to allocate the pointer to the nsw " 638 "be info database\n"); 639 return (NSCD_NO_MEMORY); 640 } 641 642 *db_p = ret; 643 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 644 (me, "backend database (db_p = %p, db = %p)\n", db_p, *db_p); 645 646 nscd_src_backend_db[srci] = (nscd_db_t **)_nscd_set( 647 (nscd_acc_data_t *)nscd_src_backend_db[srci], 648 (nscd_acc_data_t *)db_p); 649 650 return (NSCD_SUCCESS); 651 } 652 653 nscd_rc_t 654 _nscd_init_all_nsw_be_info_db(void) 655 { 656 657 int i; 658 nscd_rc_t rc; 659 char *me = "_nscd_init_all_nsw_be_info_db"; 660 661 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 662 (me, "initializing all nsw be info databases\n"); 663 664 for (i = 0; i < NSCD_NUM_SRC; i++) { 665 if ((rc = init_nsw_be_info_db(i)) != NSCD_SUCCESS) 666 return (rc); 667 } 668 669 return (NSCD_SUCCESS); 670 } 671 672 673 nscd_rc_t 674 _nscd_alloc_nsw_config() 675 { 676 nscd_nsw_config = calloc(NSCD_NUM_DB, sizeof (nscd_nsw_config_t **)); 677 if (nscd_nsw_config == NULL) 678 return (NSCD_NO_MEMORY); 679 680 return (NSCD_SUCCESS); 681 } 682 683 nscd_rc_t 684 _nscd_alloc_nsw_be_info_db() 685 { 686 int i; 687 688 _nscd_cfg_num_nsw_src_all = _nscd_cfg_num_nsw_src + 689 NSCD_NUM_SRC_FOREIGN; 690 nscd_src_backend_db = calloc(NSCD_NUM_SRC, sizeof (nscd_db_t **)); 691 if (nscd_src_backend_db == NULL) 692 return (NSCD_NO_MEMORY); 693 nscd_src_backend_db_loaded = calloc(NSCD_NUM_SRC, sizeof (int)); 694 if (nscd_src_backend_db_loaded == NULL) { 695 free(nscd_src_backend_db); 696 return (NSCD_NO_MEMORY); 697 } 698 699 /* also allocate/init the nsswitch source index/name array */ 700 _nscd_cfg_nsw_src_all = (nscd_cfg_id_t *)calloc( 701 _nscd_cfg_num_nsw_src_all + 1, sizeof (nscd_cfg_id_t)); 702 for (i = 0; i < _nscd_cfg_num_nsw_src_all + 1; i++) 703 (_nscd_cfg_nsw_src_all + i)->index = -1; 704 705 (void) memcpy(_nscd_cfg_nsw_src_all, _nscd_cfg_nsw_src, 706 _nscd_cfg_num_nsw_src * sizeof (nscd_cfg_id_t)); 707 return (NSCD_SUCCESS); 708 } 709 710 nscd_rc_t 711 _nscd_populate_nsw_backend_info() 712 { 713 int i; 714 nscd_rc_t rc; 715 716 for (i = 0; i < NSCD_NUM_SRC; i++) { 717 if (NSCD_NSW_SRC_NAME(i) == NULL) 718 continue; 719 rc = _nscd_populate_nsw_backend_info_db(i); 720 if (rc != NSCD_SUCCESS) 721 return (rc); 722 } 723 724 return (NSCD_SUCCESS); 725 } 726 727 /* 728 * The following defines nscd's own lookup and delete functions 729 * that are to be stored in nss_backend_finder_t which is used 730 * by _nscd_populate_nsw_backend_info_db() to initialize the 731 * various nss backend instances 732 */ 733 734 static const int dlopen_version = 1; 735 #ifndef NSS_DLOPEN_FORMAT 736 #define NSS_DLOPEN_FORMAT "nss_%s.so.%d" 737 #endif 738 #ifndef NSS_DLSYM_FORMAT 739 #define NSS_DLSYM_FORMAT "_nss_%s_%s_constr" 740 #define NSS_DLSYM_FORMAT_V "_nss_%s_version" 741 #endif 742 static const char dlopen_format[] = NSS_DLOPEN_FORMAT; 743 static const char dlsym_format [] = NSS_DLSYM_FORMAT; 744 static const char dlsym_format_v [] = NSS_DLSYM_FORMAT_V; 745 static const size_t format_maxlen = sizeof (dlsym_format); 746 747 /*ARGSUSED*/ 748 static nss_backend_constr_t 749 _nscd_per_src_lookup(void *handle, const char *db_name, const char *src_name, 750 void **delete_privp) 751 { 752 char *name; 753 void *dlhandle; 754 void *sym; 755 size_t len; 756 nss_backend_constr_t res = NULL; 757 758 len = format_maxlen + strlen(src_name); 759 if (db_name != NULL) 760 len += strlen(db_name); 761 name = alloca(len); 762 dlhandle = handle; 763 if ((dlhandle = handle) == NULL) { 764 (void) sprintf(name, dlopen_format, src_name, dlopen_version); 765 dlhandle = dlopen(name, RTLD_LAZY); 766 } 767 768 if (dlhandle != NULL) { 769 if (db_name != NULL) 770 (void) sprintf(name, dlsym_format, src_name, db_name); 771 else 772 (void) sprintf(name, dlsym_format_v, src_name); 773 if ((sym = dlsym(dlhandle, name)) == 0) { 774 if (handle == NULL) 775 (void) dlclose(dlhandle); 776 } else { 777 *delete_privp = dlhandle; 778 res = (nss_backend_constr_t)sym; 779 } 780 } 781 return (res); 782 } 783 784 /*ARGSUSED*/ 785 static void 786 _nscd_per_src_delete(void *delete_priv, nss_backend_constr_t dummy) 787 { 788 (void) dlclose(delete_priv); 789 } 790