xref: /illumos-gate/usr/src/cmd/nscd/nscd_nswconfig.c (revision ad0e80f7538b612141768bfda60009eb76550ee7)
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 /*
22cb5caa98Sdjl  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23cb5caa98Sdjl  * Use is subject to license terms.
24cb5caa98Sdjl  */
25cb5caa98Sdjl 
26cb5caa98Sdjl #pragma ident	"%Z%%M%	%I%	%E% SMI"
27cb5caa98Sdjl 
28cb5caa98Sdjl #include <stdlib.h>
29cb5caa98Sdjl #include <libscf_priv.h>
30cb5caa98Sdjl #include <string.h>
31cb5caa98Sdjl #include <assert.h>
32cb5caa98Sdjl #include "nscd_switch.h"
33cb5caa98Sdjl #include "nscd_log.h"
34cb5caa98Sdjl #include "nscd_db.h"
35cb5caa98Sdjl 
36cb5caa98Sdjl /*
37cb5caa98Sdjl  * nscd database for each source. It contains backend
38cb5caa98Sdjl  * info (nscd_be_info_t) for each naming database.
39cb5caa98Sdjl  * Protected by nscd_src_backend_db_lock.
40cb5caa98Sdjl  */
41cb5caa98Sdjl nscd_db_t	***nscd_src_backend_db;
42cb5caa98Sdjl static rwlock_t nscd_src_backend_db_lock = DEFAULTRWLOCK;
43cb5caa98Sdjl 
44cb5caa98Sdjl /*
45cb5caa98Sdjl  * nsswitch config monitored by nscd. Protected by
46cb5caa98Sdjl  * readers/writer lock nscd_nsw_config_lock
47cb5caa98Sdjl  */
48cb5caa98Sdjl nscd_nsw_config_t ***nscd_nsw_config;
49cb5caa98Sdjl static rwlock_t nscd_nsw_config_lock = DEFAULTRWLOCK;
50cb5caa98Sdjl 
51cb5caa98Sdjl /*
52cb5caa98Sdjl  * nsswitch source index/name array
53cb5caa98Sdjl  * (allow 16 user-defined nsswitch sources/backends)
54cb5caa98Sdjl  */
55cb5caa98Sdjl #define		NSCD_NUM_SRC_UDEF 16
56cb5caa98Sdjl nscd_cfg_id_t	*_nscd_cfg_nsw_src_all;
57cb5caa98Sdjl int		_nscd_cfg_num_nsw_src_all;
58cb5caa98Sdjl 
59cb5caa98Sdjl static void
60cb5caa98Sdjl free_nscd_nsw_config(
61cb5caa98Sdjl 	nscd_acc_data_t		*data)
62cb5caa98Sdjl {
63cb5caa98Sdjl 
64cb5caa98Sdjl 	nscd_nsw_config_t	*nsw_cfg = *(nscd_nsw_config_t **)data;
65cb5caa98Sdjl 	char			*me = "free_nscd_nsw_config";
66cb5caa98Sdjl 
67cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
68cb5caa98Sdjl 	(me, "freeing nscd nsw config %p \n", nsw_cfg);
69cb5caa98Sdjl 	if (nsw_cfg == NULL)
70cb5caa98Sdjl 		return;
71cb5caa98Sdjl 
72cb5caa98Sdjl 	if (nsw_cfg->db_name != NULL)
73cb5caa98Sdjl 		free(nsw_cfg->db_name);
74cb5caa98Sdjl 	if (nsw_cfg->nsw_cfg_str != NULL)
75cb5caa98Sdjl 		free(nsw_cfg->nsw_cfg_str);
76cb5caa98Sdjl 	if (nsw_cfg->nsw_config != NULL)
77cb5caa98Sdjl 		(void) __nsw_freeconfig_v1(nsw_cfg->nsw_config);
78cb5caa98Sdjl 	if (nsw_cfg->src_idx != NULL)
79cb5caa98Sdjl 		free(nsw_cfg->src_idx);
80cb5caa98Sdjl 
81cb5caa98Sdjl 	free(nsw_cfg);
82cb5caa98Sdjl }
83cb5caa98Sdjl 
84cb5caa98Sdjl 
85cb5caa98Sdjl void
86cb5caa98Sdjl _nscd_free_nsw_config(
87cb5caa98Sdjl 	nscd_nsw_config_t *nswcfg)
88cb5caa98Sdjl {
89cb5caa98Sdjl 	free_nscd_nsw_config((nscd_acc_data_t *)&nswcfg);
90cb5caa98Sdjl }
91cb5caa98Sdjl 
92cb5caa98Sdjl void
93cb5caa98Sdjl _nscd_free_all_nsw_config()
94cb5caa98Sdjl {
95cb5caa98Sdjl 
96cb5caa98Sdjl 	nscd_nsw_config_t	**nsw_cfg;
97cb5caa98Sdjl 	int			i;
98cb5caa98Sdjl 	char			*me = "_nscd_free_all_nsw_config";
99cb5caa98Sdjl 
100cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
101cb5caa98Sdjl 	(me, "freeing all nscd nsw config \n");
102cb5caa98Sdjl 
103cb5caa98Sdjl 	(void) rw_wrlock(&nscd_nsw_config_lock);
104cb5caa98Sdjl 	for (i = 0; i < NSCD_NUM_DB; i++) {
105cb5caa98Sdjl 
106cb5caa98Sdjl 		if ((nsw_cfg = nscd_nsw_config[i]) == NULL)
107cb5caa98Sdjl 			continue;
108cb5caa98Sdjl 
109cb5caa98Sdjl 		nscd_nsw_config[i] = (nscd_nsw_config_t **)_nscd_set(
110cb5caa98Sdjl 			(nscd_acc_data_t *)nsw_cfg, NULL);
111cb5caa98Sdjl 	}
112cb5caa98Sdjl 	(void) rw_unlock(&nscd_nsw_config_lock);
113cb5caa98Sdjl }
114cb5caa98Sdjl 
115cb5caa98Sdjl 
116cb5caa98Sdjl static void
117cb5caa98Sdjl free_nsw_backend_info_db(nscd_acc_data_t *data)
118cb5caa98Sdjl {
119cb5caa98Sdjl 
120cb5caa98Sdjl 	nscd_db_t	*db = *(nscd_db_t **)data;
121cb5caa98Sdjl 	char		*me = "free_nsw_backend_info_db";
122cb5caa98Sdjl 
123cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
124cb5caa98Sdjl 	(me, "freeing nsw backend info db %p\n", db);
125cb5caa98Sdjl 
126cb5caa98Sdjl 	if (db == NULL)
127cb5caa98Sdjl 		return;
128cb5caa98Sdjl 
129cb5caa98Sdjl 	_nscd_free_db(db);
130cb5caa98Sdjl 
131cb5caa98Sdjl }
132cb5caa98Sdjl 
133cb5caa98Sdjl void
134cb5caa98Sdjl _nscd_free_all_nsw_backend_info_db()
135cb5caa98Sdjl {
136cb5caa98Sdjl 
137cb5caa98Sdjl 	nscd_db_t	**db;
138cb5caa98Sdjl 	int		i;
139cb5caa98Sdjl 	char		*me = " _nscd_free_all_nsw_backend_info_db";
140cb5caa98Sdjl 
141cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
142cb5caa98Sdjl 	(me, "freeing all nsw backend info db\n");
143cb5caa98Sdjl 
144cb5caa98Sdjl 	(void) rw_wrlock(&nscd_src_backend_db_lock);
145cb5caa98Sdjl 	for (i = 0; i < NSCD_NUM_SRC; i++) {
146cb5caa98Sdjl 
147cb5caa98Sdjl 		if ((db = nscd_src_backend_db[i]) == NULL)
148cb5caa98Sdjl 			continue;
149cb5caa98Sdjl 
150cb5caa98Sdjl 		nscd_src_backend_db[i] = (nscd_db_t **)_nscd_set(
151cb5caa98Sdjl 			(nscd_acc_data_t *)db, NULL);
152cb5caa98Sdjl 	}
153cb5caa98Sdjl 	(void) rw_unlock(&nscd_src_backend_db_lock);
154cb5caa98Sdjl }
155cb5caa98Sdjl 
156cb5caa98Sdjl /*
157cb5caa98Sdjl  * Populate the backend info db for the 'NSCD_NSW_SRC_NAME(srci)'
158cb5caa98Sdjl  * source.  Create one entry for each source/database pair
159cb5caa98Sdjl  * (e.g., ldap:passwd, nis:hosts, etc).
160cb5caa98Sdjl  */
161cb5caa98Sdjl static nscd_rc_t
162cb5caa98Sdjl _nscd_populate_nsw_backend_info_db(int srci)
163cb5caa98Sdjl {
164cb5caa98Sdjl 	nscd_be_info_t		be_info, *bi;
165cb5caa98Sdjl 	nss_backend_finder_t	*bf;
166cb5caa98Sdjl 	nscd_nsw_config_t	*nsw_cfg;
167cb5caa98Sdjl 	int			i, size;
168cb5caa98Sdjl 	nscd_db_entry_t		*db_entry;
169cb5caa98Sdjl 	char			*src = NSCD_NSW_SRC_NAME(srci);
170cb5caa98Sdjl 	const char		*dbn;
171cb5caa98Sdjl 	char			*me = "_nscd_populate_nsw_backend_info_db";
172cb5caa98Sdjl 
173cb5caa98Sdjl 	for (i = 0; i < NSCD_NUM_DB; i++) {
174cb5caa98Sdjl 
175cb5caa98Sdjl 		if (nscd_nsw_config[i] == NULL)
176cb5caa98Sdjl 			continue;
177cb5caa98Sdjl 
178cb5caa98Sdjl 		nsw_cfg = *nscd_nsw_config[i];
179cb5caa98Sdjl 		dbn = NSCD_NSW_DB_NAME(i);
180cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
181cb5caa98Sdjl 		(me, "adding backend info for <%s : %s>\n", src, dbn);
182cb5caa98Sdjl 
183cb5caa98Sdjl 		(void) memset(&be_info, 0, sizeof (be_info));
184cb5caa98Sdjl 
185cb5caa98Sdjl 		for (bf = nsw_cfg->fe_params.finders;  bf != 0;
186cb5caa98Sdjl 				bf = bf->next) {
187cb5caa98Sdjl 			nss_backend_constr_t c;
188cb5caa98Sdjl 
189cb5caa98Sdjl 			c = (*bf->lookup)(bf->lookup_priv, dbn, src,
190cb5caa98Sdjl 				&be_info.finder_priv);
191cb5caa98Sdjl 
192cb5caa98Sdjl 			if (c != 0) {
193cb5caa98Sdjl 				be_info.be_constr = c;
194cb5caa98Sdjl 				be_info.finder = bf;
195cb5caa98Sdjl 				break;
196cb5caa98Sdjl 			}
197cb5caa98Sdjl 		}
198cb5caa98Sdjl 		if (be_info.be_constr == NULL) {
199cb5caa98Sdjl 			/*
200cb5caa98Sdjl 			 * Couldn't find the backend anywhere.
201cb5caa98Sdjl 			 * This is fine, some backend just don't
202cb5caa98Sdjl 			 * support certain databases.
203cb5caa98Sdjl 			 */
204cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
205cb5caa98Sdjl 			(me, "unable to find backend info "
206cb5caa98Sdjl 				"for <%s : %s>\n", src, dbn);
207cb5caa98Sdjl 		}
208cb5caa98Sdjl 
209cb5caa98Sdjl 		size = sizeof (nscd_be_info_t);
210cb5caa98Sdjl 
211cb5caa98Sdjl 		db_entry = _nscd_alloc_db_entry(NSCD_DATA_BACKEND_INFO,
212cb5caa98Sdjl 				dbn, size, 1, 1);
213cb5caa98Sdjl 
214cb5caa98Sdjl 		if (db_entry == NULL) {
215cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
216cb5caa98Sdjl 			(me, "unable to allocate db entry for "
217cb5caa98Sdjl 				"<%s : %s>\n", src, dbn);
218cb5caa98Sdjl 			return (NSCD_NO_MEMORY);
219cb5caa98Sdjl 		}
220cb5caa98Sdjl 
221cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
222cb5caa98Sdjl 		(me, "adding be db entry %p for <%s : %s> to db %p: "
223cb5caa98Sdjl 			"constr = %p\n", db_entry, src, dbn,
224cb5caa98Sdjl 			*nscd_src_backend_db[srci], be_info.be_constr);
225cb5caa98Sdjl 
226cb5caa98Sdjl 		bi = (nscd_be_info_t *)*(db_entry->data_array);
227cb5caa98Sdjl 		*bi = be_info;
228cb5caa98Sdjl 
229cb5caa98Sdjl 		(void) _nscd_rdlock((nscd_acc_data_t *)
230cb5caa98Sdjl 				nscd_src_backend_db[srci]);
231cb5caa98Sdjl 		(void) _nscd_add_db_entry(*nscd_src_backend_db[srci],
232cb5caa98Sdjl 			dbn, db_entry, NSCD_ADD_DB_ENTRY_LAST);
233cb5caa98Sdjl 		(void) _nscd_rw_unlock((nscd_acc_data_t *)
234cb5caa98Sdjl 				nscd_src_backend_db[srci]);
235cb5caa98Sdjl 	}
236cb5caa98Sdjl 
237cb5caa98Sdjl 	return (NSCD_SUCCESS);
238cb5caa98Sdjl }
239cb5caa98Sdjl 
240cb5caa98Sdjl /*
241cb5caa98Sdjl  * create data structures (used by the switch engine) based
242cb5caa98Sdjl  * on the input switch policy configuration and database
243cb5caa98Sdjl  * name and indexes
244cb5caa98Sdjl  */
245cb5caa98Sdjl nscd_rc_t
246cb5caa98Sdjl _nscd_create_sw_struct(
247cb5caa98Sdjl 	int				dbi,
248*ad0e80f7Smichen 	int				compat_basei,
249cb5caa98Sdjl 	const char			*dbn,
250cb5caa98Sdjl 	const char			*cfgstr,
251cb5caa98Sdjl 	void				*swcfgv1,
252cb5caa98Sdjl 	nscd_nsw_params_t		*params)
253cb5caa98Sdjl {
254cb5caa98Sdjl 	char				*me = "_nscd_create_sw_struct";
255cb5caa98Sdjl 	nscd_rc_t			rc = NSCD_SUCCESS;
256cb5caa98Sdjl 	nscd_nsw_config_t		*nsw_cfg = NULL;
257cb5caa98Sdjl 	nscd_nsw_config_t		**nsw_cfg_p = NULL;
258cb5caa98Sdjl 	struct __nsw_switchconfig_v1	*swcfg = NULL;
259cb5caa98Sdjl 	struct __nsw_lookup_v1		*lkp;
260cb5caa98Sdjl 	enum __nsw_parse_err		err;
261cb5caa98Sdjl 	int				maxsrc;
262cb5caa98Sdjl 	int				*src_idx_a = NULL;
263cb5caa98Sdjl 	int				j, k;
264cb5caa98Sdjl 
265cb5caa98Sdjl 	/*
266cb5caa98Sdjl 	 * if the nsw config string has been parsed into
267cb5caa98Sdjl 	 * a struct __nsw_switchconfig_v1, use it. If not,
268cb5caa98Sdjl 	 * create the struct.
269cb5caa98Sdjl 	 */
270cb5caa98Sdjl 	if (swcfgv1 != NULL)
271cb5caa98Sdjl 		swcfg = (struct __nsw_switchconfig_v1 *)swcfgv1;
272cb5caa98Sdjl 	else {
273cb5caa98Sdjl 		char	*cstr;
274cb5caa98Sdjl 
275cb5caa98Sdjl 		cstr = strdup(cfgstr);
276cb5caa98Sdjl 		if (cstr == NULL)
277cb5caa98Sdjl 			return (NSCD_NO_MEMORY);
278cb5caa98Sdjl 
279cb5caa98Sdjl 		/*
280cb5caa98Sdjl 		 * parse the nsw config string and create
281cb5caa98Sdjl 		 * a struct __nsw_switchconfig_v1
282cb5caa98Sdjl 		 */
283cb5caa98Sdjl 		swcfg = _nsw_getoneconfig_v1(dbn, cstr, &err);
284cb5caa98Sdjl 		free(cstr);
285cb5caa98Sdjl 		if (swcfg == NULL) {
286cb5caa98Sdjl 			rc = NSCD_CFG_SYNTAX_ERROR;
287cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
288cb5caa98Sdjl 			(me, "error: unable to process nsw config string\n");
289cb5caa98Sdjl 			goto error_exit;
290cb5caa98Sdjl 		}
291cb5caa98Sdjl 	}
292cb5caa98Sdjl 
293cb5caa98Sdjl 	/* allocate the space for a nscd_nsw_config_t */
294cb5caa98Sdjl 	nsw_cfg = calloc(1, sizeof (nscd_nsw_config_t));
295cb5caa98Sdjl 	if (nsw_cfg == NULL) {
296cb5caa98Sdjl 		rc = NSCD_NO_MEMORY;
297cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
298cb5caa98Sdjl 		(me, "error: unable to allocate an nscd_nsw_config_t\n");
299cb5caa98Sdjl 		goto error_exit;
300cb5caa98Sdjl 	}
301cb5caa98Sdjl 
302cb5caa98Sdjl 	/* need to know how many backends (sources) */
303cb5caa98Sdjl 	maxsrc = swcfg->num_lookups;
304cb5caa98Sdjl 	nsw_cfg->max_src = maxsrc;
305cb5caa98Sdjl 
306cb5caa98Sdjl 	/*
307cb5caa98Sdjl 	 * allocate an array to store the index for each
308cb5caa98Sdjl 	 * backend (source)
309cb5caa98Sdjl 	 */
310cb5caa98Sdjl 	src_idx_a = calloc(1, maxsrc * sizeof (int));
311cb5caa98Sdjl 	if (src_idx_a == NULL) {
312cb5caa98Sdjl 		rc = NSCD_NO_MEMORY;
313cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
314cb5caa98Sdjl 		(me, "error: unable to allocate an array for source index\n");
315cb5caa98Sdjl 		goto error_exit;
316cb5caa98Sdjl 	}
317cb5caa98Sdjl 
318cb5caa98Sdjl 	/*
319cb5caa98Sdjl 	 * set the index for each backend (source)
320cb5caa98Sdjl 	 */
321cb5caa98Sdjl 	lkp = swcfg->lookups;
322cb5caa98Sdjl 	for (j = 0; j < maxsrc; j++) {
323cb5caa98Sdjl 		char *usrc;
324cb5caa98Sdjl 
325cb5caa98Sdjl 		for (k = 0; k < NSCD_NUM_SRC &&
326cb5caa98Sdjl 			NSCD_NSW_SRC_NAME(k) != NULL &&
327cb5caa98Sdjl 			strcmp(lkp->service_name,
328cb5caa98Sdjl 			NSCD_NSW_SRC_NAME(k)) != 0; k++);
329cb5caa98Sdjl 
330cb5caa98Sdjl 		if (k < NSCD_NUM_SRC && NSCD_NSW_SRC_NAME(k) == NULL) {
331cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
332cb5caa98Sdjl 			(me, "unknown nsw source name %s\n",
333cb5caa98Sdjl 			lkp->service_name);
334cb5caa98Sdjl 			usrc = strdup(lkp->service_name);
335cb5caa98Sdjl 			if (usrc == NULL) {
336cb5caa98Sdjl 				rc = NSCD_NO_MEMORY;
337cb5caa98Sdjl 				_NSCD_LOG(NSCD_LOG_CONFIG,
338cb5caa98Sdjl 					NSCD_LOG_LEVEL_ERROR)
339cb5caa98Sdjl 				(me, "unable to strdup() source name\n");
340cb5caa98Sdjl 				goto error_exit;
341cb5caa98Sdjl 			}
342cb5caa98Sdjl 			NSCD_NSW_SRC_NAME(k) = usrc;
343cb5caa98Sdjl 
344cb5caa98Sdjl 			rc = _nscd_populate_nsw_backend_info_db(k);
345cb5caa98Sdjl 			if (rc != NSCD_SUCCESS) {
346cb5caa98Sdjl 				free(usrc);
347cb5caa98Sdjl 				NSCD_NSW_SRC_NAME(k) = NULL;
348cb5caa98Sdjl 				goto error_exit;
349cb5caa98Sdjl 			}
350cb5caa98Sdjl 		} else if (NSCD_NSW_SRC_NAME(k) == NULL) {
351cb5caa98Sdjl 			/*
352cb5caa98Sdjl 			 * number of user-defined source exceeded
353cb5caa98Sdjl 			 */
354cb5caa98Sdjl 			rc = NSCD_CFG_SYNTAX_ERROR;
355cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
356cb5caa98Sdjl 			(me, "error: number of user_defined source exceeded\n");
357cb5caa98Sdjl 
358cb5caa98Sdjl 			goto error_exit;
359cb5caa98Sdjl 		}
360cb5caa98Sdjl 
361cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
362cb5caa98Sdjl 			(me, "setting source index array [%d] = %d (%s)\n",
363cb5caa98Sdjl 			j, k, lkp->service_name);
364cb5caa98Sdjl 
365cb5caa98Sdjl 		src_idx_a[j] = k;
366cb5caa98Sdjl 
367cb5caa98Sdjl 		lkp = lkp->next;
368cb5caa98Sdjl 		if (lkp == NULL) break;
369cb5caa98Sdjl 
370cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
371cb5caa98Sdjl 		(me, "number of nsw sources = %d\n", nsw_cfg->max_src);
372cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
373cb5caa98Sdjl 		(me, "next nsw source is %s\n", lkp->service_name);
374cb5caa98Sdjl 	}
375cb5caa98Sdjl 
376cb5caa98Sdjl 	/* set it up to reference count the switch policy config */
377cb5caa98Sdjl 	nsw_cfg_p = (nscd_nsw_config_t **)_nscd_alloc(
378cb5caa98Sdjl 			NSCD_DATA_NSW_CONFIG,
379cb5caa98Sdjl 			sizeof (nscd_nsw_config_t **),
380cb5caa98Sdjl 			free_nscd_nsw_config,
381cb5caa98Sdjl 			NSCD_ALLOC_RWLOCK);
382cb5caa98Sdjl 
383cb5caa98Sdjl 	if (nsw_cfg_p == NULL) {
384cb5caa98Sdjl 		rc = NSCD_NO_MEMORY;
385cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
386cb5caa98Sdjl 		(me, "unable to allocate a new nsw config DB\n");
387cb5caa98Sdjl 		goto error_exit;
388cb5caa98Sdjl 	}
389cb5caa98Sdjl 	*nsw_cfg_p = nsw_cfg;
390cb5caa98Sdjl 
391cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
392cb5caa98Sdjl 	(me, "new nsw config DB %p allocated\n", nsw_cfg_p);
393cb5caa98Sdjl 
394cb5caa98Sdjl 	/* save all the data in the new nscd_nsw_config_t */
395cb5caa98Sdjl 	nsw_cfg->db_name = strdup(dbn);
396cb5caa98Sdjl 	nsw_cfg->nsw_cfg_str = strdup(cfgstr);
397cb5caa98Sdjl 	if (nsw_cfg->db_name == NULL || nsw_cfg->nsw_cfg_str == NULL) {
398cb5caa98Sdjl 		rc = NSCD_NO_MEMORY;
399cb5caa98Sdjl 		goto error_exit;
400cb5caa98Sdjl 	}
401cb5caa98Sdjl 
402cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
403cb5caa98Sdjl 	(me, "switch policy \"%s\" for database is \"%s\"\n",
404cb5caa98Sdjl 		nsw_cfg->db_name, nsw_cfg->nsw_cfg_str);
405cb5caa98Sdjl 
406cb5caa98Sdjl 	nsw_cfg->nsw_config = swcfg;
407cb5caa98Sdjl 	nsw_cfg->src_idx = src_idx_a;
408cb5caa98Sdjl 
409cb5caa98Sdjl 	/*
410cb5caa98Sdjl 	 * set default frontend params and if necessary call initf()
411cb5caa98Sdjl 	 * to initialize or override
412cb5caa98Sdjl 	 */
413cb5caa98Sdjl 	nsw_cfg->fe_params.max_active_per_src = 10;
414cb5caa98Sdjl 	nsw_cfg->fe_params.max_dormant_per_src = 1;
415cb5caa98Sdjl 	nsw_cfg->fe_params.finders = nss_default_finders;
416cb5caa98Sdjl 	if (params != NULL) {
417cb5caa98Sdjl 		nsw_cfg->fe_params = params->p;
418cb5caa98Sdjl 
419cb5caa98Sdjl 		if (params->p.flags & NSS_USE_DEFAULT_CONFIG) {
420cb5caa98Sdjl 			params->nswcfg = nsw_cfg_p;
421cb5caa98Sdjl 			/*
422cb5caa98Sdjl 			 * this nsw_cfg is not meant to last long, no need
423cb5caa98Sdjl 			 * to set up the nsw state and getent bases, just
424cb5caa98Sdjl 			 * exit with NSCD_SUCCESS
425cb5caa98Sdjl 			 */
426cb5caa98Sdjl 			nsw_cfg->nobase = 1;
427cb5caa98Sdjl 			goto error_exit;
428cb5caa98Sdjl 		}
429cb5caa98Sdjl 	} else
430cb5caa98Sdjl 		(void) (nscd_nss_db_initf[dbi])(&nsw_cfg->fe_params);
431cb5caa98Sdjl 
432cb5caa98Sdjl 	/*
433cb5caa98Sdjl 	 * activate the new nscd_nsw_config_t, the old one
434cb5caa98Sdjl 	 * will either be deleted or left on the side (and be
435cb5caa98Sdjl 	 * deleted eventually)
436cb5caa98Sdjl 	 */
437cb5caa98Sdjl 	nscd_nsw_config[dbi] = (nscd_nsw_config_t **)_nscd_set(
438cb5caa98Sdjl 		(nscd_acc_data_t *)nscd_nsw_config[dbi],
439cb5caa98Sdjl 		(nscd_acc_data_t *)nsw_cfg_p);
440cb5caa98Sdjl 
441cb5caa98Sdjl 	/*
442cb5caa98Sdjl 	 * also create a new nsw state base
443cb5caa98Sdjl 	 */
444*ad0e80f7Smichen 	if ((rc = _nscd_init_nsw_state_base(dbi, compat_basei, 1)) !=
445*ad0e80f7Smichen 		NSCD_SUCCESS) {
446cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
447cb5caa98Sdjl 		(me, "unable to initialize a nsw state base(%d)\n", dbi);
448cb5caa98Sdjl 		goto error_exit;
449cb5caa98Sdjl 	}
450cb5caa98Sdjl 
451cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
452cb5caa98Sdjl 	(me, "new nsw state base(%d) %p created\n", dbi,
453cb5caa98Sdjl 		nscd_nsw_state_base[dbi]);
454cb5caa98Sdjl 
455cb5caa98Sdjl 	/*
456cb5caa98Sdjl 	 * also create a new getent context base
457cb5caa98Sdjl 	 */
458cb5caa98Sdjl 	if ((rc = _nscd_init_getent_ctx_base(dbi, 1)) != NSCD_SUCCESS) {
459cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
460cb5caa98Sdjl 		(me, "unable to initialize a getent context base(%d)\n", dbi);
461cb5caa98Sdjl 		goto error_exit;
462cb5caa98Sdjl 	}
463cb5caa98Sdjl 
464cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
465cb5caa98Sdjl 	(me, "new getent context base(%d) %p created\n", dbi,
466cb5caa98Sdjl 	nscd_getent_ctx_base[dbi]);
467cb5caa98Sdjl 
468cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
469cb5caa98Sdjl 	(me, "new nsw config created (database = %s, "
470cb5caa98Sdjl 	"config = %s)\n", dbn, cfgstr);
471cb5caa98Sdjl 
472cb5caa98Sdjl 
473cb5caa98Sdjl 	error_exit:
474cb5caa98Sdjl 
475cb5caa98Sdjl 	if (rc != NSCD_SUCCESS) {
476cb5caa98Sdjl 
477cb5caa98Sdjl 		if (swcfgv1 == NULL && swcfg != NULL)
478cb5caa98Sdjl 			(void) __nsw_freeconfig_v1(swcfg);
479cb5caa98Sdjl 		if (src_idx_a != NULL)
480cb5caa98Sdjl 			free(src_idx_a);
481cb5caa98Sdjl 		if (nsw_cfg_p)
482cb5caa98Sdjl 			free(nsw_cfg_p);
483cb5caa98Sdjl 		if (nsw_cfg != NULL) {
484cb5caa98Sdjl 			if (nsw_cfg->db_name != NULL)
485cb5caa98Sdjl 				free(nsw_cfg->db_name);
486cb5caa98Sdjl 			if (nsw_cfg->nsw_cfg_str != NULL)
487cb5caa98Sdjl 				free(nsw_cfg->nsw_cfg_str);
488cb5caa98Sdjl 			free(nsw_cfg);
489cb5caa98Sdjl 		}
490cb5caa98Sdjl 
491cb5caa98Sdjl 		return (rc);
492cb5caa98Sdjl 	} else
493cb5caa98Sdjl 		return (NSCD_SUCCESS);
494cb5caa98Sdjl }
495cb5caa98Sdjl 
496cb5caa98Sdjl static nscd_rc_t
497cb5caa98Sdjl create_nsw_config(int dbi)
498cb5caa98Sdjl {
499cb5caa98Sdjl 
500cb5caa98Sdjl 	nscd_nsw_config_t	*nsw_cfg = NULL;
501cb5caa98Sdjl 	nscd_nsw_config_t	**nsw_cfg_p = NULL;
502cb5caa98Sdjl 	char			*me = "create_nsw_config";
503cb5caa98Sdjl 
504cb5caa98Sdjl 	/*
505cb5caa98Sdjl 	 * if pseudo-databases (initf function not defined),
506cb5caa98Sdjl 	 * don't bother now
507cb5caa98Sdjl 	 */
508cb5caa98Sdjl 	if (nscd_nss_db_initf[dbi] == NULL)
509cb5caa98Sdjl 		return (NSCD_SUCCESS);
510cb5caa98Sdjl 
511cb5caa98Sdjl 	/* allocate the space for a nscd_nsw_config_t */
512cb5caa98Sdjl 	nsw_cfg = calloc(1, sizeof (nscd_nsw_config_t));
513cb5caa98Sdjl 	if (nsw_cfg == NULL) {
514cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
515cb5caa98Sdjl 		(me, "unable to allocate a nsw config structure\n");
516cb5caa98Sdjl 		return (NSCD_NO_MEMORY);
517cb5caa98Sdjl 	}
518cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
519cb5caa98Sdjl 	(me, "nsw config structure %pallocated\n", nsw_cfg);
520cb5caa98Sdjl 
521cb5caa98Sdjl 	nsw_cfg_p = (nscd_nsw_config_t **)_nscd_alloc(
522cb5caa98Sdjl 		NSCD_DATA_NSW_CONFIG,
523cb5caa98Sdjl 		sizeof (nscd_nsw_config_t **),
524cb5caa98Sdjl 		free_nscd_nsw_config,
525cb5caa98Sdjl 		NSCD_ALLOC_RWLOCK);
526cb5caa98Sdjl 
527cb5caa98Sdjl 	if (nsw_cfg_p == NULL) {
528cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
529cb5caa98Sdjl 		(me, "unable to allocate a pointer to nsw config structure\n");
530cb5caa98Sdjl 		return (NSCD_NO_MEMORY);
531cb5caa98Sdjl 	}
532cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
533cb5caa98Sdjl 		(me, "nsw config pointer = %p\n", nsw_cfg_p);
534cb5caa98Sdjl 
535cb5caa98Sdjl 	nsw_cfg->db_name = strdup(NSCD_NSW_DB_NAME(dbi));
536cb5caa98Sdjl 	if (nsw_cfg->db_name == NULL) {
537cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
538cb5caa98Sdjl 		(me, "unable to strdup the db name\n");
539cb5caa98Sdjl 		return (NSCD_NO_MEMORY);
540cb5caa98Sdjl 	}
541cb5caa98Sdjl 
542cb5caa98Sdjl 	/*
543cb5caa98Sdjl 	 * set default frontend params and then call initf()
544cb5caa98Sdjl 	 * to initialize or override
545cb5caa98Sdjl 	 */
546cb5caa98Sdjl 	nsw_cfg->fe_params.max_active_per_src = 10;
547cb5caa98Sdjl 	nsw_cfg->fe_params.max_dormant_per_src = 1;
548cb5caa98Sdjl 	nsw_cfg->fe_params.finders = nss_default_finders;
549cb5caa98Sdjl 	(void) (nscd_nss_db_initf[dbi])(&nsw_cfg->fe_params);
550cb5caa98Sdjl 
551cb5caa98Sdjl 	/*
552cb5caa98Sdjl 	 * activate the new nscd_nsw_config_t
553cb5caa98Sdjl 	 */
554cb5caa98Sdjl 	*nsw_cfg_p = nsw_cfg;
555cb5caa98Sdjl 	nscd_nsw_config[dbi] = (nscd_nsw_config_t **)_nscd_set(
556cb5caa98Sdjl 		(nscd_acc_data_t *)nscd_nsw_config[dbi],
557cb5caa98Sdjl 		(nscd_acc_data_t *)nsw_cfg_p);
558cb5caa98Sdjl 
559cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
560cb5caa98Sdjl 	(me, "nsw config %p activated\n", nsw_cfg);
561cb5caa98Sdjl 
562cb5caa98Sdjl 	return (NSCD_SUCCESS);
563cb5caa98Sdjl }
564cb5caa98Sdjl 
565cb5caa98Sdjl nscd_rc_t
566cb5caa98Sdjl _nscd_init_all_nsw_config(void)
567cb5caa98Sdjl {
568cb5caa98Sdjl 	nscd_rc_t	rc;
569cb5caa98Sdjl 	int		i;
570cb5caa98Sdjl 	char		*me = "_nscd_init_all_nsw_config";
571cb5caa98Sdjl 
572cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
573cb5caa98Sdjl 	(me, "initializing all nsw config\n");
574cb5caa98Sdjl 
575cb5caa98Sdjl 	for (i = 0; i < NSCD_NUM_DB; i++) {
576cb5caa98Sdjl 		if ((rc = create_nsw_config(i)) != NSCD_SUCCESS)
577cb5caa98Sdjl 			return (rc);
578cb5caa98Sdjl 	}
579cb5caa98Sdjl 
580cb5caa98Sdjl 	return (NSCD_SUCCESS);
581cb5caa98Sdjl }
582cb5caa98Sdjl 
583cb5caa98Sdjl static nscd_rc_t
584cb5caa98Sdjl init_nsw_be_info_db(int srci)
585cb5caa98Sdjl {
586cb5caa98Sdjl 	nscd_db_t	*ret, **db_p;
587cb5caa98Sdjl 	char		*me = "init_nsw_be_info_db";
588cb5caa98Sdjl 
589cb5caa98Sdjl 	ret = _nscd_alloc_db(NSCD_DB_SIZE_SMALL);
590cb5caa98Sdjl 
591cb5caa98Sdjl 	if (ret == NULL) {
592cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
593cb5caa98Sdjl 		(me, "unable to allocate a nsw be info database\n");
594cb5caa98Sdjl 		return (NSCD_NO_MEMORY);
595cb5caa98Sdjl 	}
596cb5caa98Sdjl 
597cb5caa98Sdjl 	/* set up to reference count the backend info db */
598cb5caa98Sdjl 	db_p = (nscd_db_t **)
599cb5caa98Sdjl 		_nscd_alloc(NSCD_DATA_BACKEND_INFO_DB,
600cb5caa98Sdjl 		sizeof (nscd_db_t **),
601cb5caa98Sdjl 		free_nsw_backend_info_db,
602cb5caa98Sdjl 		NSCD_ALLOC_RWLOCK);
603cb5caa98Sdjl 
604cb5caa98Sdjl 	if (db_p == NULL) {
605cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
606cb5caa98Sdjl 		(me, "unable to allocate the pointer to the nsw "
607cb5caa98Sdjl 		"be info database\n");
608cb5caa98Sdjl 		return (NSCD_NO_MEMORY);
609cb5caa98Sdjl 	}
610cb5caa98Sdjl 
611cb5caa98Sdjl 	*db_p = ret;
612cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
613cb5caa98Sdjl 	(me, "backend database (db_p = %p, db = %p)\n", db_p, *db_p);
614cb5caa98Sdjl 
615cb5caa98Sdjl 	nscd_src_backend_db[srci] = (nscd_db_t **)_nscd_set(
616cb5caa98Sdjl 		(nscd_acc_data_t *)nscd_src_backend_db[srci],
617cb5caa98Sdjl 		(nscd_acc_data_t *)db_p);
618cb5caa98Sdjl 
619cb5caa98Sdjl 	return (NSCD_SUCCESS);
620cb5caa98Sdjl }
621cb5caa98Sdjl 
622cb5caa98Sdjl nscd_rc_t
623cb5caa98Sdjl _nscd_init_all_nsw_be_info_db(void)
624cb5caa98Sdjl {
625cb5caa98Sdjl 
626cb5caa98Sdjl 	int		i;
627cb5caa98Sdjl 	nscd_rc_t	rc;
628cb5caa98Sdjl 	char		*me = "_nscd_init_all_nsw_be_info_db";
629cb5caa98Sdjl 
630cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
631cb5caa98Sdjl 	(me, "initializing all nsw be info databases\n");
632cb5caa98Sdjl 
633cb5caa98Sdjl 	for (i = 0; i < NSCD_NUM_SRC; i++) {
634cb5caa98Sdjl 		if ((rc = init_nsw_be_info_db(i)) != NSCD_SUCCESS)
635cb5caa98Sdjl 			return (rc);
636cb5caa98Sdjl 	}
637cb5caa98Sdjl 
638cb5caa98Sdjl 	return (NSCD_SUCCESS);
639cb5caa98Sdjl }
640cb5caa98Sdjl 
641cb5caa98Sdjl 
642cb5caa98Sdjl nscd_rc_t
643cb5caa98Sdjl _nscd_alloc_nsw_config()
644cb5caa98Sdjl {
645cb5caa98Sdjl 	nscd_nsw_config = calloc(NSCD_NUM_DB, sizeof (nscd_nsw_config_t **));
646cb5caa98Sdjl 	if (nscd_nsw_config == NULL)
647cb5caa98Sdjl 		return (NSCD_NO_MEMORY);
648cb5caa98Sdjl 
649cb5caa98Sdjl 	return (NSCD_SUCCESS);
650cb5caa98Sdjl }
651cb5caa98Sdjl 
652cb5caa98Sdjl nscd_rc_t
653cb5caa98Sdjl _nscd_alloc_nsw_be_info_db()
654cb5caa98Sdjl {
655cb5caa98Sdjl 	int	i;
656cb5caa98Sdjl 
657cb5caa98Sdjl 	_nscd_cfg_num_nsw_src_all = _nscd_cfg_num_nsw_src + NSCD_NUM_SRC_UDEF;
658cb5caa98Sdjl 	nscd_src_backend_db = calloc(NSCD_NUM_SRC, sizeof (nscd_db_t **));
659cb5caa98Sdjl 	if (nscd_src_backend_db == NULL)
660cb5caa98Sdjl 		return (NSCD_NO_MEMORY);
661cb5caa98Sdjl 
662cb5caa98Sdjl 	/* also allocate/init the nsswitch source index/name array */
663cb5caa98Sdjl 	_nscd_cfg_nsw_src_all = (nscd_cfg_id_t *)calloc(
664cb5caa98Sdjl 		_nscd_cfg_num_nsw_src_all + 1, sizeof (nscd_cfg_id_t));
665cb5caa98Sdjl 	for (i = 0; i < _nscd_cfg_num_nsw_src_all + 1; i++)
666cb5caa98Sdjl 		(_nscd_cfg_nsw_src_all + i)->index = -1;
667cb5caa98Sdjl 
668cb5caa98Sdjl 	(void) memcpy(_nscd_cfg_nsw_src_all, _nscd_cfg_nsw_src,
669cb5caa98Sdjl 			_nscd_cfg_num_nsw_src * sizeof (nscd_cfg_id_t));
670cb5caa98Sdjl 	return (NSCD_SUCCESS);
671cb5caa98Sdjl }
672cb5caa98Sdjl 
673cb5caa98Sdjl nscd_rc_t
674cb5caa98Sdjl _nscd_populate_nsw_backend_info()
675cb5caa98Sdjl {
676cb5caa98Sdjl 	int		i;
677cb5caa98Sdjl 	nscd_rc_t	rc;
678cb5caa98Sdjl 
679cb5caa98Sdjl 	for (i = 0; i < NSCD_NUM_SRC; i++) {
680cb5caa98Sdjl 		if (NSCD_NSW_SRC_NAME(i) == NULL)
681cb5caa98Sdjl 			continue;
682cb5caa98Sdjl 		rc = _nscd_populate_nsw_backend_info_db(i);
683cb5caa98Sdjl 		if (rc != NSCD_SUCCESS)
684cb5caa98Sdjl 		return (rc);
685cb5caa98Sdjl 	}
686cb5caa98Sdjl 
687cb5caa98Sdjl 	return (NSCD_SUCCESS);
688cb5caa98Sdjl }
689