xref: /illumos-gate/usr/src/cmd/nscd/nscd_nswconfig.c (revision 055d7c804dc8f1263f0b3166ba459c65996b8697)
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 	const char			*dbn,
249 	const char			*cfgstr,
250 	void				*swcfgv1,
251 	nscd_nsw_params_t		*params)
252 {
253 	char				*me = "_nscd_create_sw_struct";
254 	nscd_rc_t			rc = NSCD_SUCCESS;
255 	nscd_nsw_config_t		*nsw_cfg = NULL;
256 	nscd_nsw_config_t		**nsw_cfg_p = NULL;
257 	struct __nsw_switchconfig_v1	*swcfg = NULL;
258 	struct __nsw_lookup_v1		*lkp;
259 	enum __nsw_parse_err		err;
260 	int				maxsrc;
261 	int				*src_idx_a = NULL;
262 	int				j, k;
263 
264 	/*
265 	 * if the nsw config string has been parsed into
266 	 * a struct __nsw_switchconfig_v1, use it. If not,
267 	 * create the struct.
268 	 */
269 	if (swcfgv1 != NULL)
270 		swcfg = (struct __nsw_switchconfig_v1 *)swcfgv1;
271 	else {
272 		char	*cstr;
273 
274 		cstr = strdup(cfgstr);
275 		if (cstr == NULL)
276 			return (NSCD_NO_MEMORY);
277 
278 		/*
279 		 * parse the nsw config string and create
280 		 * a struct __nsw_switchconfig_v1
281 		 */
282 		swcfg = _nsw_getoneconfig_v1(dbn, cstr, &err);
283 		free(cstr);
284 		if (swcfg == NULL) {
285 			rc = NSCD_CFG_SYNTAX_ERROR;
286 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
287 			(me, "error: unable to process nsw config string\n");
288 			goto error_exit;
289 		}
290 	}
291 
292 	/* allocate the space for a nscd_nsw_config_t */
293 	nsw_cfg = calloc(1, sizeof (nscd_nsw_config_t));
294 	if (nsw_cfg == NULL) {
295 		rc = NSCD_NO_MEMORY;
296 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
297 		(me, "error: unable to allocate an nscd_nsw_config_t\n");
298 		goto error_exit;
299 	}
300 
301 	/* need to know how many backends (sources) */
302 	maxsrc = swcfg->num_lookups;
303 	nsw_cfg->max_src = maxsrc;
304 
305 	/*
306 	 * allocate an array to store the index for each
307 	 * backend (source)
308 	 */
309 	src_idx_a = calloc(1, maxsrc * sizeof (int));
310 	if (src_idx_a == NULL) {
311 		rc = NSCD_NO_MEMORY;
312 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
313 		(me, "error: unable to allocate an array for source index\n");
314 		goto error_exit;
315 	}
316 
317 	/*
318 	 * set the index for each backend (source)
319 	 */
320 	lkp = swcfg->lookups;
321 	for (j = 0; j < maxsrc; j++) {
322 		char *usrc;
323 
324 		for (k = 0; k < NSCD_NUM_SRC &&
325 			NSCD_NSW_SRC_NAME(k) != NULL &&
326 			strcmp(lkp->service_name,
327 			NSCD_NSW_SRC_NAME(k)) != 0; k++);
328 
329 		if (k < NSCD_NUM_SRC && NSCD_NSW_SRC_NAME(k) == NULL) {
330 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
331 			(me, "unknown nsw source name %s\n",
332 			lkp->service_name);
333 			usrc = strdup(lkp->service_name);
334 			if (usrc == NULL) {
335 				rc = NSCD_NO_MEMORY;
336 				_NSCD_LOG(NSCD_LOG_CONFIG,
337 					NSCD_LOG_LEVEL_ERROR)
338 				(me, "unable to strdup() source name\n");
339 				goto error_exit;
340 			}
341 			NSCD_NSW_SRC_NAME(k) = usrc;
342 
343 			rc = _nscd_populate_nsw_backend_info_db(k);
344 			if (rc != NSCD_SUCCESS) {
345 				free(usrc);
346 				NSCD_NSW_SRC_NAME(k) = NULL;
347 				goto error_exit;
348 			}
349 		} else if (NSCD_NSW_SRC_NAME(k) == NULL) {
350 			/*
351 			 * number of user-defined source exceeded
352 			 */
353 			rc = NSCD_CFG_SYNTAX_ERROR;
354 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
355 			(me, "error: number of user_defined source exceeded\n");
356 
357 			goto error_exit;
358 		}
359 
360 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
361 			(me, "setting source index array [%d] = %d (%s)\n",
362 			j, k, lkp->service_name);
363 
364 		src_idx_a[j] = k;
365 
366 		lkp = lkp->next;
367 		if (lkp == NULL) break;
368 
369 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
370 		(me, "number of nsw sources = %d\n", nsw_cfg->max_src);
371 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
372 		(me, "next nsw source is %s\n", lkp->service_name);
373 	}
374 
375 	/* set it up to reference count the switch policy config */
376 	nsw_cfg_p = (nscd_nsw_config_t **)_nscd_alloc(
377 			NSCD_DATA_NSW_CONFIG,
378 			sizeof (nscd_nsw_config_t **),
379 			free_nscd_nsw_config,
380 			NSCD_ALLOC_RWLOCK);
381 
382 	if (nsw_cfg_p == NULL) {
383 		rc = NSCD_NO_MEMORY;
384 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
385 		(me, "unable to allocate a new nsw config DB\n");
386 		goto error_exit;
387 	}
388 	*nsw_cfg_p = nsw_cfg;
389 
390 	_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
391 	(me, "new nsw config DB %p allocated\n", nsw_cfg_p);
392 
393 	/* save all the data in the new nscd_nsw_config_t */
394 	nsw_cfg->db_name = strdup(dbn);
395 	nsw_cfg->nsw_cfg_str = strdup(cfgstr);
396 	if (nsw_cfg->db_name == NULL || nsw_cfg->nsw_cfg_str == NULL) {
397 		rc = NSCD_NO_MEMORY;
398 		goto error_exit;
399 	}
400 
401 	_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
402 	(me, "switch policy \"%s\" for database is \"%s\"\n",
403 		nsw_cfg->db_name, nsw_cfg->nsw_cfg_str);
404 
405 	nsw_cfg->nsw_config = swcfg;
406 	nsw_cfg->src_idx = src_idx_a;
407 
408 	/*
409 	 * set default frontend params and if necessary call initf()
410 	 * to initialize or override
411 	 */
412 	nsw_cfg->fe_params.max_active_per_src = 10;
413 	nsw_cfg->fe_params.max_dormant_per_src = 1;
414 	nsw_cfg->fe_params.finders = nss_default_finders;
415 	if (params != NULL) {
416 		nsw_cfg->fe_params = params->p;
417 
418 		if (params->p.flags & NSS_USE_DEFAULT_CONFIG) {
419 			params->nswcfg = nsw_cfg_p;
420 			/*
421 			 * this nsw_cfg is not meant to last long, no need
422 			 * to set up the nsw state and getent bases, just
423 			 * exit with NSCD_SUCCESS
424 			 */
425 			nsw_cfg->nobase = 1;
426 			goto error_exit;
427 		}
428 	} else
429 		(void) (nscd_nss_db_initf[dbi])(&nsw_cfg->fe_params);
430 
431 	/*
432 	 * activate the new nscd_nsw_config_t, the old one
433 	 * will either be deleted or left on the side (and be
434 	 * deleted eventually)
435 	 */
436 	nscd_nsw_config[dbi] = (nscd_nsw_config_t **)_nscd_set(
437 		(nscd_acc_data_t *)nscd_nsw_config[dbi],
438 		(nscd_acc_data_t *)nsw_cfg_p);
439 
440 	/*
441 	 * also create a new nsw state base
442 	 */
443 	if ((rc = _nscd_init_nsw_state_base(dbi, 1)) != NSCD_SUCCESS) {
444 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
445 		(me, "unable to initialize a nsw state base(%d)\n", dbi);
446 		goto error_exit;
447 	}
448 
449 	_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
450 	(me, "new nsw state base(%d) %p created\n", dbi,
451 		nscd_nsw_state_base[dbi]);
452 
453 	/*
454 	 * also create a new getent context base
455 	 */
456 	if ((rc = _nscd_init_getent_ctx_base(dbi, 1)) != NSCD_SUCCESS) {
457 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
458 		(me, "unable to initialize a getent context base(%d)\n", dbi);
459 		goto error_exit;
460 	}
461 
462 	_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
463 	(me, "new getent context base(%d) %p created\n", dbi,
464 	nscd_getent_ctx_base[dbi]);
465 
466 	_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
467 	(me, "new nsw config created (database = %s, "
468 	"config = %s)\n", dbn, cfgstr);
469 
470 
471 	error_exit:
472 
473 	if (rc != NSCD_SUCCESS) {
474 
475 		if (swcfgv1 == NULL && swcfg != NULL)
476 			(void) __nsw_freeconfig_v1(swcfg);
477 		if (src_idx_a != NULL)
478 			free(src_idx_a);
479 		if (nsw_cfg_p)
480 			free(nsw_cfg_p);
481 		if (nsw_cfg != NULL) {
482 			if (nsw_cfg->db_name != NULL)
483 				free(nsw_cfg->db_name);
484 			if (nsw_cfg->nsw_cfg_str != NULL)
485 				free(nsw_cfg->nsw_cfg_str);
486 			free(nsw_cfg);
487 		}
488 
489 		return (rc);
490 	} else
491 		return (NSCD_SUCCESS);
492 }
493 
494 static nscd_rc_t
495 create_nsw_config(int dbi)
496 {
497 
498 	nscd_nsw_config_t	*nsw_cfg = NULL;
499 	nscd_nsw_config_t	**nsw_cfg_p = NULL;
500 	char			*me = "create_nsw_config";
501 
502 	/*
503 	 * if pseudo-databases (initf function not defined),
504 	 * don't bother now
505 	 */
506 	if (nscd_nss_db_initf[dbi] == NULL)
507 		return (NSCD_SUCCESS);
508 
509 	/* allocate the space for a nscd_nsw_config_t */
510 	nsw_cfg = calloc(1, sizeof (nscd_nsw_config_t));
511 	if (nsw_cfg == NULL) {
512 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
513 		(me, "unable to allocate a nsw config structure\n");
514 		return (NSCD_NO_MEMORY);
515 	}
516 	_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
517 	(me, "nsw config structure %pallocated\n", nsw_cfg);
518 
519 	nsw_cfg_p = (nscd_nsw_config_t **)_nscd_alloc(
520 		NSCD_DATA_NSW_CONFIG,
521 		sizeof (nscd_nsw_config_t **),
522 		free_nscd_nsw_config,
523 		NSCD_ALLOC_RWLOCK);
524 
525 	if (nsw_cfg_p == NULL) {
526 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
527 		(me, "unable to allocate a pointer to nsw config structure\n");
528 		return (NSCD_NO_MEMORY);
529 	}
530 	_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
531 		(me, "nsw config pointer = %p\n", nsw_cfg_p);
532 
533 	nsw_cfg->db_name = strdup(NSCD_NSW_DB_NAME(dbi));
534 	if (nsw_cfg->db_name == NULL) {
535 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
536 		(me, "unable to strdup the db name\n");
537 		return (NSCD_NO_MEMORY);
538 	}
539 
540 	/*
541 	 * set default frontend params and then call initf()
542 	 * to initialize or override
543 	 */
544 	nsw_cfg->fe_params.max_active_per_src = 10;
545 	nsw_cfg->fe_params.max_dormant_per_src = 1;
546 	nsw_cfg->fe_params.finders = nss_default_finders;
547 	(void) (nscd_nss_db_initf[dbi])(&nsw_cfg->fe_params);
548 
549 	/*
550 	 * activate the new nscd_nsw_config_t
551 	 */
552 	*nsw_cfg_p = nsw_cfg;
553 	nscd_nsw_config[dbi] = (nscd_nsw_config_t **)_nscd_set(
554 		(nscd_acc_data_t *)nscd_nsw_config[dbi],
555 		(nscd_acc_data_t *)nsw_cfg_p);
556 
557 	_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
558 	(me, "nsw config %p activated\n", nsw_cfg);
559 
560 	return (NSCD_SUCCESS);
561 }
562 
563 nscd_rc_t
564 _nscd_init_all_nsw_config(void)
565 {
566 	nscd_rc_t	rc;
567 	int		i;
568 	char		*me = "_nscd_init_all_nsw_config";
569 
570 	_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
571 	(me, "initializing all nsw config\n");
572 
573 	for (i = 0; i < NSCD_NUM_DB; i++) {
574 		if ((rc = create_nsw_config(i)) != NSCD_SUCCESS)
575 			return (rc);
576 	}
577 
578 	return (NSCD_SUCCESS);
579 }
580 
581 static nscd_rc_t
582 init_nsw_be_info_db(int srci)
583 {
584 	nscd_db_t	*ret, **db_p;
585 	char		*me = "init_nsw_be_info_db";
586 
587 	ret = _nscd_alloc_db(NSCD_DB_SIZE_SMALL);
588 
589 	if (ret == NULL) {
590 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
591 		(me, "unable to allocate a nsw be info database\n");
592 		return (NSCD_NO_MEMORY);
593 	}
594 
595 	/* set up to reference count the backend info db */
596 	db_p = (nscd_db_t **)
597 		_nscd_alloc(NSCD_DATA_BACKEND_INFO_DB,
598 		sizeof (nscd_db_t **),
599 		free_nsw_backend_info_db,
600 		NSCD_ALLOC_RWLOCK);
601 
602 	if (db_p == NULL) {
603 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
604 		(me, "unable to allocate the pointer to the nsw "
605 		"be info database\n");
606 		return (NSCD_NO_MEMORY);
607 	}
608 
609 	*db_p = ret;
610 	_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
611 	(me, "backend database (db_p = %p, db = %p)\n", db_p, *db_p);
612 
613 	nscd_src_backend_db[srci] = (nscd_db_t **)_nscd_set(
614 		(nscd_acc_data_t *)nscd_src_backend_db[srci],
615 		(nscd_acc_data_t *)db_p);
616 
617 	return (NSCD_SUCCESS);
618 }
619 
620 nscd_rc_t
621 _nscd_init_all_nsw_be_info_db(void)
622 {
623 
624 	int		i;
625 	nscd_rc_t	rc;
626 	char		*me = "_nscd_init_all_nsw_be_info_db";
627 
628 	_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
629 	(me, "initializing all nsw be info databases\n");
630 
631 	for (i = 0; i < NSCD_NUM_SRC; i++) {
632 		if ((rc = init_nsw_be_info_db(i)) != NSCD_SUCCESS)
633 			return (rc);
634 	}
635 
636 	return (NSCD_SUCCESS);
637 }
638 
639 
640 nscd_rc_t
641 _nscd_alloc_nsw_config()
642 {
643 	nscd_nsw_config = calloc(NSCD_NUM_DB, sizeof (nscd_nsw_config_t **));
644 	if (nscd_nsw_config == NULL)
645 		return (NSCD_NO_MEMORY);
646 
647 	return (NSCD_SUCCESS);
648 }
649 
650 nscd_rc_t
651 _nscd_alloc_nsw_be_info_db()
652 {
653 	int	i;
654 
655 	_nscd_cfg_num_nsw_src_all = _nscd_cfg_num_nsw_src + NSCD_NUM_SRC_UDEF;
656 	nscd_src_backend_db = calloc(NSCD_NUM_SRC, sizeof (nscd_db_t **));
657 	if (nscd_src_backend_db == NULL)
658 		return (NSCD_NO_MEMORY);
659 
660 	/* also allocate/init the nsswitch source index/name array */
661 	_nscd_cfg_nsw_src_all = (nscd_cfg_id_t *)calloc(
662 		_nscd_cfg_num_nsw_src_all + 1, sizeof (nscd_cfg_id_t));
663 	for (i = 0; i < _nscd_cfg_num_nsw_src_all + 1; i++)
664 		(_nscd_cfg_nsw_src_all + i)->index = -1;
665 
666 	(void) memcpy(_nscd_cfg_nsw_src_all, _nscd_cfg_nsw_src,
667 			_nscd_cfg_num_nsw_src * sizeof (nscd_cfg_id_t));
668 	return (NSCD_SUCCESS);
669 }
670 
671 nscd_rc_t
672 _nscd_populate_nsw_backend_info()
673 {
674 	int		i;
675 	nscd_rc_t	rc;
676 
677 	for (i = 0; i < NSCD_NUM_SRC; i++) {
678 		if (NSCD_NSW_SRC_NAME(i) == NULL)
679 			continue;
680 		rc = _nscd_populate_nsw_backend_info_db(i);
681 		if (rc != NSCD_SUCCESS)
682 		return (rc);
683 	}
684 
685 	return (NSCD_SUCCESS);
686 }
687