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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <nss_common.h>
31 #include <libscf_priv.h>
34 #include "nscd_switch.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
= {
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
;
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
);
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
);
103 _nscd_free_nsw_config(
104 nscd_nsw_config_t
*nswcfg
)
106 free_nscd_nsw_config((nscd_acc_data_t
*)&nswcfg
);
110 _nscd_free_all_nsw_config()
113 nscd_nsw_config_t
**nsw_cfg
;
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
)
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
);
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
);
151 _nscd_free_all_nsw_backend_info_db()
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
)
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).
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
;
186 nscd_db_entry_t
*db_entry
;
187 char *src
= NSCD_NSW_SRC_NAME(srci
);
189 char *me
= "_nscd_populate_nsw_backend_info_db";
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
);
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
)
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
);
224 be_info
.be_constr
= c
;
226 be_info
.finder_priv
= handle
;
227 be_info
.be_version
= be_version
;
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
,
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
);
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
280 _nscd_create_sw_struct(
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
;
296 int *src_idx_a
= NULL
;
300 * if the nsw config string has been parsed into
301 * a struct __nsw_switchconfig_v1, use it. If not,
305 swcfg
= (struct __nsw_switchconfig_v1
*)swcfgv1
;
309 cstr
= strdup(cfgstr
);
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
);
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");
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
) {
331 _NSCD_LOG(NSCD_LOG_CONFIG
, NSCD_LOG_LEVEL_ERROR
)
332 (me
, "error: unable to allocate an nscd_nsw_config_t\n");
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
344 src_idx_a
= calloc(1, maxsrc
* sizeof (int));
345 if (src_idx_a
== NULL
) {
347 _NSCD_LOG(NSCD_LOG_CONFIG
, NSCD_LOG_LEVEL_ERROR
)
348 (me
, "error: unable to allocate an array for source index\n");
353 * set the index for each backend (source)
355 lkp
= swcfg
->lookups
;
356 for (j
= 0; j
< maxsrc
; j
++) {
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;
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
);
371 _NSCD_LOG(NSCD_LOG_CONFIG
, NSCD_LOG_LEVEL_ERROR
)
372 (me
, "unable to strdup() source name\n");
375 NSCD_NSW_SRC_NAME(k
) = usrc
;
377 rc
= _nscd_populate_nsw_backend_info_db(k
);
378 if (rc
!= NSCD_SUCCESS
) {
380 NSCD_NSW_SRC_NAME(k
) = NULL
;
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");
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
);
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
,
414 if (nsw_cfg_p
== NULL
) {
416 _NSCD_LOG(NSCD_LOG_CONFIG
, NSCD_LOG_LEVEL_ERROR
)
417 (me
, "unable to allocate a new nsw config DB\n");
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
) {
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
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)) !=
468 _NSCD_LOG(NSCD_LOG_CONFIG
, NSCD_LOG_LEVEL_ERROR
)
469 (me
, "unable to initialize a nsw state base(%d)\n", dbi
);
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
);
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
);
508 if (rc
!= NSCD_SUCCESS
) {
510 if (swcfgv1
== NULL
&& swcfg
!= NULL
)
511 (void) __nsw_freeconfig_v1(swcfg
);
514 if (nsw_cfg
!= NULL
) {
515 free(nsw_cfg
->db_name
);
516 free(nsw_cfg
->nsw_cfg_str
);
522 return (NSCD_SUCCESS
);
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
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
) {
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
);
610 _nscd_init_all_nsw_config(void)
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
)
624 return (NSCD_SUCCESS
);
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
);
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
,
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
);
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
);
665 _nscd_init_all_nsw_be_info_db(void)
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
)
680 return (NSCD_SUCCESS
);
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
);
695 _nscd_alloc_nsw_be_info_db()
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
);
722 _nscd_populate_nsw_backend_info()
727 for (i
= 0; i
< NSCD_NUM_SRC
; i
++) {
728 if (NSCD_NSW_SRC_NAME(i
) == NULL
)
730 rc
= _nscd_populate_nsw_backend_info_db(i
);
731 if (rc
!= NSCD_SUCCESS
)
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"
749 #ifndef NSS_DLSYM_FORMAT
750 #define NSS_DLSYM_FORMAT "_nss_%s_%s_constr"
751 #define NSS_DLSYM_FORMAT_V "_nss_%s_version"
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
);
759 static nss_backend_constr_t
760 _nscd_per_src_lookup(void *handle
, const char *db_name
, const char *src_name
,
767 nss_backend_constr_t res
= NULL
;
769 len
= format_maxlen
+ strlen(src_name
);
771 len
+= strlen(db_name
);
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
) {
781 (void) sprintf(name
, dlsym_format
, src_name
, db_name
);
783 (void) sprintf(name
, dlsym_format_v
, src_name
);
784 if ((sym
= dlsym(dlhandle
, name
)) == 0) {
786 (void) dlclose(dlhandle
);
788 *delete_privp
= dlhandle
;
789 res
= (nss_backend_constr_t
)sym
;
797 _nscd_per_src_delete(void *delete_priv
, nss_backend_constr_t dummy
)
799 (void) dlclose(delete_priv
);