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