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