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