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