comm: add -Wall
[unleashed.git] / usr / src / cmd / nscd / nscd_nswconfig.c
blob4f5497765e743c1dffc542f260278043aaada74d
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <nss_common.h>
27 #include <dlfcn.h>
28 #include <alloca.h>
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"
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
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);
47 static nss_backend_finder_t _nscd_per_src = {
48 _nscd_per_src_lookup,
49 _nscd_per_src_delete,
51 0 };
53 nss_backend_finder_t *_nscd_nss_finders = &_nscd_per_src;
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.
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;
65 * nsswitch config monitored by nscd. Protected by
66 * readers/writer lock nscd_nsw_config_lock
68 nscd_nsw_config_t ***nscd_nsw_config;
69 static rwlock_t nscd_nsw_config_lock = DEFAULTRWLOCK;
72 * nsswitch source index/name array
73 * (allow 32 foreign nsswitch sources/backends)
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;
79 static void
80 free_nscd_nsw_config(
81 nscd_acc_data_t *data)
84 nscd_nsw_config_t *nsw_cfg = *(nscd_nsw_config_t **)data;
85 char *me = "free_nscd_nsw_config";
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;
92 free(nsw_cfg->db_name);
93 free(nsw_cfg->nsw_cfg_str);
94 if (nsw_cfg->nsw_config != NULL)
95 (void) __nsw_freeconfig_v1(nsw_cfg->nsw_config);
96 free(nsw_cfg->src_idx);
98 free(nsw_cfg);
102 void
103 _nscd_free_nsw_config(
104 nscd_nsw_config_t *nswcfg)
106 free_nscd_nsw_config((nscd_acc_data_t *)&nswcfg);
109 void
110 _nscd_free_all_nsw_config()
113 nscd_nsw_config_t **nsw_cfg;
114 int i;
115 char *me = "_nscd_free_all_nsw_config";
117 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
118 (me, "freeing all nscd nsw config \n");
120 (void) rw_wrlock(&nscd_nsw_config_lock);
121 for (i = 0; i < NSCD_NUM_DB; i++) {
123 if ((nsw_cfg = nscd_nsw_config[i]) == NULL)
124 continue;
126 nscd_nsw_config[i] = (nscd_nsw_config_t **)_nscd_set(
127 (nscd_acc_data_t *)nsw_cfg, NULL);
129 (void) rw_unlock(&nscd_nsw_config_lock);
133 static void
134 free_nsw_backend_info_db(nscd_acc_data_t *data)
137 nscd_db_t *db = *(nscd_db_t **)data;
138 char *me = "free_nsw_backend_info_db";
140 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
141 (me, "freeing nsw backend info db %p\n", db);
143 if (db == NULL)
144 return;
146 _nscd_free_db(db);
150 void
151 _nscd_free_all_nsw_backend_info_db()
154 nscd_db_t **db;
155 int i;
156 char *me = " _nscd_free_all_nsw_backend_info_db";
158 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
159 (me, "freeing all nsw backend info db\n");
161 (void) rw_wrlock(&nscd_src_backend_db_lock);
162 for (i = 0; i < NSCD_NUM_SRC; i++) {
164 if ((db = nscd_src_backend_db[i]) == NULL)
165 continue;
167 nscd_src_backend_db[i] = (nscd_db_t **)_nscd_set(
168 (nscd_acc_data_t *)db, NULL);
169 nscd_src_backend_db_loaded[i] = 0;
171 (void) rw_unlock(&nscd_src_backend_db_lock);
175 * Populate the backend info db for the 'NSCD_NSW_SRC_NAME(srci)'
176 * source. Create one entry for each source/database pair
177 * (e.g., ldap:passwd, nis:hosts, etc).
179 static nscd_rc_t
180 _nscd_populate_nsw_backend_info_db(int srci)
182 nscd_be_info_t be_info, *bi;
183 nss_backend_finder_t *bf;
184 nscd_nsw_config_t *nsw_cfg;
185 int i, size;
186 nscd_db_entry_t *db_entry;
187 char *src = NSCD_NSW_SRC_NAME(srci);
188 const char *dbn;
189 char *me = "_nscd_populate_nsw_backend_info_db";
190 void *handle = NULL;
191 nss_backend_constr_t c;
192 void *be_version = &_nscd_be_version;
194 /* get the version number of the backend (if available) */
195 if (srci >= _nscd_cfg_num_nsw_src) { /* a foreign backend */
196 c = _nscd_per_src_lookup(handle, NULL, src, &handle);
197 if (c == NULL)
198 be_version = NULL;
199 else
200 be_version = (void *)c;
202 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
203 (me, "foreign backend: _nss_%s_version = %p ", src, be_version);
206 for (i = 0; i < NSCD_NUM_DB; i++) {
208 /* no nsswitch configuration, no backend info db population */
209 if (nscd_nsw_config[i] == NULL || *nscd_nsw_config[i] == NULL)
210 continue;
212 nsw_cfg = *nscd_nsw_config[i];
213 dbn = NSCD_NSW_DB_NAME(i);
214 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
215 (me, "adding backend info for <%s : %s>\n", src, dbn);
217 (void) memset(&be_info, 0, sizeof (be_info));
219 for (bf = nsw_cfg->fe_params.finders; bf != 0; bf = bf->next) {
221 c = (*bf->lookup)(handle, dbn, src, &handle);
223 if (c != 0) {
224 be_info.be_constr = c;
225 be_info.finder = bf;
226 be_info.finder_priv = handle;
227 be_info.be_version = be_version;
228 break;
231 if (be_info.be_constr == NULL) {
233 * Couldn't find the backend anywhere.
234 * This is fine, some backend just don't
235 * support certain databases.
237 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
238 (me, "unable to find backend info "
239 "for <%s : %s>\n", src, dbn);
242 size = sizeof (nscd_be_info_t);
244 db_entry = _nscd_alloc_db_entry(NSCD_DATA_BACKEND_INFO,
245 dbn, size, 1, 1);
247 if (db_entry == NULL) {
248 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
249 (me, "unable to allocate db entry for "
250 "<%s : %s>\n", src, dbn);
251 return (NSCD_NO_MEMORY);
254 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
255 (me, "adding be db entry %p for <%s : %s> to db %p: "
256 "constr = %p\n", db_entry, src, dbn,
257 *nscd_src_backend_db[srci], be_info.be_constr);
259 bi = (nscd_be_info_t *)*(db_entry->data_array);
260 *bi = be_info;
262 (void) _nscd_wrlock((nscd_acc_data_t *)
263 nscd_src_backend_db[srci]);
264 nscd_src_backend_db_loaded[srci] = 1;
265 (void) _nscd_add_db_entry(*nscd_src_backend_db[srci],
266 dbn, db_entry, NSCD_ADD_DB_ENTRY_LAST);
267 (void) _nscd_rw_unlock((nscd_acc_data_t *)
268 nscd_src_backend_db[srci]);
271 return (NSCD_SUCCESS);
275 * create data structures (used by the switch engine) based
276 * on the input switch policy configuration and database
277 * name and indexes
279 nscd_rc_t
280 _nscd_create_sw_struct(
281 int dbi,
282 int compat_basei,
283 const char *dbn,
284 const char *cfgstr,
285 void *swcfgv1,
286 nscd_nsw_params_t *params)
288 char *me = "_nscd_create_sw_struct";
289 nscd_rc_t rc = NSCD_SUCCESS;
290 nscd_nsw_config_t *nsw_cfg = NULL;
291 nscd_nsw_config_t **nsw_cfg_p = NULL;
292 struct __nsw_switchconfig_v1 *swcfg = NULL;
293 struct __nsw_lookup_v1 *lkp;
294 enum __nsw_parse_err err;
295 int maxsrc;
296 int *src_idx_a = NULL;
297 int j, k;
300 * if the nsw config string has been parsed into
301 * a struct __nsw_switchconfig_v1, use it. If not,
302 * create the struct.
304 if (swcfgv1 != NULL)
305 swcfg = (struct __nsw_switchconfig_v1 *)swcfgv1;
306 else {
307 char *cstr;
309 cstr = strdup(cfgstr);
310 if (cstr == NULL)
311 return (NSCD_NO_MEMORY);
314 * parse the nsw config string and create
315 * a struct __nsw_switchconfig_v1
317 swcfg = _nsw_getoneconfig_v1(dbn, cstr, &err);
318 free(cstr);
319 if (swcfg == NULL) {
320 rc = NSCD_CFG_SYNTAX_ERROR;
321 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
322 (me, "error: unable to process nsw config string\n");
323 goto error_exit;
327 /* allocate the space for a nscd_nsw_config_t */
328 nsw_cfg = calloc(1, sizeof (nscd_nsw_config_t));
329 if (nsw_cfg == NULL) {
330 rc = NSCD_NO_MEMORY;
331 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
332 (me, "error: unable to allocate an nscd_nsw_config_t\n");
333 goto error_exit;
336 /* need to know how many backends (sources) */
337 maxsrc = swcfg->num_lookups;
338 nsw_cfg->max_src = maxsrc;
341 * allocate an array to store the index for each
342 * backend (source)
344 src_idx_a = calloc(1, maxsrc * sizeof (int));
345 if (src_idx_a == NULL) {
346 rc = NSCD_NO_MEMORY;
347 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
348 (me, "error: unable to allocate an array for source index\n");
349 goto error_exit;
353 * set the index for each backend (source)
355 lkp = swcfg->lookups;
356 for (j = 0; j < maxsrc; j++) {
357 char *usrc;
359 for (k = 0; k < NSCD_NUM_SRC && NSCD_NSW_SRC_NAME(k) != NULL &&
360 strcmp(lkp->service_name, NSCD_NSW_SRC_NAME(k)) != 0;
361 k++) {
362 /* empty */
365 if (k < NSCD_NUM_SRC && nscd_src_backend_db_loaded[k] == 0) {
366 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
367 (me, "unknown nsw source name %s\n", lkp->service_name);
368 usrc = strdup(lkp->service_name);
369 if (usrc == NULL) {
370 rc = NSCD_NO_MEMORY;
371 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
372 (me, "unable to strdup() source name\n");
373 goto error_exit;
375 NSCD_NSW_SRC_NAME(k) = usrc;
377 rc = _nscd_populate_nsw_backend_info_db(k);
378 if (rc != NSCD_SUCCESS) {
379 free(usrc);
380 NSCD_NSW_SRC_NAME(k) = NULL;
381 goto error_exit;
383 } else if (NSCD_NSW_SRC_NAME(k) == NULL) {
385 * number of user-defined source exceeded
387 rc = NSCD_CFG_SYNTAX_ERROR;
388 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
389 (me, "error: number of user_defined source exceeded\n");
391 goto error_exit;
394 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
395 (me, "setting source index array [%d] = %d (%s)\n",
396 j, k, lkp->service_name);
398 src_idx_a[j] = k;
400 lkp = lkp->next;
401 if (lkp == NULL) break;
403 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
404 (me, "number of nsw sources = %d\n", nsw_cfg->max_src);
405 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
406 (me, "next nsw source is %s\n", lkp->service_name);
409 /* set it up to reference count the switch policy config */
410 nsw_cfg_p = (nscd_nsw_config_t **)_nscd_alloc(NSCD_DATA_NSW_CONFIG,
411 sizeof (nscd_nsw_config_t **), free_nscd_nsw_config,
412 NSCD_ALLOC_RWLOCK);
414 if (nsw_cfg_p == NULL) {
415 rc = NSCD_NO_MEMORY;
416 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
417 (me, "unable to allocate a new nsw config DB\n");
418 goto error_exit;
420 *nsw_cfg_p = nsw_cfg;
422 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
423 (me, "new nsw config DB %p allocated\n", nsw_cfg_p);
425 /* save all the data in the new nscd_nsw_config_t */
426 nsw_cfg->db_name = strdup(dbn);
427 nsw_cfg->nsw_cfg_str = strdup(cfgstr);
428 if (nsw_cfg->db_name == NULL || nsw_cfg->nsw_cfg_str == NULL) {
429 rc = NSCD_NO_MEMORY;
430 goto error_exit;
433 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
434 (me, "switch policy \"%s\" for database is \"%s\"\n",
435 nsw_cfg->db_name, nsw_cfg->nsw_cfg_str);
437 nsw_cfg->nsw_config = swcfg;
438 nsw_cfg->src_idx = src_idx_a;
441 * set default frontend params and if necessary call initf()
442 * to initialize or override
444 nsw_cfg->fe_params.max_active_per_src = 10;
445 nsw_cfg->fe_params.max_dormant_per_src = 1;
446 nsw_cfg->fe_params.finders = _nscd_nss_finders;
447 if (params != NULL) {
448 nsw_cfg->fe_params = params->p;
450 if (params->p.flags & NSS_USE_DEFAULT_CONFIG) {
451 params->nswcfg = nsw_cfg_p;
453 * this nsw_cfg is not meant to last long, no need
454 * to set up the nsw state and getent bases, just
455 * exit with NSCD_SUCCESS
457 nsw_cfg->nobase = 1;
458 goto error_exit;
460 } else
461 (void) (nscd_nss_db_initf[dbi])(&nsw_cfg->fe_params);
464 * also create a new nsw state base
466 if ((rc = _nscd_init_nsw_state_base(dbi, compat_basei, 1)) !=
467 NSCD_SUCCESS) {
468 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
469 (me, "unable to initialize a nsw state base(%d)\n", dbi);
470 goto error_exit;
473 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
474 (me, "new nsw state base(%d) %p created\n", dbi,
475 nscd_nsw_state_base[dbi]);
478 * also create a new getent context base
480 if ((rc = _nscd_init_getent_ctx_base(dbi, 1)) != NSCD_SUCCESS) {
481 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
482 (me, "unable to initialize a getent context base(%d)\n", dbi);
483 goto error_exit;
486 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
487 (me, "new getent context base(%d) %p created\n", dbi,
488 nscd_getent_ctx_base[dbi]);
490 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
491 (me, "new nsw config created (database = %s, "
492 "config = %s)\n", dbn, cfgstr);
495 * Activate the new nscd_nsw_config_t and make it the
496 * current nsswitch config. The old one pointed to by
497 * nscd_nsw_config[dbi] will either be destroyed
498 * immediately or left on the side line (and be
499 * destroyed eventually). __nscd_set() will set the
500 * associated flags to make it happen.
502 nscd_nsw_config[dbi] = (nscd_nsw_config_t **)_nscd_set(
503 (nscd_acc_data_t *)nscd_nsw_config[dbi],
504 (nscd_acc_data_t *)nsw_cfg_p);
506 error_exit:
508 if (rc != NSCD_SUCCESS) {
510 if (swcfgv1 == NULL && swcfg != NULL)
511 (void) __nsw_freeconfig_v1(swcfg);
512 free(src_idx_a);
513 free(nsw_cfg_p);
514 if (nsw_cfg != NULL) {
515 free(nsw_cfg->db_name);
516 free(nsw_cfg->nsw_cfg_str);
517 free(nsw_cfg);
520 return (rc);
521 } else
522 return (NSCD_SUCCESS);
525 static nscd_rc_t
526 create_nsw_config(int dbi)
529 nscd_nsw_config_t *nsw_cfg = NULL;
530 nscd_nsw_config_t **nsw_cfg_p = NULL;
531 char *me = "create_nsw_config";
534 * Allocate a pointer space for saving a pointer to a
535 * nscd_nsw_config_t. _nscd_alloc() will also create
536 * a nscd_access_t header with a rwlock_t and mutex_t
537 * for controlling later access to the data pointed
538 * to by the pointer.
540 nsw_cfg_p = (nscd_nsw_config_t **)_nscd_alloc(NSCD_DATA_NSW_CONFIG,
541 sizeof (nscd_nsw_config_t **), free_nscd_nsw_config,
542 NSCD_ALLOC_RWLOCK | NSCD_ALLOC_MUTEX);
544 if (nsw_cfg_p == NULL) {
545 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
546 (me, "unable to allocate a space for a nsw config pointer\n");
547 return (NSCD_NO_MEMORY);
549 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
550 (me, "addr for saving nsw config pointer = %p\n", nsw_cfg_p);
553 * If pseudo-databases (initf function not defined),
554 * no need to create a nscd_nsw_config_t yet,
555 * so put a NULL pointer in the pointer space.
557 if (nscd_nss_db_initf[dbi] == NULL) {
558 *nsw_cfg_p = NULL;
559 nscd_nsw_config[dbi] = (nscd_nsw_config_t **)_nscd_set(
560 (nscd_acc_data_t *)nscd_nsw_config[dbi],
561 (nscd_acc_data_t *)nsw_cfg_p);
563 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
564 (me, "pointer to nsw config has been set to NULL\n");
566 return (NSCD_SUCCESS);
569 /* allocate the space for a nscd_nsw_config_t */
570 nsw_cfg = calloc(1, sizeof (nscd_nsw_config_t));
571 if (nsw_cfg == NULL) {
572 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
573 (me, "unable to allocate a nsw config structure\n");
574 return (NSCD_NO_MEMORY);
576 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
577 (me, "nsw config structure %pallocated\n", nsw_cfg);
579 nsw_cfg->db_name = strdup(NSCD_NSW_DB_NAME(dbi));
580 if (nsw_cfg->db_name == NULL) {
581 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
582 (me, "unable to strdup the db name\n");
583 return (NSCD_NO_MEMORY);
587 * set default frontend params and then call initf()
588 * to initialize or override
590 nsw_cfg->fe_params.max_active_per_src = 10;
591 nsw_cfg->fe_params.max_dormant_per_src = 1;
592 nsw_cfg->fe_params.finders = _nscd_nss_finders;
593 (void) (nscd_nss_db_initf[dbi])(&nsw_cfg->fe_params);
596 * activate the new nscd_nsw_config_t
598 *nsw_cfg_p = nsw_cfg;
599 nscd_nsw_config[dbi] = (nscd_nsw_config_t **)_nscd_set(
600 (nscd_acc_data_t *)nscd_nsw_config[dbi],
601 (nscd_acc_data_t *)nsw_cfg_p);
603 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
604 (me, "nsw config %p activated\n", nsw_cfg);
606 return (NSCD_SUCCESS);
609 nscd_rc_t
610 _nscd_init_all_nsw_config(void)
612 nscd_rc_t rc;
613 int i;
614 char *me = "_nscd_init_all_nsw_config";
616 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
617 (me, "initializing all nsw config\n");
619 for (i = 0; i < NSCD_NUM_DB; i++) {
620 if ((rc = create_nsw_config(i)) != NSCD_SUCCESS)
621 return (rc);
624 return (NSCD_SUCCESS);
627 static nscd_rc_t
628 init_nsw_be_info_db(int srci)
630 nscd_db_t *ret, **db_p;
631 char *me = "init_nsw_be_info_db";
633 ret = _nscd_alloc_db(NSCD_DB_SIZE_SMALL);
635 if (ret == NULL) {
636 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
637 (me, "unable to allocate a nsw be info database\n");
638 return (NSCD_NO_MEMORY);
641 /* set up to reference count the backend info db */
642 db_p = (nscd_db_t **)_nscd_alloc(NSCD_DATA_BACKEND_INFO_DB,
643 sizeof (nscd_db_t **), free_nsw_backend_info_db,
644 NSCD_ALLOC_RWLOCK);
646 if (db_p == NULL) {
647 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
648 (me, "unable to allocate the pointer to the nsw "
649 "be info database\n");
650 return (NSCD_NO_MEMORY);
653 *db_p = ret;
654 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
655 (me, "backend database (db_p = %p, db = %p)\n", db_p, *db_p);
657 nscd_src_backend_db[srci] = (nscd_db_t **)_nscd_set(
658 (nscd_acc_data_t *)nscd_src_backend_db[srci],
659 (nscd_acc_data_t *)db_p);
661 return (NSCD_SUCCESS);
664 nscd_rc_t
665 _nscd_init_all_nsw_be_info_db(void)
668 int i;
669 nscd_rc_t rc;
670 char *me = "_nscd_init_all_nsw_be_info_db";
672 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
673 (me, "initializing all nsw be info databases\n");
675 for (i = 0; i < NSCD_NUM_SRC; i++) {
676 if ((rc = init_nsw_be_info_db(i)) != NSCD_SUCCESS)
677 return (rc);
680 return (NSCD_SUCCESS);
684 nscd_rc_t
685 _nscd_alloc_nsw_config()
687 nscd_nsw_config = calloc(NSCD_NUM_DB, sizeof (nscd_nsw_config_t **));
688 if (nscd_nsw_config == NULL)
689 return (NSCD_NO_MEMORY);
691 return (NSCD_SUCCESS);
694 nscd_rc_t
695 _nscd_alloc_nsw_be_info_db()
697 int i;
699 _nscd_cfg_num_nsw_src_all = _nscd_cfg_num_nsw_src +
700 NSCD_NUM_SRC_FOREIGN;
701 nscd_src_backend_db = calloc(NSCD_NUM_SRC, sizeof (nscd_db_t **));
702 if (nscd_src_backend_db == NULL)
703 return (NSCD_NO_MEMORY);
704 nscd_src_backend_db_loaded = calloc(NSCD_NUM_SRC, sizeof (int));
705 if (nscd_src_backend_db_loaded == NULL) {
706 free(nscd_src_backend_db);
707 return (NSCD_NO_MEMORY);
710 /* also allocate/init the nsswitch source index/name array */
711 _nscd_cfg_nsw_src_all = (nscd_cfg_id_t *)calloc(
712 _nscd_cfg_num_nsw_src_all + 1, sizeof (nscd_cfg_id_t));
713 for (i = 0; i < _nscd_cfg_num_nsw_src_all + 1; i++)
714 (_nscd_cfg_nsw_src_all + i)->index = -1;
716 (void) memcpy(_nscd_cfg_nsw_src_all, _nscd_cfg_nsw_src,
717 _nscd_cfg_num_nsw_src * sizeof (nscd_cfg_id_t));
718 return (NSCD_SUCCESS);
721 nscd_rc_t
722 _nscd_populate_nsw_backend_info()
724 int i;
725 nscd_rc_t rc;
727 for (i = 0; i < NSCD_NUM_SRC; i++) {
728 if (NSCD_NSW_SRC_NAME(i) == NULL)
729 continue;
730 rc = _nscd_populate_nsw_backend_info_db(i);
731 if (rc != NSCD_SUCCESS)
732 return (rc);
735 return (NSCD_SUCCESS);
739 * The following defines nscd's own lookup and delete functions
740 * that are to be stored in nss_backend_finder_t which is used
741 * by _nscd_populate_nsw_backend_info_db() to initialize the
742 * various nss backend instances
745 static const int dlopen_version = 1;
746 #ifndef NSS_DLOPEN_FORMAT
747 #define NSS_DLOPEN_FORMAT "nss_%s.so.%d"
748 #endif
749 #ifndef NSS_DLSYM_FORMAT
750 #define NSS_DLSYM_FORMAT "_nss_%s_%s_constr"
751 #define NSS_DLSYM_FORMAT_V "_nss_%s_version"
752 #endif
753 static const char dlopen_format[] = NSS_DLOPEN_FORMAT;
754 static const char dlsym_format [] = NSS_DLSYM_FORMAT;
755 static const char dlsym_format_v [] = NSS_DLSYM_FORMAT_V;
756 static const size_t format_maxlen = sizeof (dlsym_format);
758 /*ARGSUSED*/
759 static nss_backend_constr_t
760 _nscd_per_src_lookup(void *handle, const char *db_name, const char *src_name,
761 void **delete_privp)
763 char *name;
764 void *dlhandle;
765 void *sym;
766 size_t len;
767 nss_backend_constr_t res = NULL;
769 len = format_maxlen + strlen(src_name);
770 if (db_name != NULL)
771 len += strlen(db_name);
772 name = alloca(len);
773 dlhandle = handle;
774 if ((dlhandle = handle) == NULL) {
775 (void) sprintf(name, dlopen_format, src_name, dlopen_version);
776 dlhandle = dlopen(name, RTLD_LAZY);
779 if (dlhandle != NULL) {
780 if (db_name != NULL)
781 (void) sprintf(name, dlsym_format, src_name, db_name);
782 else
783 (void) sprintf(name, dlsym_format_v, src_name);
784 if ((sym = dlsym(dlhandle, name)) == 0) {
785 if (handle == NULL)
786 (void) dlclose(dlhandle);
787 } else {
788 *delete_privp = dlhandle;
789 res = (nss_backend_constr_t)sym;
792 return (res);
795 /*ARGSUSED*/
796 static void
797 _nscd_per_src_delete(void *delete_priv, nss_backend_constr_t dummy)
799 (void) dlclose(delete_priv);