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