xref: /titanic_44/usr/src/cmd/nscd/nscd_config.c (revision cb5caa98562cf06753163f558cbcfe30b8f4673a)
1*cb5caa98Sdjl /*
2*cb5caa98Sdjl  * CDDL HEADER START
3*cb5caa98Sdjl  *
4*cb5caa98Sdjl  * The contents of this file are subject to the terms of the
5*cb5caa98Sdjl  * Common Development and Distribution License (the "License").
6*cb5caa98Sdjl  * You may not use this file except in compliance with the License.
7*cb5caa98Sdjl  *
8*cb5caa98Sdjl  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*cb5caa98Sdjl  * or http://www.opensolaris.org/os/licensing.
10*cb5caa98Sdjl  * See the License for the specific language governing permissions
11*cb5caa98Sdjl  * and limitations under the License.
12*cb5caa98Sdjl  *
13*cb5caa98Sdjl  * When distributing Covered Code, include this CDDL HEADER in each
14*cb5caa98Sdjl  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*cb5caa98Sdjl  * If applicable, add the following below this CDDL HEADER, with the
16*cb5caa98Sdjl  * fields enclosed by brackets "[]" replaced with your own identifying
17*cb5caa98Sdjl  * information: Portions Copyright [yyyy] [name of copyright owner]
18*cb5caa98Sdjl  *
19*cb5caa98Sdjl  * CDDL HEADER END
20*cb5caa98Sdjl  */
21*cb5caa98Sdjl /*
22*cb5caa98Sdjl  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23*cb5caa98Sdjl  * Use is subject to license terms.
24*cb5caa98Sdjl  */
25*cb5caa98Sdjl 
26*cb5caa98Sdjl #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*cb5caa98Sdjl 
28*cb5caa98Sdjl #include <stdio.h>
29*cb5caa98Sdjl #include <stdlib.h>
30*cb5caa98Sdjl #include <locale.h>		/* gettext */
31*cb5caa98Sdjl #include <dlfcn.h>
32*cb5caa98Sdjl #include <string.h>
33*cb5caa98Sdjl #include <sys/varargs.h>
34*cb5caa98Sdjl #include <errno.h>
35*cb5caa98Sdjl #include "nscd_db.h"
36*cb5caa98Sdjl #include "nscd_config.h"
37*cb5caa98Sdjl #include "nscd_cfgdef.h"
38*cb5caa98Sdjl #include "nscd_log.h"
39*cb5caa98Sdjl 
40*cb5caa98Sdjl typedef struct {
41*cb5caa98Sdjl 	rwlock_t	*global;
42*cb5caa98Sdjl 	rwlock_t	*alldb;
43*cb5caa98Sdjl 	rwlock_t	*nswdb;
44*cb5caa98Sdjl } nscd_cfg_lock_t;
45*cb5caa98Sdjl 
46*cb5caa98Sdjl static rwlock_t		cfg_paramDB_rwlock = DEFAULTRWLOCK;
47*cb5caa98Sdjl static nscd_db_t	*cfg_paramDB = NULL;
48*cb5caa98Sdjl 
49*cb5caa98Sdjl static	nscd_cfg_global_data_t 	*nscd_cfg_global_current;
50*cb5caa98Sdjl static	nscd_cfg_nsw_db_data_t	*nscd_cfg_nsw_db_data_current;
51*cb5caa98Sdjl static	nscd_cfg_nsw_db_data_t	*nscd_cfg_nsw_alldb_current;
52*cb5caa98Sdjl static	rwlock_t		*nscd_cfg_global_rwlock;
53*cb5caa98Sdjl static	rwlock_t		*nscd_cfg_nsw_db_data_rwlock;
54*cb5caa98Sdjl static	rwlock_t		*nscd_cfg_nsw_alldb_rwlock;
55*cb5caa98Sdjl 
56*cb5caa98Sdjl extern	int			_nscd_cfg_num_nsw_src_all;
57*cb5caa98Sdjl extern	nscd_cfg_id_t		*_nscd_cfg_nsw_src_all;
58*cb5caa98Sdjl 
59*cb5caa98Sdjl nscd_cfg_error_t *
60*cb5caa98Sdjl _nscd_cfg_make_error(
61*cb5caa98Sdjl 	nscd_rc_t	rc,
62*cb5caa98Sdjl 	char		*msg)
63*cb5caa98Sdjl {
64*cb5caa98Sdjl 
65*cb5caa98Sdjl 	nscd_cfg_error_t	*ret;
66*cb5caa98Sdjl 	int			size, msglen;
67*cb5caa98Sdjl 
68*cb5caa98Sdjl 	msglen = (msg != NULL ? strlen(msg) + 1 : 0);
69*cb5caa98Sdjl 
70*cb5caa98Sdjl 	size = sizeof (nscd_cfg_error_t) + msglen;
71*cb5caa98Sdjl 
72*cb5caa98Sdjl 	ret = calloc(1, size);
73*cb5caa98Sdjl 	if (ret == NULL)
74*cb5caa98Sdjl 		return (NULL);
75*cb5caa98Sdjl 
76*cb5caa98Sdjl 	ret->rc = rc;
77*cb5caa98Sdjl 	if (msg != NULL) {
78*cb5caa98Sdjl 		ret->msg = (char *)ret +
79*cb5caa98Sdjl 			sizeof (nscd_cfg_error_t);
80*cb5caa98Sdjl 		(void) memcpy(ret->msg, msg, msglen);
81*cb5caa98Sdjl 	}
82*cb5caa98Sdjl 
83*cb5caa98Sdjl 	return (ret);
84*cb5caa98Sdjl }
85*cb5caa98Sdjl 
86*cb5caa98Sdjl static nscd_rc_t
87*cb5caa98Sdjl _nscd_cfg_get_list(
88*cb5caa98Sdjl 	nscd_cfg_list_t		**list,
89*cb5caa98Sdjl 	nscd_cfg_list_type_t	type)
90*cb5caa98Sdjl {
91*cb5caa98Sdjl 	char			*me = "_nscd_cfg_get_list";
92*cb5caa98Sdjl 	int			i, num, size;
93*cb5caa98Sdjl 	nscd_cfg_id_t		*l;
94*cb5caa98Sdjl 	nscd_cfg_list_t 	*ret;
95*cb5caa98Sdjl 	nscd_cfg_param_desc_t	*pl;
96*cb5caa98Sdjl 	nscd_cfg_stat_desc_t	*sl;
97*cb5caa98Sdjl 	void			*p;
98*cb5caa98Sdjl 
99*cb5caa98Sdjl 	if (list == NULL) {
100*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
101*cb5caa98Sdjl 		(me, "invalid argument: list = %p\n", list);
102*cb5caa98Sdjl 
103*cb5caa98Sdjl 		return (NSCD_INVALID_ARGUMENT);
104*cb5caa98Sdjl 	}
105*cb5caa98Sdjl 	*list = NULL;
106*cb5caa98Sdjl 
107*cb5caa98Sdjl 	switch (type) {
108*cb5caa98Sdjl 	case NSCD_CFG_LIST_NSW_DB:
109*cb5caa98Sdjl 
110*cb5caa98Sdjl 		num = _nscd_cfg_num_nsw_db;
111*cb5caa98Sdjl 		l = &_nscd_cfg_nsw_db[0];
112*cb5caa98Sdjl 		break;
113*cb5caa98Sdjl 
114*cb5caa98Sdjl 	case NSCD_CFG_LIST_NSW_SRC:
115*cb5caa98Sdjl 
116*cb5caa98Sdjl 		num = _nscd_cfg_num_nsw_src_all;
117*cb5caa98Sdjl 		l = _nscd_cfg_nsw_src_all;
118*cb5caa98Sdjl 		break;
119*cb5caa98Sdjl 
120*cb5caa98Sdjl 	case NSCD_CFG_LIST_PARAM:
121*cb5caa98Sdjl 
122*cb5caa98Sdjl 		num = _nscd_cfg_num_param;
123*cb5caa98Sdjl 		pl = &_nscd_cfg_param_desc[0];
124*cb5caa98Sdjl 		break;
125*cb5caa98Sdjl 
126*cb5caa98Sdjl 	case NSCD_CFG_LIST_STAT:
127*cb5caa98Sdjl 
128*cb5caa98Sdjl 		num = _nscd_cfg_num_stat;
129*cb5caa98Sdjl 		sl = &_nscd_cfg_stat_desc[0];
130*cb5caa98Sdjl 		break;
131*cb5caa98Sdjl 
132*cb5caa98Sdjl 	default:
133*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
134*cb5caa98Sdjl 		(me, "invalid argument: type (%d)\n", type);
135*cb5caa98Sdjl 
136*cb5caa98Sdjl 		return (NSCD_INVALID_ARGUMENT);
137*cb5caa98Sdjl 		break;
138*cb5caa98Sdjl 	}
139*cb5caa98Sdjl 
140*cb5caa98Sdjl 	size =  sizeof (nscd_cfg_list_t) + sizeof (nscd_cfg_id_t *) * (num + 1);
141*cb5caa98Sdjl 
142*cb5caa98Sdjl 	ret = calloc(1, size);
143*cb5caa98Sdjl 	if (ret == NULL)
144*cb5caa98Sdjl 		return (NSCD_NO_MEMORY);
145*cb5caa98Sdjl 
146*cb5caa98Sdjl 	ret->num = num;
147*cb5caa98Sdjl 	p = (char *)ret + sizeof (nscd_cfg_list_t);
148*cb5caa98Sdjl 	ret->list = (nscd_cfg_id_t **)p;
149*cb5caa98Sdjl 
150*cb5caa98Sdjl 	if (type == NSCD_CFG_LIST_PARAM) {
151*cb5caa98Sdjl 		for (i = 0; i <= num; i++)
152*cb5caa98Sdjl 			ret->list[i] = (nscd_cfg_id_t *)&pl[i];
153*cb5caa98Sdjl 	} else if (type == NSCD_CFG_LIST_STAT) {
154*cb5caa98Sdjl 		for (i = 0; i <= num; i++)
155*cb5caa98Sdjl 			ret->list[i] = (nscd_cfg_id_t *)&sl[i];
156*cb5caa98Sdjl 	} else {
157*cb5caa98Sdjl 		for (i = 0; i <= num; i++)
158*cb5caa98Sdjl 			ret->list[i] = &l[i];
159*cb5caa98Sdjl 	}
160*cb5caa98Sdjl 
161*cb5caa98Sdjl 	*list = ret;
162*cb5caa98Sdjl 
163*cb5caa98Sdjl 	return (NSCD_SUCCESS);
164*cb5caa98Sdjl }
165*cb5caa98Sdjl 
166*cb5caa98Sdjl nscd_rc_t
167*cb5caa98Sdjl _nscd_cfg_get_param_desc_list(
168*cb5caa98Sdjl 	nscd_cfg_param_desc_list_t **list)
169*cb5caa98Sdjl {
170*cb5caa98Sdjl 	return (_nscd_cfg_get_list((nscd_cfg_list_t **)list,
171*cb5caa98Sdjl 		NSCD_CFG_LIST_PARAM));
172*cb5caa98Sdjl }
173*cb5caa98Sdjl 
174*cb5caa98Sdjl /* find function pointer in the executable via dlopen(0) */
175*cb5caa98Sdjl static nscd_rc_t
176*cb5caa98Sdjl _nscd_cfg_init_funcs(
177*cb5caa98Sdjl 	char			*name,
178*cb5caa98Sdjl 	void			**func_p,
179*cb5caa98Sdjl 	nscd_cfg_error_t	**errorp)
180*cb5caa98Sdjl {
181*cb5caa98Sdjl 	char			*me = "_nscd_cfg_init_funcs";
182*cb5caa98Sdjl 	char			msg[NSCD_CFG_MAX_ERR_MSG_LEN];
183*cb5caa98Sdjl 	static void		*handle = NULL;
184*cb5caa98Sdjl 	void			*sym;
185*cb5caa98Sdjl 	nscd_rc_t		rc = NSCD_SUCCESS;
186*cb5caa98Sdjl 
187*cb5caa98Sdjl 	if (name == NULL && handle != NULL) {
188*cb5caa98Sdjl 		(void) dlclose(handle);
189*cb5caa98Sdjl 		return (rc);
190*cb5caa98Sdjl 	}
191*cb5caa98Sdjl 	if (name == NULL)
192*cb5caa98Sdjl 		return (rc);
193*cb5caa98Sdjl 
194*cb5caa98Sdjl 	if (handle == NULL) {
195*cb5caa98Sdjl 		handle = dlopen((const char *)0, RTLD_LAZY);
196*cb5caa98Sdjl 		if (handle == NULL) {
197*cb5caa98Sdjl 
198*cb5caa98Sdjl 			rc = NSCD_CFG_DLOPEN_ERROR;
199*cb5caa98Sdjl 			(void) snprintf(msg, sizeof (msg),
200*cb5caa98Sdjl 			gettext("unable to dlopen the nscd executable: %s"),
201*cb5caa98Sdjl 				dlerror());
202*cb5caa98Sdjl 			goto error_exit;
203*cb5caa98Sdjl 		}
204*cb5caa98Sdjl 	}
205*cb5caa98Sdjl 
206*cb5caa98Sdjl 	if (func_p) {
207*cb5caa98Sdjl 		if ((sym = dlsym(handle, name)) == NULL) {
208*cb5caa98Sdjl 
209*cb5caa98Sdjl 			rc = NSCD_CFG_DLSYM_ERROR;
210*cb5caa98Sdjl 			(void) snprintf(msg, sizeof (msg),
211*cb5caa98Sdjl gettext("unable to get the address of a symbol in the nscd executable: %s"),
212*cb5caa98Sdjl 				dlerror());
213*cb5caa98Sdjl 			goto error_exit;
214*cb5caa98Sdjl 		} else
215*cb5caa98Sdjl 			(void) memcpy(func_p, &sym, sizeof (void *));
216*cb5caa98Sdjl 	}
217*cb5caa98Sdjl 
218*cb5caa98Sdjl 	return (rc);
219*cb5caa98Sdjl 
220*cb5caa98Sdjl 	error_exit:
221*cb5caa98Sdjl 
222*cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
223*cb5caa98Sdjl 	(me, "%s\n", msg);
224*cb5caa98Sdjl 	if (errorp != NULL)
225*cb5caa98Sdjl 		*errorp = _nscd_cfg_make_error(rc, msg);
226*cb5caa98Sdjl 
227*cb5caa98Sdjl 	return (rc);
228*cb5caa98Sdjl }
229*cb5caa98Sdjl 
230*cb5caa98Sdjl 
231*cb5caa98Sdjl /*
232*cb5caa98Sdjl  * FUNCTION: _nscd_cfg_create_paramDB
233*cb5caa98Sdjl  *
234*cb5caa98Sdjl  * Create the internal config parameter database
235*cb5caa98Sdjl  */
236*cb5caa98Sdjl static nscd_db_t *
237*cb5caa98Sdjl _nscd_cfg_create_paramDB()
238*cb5caa98Sdjl {
239*cb5caa98Sdjl 
240*cb5caa98Sdjl 	nscd_db_t	*ret;
241*cb5caa98Sdjl 
242*cb5caa98Sdjl 	(void) rw_wrlock(&cfg_paramDB_rwlock);
243*cb5caa98Sdjl 
244*cb5caa98Sdjl 	ret = _nscd_alloc_db(NSCD_DB_SIZE_MEDIUM);
245*cb5caa98Sdjl 
246*cb5caa98Sdjl 	if (ret != NULL)
247*cb5caa98Sdjl 		cfg_paramDB = ret;
248*cb5caa98Sdjl 
249*cb5caa98Sdjl 	(void) rw_unlock(&cfg_paramDB_rwlock);
250*cb5caa98Sdjl 
251*cb5caa98Sdjl 	return (ret);
252*cb5caa98Sdjl }
253*cb5caa98Sdjl 
254*cb5caa98Sdjl /*
255*cb5caa98Sdjl  * FUNCTION: _nscd_cfg_add_index_entry
256*cb5caa98Sdjl  *
257*cb5caa98Sdjl  * Add a config index entry (a name to index mapping)
258*cb5caa98Sdjl  * to the internal configuration database.
259*cb5caa98Sdjl  */
260*cb5caa98Sdjl static nscd_rc_t
261*cb5caa98Sdjl _nscd_cfg_add_index_entry(
262*cb5caa98Sdjl 	char			*name,
263*cb5caa98Sdjl 	int			index,
264*cb5caa98Sdjl 	nscd_cfg_list_type_t	type)
265*cb5caa98Sdjl {
266*cb5caa98Sdjl 	int		*idx;
267*cb5caa98Sdjl 	int		size;
268*cb5caa98Sdjl 	int		dbe_type;
269*cb5caa98Sdjl 	nscd_db_entry_t	*db_entry;
270*cb5caa98Sdjl 
271*cb5caa98Sdjl 	if (name == NULL)
272*cb5caa98Sdjl 		return (NSCD_INVALID_ARGUMENT);
273*cb5caa98Sdjl 
274*cb5caa98Sdjl 	if (type == NSCD_CFG_LIST_NSW_DB)
275*cb5caa98Sdjl 		dbe_type = NSCD_DATA_CFG_NSW_DB_INDEX;
276*cb5caa98Sdjl 	else if (type == NSCD_CFG_LIST_NSW_SRC)
277*cb5caa98Sdjl 		dbe_type = NSCD_DATA_CFG_NSW_SRC_INDEX;
278*cb5caa98Sdjl 	else if (type == NSCD_CFG_LIST_PARAM)
279*cb5caa98Sdjl 		dbe_type = NSCD_DATA_CFG_PARAM_INDEX;
280*cb5caa98Sdjl 	else if (type == NSCD_CFG_LIST_STAT)
281*cb5caa98Sdjl 		dbe_type = NSCD_DATA_CFG_STAT_INDEX;
282*cb5caa98Sdjl 
283*cb5caa98Sdjl 	size = sizeof (int);
284*cb5caa98Sdjl 
285*cb5caa98Sdjl 	db_entry = _nscd_alloc_db_entry(dbe_type, (const char *)name,
286*cb5caa98Sdjl 			size, 1, 1);
287*cb5caa98Sdjl 	if (db_entry == NULL)
288*cb5caa98Sdjl 		return (NSCD_NO_MEMORY);
289*cb5caa98Sdjl 
290*cb5caa98Sdjl 	idx = (int *)*(db_entry->data_array);
291*cb5caa98Sdjl 	*idx = index;
292*cb5caa98Sdjl 
293*cb5caa98Sdjl 	(void) rw_wrlock(&cfg_paramDB_rwlock);
294*cb5caa98Sdjl 	(void) _nscd_add_db_entry(cfg_paramDB, name, db_entry,
295*cb5caa98Sdjl 		NSCD_ADD_DB_ENTRY_FIRST);
296*cb5caa98Sdjl 	(void) rw_unlock(&cfg_paramDB_rwlock);
297*cb5caa98Sdjl 
298*cb5caa98Sdjl 	return (NSCD_SUCCESS);
299*cb5caa98Sdjl }
300*cb5caa98Sdjl 
301*cb5caa98Sdjl /*
302*cb5caa98Sdjl  * FUNCTION: _nscd_cfg_get_index
303*cb5caa98Sdjl  *
304*cb5caa98Sdjl  * Get the index of a config data item by searching the internal config
305*cb5caa98Sdjl  * database. Do not free the returned data.
306*cb5caa98Sdjl  */
307*cb5caa98Sdjl static int
308*cb5caa98Sdjl _nscd_cfg_get_index(
309*cb5caa98Sdjl 	char			*name,
310*cb5caa98Sdjl 	nscd_cfg_list_type_t	type)
311*cb5caa98Sdjl {
312*cb5caa98Sdjl 	int			index = -1, dbe_type;
313*cb5caa98Sdjl 	const nscd_db_entry_t	*db_entry;
314*cb5caa98Sdjl 
315*cb5caa98Sdjl 	if (name == NULL)
316*cb5caa98Sdjl 		return (-1);
317*cb5caa98Sdjl 
318*cb5caa98Sdjl 	if (type == NSCD_CFG_LIST_NSW_DB)
319*cb5caa98Sdjl 		dbe_type = NSCD_DATA_CFG_NSW_DB_INDEX;
320*cb5caa98Sdjl 	else if (type == NSCD_CFG_LIST_NSW_SRC)
321*cb5caa98Sdjl 		dbe_type = NSCD_DATA_CFG_NSW_SRC_INDEX;
322*cb5caa98Sdjl 	else if (type == NSCD_CFG_LIST_PARAM)
323*cb5caa98Sdjl 		dbe_type = NSCD_DATA_CFG_PARAM_INDEX;
324*cb5caa98Sdjl 	else if (type == NSCD_CFG_LIST_STAT)
325*cb5caa98Sdjl 		dbe_type = NSCD_DATA_CFG_STAT_INDEX;
326*cb5caa98Sdjl 	else
327*cb5caa98Sdjl 		return (-1);
328*cb5caa98Sdjl 
329*cb5caa98Sdjl 	db_entry = _nscd_get_db_entry(cfg_paramDB, dbe_type,
330*cb5caa98Sdjl 		(const char *)name, NSCD_GET_FIRST_DB_ENTRY, 0);
331*cb5caa98Sdjl 
332*cb5caa98Sdjl 	if (db_entry != NULL)
333*cb5caa98Sdjl 		index = *(int *)*(db_entry->data_array);
334*cb5caa98Sdjl 
335*cb5caa98Sdjl 	return (index);
336*cb5caa98Sdjl }
337*cb5caa98Sdjl 
338*cb5caa98Sdjl static nscd_rc_t
339*cb5caa98Sdjl _nscd_cfg_verify_group_info(
340*cb5caa98Sdjl 	nscd_cfg_group_info_t	*g_info,
341*cb5caa98Sdjl 	nscd_cfg_param_desc_t	*gdesc)
342*cb5caa98Sdjl {
343*cb5caa98Sdjl 
344*cb5caa98Sdjl 	char			*me = "_nscd_cfg_verify_group_info";
345*cb5caa98Sdjl 	void			*vp;
346*cb5caa98Sdjl 	nscd_cfg_group_info_t	*gi;
347*cb5caa98Sdjl 
348*cb5caa98Sdjl 	if (_nscd_cfg_flag_is_set(gdesc->pflag, NSCD_CFG_PFLAG_GLOBAL)) {
349*cb5caa98Sdjl 		vp = (char *)&nscd_cfg_global_default +
350*cb5caa98Sdjl 			gdesc->g_offset;
351*cb5caa98Sdjl 		gi = (nscd_cfg_group_info_t *)vp;
352*cb5caa98Sdjl 	} else {
353*cb5caa98Sdjl 		vp = (char *)&nscd_cfg_nsw_db_data_default +
354*cb5caa98Sdjl 			gdesc->g_offset;
355*cb5caa98Sdjl 		gi = (nscd_cfg_group_info_t *)vp;
356*cb5caa98Sdjl 
357*cb5caa98Sdjl 	}
358*cb5caa98Sdjl 
359*cb5caa98Sdjl 	if (g_info->num_param == gi->num_param &&
360*cb5caa98Sdjl 		_nscd_cfg_bitmap_is_equal(g_info->bitmap, gi->bitmap))
361*cb5caa98Sdjl 		return (NSCD_SUCCESS);
362*cb5caa98Sdjl 
363*cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
364*cb5caa98Sdjl 	(me, "ERROR: group (%s) info mismatched: group info "
365*cb5caa98Sdjl 	"(%d, %#6.4x) not equal to that of default configuration data "
366*cb5caa98Sdjl 	"(%d, %#6.4x)\n", gdesc->id.name, g_info->num_param,
367*cb5caa98Sdjl 	_nscd_cfg_bitmap_value(g_info->bitmap), gi->num_param,
368*cb5caa98Sdjl 	_nscd_cfg_bitmap_value(gi->bitmap));
369*cb5caa98Sdjl 
370*cb5caa98Sdjl 	return (NSCD_CFG_PARAM_DESC_ERROR);
371*cb5caa98Sdjl 
372*cb5caa98Sdjl }
373*cb5caa98Sdjl 
374*cb5caa98Sdjl 
375*cb5caa98Sdjl static nscd_rc_t
376*cb5caa98Sdjl _nscd_cfg_init_nsw()
377*cb5caa98Sdjl {
378*cb5caa98Sdjl 	char			*me = "_nscd_cfg_init_nsw";
379*cb5caa98Sdjl 	int			i, j, idx, rc, num;
380*cb5caa98Sdjl 	nscd_cfg_id_t		*id;
381*cb5caa98Sdjl 	nscd_cfg_list_type_t	type[2] = { NSCD_CFG_LIST_NSW_DB,
382*cb5caa98Sdjl 					NSCD_CFG_LIST_NSW_SRC };
383*cb5caa98Sdjl 
384*cb5caa98Sdjl 	nscd_cfg_id_t		*list[2] = { _nscd_cfg_nsw_db, NULL};
385*cb5caa98Sdjl 
386*cb5caa98Sdjl 	list[1] = _nscd_cfg_nsw_src_all;
387*cb5caa98Sdjl 
388*cb5caa98Sdjl 	for (j = 0; j < 2; j++) {
389*cb5caa98Sdjl 
390*cb5caa98Sdjl 		if (j == 0)
391*cb5caa98Sdjl 			num = _nscd_cfg_num_nsw_db + 1;
392*cb5caa98Sdjl 		else
393*cb5caa98Sdjl 			num = _nscd_cfg_num_nsw_src_all;
394*cb5caa98Sdjl 
395*cb5caa98Sdjl 		for (i = 0; i < num; i++) {
396*cb5caa98Sdjl 
397*cb5caa98Sdjl 			/*
398*cb5caa98Sdjl 			 * _nscd_cfg_nsw_alldb is the id for the
399*cb5caa98Sdjl 			 * special ALLDB (defaults for all db)
400*cb5caa98Sdjl 			 */
401*cb5caa98Sdjl 			if (j == 0 && i == _nscd_cfg_num_nsw_db) {
402*cb5caa98Sdjl 				id = &_nscd_cfg_nsw_alldb;
403*cb5caa98Sdjl 				idx = NSCD_CFG_NSW_ALLDB_INDEX;
404*cb5caa98Sdjl 			} else {
405*cb5caa98Sdjl 				id = &(list[j])[i];
406*cb5caa98Sdjl 				id->index = idx = i;
407*cb5caa98Sdjl 			}
408*cb5caa98Sdjl 
409*cb5caa98Sdjl 			if (id->name == NULL)
410*cb5caa98Sdjl 				continue;
411*cb5caa98Sdjl 
412*cb5caa98Sdjl 			if ((rc = _nscd_cfg_add_index_entry(id->name,
413*cb5caa98Sdjl 				idx, type[j])) != NSCD_SUCCESS) {
414*cb5caa98Sdjl 
415*cb5caa98Sdjl 				_NSCD_LOG(NSCD_LOG_CONFIG,
416*cb5caa98Sdjl 					NSCD_LOG_LEVEL_ERROR)
417*cb5caa98Sdjl 				(me, "unable to add index entry for "
418*cb5caa98Sdjl 				"nsswitch entry %s\n", id->name);
419*cb5caa98Sdjl 
420*cb5caa98Sdjl 				_nscd_free_db(cfg_paramDB);
421*cb5caa98Sdjl 				return (rc);
422*cb5caa98Sdjl 			}
423*cb5caa98Sdjl 		}
424*cb5caa98Sdjl 	}
425*cb5caa98Sdjl 
426*cb5caa98Sdjl 	return (NSCD_SUCCESS);
427*cb5caa98Sdjl }
428*cb5caa98Sdjl 
429*cb5caa98Sdjl /*
430*cb5caa98Sdjl  * get the address of a function in the nscd executable
431*cb5caa98Sdjl  * and store it in where 'dest_p' points to
432*cb5caa98Sdjl  */
433*cb5caa98Sdjl static nscd_rc_t
434*cb5caa98Sdjl _nscd_cfg_get_funcp(
435*cb5caa98Sdjl 	char			*name,
436*cb5caa98Sdjl 	void			*dest_p,
437*cb5caa98Sdjl 	void			**gfunc_a,
438*cb5caa98Sdjl 	nscd_cfg_error_t	**errorp)
439*cb5caa98Sdjl {
440*cb5caa98Sdjl 
441*cb5caa98Sdjl 	void			*func;
442*cb5caa98Sdjl 	nscd_rc_t		rc;
443*cb5caa98Sdjl 
444*cb5caa98Sdjl 	if (gfunc_a != NULL) {
445*cb5caa98Sdjl 
446*cb5caa98Sdjl 		if (strcmp(name, NSCD_CFG_FUNC_NAME_AS_GROUP) == 0)
447*cb5caa98Sdjl 			(void) memcpy(dest_p, gfunc_a, sizeof (void *));
448*cb5caa98Sdjl 
449*cb5caa98Sdjl 		return (NSCD_SUCCESS);
450*cb5caa98Sdjl 	}
451*cb5caa98Sdjl 
452*cb5caa98Sdjl 	rc = _nscd_cfg_init_funcs(name, &func, errorp);
453*cb5caa98Sdjl 	if (rc != NSCD_SUCCESS)
454*cb5caa98Sdjl 		return (rc);
455*cb5caa98Sdjl 	(void) memcpy(dest_p, &func, sizeof (func));
456*cb5caa98Sdjl 
457*cb5caa98Sdjl 	return (NSCD_SUCCESS);
458*cb5caa98Sdjl }
459*cb5caa98Sdjl 
460*cb5caa98Sdjl static nscd_rc_t
461*cb5caa98Sdjl _nscd_cfg_init_param()
462*cb5caa98Sdjl {
463*cb5caa98Sdjl 	char			*me = "_nscd_cfg_init_param";
464*cb5caa98Sdjl 	int			i, gi, fn = 0;
465*cb5caa98Sdjl 	nscd_cfg_id_t		*id;
466*cb5caa98Sdjl 	nscd_cfg_param_desc_t	*desc, *gdesc = NULL;
467*cb5caa98Sdjl 	nscd_cfg_group_info_t	g_info;
468*cb5caa98Sdjl 	nscd_cfg_list_type_t	type = NSCD_CFG_LIST_PARAM;
469*cb5caa98Sdjl 	nscd_rc_t		rc;
470*cb5caa98Sdjl 	void			*nfunc, *vfunc;
471*cb5caa98Sdjl 
472*cb5caa98Sdjl 	if (_nscd_cfg_create_paramDB() == NULL)
473*cb5caa98Sdjl 		return (NSCD_NO_MEMORY);
474*cb5caa98Sdjl 
475*cb5caa98Sdjl 	desc = &_nscd_cfg_param_desc[0];
476*cb5caa98Sdjl 
477*cb5caa98Sdjl 	/*
478*cb5caa98Sdjl 	 * need to loop to the last (+1) param description
479*cb5caa98Sdjl 	 * which is a fake group and which marks the end
480*cb5caa98Sdjl 	 * of list. It is used to signal the end of the
481*cb5caa98Sdjl 	 * previous group so that the proper data will be
482*cb5caa98Sdjl 	 * set for that group
483*cb5caa98Sdjl 	 */
484*cb5caa98Sdjl 	for (i = 0; i < _nscd_cfg_num_param + 1; i++, desc++) {
485*cb5caa98Sdjl 
486*cb5caa98Sdjl 		id = (nscd_cfg_id_t *)desc;
487*cb5caa98Sdjl 
488*cb5caa98Sdjl 		if (_nscd_cfg_flag_is_set(desc->pflag,
489*cb5caa98Sdjl 			NSCD_CFG_PFLAG_GROUP)) {
490*cb5caa98Sdjl 
491*cb5caa98Sdjl 			if (gdesc != NULL) {
492*cb5caa98Sdjl 				g_info.num_param = fn;
493*cb5caa98Sdjl 				gdesc->p_fn = fn;
494*cb5caa98Sdjl 
495*cb5caa98Sdjl 				if ((rc = _nscd_cfg_verify_group_info(
496*cb5caa98Sdjl 					&g_info, gdesc)) != NSCD_SUCCESS)
497*cb5caa98Sdjl 					return (rc);
498*cb5caa98Sdjl 			}
499*cb5caa98Sdjl 
500*cb5caa98Sdjl 			gi = i;
501*cb5caa98Sdjl 			fn = 0;
502*cb5caa98Sdjl 			gdesc = desc;
503*cb5caa98Sdjl 			g_info.bitmap = NSCD_CFG_BITMAP_ZERO;
504*cb5caa98Sdjl 			nfunc = NULL;
505*cb5caa98Sdjl 			vfunc = NULL;
506*cb5caa98Sdjl 
507*cb5caa98Sdjl 			/*
508*cb5caa98Sdjl 			 * set the notify/verify functions
509*cb5caa98Sdjl 			 */
510*cb5caa98Sdjl 			if (gdesc->nfunc_name != NULL) {
511*cb5caa98Sdjl 				rc = _nscd_cfg_get_funcp(gdesc->nfunc_name,
512*cb5caa98Sdjl 					&gdesc->notify, NULL, NULL);
513*cb5caa98Sdjl 				if (rc != NULL)
514*cb5caa98Sdjl 					return (rc);
515*cb5caa98Sdjl 				nfunc = (void *)gdesc->notify;
516*cb5caa98Sdjl 			}
517*cb5caa98Sdjl 			if (gdesc->vfunc_name != NULL) {
518*cb5caa98Sdjl 				rc = _nscd_cfg_get_funcp(gdesc->vfunc_name,
519*cb5caa98Sdjl 					&gdesc->verify, NULL, NULL);
520*cb5caa98Sdjl 				if (rc != NULL)
521*cb5caa98Sdjl 					return (rc);
522*cb5caa98Sdjl 				vfunc = (void *)gdesc->verify;
523*cb5caa98Sdjl 			}
524*cb5caa98Sdjl 		} else {
525*cb5caa98Sdjl 			if (i == 0) {
526*cb5caa98Sdjl 
527*cb5caa98Sdjl 				_NSCD_LOG(NSCD_LOG_CONFIG,
528*cb5caa98Sdjl 						NSCD_LOG_LEVEL_ERROR)
529*cb5caa98Sdjl 				(me, "ERROR: first parameter "
530*cb5caa98Sdjl 				"description is not for a group\n");
531*cb5caa98Sdjl 
532*cb5caa98Sdjl 				return (NSCD_CFG_PARAM_DESC_ERROR);
533*cb5caa98Sdjl 			}
534*cb5caa98Sdjl 
535*cb5caa98Sdjl 			/*
536*cb5caa98Sdjl 			 * set bitmap: the rightmost bit represents
537*cb5caa98Sdjl 			 * the first member (index = 0) in the group,
538*cb5caa98Sdjl 			 * the next bit is for the second member
539*cb5caa98Sdjl 			 * (index = 1), and so on
540*cb5caa98Sdjl 			 */
541*cb5caa98Sdjl 			_nscd_cfg_bitmap_set_nth(g_info.bitmap, fn);
542*cb5caa98Sdjl 
543*cb5caa98Sdjl 			desc->p_fn = fn++;
544*cb5caa98Sdjl 
545*cb5caa98Sdjl 			/*
546*cb5caa98Sdjl 			 * set the notify/verify functions
547*cb5caa98Sdjl 			 */
548*cb5caa98Sdjl 			if (desc->nfunc_name != NULL) {
549*cb5caa98Sdjl 				rc = _nscd_cfg_get_funcp(desc->nfunc_name,
550*cb5caa98Sdjl 					&desc->notify, &nfunc, NULL);
551*cb5caa98Sdjl 				if (rc != NULL)
552*cb5caa98Sdjl 					return (rc);
553*cb5caa98Sdjl 			}
554*cb5caa98Sdjl 			if (desc->vfunc_name != NULL) {
555*cb5caa98Sdjl 				rc = _nscd_cfg_get_funcp(desc->vfunc_name,
556*cb5caa98Sdjl 					&desc->verify, &vfunc, NULL);
557*cb5caa98Sdjl 				if (rc != NULL)
558*cb5caa98Sdjl 					return (rc);
559*cb5caa98Sdjl 			}
560*cb5caa98Sdjl 		}
561*cb5caa98Sdjl 
562*cb5caa98Sdjl 		/* if end of list reached, we are done */
563*cb5caa98Sdjl 		if (i == _nscd_cfg_num_param)
564*cb5caa98Sdjl 			break;
565*cb5caa98Sdjl 
566*cb5caa98Sdjl 		desc->g_index = gi;
567*cb5caa98Sdjl 
568*cb5caa98Sdjl 		id->index = i;
569*cb5caa98Sdjl 
570*cb5caa98Sdjl 		if ((rc = _nscd_cfg_add_index_entry(id->name,
571*cb5caa98Sdjl 			i, type)) != NSCD_SUCCESS) {
572*cb5caa98Sdjl 
573*cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
574*cb5caa98Sdjl 			(me, "unable to add index entry for parameter "
575*cb5caa98Sdjl 			"%s\n", id->name);
576*cb5caa98Sdjl 
577*cb5caa98Sdjl 			_nscd_free_db(cfg_paramDB);
578*cb5caa98Sdjl 			return (rc);
579*cb5caa98Sdjl 		} else {
580*cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
581*cb5caa98Sdjl 			(me, "index entry for parameter "
582*cb5caa98Sdjl 			"%s added\n", id->name);
583*cb5caa98Sdjl 		}
584*cb5caa98Sdjl 	}
585*cb5caa98Sdjl 
586*cb5caa98Sdjl 	return (_nscd_cfg_init_nsw());
587*cb5caa98Sdjl }
588*cb5caa98Sdjl 
589*cb5caa98Sdjl static nscd_rc_t
590*cb5caa98Sdjl _nscd_cfg_init_stat()
591*cb5caa98Sdjl {
592*cb5caa98Sdjl 	char			*me = "_nscd_cfg_init_stat";
593*cb5caa98Sdjl 	int			i, gi, fn = 0;
594*cb5caa98Sdjl 	nscd_cfg_id_t		*id;
595*cb5caa98Sdjl 	nscd_cfg_stat_desc_t	*desc, *gdesc = NULL;
596*cb5caa98Sdjl 	nscd_cfg_group_info_t	g_info;
597*cb5caa98Sdjl 	nscd_cfg_list_type_t	type = NSCD_CFG_LIST_STAT;
598*cb5caa98Sdjl 	nscd_rc_t		rc;
599*cb5caa98Sdjl 	void			*gsfunc;
600*cb5caa98Sdjl 
601*cb5caa98Sdjl 	desc = &_nscd_cfg_stat_desc[0];
602*cb5caa98Sdjl 
603*cb5caa98Sdjl 	/*
604*cb5caa98Sdjl 	 * need to loop to the last (+1) stat description
605*cb5caa98Sdjl 	 * which is a fake group and which marks the end
606*cb5caa98Sdjl 	 * of list. It is used to signal the end of the
607*cb5caa98Sdjl 	 * previous group so that the proper data will be
608*cb5caa98Sdjl 	 * set for that group
609*cb5caa98Sdjl 	 */
610*cb5caa98Sdjl 	for (i = 0; i < _nscd_cfg_num_stat + 1; i++, desc++) {
611*cb5caa98Sdjl 
612*cb5caa98Sdjl 		id = (nscd_cfg_id_t *)desc;
613*cb5caa98Sdjl 
614*cb5caa98Sdjl 		if (_nscd_cfg_flag_is_set(desc->sflag,
615*cb5caa98Sdjl 			NSCD_CFG_SFLAG_GROUP)) {
616*cb5caa98Sdjl 
617*cb5caa98Sdjl 			if (gdesc != NULL) {
618*cb5caa98Sdjl 				g_info.num_param = fn;
619*cb5caa98Sdjl 				gdesc->s_fn = fn;
620*cb5caa98Sdjl 
621*cb5caa98Sdjl 				if (g_info.num_param !=
622*cb5caa98Sdjl 					gdesc->gi.num_param ||
623*cb5caa98Sdjl 					!_nscd_cfg_bitmap_is_equal(
624*cb5caa98Sdjl 					g_info.bitmap, gdesc->gi.bitmap)) {
625*cb5caa98Sdjl 
626*cb5caa98Sdjl 					_NSCD_LOG(NSCD_LOG_CONFIG,
627*cb5caa98Sdjl 						NSCD_LOG_LEVEL_ERROR)
628*cb5caa98Sdjl 					(me, "ERROR: group (%s) "
629*cb5caa98Sdjl 					"info mismatched: "
630*cb5caa98Sdjl 					"group info (%d, %#6.4x) not "
631*cb5caa98Sdjl 					"equal to the predefined one "
632*cb5caa98Sdjl 					"(%d, %#6.4x)\n", gdesc->id.name,
633*cb5caa98Sdjl 					g_info.num_param,
634*cb5caa98Sdjl 					_nscd_cfg_bitmap_value(g_info.bitmap),
635*cb5caa98Sdjl 					gdesc->gi.num_param,
636*cb5caa98Sdjl 					_nscd_cfg_bitmap_value(
637*cb5caa98Sdjl 						gdesc->gi.bitmap));
638*cb5caa98Sdjl 
639*cb5caa98Sdjl 					exit(1);
640*cb5caa98Sdjl 					return (NSCD_CFG_STAT_DESC_ERROR);
641*cb5caa98Sdjl 				}
642*cb5caa98Sdjl 			}
643*cb5caa98Sdjl 
644*cb5caa98Sdjl 			gi = i;
645*cb5caa98Sdjl 			fn = 0;
646*cb5caa98Sdjl 			gdesc = desc;
647*cb5caa98Sdjl 			g_info.bitmap = NSCD_CFG_BITMAP_ZERO;
648*cb5caa98Sdjl 			gsfunc = NULL;
649*cb5caa98Sdjl 
650*cb5caa98Sdjl 			/*
651*cb5caa98Sdjl 			 * set the get_stat function
652*cb5caa98Sdjl 			 */
653*cb5caa98Sdjl 			if (gdesc->gsfunc_name != NULL) {
654*cb5caa98Sdjl 				rc = _nscd_cfg_get_funcp(gdesc->gsfunc_name,
655*cb5caa98Sdjl 					&gdesc->get_stat, NULL, NULL);
656*cb5caa98Sdjl 				if (rc != NULL)
657*cb5caa98Sdjl 					return (rc);
658*cb5caa98Sdjl 				gsfunc = (void *)gdesc->get_stat;
659*cb5caa98Sdjl 			}
660*cb5caa98Sdjl 		} else {
661*cb5caa98Sdjl 			if (i == 0) {
662*cb5caa98Sdjl 
663*cb5caa98Sdjl 				_NSCD_LOG(NSCD_LOG_CONFIG,
664*cb5caa98Sdjl 						NSCD_LOG_LEVEL_ERROR)
665*cb5caa98Sdjl 				(me, "ERROR: first stat "
666*cb5caa98Sdjl 				"description is not for a group\n");
667*cb5caa98Sdjl 
668*cb5caa98Sdjl 				return (NSCD_CFG_STAT_DESC_ERROR);
669*cb5caa98Sdjl 			}
670*cb5caa98Sdjl 
671*cb5caa98Sdjl 			/*
672*cb5caa98Sdjl 			 * set bitmap: the rightmost bit represents
673*cb5caa98Sdjl 			 * the first member (index = 0) in the group,
674*cb5caa98Sdjl 			 * the next bit is for the second member
675*cb5caa98Sdjl 			 * (index = 1), and so on
676*cb5caa98Sdjl 			 */
677*cb5caa98Sdjl 			_nscd_cfg_bitmap_set_nth(g_info.bitmap, fn);
678*cb5caa98Sdjl 
679*cb5caa98Sdjl 			desc->s_fn = fn++;
680*cb5caa98Sdjl 
681*cb5caa98Sdjl 			/*
682*cb5caa98Sdjl 			 * set the get_stat function
683*cb5caa98Sdjl 			 */
684*cb5caa98Sdjl 			if (desc->gsfunc_name != NULL) {
685*cb5caa98Sdjl 				rc = _nscd_cfg_get_funcp(desc->gsfunc_name,
686*cb5caa98Sdjl 					&desc->get_stat, &gsfunc, NULL);
687*cb5caa98Sdjl 				if (rc != NULL)
688*cb5caa98Sdjl 					return (rc);
689*cb5caa98Sdjl 			}
690*cb5caa98Sdjl 		}
691*cb5caa98Sdjl 
692*cb5caa98Sdjl 		/* if end of list reached, we are done */
693*cb5caa98Sdjl 		if (i == _nscd_cfg_num_stat)
694*cb5caa98Sdjl 			break;
695*cb5caa98Sdjl 
696*cb5caa98Sdjl 		desc->g_index = gi;
697*cb5caa98Sdjl 
698*cb5caa98Sdjl 		id->index = i;
699*cb5caa98Sdjl 
700*cb5caa98Sdjl 		if ((rc = _nscd_cfg_add_index_entry(id->name,
701*cb5caa98Sdjl 			i, type)) != NSCD_SUCCESS) {
702*cb5caa98Sdjl 
703*cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
704*cb5caa98Sdjl 			(me, "unable to add index entry for stat "
705*cb5caa98Sdjl 			"description %s\n", id->name);
706*cb5caa98Sdjl 
707*cb5caa98Sdjl 			_nscd_free_db(cfg_paramDB);
708*cb5caa98Sdjl 			return (rc);
709*cb5caa98Sdjl 		} else {
710*cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
711*cb5caa98Sdjl 			(me, "index entry for stat description "
712*cb5caa98Sdjl 			"%s added\n", id->name);
713*cb5caa98Sdjl 		}
714*cb5caa98Sdjl 	}
715*cb5caa98Sdjl 
716*cb5caa98Sdjl 	return (NSCD_SUCCESS);
717*cb5caa98Sdjl }
718*cb5caa98Sdjl 
719*cb5caa98Sdjl static nscd_rc_t
720*cb5caa98Sdjl _nscd_cfg_copy_vlen_data(
721*cb5caa98Sdjl 	void			*data,
722*cb5caa98Sdjl 	void			**new_data_p,
723*cb5caa98Sdjl 	nscd_cfg_param_desc_t	*desc,
724*cb5caa98Sdjl 	int			*data_len,
725*cb5caa98Sdjl 	nscd_bool_t		in)
726*cb5caa98Sdjl {
727*cb5caa98Sdjl 	int			len, dlen;
728*cb5caa98Sdjl 	nscd_cfg_vlen_data_t	*v = NULL;
729*cb5caa98Sdjl 
730*cb5caa98Sdjl 	*new_data_p = NULL;
731*cb5caa98Sdjl 	*data_len = 0;
732*cb5caa98Sdjl 
733*cb5caa98Sdjl 	/* it is OK if there is nothing to copy */
734*cb5caa98Sdjl 	if (data == NULL)
735*cb5caa98Sdjl 		return (NSCD_SUCCESS);
736*cb5caa98Sdjl 
737*cb5caa98Sdjl 	/*
738*cb5caa98Sdjl 	 * if copy to the config store we need to allocate space
739*cb5caa98Sdjl 	 * for the extra vlen header
740*cb5caa98Sdjl 	 */
741*cb5caa98Sdjl 	if (desc->type == NSCD_CFG_DATA_STRING) {
742*cb5caa98Sdjl 		len = dlen = strlen((char *)data) + 1;
743*cb5caa98Sdjl 		if (in == nscd_true)
744*cb5caa98Sdjl 			len += sizeof (nscd_cfg_vlen_data_t);
745*cb5caa98Sdjl 	} else {
746*cb5caa98Sdjl 		/*
747*cb5caa98Sdjl 		 * should not be here, since for now
748*cb5caa98Sdjl 		 * only string variable length data
749*cb5caa98Sdjl 		 * is supported
750*cb5caa98Sdjl 		 */
751*cb5caa98Sdjl 		*new_data_p = NULL;
752*cb5caa98Sdjl 		return (NSCD_CFG_PARAM_DESC_ERROR);
753*cb5caa98Sdjl 	}
754*cb5caa98Sdjl 
755*cb5caa98Sdjl 	v = calloc(1, len);
756*cb5caa98Sdjl 	if (v == NULL) {
757*cb5caa98Sdjl 		*new_data_p = NULL;
758*cb5caa98Sdjl 		return (NSCD_NO_MEMORY);
759*cb5caa98Sdjl 	}
760*cb5caa98Sdjl 
761*cb5caa98Sdjl 	/*
762*cb5caa98Sdjl 	 * if copy to the config store, set up
763*cb5caa98Sdjl 	 * the extra vlen header in which the
764*cb5caa98Sdjl 	 * pointer to, and length of, the real
765*cb5caa98Sdjl 	 * data are kept. The pointer to the real
766*cb5caa98Sdjl 	 * data, not the vlen header, is returned.
767*cb5caa98Sdjl 	 */
768*cb5caa98Sdjl 	if (in == nscd_true) {
769*cb5caa98Sdjl 		v->ptr = (char *)v + sizeof (nscd_cfg_vlen_data_t);
770*cb5caa98Sdjl 		v->len = dlen;
771*cb5caa98Sdjl 		(void) memcpy(v->ptr, data, dlen);
772*cb5caa98Sdjl 		*new_data_p = v->ptr;
773*cb5caa98Sdjl 	} else {
774*cb5caa98Sdjl 		(void) memcpy(v, data, dlen);
775*cb5caa98Sdjl 		*new_data_p = v;
776*cb5caa98Sdjl 	}
777*cb5caa98Sdjl 	*data_len = dlen;
778*cb5caa98Sdjl 
779*cb5caa98Sdjl 	return (NSCD_SUCCESS);
780*cb5caa98Sdjl }
781*cb5caa98Sdjl 
782*cb5caa98Sdjl static void
783*cb5caa98Sdjl _nscd_cfg_free_vlen_data_int(
784*cb5caa98Sdjl 	void	*data)
785*cb5caa98Sdjl {
786*cb5caa98Sdjl 	nscd_cfg_vlen_data_t	*v = NULL;
787*cb5caa98Sdjl 	void			*p;
788*cb5caa98Sdjl 
789*cb5caa98Sdjl 	if (data == NULL)
790*cb5caa98Sdjl 		return;
791*cb5caa98Sdjl 
792*cb5caa98Sdjl 	p = (char *)data - sizeof (nscd_cfg_vlen_data_t);
793*cb5caa98Sdjl 	v = (nscd_cfg_vlen_data_t *)p;
794*cb5caa98Sdjl 	if (v->ptr == data)
795*cb5caa98Sdjl 		free(v);
796*cb5caa98Sdjl }
797*cb5caa98Sdjl 
798*cb5caa98Sdjl static nscd_rc_t
799*cb5caa98Sdjl _nscd_cfg_set_vlen_data_int(
800*cb5caa98Sdjl 	void		*src,
801*cb5caa98Sdjl 	void		*dest,
802*cb5caa98Sdjl 	nscd_bool_t	global)
803*cb5caa98Sdjl {
804*cb5caa98Sdjl 	int			i, offset, dlen = 0;
805*cb5caa98Sdjl 	void			*s, *d, *new;
806*cb5caa98Sdjl 	void			*cptr;
807*cb5caa98Sdjl 	nscd_rc_t		rc;
808*cb5caa98Sdjl 	nscd_cfg_param_desc_t	*desc;
809*cb5caa98Sdjl 
810*cb5caa98Sdjl 	desc = &_nscd_cfg_param_desc[0];
811*cb5caa98Sdjl 	for (i = 0; i < _nscd_cfg_num_param; i++, desc++) {
812*cb5caa98Sdjl 
813*cb5caa98Sdjl 		if (global == nscd_true &&
814*cb5caa98Sdjl 			_nscd_cfg_flag_is_not_set(desc->pflag,
815*cb5caa98Sdjl 				NSCD_CFG_PFLAG_GLOBAL))
816*cb5caa98Sdjl 			continue;
817*cb5caa98Sdjl 		else if (global != nscd_true &&
818*cb5caa98Sdjl 			_nscd_cfg_flag_is_set(desc->pflag,
819*cb5caa98Sdjl 				NSCD_CFG_PFLAG_GLOBAL))
820*cb5caa98Sdjl 			continue;
821*cb5caa98Sdjl 
822*cb5caa98Sdjl 		if (_nscd_cfg_flag_is_set(desc->pflag,
823*cb5caa98Sdjl 				NSCD_CFG_PFLAG_VLEN_DATA)) {
824*cb5caa98Sdjl 
825*cb5caa98Sdjl 			offset = desc->g_offset + desc->p_offset;
826*cb5caa98Sdjl 
827*cb5caa98Sdjl 			s = (char *)src + offset;
828*cb5caa98Sdjl 			cptr = *(char **)s;
829*cb5caa98Sdjl 
830*cb5caa98Sdjl 			rc = _nscd_cfg_copy_vlen_data(cptr, &new,
831*cb5caa98Sdjl 					desc, &dlen, nscd_true);
832*cb5caa98Sdjl 			if (rc != NSCD_SUCCESS)
833*cb5caa98Sdjl 				return (rc);
834*cb5caa98Sdjl 
835*cb5caa98Sdjl 			d = (char *)dest + offset;
836*cb5caa98Sdjl 			/* free the old vlen data */
837*cb5caa98Sdjl 			if (*(char **)d == NULL)
838*cb5caa98Sdjl 				_nscd_cfg_free_vlen_data_int(*(char **)d);
839*cb5caa98Sdjl 
840*cb5caa98Sdjl 			*(char **)d = new;
841*cb5caa98Sdjl 		}
842*cb5caa98Sdjl 	}
843*cb5caa98Sdjl 
844*cb5caa98Sdjl 	return (NSCD_SUCCESS);
845*cb5caa98Sdjl }
846*cb5caa98Sdjl 
847*cb5caa98Sdjl static void *
848*cb5caa98Sdjl _nscd_cfg_locate_vlen_data(
849*cb5caa98Sdjl 	void	*cfg_data,
850*cb5caa98Sdjl 	int	*len)
851*cb5caa98Sdjl {
852*cb5caa98Sdjl 	void	*ptr, *ret;
853*cb5caa98Sdjl 
854*cb5caa98Sdjl 	ptr = *(char **)cfg_data;
855*cb5caa98Sdjl 	ret = ptr;
856*cb5caa98Sdjl 	if (ret == NULL) {
857*cb5caa98Sdjl 		*len = 0;
858*cb5caa98Sdjl 		return (NULL);
859*cb5caa98Sdjl 	}
860*cb5caa98Sdjl 	ptr = (char *)ptr - sizeof (nscd_cfg_vlen_data_t);
861*cb5caa98Sdjl 	*len = ((nscd_cfg_vlen_data_t *)ptr)->len;
862*cb5caa98Sdjl 
863*cb5caa98Sdjl 	return (ret);
864*cb5caa98Sdjl }
865*cb5caa98Sdjl 
866*cb5caa98Sdjl static void
867*cb5caa98Sdjl _nscd_cfg_lock(
868*cb5caa98Sdjl 	nscd_bool_t	is_read,
869*cb5caa98Sdjl 	nscd_cfg_lock_t	*cfglock)
870*cb5caa98Sdjl {
871*cb5caa98Sdjl 
872*cb5caa98Sdjl 	int	(*lockfunc)(rwlock_t *);
873*cb5caa98Sdjl 
874*cb5caa98Sdjl 	if (cfglock == NULL)
875*cb5caa98Sdjl 		return;
876*cb5caa98Sdjl 
877*cb5caa98Sdjl 	if (is_read == nscd_true)
878*cb5caa98Sdjl 		lockfunc = rw_rdlock;
879*cb5caa98Sdjl 	else
880*cb5caa98Sdjl 		lockfunc = rw_wrlock;
881*cb5caa98Sdjl 
882*cb5caa98Sdjl 	if (cfglock->global != NULL) {
883*cb5caa98Sdjl 
884*cb5caa98Sdjl 		(lockfunc)(cfglock->global);
885*cb5caa98Sdjl 		return;
886*cb5caa98Sdjl 	}
887*cb5caa98Sdjl 
888*cb5caa98Sdjl 	if (cfglock->alldb != NULL)
889*cb5caa98Sdjl 		(lockfunc)(cfglock->alldb);
890*cb5caa98Sdjl 
891*cb5caa98Sdjl 	if (cfglock->nswdb != NULL)
892*cb5caa98Sdjl 		(lockfunc)(cfglock->nswdb);
893*cb5caa98Sdjl }
894*cb5caa98Sdjl 
895*cb5caa98Sdjl static void
896*cb5caa98Sdjl _nscd_cfg_unlock(
897*cb5caa98Sdjl 	nscd_cfg_lock_t	*cfglock)
898*cb5caa98Sdjl {
899*cb5caa98Sdjl 	if (cfglock == NULL)
900*cb5caa98Sdjl 		return;
901*cb5caa98Sdjl 
902*cb5caa98Sdjl 	if (cfglock->global != NULL) {
903*cb5caa98Sdjl 
904*cb5caa98Sdjl 		(void) rw_unlock(cfglock->global);
905*cb5caa98Sdjl 		free(cfglock);
906*cb5caa98Sdjl 		return;
907*cb5caa98Sdjl 	}
908*cb5caa98Sdjl 
909*cb5caa98Sdjl 	if (cfglock->nswdb != NULL)
910*cb5caa98Sdjl 		(void) rw_unlock(cfglock->nswdb);
911*cb5caa98Sdjl 
912*cb5caa98Sdjl 	if (cfglock->alldb != NULL)
913*cb5caa98Sdjl 		(void) rw_unlock(cfglock->alldb);
914*cb5caa98Sdjl 
915*cb5caa98Sdjl 	free(cfglock);
916*cb5caa98Sdjl }
917*cb5caa98Sdjl 
918*cb5caa98Sdjl /*
919*cb5caa98Sdjl  * If vlen_data_addr is given, it will be set to the
920*cb5caa98Sdjl  * address of the pointer pointing to the vlen data.
921*cb5caa98Sdjl  * 'cfglock' will be set to point to the reader/writer
922*cb5caa98Sdjl  * lock(s) protecting the (group) configuration data.
923*cb5caa98Sdjl  */
924*cb5caa98Sdjl static nscd_rc_t
925*cb5caa98Sdjl _nscd_cfg_locate_cfg_data(
926*cb5caa98Sdjl 	void			**cfg_data,
927*cb5caa98Sdjl 	nscd_bool_t		is_read,
928*cb5caa98Sdjl 	nscd_cfg_param_desc_t	*desc,
929*cb5caa98Sdjl 	nscd_cfg_id_t		*nswdb,
930*cb5caa98Sdjl 	nscd_bool_t		get_group,
931*cb5caa98Sdjl 	void			**vlen_data_addr,
932*cb5caa98Sdjl 	int			*len,
933*cb5caa98Sdjl 	nscd_cfg_lock_t		**cfglock)
934*cb5caa98Sdjl {
935*cb5caa98Sdjl 	int		offset;
936*cb5caa98Sdjl 
937*cb5caa98Sdjl 	*cfg_data = NULL;
938*cb5caa98Sdjl 	if (len != NULL)
939*cb5caa98Sdjl 		*len = 0;
940*cb5caa98Sdjl 	if (vlen_data_addr != NULL)
941*cb5caa98Sdjl 		*vlen_data_addr = NULL;
942*cb5caa98Sdjl 
943*cb5caa98Sdjl 	if (cfglock != NULL) {
944*cb5caa98Sdjl 		*cfglock = calloc(1, sizeof (nscd_cfg_lock_t));
945*cb5caa98Sdjl 		if (*cfglock == NULL)
946*cb5caa98Sdjl 			return (NSCD_NO_MEMORY);
947*cb5caa98Sdjl 	}
948*cb5caa98Sdjl 
949*cb5caa98Sdjl 	/* assume if nswdb is NULL, the param is a global one */
950*cb5caa98Sdjl 	if (nswdb == NULL) {
951*cb5caa98Sdjl 
952*cb5caa98Sdjl 		offset = desc->g_offset;
953*cb5caa98Sdjl 		if (get_group != nscd_true)
954*cb5caa98Sdjl 			offset += desc->p_offset;
955*cb5caa98Sdjl 		*cfg_data = (char *)nscd_cfg_global_current + offset;
956*cb5caa98Sdjl 
957*cb5caa98Sdjl 		if (cfglock != NULL)
958*cb5caa98Sdjl 			(*cfglock)->global = nscd_cfg_global_rwlock;
959*cb5caa98Sdjl 
960*cb5caa98Sdjl 	} else if (nswdb->index == NSCD_CFG_NSW_ALLDB_INDEX) {
961*cb5caa98Sdjl 
962*cb5caa98Sdjl 		offset = desc->g_offset;
963*cb5caa98Sdjl 		if (get_group != nscd_true)
964*cb5caa98Sdjl 			offset += desc->p_offset;
965*cb5caa98Sdjl 		*cfg_data = (char *)nscd_cfg_nsw_alldb_current +
966*cb5caa98Sdjl 			offset;
967*cb5caa98Sdjl 
968*cb5caa98Sdjl 		if (cfglock != NULL)
969*cb5caa98Sdjl 			(*cfglock)->alldb = nscd_cfg_nsw_alldb_rwlock;
970*cb5caa98Sdjl 
971*cb5caa98Sdjl 	} else {
972*cb5caa98Sdjl 
973*cb5caa98Sdjl 		offset = nswdb->index *
974*cb5caa98Sdjl 			(sizeof (nscd_cfg_nsw_db_data_t)) + desc->g_offset;
975*cb5caa98Sdjl 		if (get_group != nscd_true)
976*cb5caa98Sdjl 			offset += desc->p_offset;
977*cb5caa98Sdjl 		*cfg_data = (char *)nscd_cfg_nsw_db_data_current +
978*cb5caa98Sdjl 			offset;
979*cb5caa98Sdjl 
980*cb5caa98Sdjl 		if (cfglock != NULL) {
981*cb5caa98Sdjl 			(*cfglock)->nswdb =
982*cb5caa98Sdjl 			&nscd_cfg_nsw_db_data_rwlock[nswdb->index];
983*cb5caa98Sdjl 
984*cb5caa98Sdjl 			(*cfglock)->alldb = nscd_cfg_nsw_alldb_rwlock;
985*cb5caa98Sdjl 		}
986*cb5caa98Sdjl 	}
987*cb5caa98Sdjl 
988*cb5caa98Sdjl 	/* lock the config data */
989*cb5caa98Sdjl 	if (cfglock != NULL)
990*cb5caa98Sdjl 		_nscd_cfg_lock(is_read, *cfglock);
991*cb5caa98Sdjl 
992*cb5caa98Sdjl 	if (get_group != nscd_true &&
993*cb5caa98Sdjl 		_nscd_cfg_flag_is_not_set(desc->pflag,
994*cb5caa98Sdjl 			NSCD_CFG_PFLAG_GROUP) &&
995*cb5caa98Sdjl 		(_nscd_cfg_flag_is_set(desc->pflag,
996*cb5caa98Sdjl 			NSCD_CFG_PFLAG_VLEN_DATA))) {
997*cb5caa98Sdjl 		if (vlen_data_addr != NULL)
998*cb5caa98Sdjl 			*vlen_data_addr = *cfg_data;
999*cb5caa98Sdjl 		*cfg_data = _nscd_cfg_locate_vlen_data(*cfg_data, len);
1000*cb5caa98Sdjl 		return (NSCD_SUCCESS);
1001*cb5caa98Sdjl 	}
1002*cb5caa98Sdjl 
1003*cb5caa98Sdjl 	if (len != NULL) {
1004*cb5caa98Sdjl 		if (get_group == nscd_true)
1005*cb5caa98Sdjl 			*len = desc->g_size;
1006*cb5caa98Sdjl 		else
1007*cb5caa98Sdjl 			*len = desc->p_size;
1008*cb5caa98Sdjl 	}
1009*cb5caa98Sdjl 
1010*cb5caa98Sdjl 	return (NSCD_SUCCESS);
1011*cb5caa98Sdjl }
1012*cb5caa98Sdjl 
1013*cb5caa98Sdjl /*
1014*cb5caa98Sdjl  * perform the preliminary (range) check on 'data' based on the
1015*cb5caa98Sdjl  * datatype (desc->datatype) of the config parameter
1016*cb5caa98Sdjl  */
1017*cb5caa98Sdjl nscd_rc_t
1018*cb5caa98Sdjl _nscd_cfg_prelim_check(
1019*cb5caa98Sdjl 	nscd_cfg_param_desc_t	*desc,
1020*cb5caa98Sdjl 	void			*data,
1021*cb5caa98Sdjl 	nscd_cfg_error_t	**errorp)
1022*cb5caa98Sdjl {
1023*cb5caa98Sdjl 
1024*cb5caa98Sdjl 	char			*me = "_nscd_cfg_prelim_check";
1025*cb5caa98Sdjl 	char			msg[NSCD_CFG_MAX_ERR_MSG_LEN];
1026*cb5caa98Sdjl 	nscd_cfg_str_check_t	*sc;
1027*cb5caa98Sdjl 	nscd_cfg_int_check_t	*ic;
1028*cb5caa98Sdjl 	nscd_cfg_bitmap_check_t	*bmc;
1029*cb5caa98Sdjl 	nscd_rc_t		rc = NSCD_CFG_PRELIM_CHECK_FAILED;
1030*cb5caa98Sdjl 
1031*cb5caa98Sdjl 	if ((nscd_cfg_str_check_t *)desc->p_check == NULL)
1032*cb5caa98Sdjl 		return (NSCD_SUCCESS);
1033*cb5caa98Sdjl 
1034*cb5caa98Sdjl 	switch (desc->type) {
1035*cb5caa98Sdjl 
1036*cb5caa98Sdjl 	case NSCD_CFG_DATA_STRING:
1037*cb5caa98Sdjl 
1038*cb5caa98Sdjl 		sc = (nscd_cfg_str_check_t *)desc->p_check;
1039*cb5caa98Sdjl 		if (sc->must_not_null == nscd_true && data == NULL) {
1040*cb5caa98Sdjl 
1041*cb5caa98Sdjl 			if (errorp == NULL)
1042*cb5caa98Sdjl 				break;
1043*cb5caa98Sdjl 
1044*cb5caa98Sdjl 			(void) snprintf(msg, sizeof (msg),
1045*cb5caa98Sdjl 			gettext("data must be specified for %s"),
1046*cb5caa98Sdjl 			desc->id.name);
1047*cb5caa98Sdjl 
1048*cb5caa98Sdjl 			break;
1049*cb5caa98Sdjl 		}
1050*cb5caa98Sdjl 
1051*cb5caa98Sdjl 		if (data == NULL) {
1052*cb5caa98Sdjl 			rc = NSCD_SUCCESS;
1053*cb5caa98Sdjl 			break;
1054*cb5caa98Sdjl 		}
1055*cb5caa98Sdjl 
1056*cb5caa98Sdjl 		if (sc->maxlen != 0 &&
1057*cb5caa98Sdjl 			strlen((char *)data) > sc->maxlen) {
1058*cb5caa98Sdjl 
1059*cb5caa98Sdjl 			if (errorp == NULL)
1060*cb5caa98Sdjl 				break;
1061*cb5caa98Sdjl 
1062*cb5caa98Sdjl 			(void) snprintf(msg, sizeof (msg),
1063*cb5caa98Sdjl 		gettext("length of data (%s) for %s larger than %d"),
1064*cb5caa98Sdjl 				(char *)data, desc->id.name, sc->maxlen);
1065*cb5caa98Sdjl 			break;
1066*cb5caa98Sdjl 		}
1067*cb5caa98Sdjl 
1068*cb5caa98Sdjl 		rc = NSCD_SUCCESS;
1069*cb5caa98Sdjl 
1070*cb5caa98Sdjl 		break;
1071*cb5caa98Sdjl 
1072*cb5caa98Sdjl 	case NSCD_CFG_DATA_INTEGER:
1073*cb5caa98Sdjl 
1074*cb5caa98Sdjl 		ic = (nscd_cfg_int_check_t *)desc->p_check;
1075*cb5caa98Sdjl 		if (*(int *)data > ic->max ||
1076*cb5caa98Sdjl 			*(int *)data < ic->min) {
1077*cb5caa98Sdjl 
1078*cb5caa98Sdjl 			if (errorp == NULL)
1079*cb5caa98Sdjl 				break;
1080*cb5caa98Sdjl 
1081*cb5caa98Sdjl 			(void) snprintf(msg, sizeof (msg),
1082*cb5caa98Sdjl 		gettext("data (%d) for %s out of range (%d - %d)"),
1083*cb5caa98Sdjl 				*(int *)data, desc->id.name,
1084*cb5caa98Sdjl 				ic->min, ic->max);
1085*cb5caa98Sdjl 
1086*cb5caa98Sdjl 			break;
1087*cb5caa98Sdjl 		}
1088*cb5caa98Sdjl 
1089*cb5caa98Sdjl 		rc = NSCD_SUCCESS;
1090*cb5caa98Sdjl 
1091*cb5caa98Sdjl 		break;
1092*cb5caa98Sdjl 
1093*cb5caa98Sdjl 	case NSCD_CFG_DATA_BITMAP:
1094*cb5caa98Sdjl 
1095*cb5caa98Sdjl 		bmc = (nscd_cfg_bitmap_check_t *)desc->p_check;
1096*cb5caa98Sdjl 		if (_nscd_cfg_bitmap_value(*(nscd_cfg_bitmap_t *)data) &
1097*cb5caa98Sdjl 			~(bmc->valid_bits)) {
1098*cb5caa98Sdjl 
1099*cb5caa98Sdjl 			if (errorp == NULL)
1100*cb5caa98Sdjl 				break;
1101*cb5caa98Sdjl 
1102*cb5caa98Sdjl 			(void) snprintf(msg, sizeof (msg),
1103*cb5caa98Sdjl 		gettext("data (%#6.4x) for %s contain bit not in 0x%x"),
1104*cb5caa98Sdjl 				_nscd_cfg_bitmap_value(
1105*cb5caa98Sdjl 					*(nscd_cfg_bitmap_t *)data),
1106*cb5caa98Sdjl 				desc->id.name,
1107*cb5caa98Sdjl 				_nscd_cfg_bitmap_value(bmc->valid_bits));
1108*cb5caa98Sdjl 			break;
1109*cb5caa98Sdjl 		}
1110*cb5caa98Sdjl 
1111*cb5caa98Sdjl 		rc = NSCD_SUCCESS;
1112*cb5caa98Sdjl 
1113*cb5caa98Sdjl 		break;
1114*cb5caa98Sdjl 	}
1115*cb5caa98Sdjl 
1116*cb5caa98Sdjl 	if (rc != NSCD_SUCCESS && errorp != NULL) {
1117*cb5caa98Sdjl 		*errorp = _nscd_cfg_make_error(rc, msg);
1118*cb5caa98Sdjl 
1119*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
1120*cb5caa98Sdjl 		(me, "invalid argument: %s\n", (*errorp)->msg);
1121*cb5caa98Sdjl 	}
1122*cb5caa98Sdjl 
1123*cb5caa98Sdjl 	return (rc);
1124*cb5caa98Sdjl }
1125*cb5caa98Sdjl 
1126*cb5caa98Sdjl static nscd_rc_t
1127*cb5caa98Sdjl _nscd_cfg_notify_i(
1128*cb5caa98Sdjl 	nscd_cfg_param_desc_t	*desc,
1129*cb5caa98Sdjl 	nscd_cfg_id_t		*nswdb,
1130*cb5caa98Sdjl 	int			*skip,
1131*cb5caa98Sdjl 	nscd_cfg_error_t	**errorp)
1132*cb5caa98Sdjl {
1133*cb5caa98Sdjl 
1134*cb5caa98Sdjl 	char			*me = "_nscd_cfg_notify_i";
1135*cb5caa98Sdjl 	int			i, num, skip_bk;
1136*cb5caa98Sdjl 	void			*cfg_data, *cdata;
1137*cb5caa98Sdjl 	void			*cookie = NULL;
1138*cb5caa98Sdjl 	nscd_rc_t		rc;
1139*cb5caa98Sdjl 	nscd_cfg_flag_t		dflag, dflag1;
1140*cb5caa98Sdjl 	nscd_cfg_bitmap_t	bitmap_c, bitmap_s, *bitmap_addr;
1141*cb5caa98Sdjl 	nscd_cfg_group_info_t	*gi;
1142*cb5caa98Sdjl 
1143*cb5caa98Sdjl 	if (errorp != NULL)
1144*cb5caa98Sdjl 		*errorp = NULL;
1145*cb5caa98Sdjl 
1146*cb5caa98Sdjl 	if (skip == NULL)
1147*cb5caa98Sdjl 		skip = &skip_bk;
1148*cb5caa98Sdjl 
1149*cb5caa98Sdjl 	*skip = 0;
1150*cb5caa98Sdjl 
1151*cb5caa98Sdjl 	if (_nscd_cfg_flag_is_not_set(desc->pflag,
1152*cb5caa98Sdjl 		NSCD_CFG_PFLAG_GROUP)) {
1153*cb5caa98Sdjl 
1154*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
1155*cb5caa98Sdjl 		(me, "ERROR: expect parameter description for group, "
1156*cb5caa98Sdjl 		"but receive parameter description is for %s\n",
1157*cb5caa98Sdjl 		desc->id.name);
1158*cb5caa98Sdjl 
1159*cb5caa98Sdjl 		return (NSCD_CFG_PARAM_DESC_ERROR);
1160*cb5caa98Sdjl 	}
1161*cb5caa98Sdjl 
1162*cb5caa98Sdjl 	/*
1163*cb5caa98Sdjl 	 * Set data flag going with data to be sent to the
1164*cb5caa98Sdjl 	 * verify/notify routines. Allowing the config flag
1165*cb5caa98Sdjl 	 * be exipandable, set the bits one by one.
1166*cb5caa98Sdjl 	 */
1167*cb5caa98Sdjl 	dflag = NSCD_CFG_FLAG_ZERO;
1168*cb5caa98Sdjl 	dflag = _nscd_cfg_flag_set(dflag, NSCD_CFG_DFLAG_STATIC_DATA);
1169*cb5caa98Sdjl 	dflag = _nscd_cfg_flag_set(dflag, NSCD_CFG_DFLAG_INIT);
1170*cb5caa98Sdjl 	dflag = _nscd_cfg_flag_set(dflag, NSCD_CFG_DFLAG_GROUP);
1171*cb5caa98Sdjl 	if (_nscd_cfg_flag_is_set(desc->pflag,
1172*cb5caa98Sdjl 		NSCD_CFG_PFLAG_INIT_SET_ALL_DB))
1173*cb5caa98Sdjl 		dflag = _nscd_cfg_flag_set(dflag,
1174*cb5caa98Sdjl 			NSCD_CFG_DFLAG_SET_ALL_DB);
1175*cb5caa98Sdjl 
1176*cb5caa98Sdjl 	/* get to the group data in the config store */
1177*cb5caa98Sdjl 	rc = _nscd_cfg_locate_cfg_data(&cfg_data, nscd_true,
1178*cb5caa98Sdjl 			desc, nswdb, nscd_true, NULL, NULL, NULL);
1179*cb5caa98Sdjl 	if (rc != NSCD_SUCCESS)
1180*cb5caa98Sdjl 		goto error;
1181*cb5caa98Sdjl 
1182*cb5caa98Sdjl 	/*
1183*cb5caa98Sdjl 	 * the static bitmap associated with the group
1184*cb5caa98Sdjl 	 * may be replaced before sending to the components,
1185*cb5caa98Sdjl 	 * so save the bitmap for later use
1186*cb5caa98Sdjl 	 */
1187*cb5caa98Sdjl 	gi = _nscd_cfg_get_gi(cfg_data);
1188*cb5caa98Sdjl 	bitmap_c = gi->bitmap;
1189*cb5caa98Sdjl 	bitmap_addr = &(gi->bitmap);
1190*cb5caa98Sdjl 
1191*cb5caa98Sdjl 	/*
1192*cb5caa98Sdjl 	 * the elements in this group will all be handled
1193*cb5caa98Sdjl 	 * so the caller can skip them
1194*cb5caa98Sdjl 	 */
1195*cb5caa98Sdjl 	*skip = desc->p_fn;
1196*cb5caa98Sdjl 
1197*cb5caa98Sdjl 	if (_nscd_cfg_flag_is_set(desc->pflag,
1198*cb5caa98Sdjl 			NSCD_CFG_PFLAG_INIT_SEND_WHOLE_GROUP))
1199*cb5caa98Sdjl 		/* send the entire group just once */
1200*cb5caa98Sdjl 		num = 1;
1201*cb5caa98Sdjl 
1202*cb5caa98Sdjl 	else { /* send individual members one by one */
1203*cb5caa98Sdjl 
1204*cb5caa98Sdjl 		num = desc->p_fn;
1205*cb5caa98Sdjl 
1206*cb5caa98Sdjl 		/*
1207*cb5caa98Sdjl 		 * skip the first desc which is for the group
1208*cb5caa98Sdjl 		 * and get to the desc for the first member
1209*cb5caa98Sdjl 		 */
1210*cb5caa98Sdjl 		desc++;
1211*cb5caa98Sdjl 
1212*cb5caa98Sdjl 		dflag = _nscd_cfg_flag_unset(dflag,
1213*cb5caa98Sdjl 			NSCD_CFG_DFLAG_GROUP);
1214*cb5caa98Sdjl 	}
1215*cb5caa98Sdjl 
1216*cb5caa98Sdjl 	dflag1 = dflag;
1217*cb5caa98Sdjl 	for (i = 0; i < num; i++, desc++) {
1218*cb5caa98Sdjl 
1219*cb5caa98Sdjl 		dflag = dflag1;
1220*cb5caa98Sdjl 
1221*cb5caa98Sdjl 		if (_nscd_cfg_flag_is_set(desc->pflag,
1222*cb5caa98Sdjl 				NSCD_CFG_PFLAG_SEND_BIT_SELECTED)) {
1223*cb5caa98Sdjl 
1224*cb5caa98Sdjl 			/* set the bitmap to select just this member */
1225*cb5caa98Sdjl 			bitmap_s = NSCD_CFG_BITMAP_ZERO;
1226*cb5caa98Sdjl 			_nscd_cfg_bitmap_set_nth(bitmap_s, i);
1227*cb5caa98Sdjl 			/* replace the bitmap in the cfg data */
1228*cb5caa98Sdjl 			_nscd_cfg_bitmap_set(bitmap_addr, bitmap_s);
1229*cb5caa98Sdjl 
1230*cb5caa98Sdjl 			/*
1231*cb5caa98Sdjl 			 * send the whole group but with only one
1232*cb5caa98Sdjl 			 * member selected
1233*cb5caa98Sdjl 			 */
1234*cb5caa98Sdjl 			cdata = cfg_data;
1235*cb5caa98Sdjl 
1236*cb5caa98Sdjl 			dflag = _nscd_cfg_flag_set(dflag,
1237*cb5caa98Sdjl 				NSCD_CFG_DFLAG_GROUP);
1238*cb5caa98Sdjl 			dflag = _nscd_cfg_flag_set(dflag,
1239*cb5caa98Sdjl 				NSCD_CFG_DFLAG_BIT_SELECTED);
1240*cb5caa98Sdjl 		} else {
1241*cb5caa98Sdjl 			/*
1242*cb5caa98Sdjl 			 * send param data or group data:
1243*cb5caa98Sdjl 			 * param data - non-xero desc->p_offset
1244*cb5caa98Sdjl 			 * group data - zero desc->p_offset
1245*cb5caa98Sdjl 			 */
1246*cb5caa98Sdjl 			cdata = (char *)cfg_data + desc->p_offset;
1247*cb5caa98Sdjl 
1248*cb5caa98Sdjl 			/*
1249*cb5caa98Sdjl 			 * if variable length data, need to send pointer
1250*cb5caa98Sdjl 			 * to the data (not the address of the pointer)
1251*cb5caa98Sdjl 			 */
1252*cb5caa98Sdjl 			if (_nscd_cfg_flag_is_set(desc->pflag,
1253*cb5caa98Sdjl 				NSCD_CFG_PFLAG_VLEN_DATA))
1254*cb5caa98Sdjl 				cdata = *(char **)cdata;
1255*cb5caa98Sdjl 		}
1256*cb5caa98Sdjl 
1257*cb5caa98Sdjl 		if (desc->verify != NULL) {
1258*cb5caa98Sdjl 			dflag = _nscd_cfg_flag_set(dflag,
1259*cb5caa98Sdjl 				NSCD_CFG_DFLAG_VERIFY);
1260*cb5caa98Sdjl 			rc = desc->verify(cdata, desc, nswdb,
1261*cb5caa98Sdjl 				dflag, errorp, &cookie);
1262*cb5caa98Sdjl 			if (rc != NSCD_SUCCESS)
1263*cb5caa98Sdjl 				goto error;
1264*cb5caa98Sdjl 		}
1265*cb5caa98Sdjl 
1266*cb5caa98Sdjl 		if (desc->notify != NULL) {
1267*cb5caa98Sdjl 			dflag = _nscd_cfg_flag_set(dflag,
1268*cb5caa98Sdjl 				NSCD_CFG_DFLAG_NOTIFY);
1269*cb5caa98Sdjl 
1270*cb5caa98Sdjl 			rc = desc->notify(cfg_data, desc, nswdb,
1271*cb5caa98Sdjl 				dflag, errorp, cookie);
1272*cb5caa98Sdjl 			if (rc != NSCD_SUCCESS)
1273*cb5caa98Sdjl 				goto error;
1274*cb5caa98Sdjl 		}
1275*cb5caa98Sdjl 	}
1276*cb5caa98Sdjl 
1277*cb5caa98Sdjl 	rc = NSCD_SUCCESS;
1278*cb5caa98Sdjl 
1279*cb5caa98Sdjl 	/* restore the bitmap in the cfg data */
1280*cb5caa98Sdjl 	_nscd_cfg_bitmap_set(bitmap_addr, bitmap_c);
1281*cb5caa98Sdjl 
1282*cb5caa98Sdjl 	error:
1283*cb5caa98Sdjl 
1284*cb5caa98Sdjl 	return (rc);
1285*cb5caa98Sdjl 
1286*cb5caa98Sdjl }
1287*cb5caa98Sdjl 
1288*cb5caa98Sdjl static nscd_rc_t
1289*cb5caa98Sdjl _nscd_cfg_notify_init(
1290*cb5caa98Sdjl 	nscd_cfg_error_t	**errorp)
1291*cb5caa98Sdjl {
1292*cb5caa98Sdjl 	int			i, j, skip;
1293*cb5caa98Sdjl 	nscd_rc_t		rc;
1294*cb5caa98Sdjl 	nscd_cfg_id_t		*nswdb = NULL;
1295*cb5caa98Sdjl 	nscd_cfg_param_desc_t	*desc;
1296*cb5caa98Sdjl 
1297*cb5caa98Sdjl 	if (errorp != NULL)
1298*cb5caa98Sdjl 		*errorp = NULL;
1299*cb5caa98Sdjl 
1300*cb5caa98Sdjl 	for (i = 0; i < _nscd_cfg_num_param; i++) {
1301*cb5caa98Sdjl 
1302*cb5caa98Sdjl 		desc = &_nscd_cfg_param_desc[i];
1303*cb5caa98Sdjl 
1304*cb5caa98Sdjl 		if (_nscd_cfg_flag_is_set(desc->pflag,
1305*cb5caa98Sdjl 			NSCD_CFG_PFLAG_GLOBAL)) { /* global cfg data */
1306*cb5caa98Sdjl 
1307*cb5caa98Sdjl 			rc = _nscd_cfg_notify_i(desc, NULL, &skip, errorp);
1308*cb5caa98Sdjl 		} else {
1309*cb5caa98Sdjl 
1310*cb5caa98Sdjl 			/*
1311*cb5caa98Sdjl 			 * if use defaults for all nsswitch database,
1312*cb5caa98Sdjl 			 * send the config data to verify/notify once
1313*cb5caa98Sdjl 			 */
1314*cb5caa98Sdjl 			if (_nscd_cfg_flag_is_set(desc->pflag,
1315*cb5caa98Sdjl 				NSCD_CFG_PFLAG_INIT_SET_ALL_DB)) {
1316*cb5caa98Sdjl 
1317*cb5caa98Sdjl 				nswdb = &_nscd_cfg_nsw_alldb;
1318*cb5caa98Sdjl 
1319*cb5caa98Sdjl 				rc = _nscd_cfg_notify_i(desc, nswdb,
1320*cb5caa98Sdjl 					&skip, errorp);
1321*cb5caa98Sdjl 			} else { /* send data once for each nsw db */
1322*cb5caa98Sdjl 
1323*cb5caa98Sdjl 				for (j = 0; j < _nscd_cfg_num_nsw_db;
1324*cb5caa98Sdjl 					j++) {
1325*cb5caa98Sdjl 
1326*cb5caa98Sdjl 					nswdb = &_nscd_cfg_nsw_db[j];
1327*cb5caa98Sdjl 
1328*cb5caa98Sdjl 					rc = _nscd_cfg_notify_i(desc,
1329*cb5caa98Sdjl 						nswdb, &skip, errorp);
1330*cb5caa98Sdjl 				}
1331*cb5caa98Sdjl 			}
1332*cb5caa98Sdjl 		}
1333*cb5caa98Sdjl 
1334*cb5caa98Sdjl 		if (rc != NSCD_SUCCESS)
1335*cb5caa98Sdjl 			return (rc);
1336*cb5caa98Sdjl 
1337*cb5caa98Sdjl 		i += skip;
1338*cb5caa98Sdjl 	}
1339*cb5caa98Sdjl 
1340*cb5caa98Sdjl 	return (NSCD_SUCCESS);
1341*cb5caa98Sdjl }
1342*cb5caa98Sdjl 
1343*cb5caa98Sdjl nscd_rc_t
1344*cb5caa98Sdjl _nscd_cfg_init(
1345*cb5caa98Sdjl 	nscd_cfg_error_t		**errorp)
1346*cb5caa98Sdjl {
1347*cb5caa98Sdjl 
1348*cb5caa98Sdjl 	int				i, j, datalen;
1349*cb5caa98Sdjl 	int				dbi = 0, dbj = 0;
1350*cb5caa98Sdjl 	char				*dest, *src;
1351*cb5caa98Sdjl 	char				*dbni = NULL, *dbnj = NULL;
1352*cb5caa98Sdjl 	nscd_rc_t			rc;
1353*cb5caa98Sdjl 	nscd_cfg_nsw_spc_default_t	*spc;
1354*cb5caa98Sdjl 
1355*cb5caa98Sdjl 	if (errorp != NULL)
1356*cb5caa98Sdjl 		*errorp = NULL;
1357*cb5caa98Sdjl 
1358*cb5caa98Sdjl 	rc = _nscd_cfg_init_param();
1359*cb5caa98Sdjl 	if (rc != NSCD_SUCCESS)
1360*cb5caa98Sdjl 		return (rc);
1361*cb5caa98Sdjl 
1362*cb5caa98Sdjl 	rc = _nscd_cfg_init_stat();
1363*cb5caa98Sdjl 	if (rc != NSCD_SUCCESS)
1364*cb5caa98Sdjl 		return (rc);
1365*cb5caa98Sdjl 
1366*cb5caa98Sdjl 	nscd_cfg_global_current = calloc(1,
1367*cb5caa98Sdjl 			sizeof (nscd_cfg_global_data_t));
1368*cb5caa98Sdjl 	if (nscd_cfg_global_current == NULL)
1369*cb5caa98Sdjl 		return (NSCD_NO_MEMORY);
1370*cb5caa98Sdjl 
1371*cb5caa98Sdjl 	nscd_cfg_nsw_alldb_current = calloc(1,
1372*cb5caa98Sdjl 		sizeof (nscd_cfg_nsw_db_data_t));
1373*cb5caa98Sdjl 	if (nscd_cfg_nsw_alldb_current == NULL)
1374*cb5caa98Sdjl 		return (NSCD_NO_MEMORY);
1375*cb5caa98Sdjl 
1376*cb5caa98Sdjl 	nscd_cfg_nsw_db_data_current = calloc(_nscd_cfg_num_nsw_db,
1377*cb5caa98Sdjl 		sizeof (nscd_cfg_nsw_db_data_t));
1378*cb5caa98Sdjl 	if (nscd_cfg_nsw_db_data_current == NULL)
1379*cb5caa98Sdjl 		return (NSCD_NO_MEMORY);
1380*cb5caa98Sdjl 
1381*cb5caa98Sdjl 	nscd_cfg_global_rwlock = calloc(1, sizeof (rwlock_t));
1382*cb5caa98Sdjl 	if (nscd_cfg_global_rwlock == NULL)
1383*cb5caa98Sdjl 		return (NSCD_NO_MEMORY);
1384*cb5caa98Sdjl 	(void) rwlock_init(nscd_cfg_global_rwlock, NULL, NULL);
1385*cb5caa98Sdjl 
1386*cb5caa98Sdjl 	*nscd_cfg_global_current = nscd_cfg_global_default;
1387*cb5caa98Sdjl 
1388*cb5caa98Sdjl 	rc = _nscd_cfg_set_vlen_data_int(&nscd_cfg_global_default,
1389*cb5caa98Sdjl 		nscd_cfg_global_current, nscd_true);
1390*cb5caa98Sdjl 	if (rc != NSCD_SUCCESS)
1391*cb5caa98Sdjl 		return (rc);
1392*cb5caa98Sdjl 
1393*cb5caa98Sdjl 	nscd_cfg_nsw_db_data_rwlock = calloc(_nscd_cfg_num_nsw_db,
1394*cb5caa98Sdjl 		sizeof (rwlock_t));
1395*cb5caa98Sdjl 	if (nscd_cfg_nsw_db_data_rwlock == NULL)
1396*cb5caa98Sdjl 		return (NSCD_NO_MEMORY);
1397*cb5caa98Sdjl 
1398*cb5caa98Sdjl 	/* set per switch db config to the default for all db's */
1399*cb5caa98Sdjl 	for (i = 0; i < _nscd_cfg_num_nsw_db; i++) {
1400*cb5caa98Sdjl 
1401*cb5caa98Sdjl 		nscd_cfg_nsw_db_data_current[i] =
1402*cb5caa98Sdjl 			nscd_cfg_nsw_db_data_default;
1403*cb5caa98Sdjl 
1404*cb5caa98Sdjl 		(void) rwlock_init(&nscd_cfg_nsw_db_data_rwlock[i],
1405*cb5caa98Sdjl 			NULL, NULL);
1406*cb5caa98Sdjl 	}
1407*cb5caa98Sdjl 
1408*cb5caa98Sdjl 	/* add db specific defaults */
1409*cb5caa98Sdjl 	for (i = 0; i < _nscd_cfg_num_nsw_default; i++) {
1410*cb5caa98Sdjl 
1411*cb5caa98Sdjl 		if (_nscd_cfg_nsw_spc_default[i].data == NULL)
1412*cb5caa98Sdjl 			continue;
1413*cb5caa98Sdjl 
1414*cb5caa98Sdjl 		if (_nscd_cfg_nsw_spc_default[i].db != dbni) {
1415*cb5caa98Sdjl 			for (j = 0; j < _nscd_cfg_num_nsw_db; j++) {
1416*cb5caa98Sdjl 
1417*cb5caa98Sdjl 				if (strcmp(_nscd_cfg_nsw_db[j].name,
1418*cb5caa98Sdjl 					_nscd_cfg_nsw_spc_default[i].db) != 0)
1419*cb5caa98Sdjl 					continue;
1420*cb5caa98Sdjl 
1421*cb5caa98Sdjl 				dbi = _nscd_cfg_nsw_db[j].index;
1422*cb5caa98Sdjl 				dbni = _nscd_cfg_nsw_db[j].name;
1423*cb5caa98Sdjl 				break;
1424*cb5caa98Sdjl 			}
1425*cb5caa98Sdjl 		}
1426*cb5caa98Sdjl 
1427*cb5caa98Sdjl 		dest = (char *)&nscd_cfg_nsw_db_data_current[dbi] +
1428*cb5caa98Sdjl 			_nscd_cfg_nsw_spc_default[i].group_off +
1429*cb5caa98Sdjl 			_nscd_cfg_nsw_spc_default[i].param_off;
1430*cb5caa98Sdjl 
1431*cb5caa98Sdjl 		src = _nscd_cfg_nsw_spc_default[i].data;
1432*cb5caa98Sdjl 		datalen = _nscd_cfg_nsw_spc_default[i].data_len;
1433*cb5caa98Sdjl 
1434*cb5caa98Sdjl 		(void) memcpy(dest, src, datalen);
1435*cb5caa98Sdjl 	}
1436*cb5caa98Sdjl 
1437*cb5caa98Sdjl 	/* add db specific defaults via links */
1438*cb5caa98Sdjl 	for (i = 0; i < _nscd_cfg_num_link_default; i++) {
1439*cb5caa98Sdjl 
1440*cb5caa98Sdjl 		if (_nscd_cfg_nsw_link_default[i].data == NULL)
1441*cb5caa98Sdjl 			continue;
1442*cb5caa98Sdjl 
1443*cb5caa98Sdjl 		spc = _nscd_cfg_nsw_link_default[i].data;
1444*cb5caa98Sdjl 
1445*cb5caa98Sdjl 		if (_nscd_cfg_nsw_link_default[i].db != dbni) {
1446*cb5caa98Sdjl 			for (j = 0; j < _nscd_cfg_num_nsw_db; j++) {
1447*cb5caa98Sdjl 
1448*cb5caa98Sdjl 				if (strcmp(_nscd_cfg_nsw_db[j].name,
1449*cb5caa98Sdjl 					_nscd_cfg_nsw_link_default[i].db) != 0)
1450*cb5caa98Sdjl 					continue;
1451*cb5caa98Sdjl 
1452*cb5caa98Sdjl 				dbi = _nscd_cfg_nsw_db[j].index;
1453*cb5caa98Sdjl 				dbni = _nscd_cfg_nsw_db[j].name;
1454*cb5caa98Sdjl 				break;
1455*cb5caa98Sdjl 			}
1456*cb5caa98Sdjl 		}
1457*cb5caa98Sdjl 
1458*cb5caa98Sdjl 		dest = (char *)&nscd_cfg_nsw_db_data_current[dbi] +
1459*cb5caa98Sdjl 			_nscd_cfg_nsw_link_default[i].group_off +
1460*cb5caa98Sdjl 			_nscd_cfg_nsw_link_default[i].param_off;
1461*cb5caa98Sdjl 
1462*cb5caa98Sdjl 		if (_nscd_cfg_nsw_db[j].name != dbnj) {
1463*cb5caa98Sdjl 			for (j = 0; j < _nscd_cfg_num_nsw_db; j++) {
1464*cb5caa98Sdjl 
1465*cb5caa98Sdjl 				if (strcmp(spc->db,
1466*cb5caa98Sdjl 					_nscd_cfg_nsw_db[j].name) != 0)
1467*cb5caa98Sdjl 					continue;
1468*cb5caa98Sdjl 
1469*cb5caa98Sdjl 				dbnj = _nscd_cfg_nsw_db[j].name;
1470*cb5caa98Sdjl 				dbj = _nscd_cfg_nsw_db[j].index;
1471*cb5caa98Sdjl 				break;
1472*cb5caa98Sdjl 			}
1473*cb5caa98Sdjl 		}
1474*cb5caa98Sdjl 
1475*cb5caa98Sdjl 		src = (char *)&nscd_cfg_nsw_db_data_current[dbj] +
1476*cb5caa98Sdjl 				spc->group_off + spc->param_off;
1477*cb5caa98Sdjl 		datalen = spc->data_len;
1478*cb5caa98Sdjl 
1479*cb5caa98Sdjl 		(void) memcpy(dest, src, datalen);
1480*cb5caa98Sdjl 	}
1481*cb5caa98Sdjl 
1482*cb5caa98Sdjl 	/* fix up variable length fields */
1483*cb5caa98Sdjl 	for (i = 0; i < _nscd_cfg_num_nsw_db; i++) {
1484*cb5caa98Sdjl 
1485*cb5caa98Sdjl 		rc = _nscd_cfg_set_vlen_data_int(
1486*cb5caa98Sdjl 			&nscd_cfg_nsw_db_data_current[i],
1487*cb5caa98Sdjl 			&nscd_cfg_nsw_db_data_current[i], nscd_false);
1488*cb5caa98Sdjl 		if (rc != NSCD_SUCCESS)
1489*cb5caa98Sdjl 			return (rc);
1490*cb5caa98Sdjl 	}
1491*cb5caa98Sdjl 
1492*cb5caa98Sdjl 	nscd_cfg_nsw_alldb_rwlock = calloc(1, sizeof (rwlock_t));
1493*cb5caa98Sdjl 	if (nscd_cfg_nsw_alldb_rwlock == NULL)
1494*cb5caa98Sdjl 		return (NSCD_NO_MEMORY);
1495*cb5caa98Sdjl 
1496*cb5caa98Sdjl 	(void) rwlock_init(nscd_cfg_nsw_alldb_rwlock, NULL, NULL);
1497*cb5caa98Sdjl 
1498*cb5caa98Sdjl 	rc = _nscd_cfg_set_vlen_data_int(
1499*cb5caa98Sdjl 		&nscd_cfg_nsw_db_data_default,
1500*cb5caa98Sdjl 		&nscd_cfg_nsw_alldb_current, nscd_false);
1501*cb5caa98Sdjl 	if (rc != NSCD_SUCCESS)
1502*cb5caa98Sdjl 		return (rc);
1503*cb5caa98Sdjl 
1504*cb5caa98Sdjl 	/*
1505*cb5caa98Sdjl 	 * notify and send the configuration data to
1506*cb5caa98Sdjl 	 * the nscd components
1507*cb5caa98Sdjl 	 */
1508*cb5caa98Sdjl 	rc = _nscd_cfg_notify_init(errorp);
1509*cb5caa98Sdjl 	if (rc != NSCD_SUCCESS)
1510*cb5caa98Sdjl 		return (rc);
1511*cb5caa98Sdjl 
1512*cb5caa98Sdjl 	return (NSCD_SUCCESS);
1513*cb5caa98Sdjl }
1514*cb5caa98Sdjl 
1515*cb5caa98Sdjl static nscd_rc_t
1516*cb5caa98Sdjl _nscd_cfg_get_handle_common(
1517*cb5caa98Sdjl 	nscd_cfg_list_type_t	type,
1518*cb5caa98Sdjl 	char			*name,
1519*cb5caa98Sdjl 	char			*nswdb_name,
1520*cb5caa98Sdjl 	nscd_cfg_handle_t	**handle,
1521*cb5caa98Sdjl 	nscd_cfg_error_t	**errorp)
1522*cb5caa98Sdjl {
1523*cb5caa98Sdjl 
1524*cb5caa98Sdjl 	int			i, is_global;
1525*cb5caa98Sdjl 	char			*desc_str;
1526*cb5caa98Sdjl 	nscd_cfg_handle_t	*h;
1527*cb5caa98Sdjl 	nscd_cfg_param_desc_t	*pdesc;
1528*cb5caa98Sdjl 	nscd_cfg_stat_desc_t	*sdesc;
1529*cb5caa98Sdjl 	char			*me = "_nscd_cfg_get_handle_common";
1530*cb5caa98Sdjl 	char			msg[NSCD_CFG_MAX_ERR_MSG_LEN];
1531*cb5caa98Sdjl 	nscd_rc_t		rc = NSCD_INVALID_ARGUMENT;
1532*cb5caa98Sdjl 
1533*cb5caa98Sdjl 	if (handle == NULL) {
1534*cb5caa98Sdjl 
1535*cb5caa98Sdjl 		(void) snprintf(msg, sizeof (msg),
1536*cb5caa98Sdjl 			gettext("address of handle not specified"));
1537*cb5caa98Sdjl 		if (errorp)
1538*cb5caa98Sdjl 			*errorp = _nscd_cfg_make_error(rc, msg);
1539*cb5caa98Sdjl 
1540*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
1541*cb5caa98Sdjl 		(me, "invalid argument: %s\n", msg);
1542*cb5caa98Sdjl 
1543*cb5caa98Sdjl 		return (rc);
1544*cb5caa98Sdjl 	}
1545*cb5caa98Sdjl 
1546*cb5caa98Sdjl 	*handle = NULL;
1547*cb5caa98Sdjl 
1548*cb5caa98Sdjl 	if (name == NULL) {
1549*cb5caa98Sdjl 
1550*cb5caa98Sdjl 		(void) snprintf(msg, sizeof (msg),
1551*cb5caa98Sdjl 			gettext("name not specified"));
1552*cb5caa98Sdjl 		if (errorp)
1553*cb5caa98Sdjl 			*errorp = _nscd_cfg_make_error(rc, msg);
1554*cb5caa98Sdjl 
1555*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
1556*cb5caa98Sdjl 		(me, "invalid argument: %s\n");
1557*cb5caa98Sdjl 
1558*cb5caa98Sdjl 		return (rc);
1559*cb5caa98Sdjl 	}
1560*cb5caa98Sdjl 
1561*cb5caa98Sdjl 	h = calloc(1, sizeof (nscd_cfg_handle_t));
1562*cb5caa98Sdjl 	if (h == NULL)
1563*cb5caa98Sdjl 		return (NSCD_NO_MEMORY);
1564*cb5caa98Sdjl 	h->type = type;
1565*cb5caa98Sdjl 
1566*cb5caa98Sdjl 	if (type == NSCD_CFG_LIST_PARAM)
1567*cb5caa98Sdjl 		desc_str = gettext("configuration parameter");
1568*cb5caa98Sdjl 	else
1569*cb5caa98Sdjl 		desc_str = gettext("statistics");
1570*cb5caa98Sdjl 
1571*cb5caa98Sdjl 	/* get param or stat descriptor */
1572*cb5caa98Sdjl 	i = _nscd_cfg_get_index(name, type);
1573*cb5caa98Sdjl 	if (i != -1) {
1574*cb5caa98Sdjl 
1575*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
1576*cb5caa98Sdjl 		(me, "%s: index of %s is %d\n", desc_str, name, i);
1577*cb5caa98Sdjl 
1578*cb5caa98Sdjl 		if (type == NSCD_CFG_LIST_PARAM) {
1579*cb5caa98Sdjl 			pdesc = &_nscd_cfg_param_desc[i];
1580*cb5caa98Sdjl 			(void) memcpy(&h->desc, &pdesc, sizeof (pdesc));
1581*cb5caa98Sdjl 			is_global = _nscd_cfg_flag_is_set(
1582*cb5caa98Sdjl 				pdesc->pflag, NSCD_CFG_PFLAG_GLOBAL);
1583*cb5caa98Sdjl 
1584*cb5caa98Sdjl 			/* hidden params are not exposed */
1585*cb5caa98Sdjl 			if (_nscd_cfg_flag_is_set(
1586*cb5caa98Sdjl 				pdesc->pflag, NSCD_CFG_PFLAG_HIDDEN))
1587*cb5caa98Sdjl 				i = -1;
1588*cb5caa98Sdjl 
1589*cb5caa98Sdjl 			if (_nscd_cfg_flag_is_set(pdesc->pflag,
1590*cb5caa98Sdjl 					NSCD_CFG_PFLAG_OBSOLETE)) {
1591*cb5caa98Sdjl 				_NSCD_LOG(NSCD_LOG_CONFIG,
1592*cb5caa98Sdjl 					NSCD_LOG_LEVEL_WARNING)
1593*cb5caa98Sdjl 					(me,
1594*cb5caa98Sdjl 			gettext("%s: %s is obsolete and will be ignored\n"),
1595*cb5caa98Sdjl 					desc_str, name);
1596*cb5caa98Sdjl 			}
1597*cb5caa98Sdjl 		} else {
1598*cb5caa98Sdjl 			sdesc = &_nscd_cfg_stat_desc[i];
1599*cb5caa98Sdjl 			(void) memcpy(&h->desc, &sdesc, sizeof (sdesc));
1600*cb5caa98Sdjl 			is_global = _nscd_cfg_flag_is_set(
1601*cb5caa98Sdjl 				sdesc->sflag, NSCD_CFG_SFLAG_GLOBAL);
1602*cb5caa98Sdjl 		}
1603*cb5caa98Sdjl 	}
1604*cb5caa98Sdjl 
1605*cb5caa98Sdjl 	if (i == -1) {
1606*cb5caa98Sdjl 
1607*cb5caa98Sdjl 		(void) snprintf(msg, sizeof (msg),
1608*cb5caa98Sdjl 			gettext("%s: unknown name \"%s\""), desc_str, name);
1609*cb5caa98Sdjl 		if (errorp)
1610*cb5caa98Sdjl 			*errorp = _nscd_cfg_make_error(rc, msg);
1611*cb5caa98Sdjl 
1612*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
1613*cb5caa98Sdjl 		(me, "%s\n", msg);
1614*cb5caa98Sdjl 
1615*cb5caa98Sdjl 		free(h);
1616*cb5caa98Sdjl 		return (rc);
1617*cb5caa98Sdjl 	}
1618*cb5caa98Sdjl 
1619*cb5caa98Sdjl 	/*
1620*cb5caa98Sdjl 	 * if the param/stat is not a global one, we need to
1621*cb5caa98Sdjl 	 * know which nsswitch database we are dealing with
1622*cb5caa98Sdjl 	 */
1623*cb5caa98Sdjl 	if (is_global == 0) {
1624*cb5caa98Sdjl 		if (nswdb_name == NULL) {
1625*cb5caa98Sdjl 
1626*cb5caa98Sdjl 			(void) snprintf(msg, sizeof (msg),
1627*cb5caa98Sdjl 			gettext("%s: switch database name not specified"),
1628*cb5caa98Sdjl 				desc_str);
1629*cb5caa98Sdjl 			if (errorp)
1630*cb5caa98Sdjl 				*errorp = _nscd_cfg_make_error(rc, msg);
1631*cb5caa98Sdjl 
1632*cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
1633*cb5caa98Sdjl 			(me, "%s for non-global param or stat %s\n",
1634*cb5caa98Sdjl 			msg, name);
1635*cb5caa98Sdjl 
1636*cb5caa98Sdjl 			free(h);
1637*cb5caa98Sdjl 			return (rc);
1638*cb5caa98Sdjl 		}
1639*cb5caa98Sdjl 	} else {
1640*cb5caa98Sdjl 
1641*cb5caa98Sdjl 		if (nswdb_name != NULL) {
1642*cb5caa98Sdjl 
1643*cb5caa98Sdjl 			(void) snprintf(msg, sizeof (msg),
1644*cb5caa98Sdjl 	gettext("%s: switch database specified for global data"),
1645*cb5caa98Sdjl 				desc_str);
1646*cb5caa98Sdjl 			if (errorp)
1647*cb5caa98Sdjl 				*errorp = _nscd_cfg_make_error(rc, msg);
1648*cb5caa98Sdjl 
1649*cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
1650*cb5caa98Sdjl 			(me, "%s %s\n", msg, name);
1651*cb5caa98Sdjl 
1652*cb5caa98Sdjl 			free(h);
1653*cb5caa98Sdjl 			return (rc);
1654*cb5caa98Sdjl 		}
1655*cb5caa98Sdjl 
1656*cb5caa98Sdjl 		*handle = h;
1657*cb5caa98Sdjl 		return (NSCD_SUCCESS);
1658*cb5caa98Sdjl 	}
1659*cb5caa98Sdjl 
1660*cb5caa98Sdjl 	/* get nsw DB id */
1661*cb5caa98Sdjl 	i = _nscd_cfg_get_index(nswdb_name, NSCD_CFG_LIST_NSW_DB);
1662*cb5caa98Sdjl 	if (i != -1) {
1663*cb5caa98Sdjl 
1664*cb5caa98Sdjl 		if (i == NSCD_CFG_NSW_ALLDB_INDEX)
1665*cb5caa98Sdjl 			h->nswdb = &_nscd_cfg_nsw_alldb;
1666*cb5caa98Sdjl 		else
1667*cb5caa98Sdjl 			h->nswdb = &_nscd_cfg_nsw_db[i];
1668*cb5caa98Sdjl 
1669*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
1670*cb5caa98Sdjl 		(me, "%s: index of %s is %d\n",
1671*cb5caa98Sdjl 			desc_str, nswdb_name, i);
1672*cb5caa98Sdjl 	} else {
1673*cb5caa98Sdjl 
1674*cb5caa98Sdjl 		(void) snprintf(msg, sizeof (msg),
1675*cb5caa98Sdjl 			gettext("%s: unknown switch database name \"%s\""),
1676*cb5caa98Sdjl 			desc_str, nswdb_name);
1677*cb5caa98Sdjl 		if (errorp)
1678*cb5caa98Sdjl 			*errorp = _nscd_cfg_make_error(rc, msg);
1679*cb5caa98Sdjl 
1680*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
1681*cb5caa98Sdjl 		(me, "%s\n", msg);
1682*cb5caa98Sdjl 
1683*cb5caa98Sdjl 		free(h);
1684*cb5caa98Sdjl 		return (NSCD_CFG_UNSUPPORTED_SWITCH_DB);
1685*cb5caa98Sdjl 	}
1686*cb5caa98Sdjl 
1687*cb5caa98Sdjl 	*handle = h;
1688*cb5caa98Sdjl 
1689*cb5caa98Sdjl 	return (NSCD_SUCCESS);
1690*cb5caa98Sdjl }
1691*cb5caa98Sdjl 
1692*cb5caa98Sdjl nscd_rc_t
1693*cb5caa98Sdjl _nscd_cfg_get_handle(
1694*cb5caa98Sdjl 	char			*param_name,
1695*cb5caa98Sdjl 	char			*nswdb_name,
1696*cb5caa98Sdjl 	nscd_cfg_handle_t	**handle,
1697*cb5caa98Sdjl 	nscd_cfg_error_t	**errorp)
1698*cb5caa98Sdjl {
1699*cb5caa98Sdjl 
1700*cb5caa98Sdjl 	return (_nscd_cfg_get_handle_common(NSCD_CFG_LIST_PARAM,
1701*cb5caa98Sdjl 		param_name, nswdb_name, handle, errorp));
1702*cb5caa98Sdjl }
1703*cb5caa98Sdjl 
1704*cb5caa98Sdjl nscd_rc_t
1705*cb5caa98Sdjl _nscd_cfg_get_stat_handle(
1706*cb5caa98Sdjl 	char			*stat_name,
1707*cb5caa98Sdjl 	char			*nswdb_name,
1708*cb5caa98Sdjl 	nscd_cfg_handle_t	**handle,
1709*cb5caa98Sdjl 	nscd_cfg_error_t	**errorp)
1710*cb5caa98Sdjl {
1711*cb5caa98Sdjl 
1712*cb5caa98Sdjl 	return (_nscd_cfg_get_handle_common(NSCD_CFG_LIST_STAT,
1713*cb5caa98Sdjl 		stat_name, nswdb_name, handle, errorp));
1714*cb5caa98Sdjl }
1715*cb5caa98Sdjl 
1716*cb5caa98Sdjl void
1717*cb5caa98Sdjl _nscd_cfg_free_handle(
1718*cb5caa98Sdjl 	nscd_cfg_handle_t	*handle)
1719*cb5caa98Sdjl {
1720*cb5caa98Sdjl 
1721*cb5caa98Sdjl 	free(handle);
1722*cb5caa98Sdjl 
1723*cb5caa98Sdjl }
1724*cb5caa98Sdjl 
1725*cb5caa98Sdjl static void
1726*cb5caa98Sdjl _nscd_cfg_free_vlen_data_group(
1727*cb5caa98Sdjl 	nscd_cfg_param_desc_t	*gdesc,
1728*cb5caa98Sdjl 	void			*group_data,
1729*cb5caa98Sdjl 	nscd_bool_t		in)
1730*cb5caa98Sdjl {
1731*cb5caa98Sdjl 	int			num;
1732*cb5caa98Sdjl 	void			*dest, *ptr;
1733*cb5caa98Sdjl 	nscd_cfg_param_desc_t	*desc;
1734*cb5caa98Sdjl 
1735*cb5caa98Sdjl 	desc = gdesc;
1736*cb5caa98Sdjl 
1737*cb5caa98Sdjl 	num = ((nscd_cfg_group_info_t *)group_data)->num_param;
1738*cb5caa98Sdjl 
1739*cb5caa98Sdjl 	while (num-- > 0) {
1740*cb5caa98Sdjl 
1741*cb5caa98Sdjl 		desc++;
1742*cb5caa98Sdjl 
1743*cb5caa98Sdjl 		/* skip fixed length data */
1744*cb5caa98Sdjl 		if (_nscd_cfg_flag_is_not_set(desc->pflag,
1745*cb5caa98Sdjl 				NSCD_CFG_PFLAG_VLEN_DATA))
1746*cb5caa98Sdjl 			continue;
1747*cb5caa98Sdjl 
1748*cb5caa98Sdjl 		dest = (char *)group_data + desc->p_offset;
1749*cb5caa98Sdjl 		ptr = *(char **)dest;
1750*cb5caa98Sdjl 		if (ptr == NULL)
1751*cb5caa98Sdjl 			continue;
1752*cb5caa98Sdjl 		if (in == nscd_true)
1753*cb5caa98Sdjl 			_nscd_cfg_free_vlen_data_int(ptr);
1754*cb5caa98Sdjl 		else
1755*cb5caa98Sdjl 			free(ptr);
1756*cb5caa98Sdjl 	}
1757*cb5caa98Sdjl }
1758*cb5caa98Sdjl 
1759*cb5caa98Sdjl void
1760*cb5caa98Sdjl _nscd_cfg_free_param_data(
1761*cb5caa98Sdjl 	void			*data)
1762*cb5caa98Sdjl {
1763*cb5caa98Sdjl 
1764*cb5caa98Sdjl 	if (data == NULL)
1765*cb5caa98Sdjl 		return;
1766*cb5caa98Sdjl 
1767*cb5caa98Sdjl 	free(data);
1768*cb5caa98Sdjl }
1769*cb5caa98Sdjl 
1770*cb5caa98Sdjl void
1771*cb5caa98Sdjl _nscd_cfg_free_group_data(
1772*cb5caa98Sdjl 	nscd_cfg_handle_t	*handle,
1773*cb5caa98Sdjl 	void			*data)
1774*cb5caa98Sdjl {
1775*cb5caa98Sdjl 
1776*cb5caa98Sdjl 	nscd_cfg_param_desc_t	*desc;
1777*cb5caa98Sdjl 	nscd_cfg_group_info_t	*gi;
1778*cb5caa98Sdjl 
1779*cb5caa98Sdjl 	if (handle == NULL || data == NULL)
1780*cb5caa98Sdjl 		return;
1781*cb5caa98Sdjl 
1782*cb5caa98Sdjl 	desc = _nscd_cfg_get_desc(handle);
1783*cb5caa98Sdjl 	gi = (nscd_cfg_group_info_t *)data;
1784*cb5caa98Sdjl 	if (desc->p_fn != gi->num_param)
1785*cb5caa98Sdjl 		return;
1786*cb5caa98Sdjl 
1787*cb5caa98Sdjl 	_nscd_cfg_free_vlen_data_group(desc, data, nscd_false);
1788*cb5caa98Sdjl 
1789*cb5caa98Sdjl 	free(data);
1790*cb5caa98Sdjl }
1791*cb5caa98Sdjl 
1792*cb5caa98Sdjl void
1793*cb5caa98Sdjl _nscd_cfg_free_error(
1794*cb5caa98Sdjl 	nscd_cfg_error_t	*error)
1795*cb5caa98Sdjl {
1796*cb5caa98Sdjl 
1797*cb5caa98Sdjl 	if (error == NULL)
1798*cb5caa98Sdjl 		return;
1799*cb5caa98Sdjl 
1800*cb5caa98Sdjl 	free(error);
1801*cb5caa98Sdjl }
1802*cb5caa98Sdjl 
1803*cb5caa98Sdjl static nscd_rc_t
1804*cb5caa98Sdjl _nscd_cfg_copy_param_data(
1805*cb5caa98Sdjl 	nscd_cfg_param_desc_t	*desc,
1806*cb5caa98Sdjl 	void			*dest,
1807*cb5caa98Sdjl 	void			*pdata,
1808*cb5caa98Sdjl 	nscd_bool_t		in,
1809*cb5caa98Sdjl 	nscd_bool_t		set_addr)
1810*cb5caa98Sdjl {
1811*cb5caa98Sdjl 
1812*cb5caa98Sdjl 	char			*me = "_nscd_cfg_copy_param_data";
1813*cb5caa98Sdjl 	void			*tmp;
1814*cb5caa98Sdjl 	int			dlen;
1815*cb5caa98Sdjl 	nscd_rc_t		rc = NSCD_SUCCESS;
1816*cb5caa98Sdjl 
1817*cb5caa98Sdjl 	if (desc == NULL || dest == NULL) {
1818*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
1819*cb5caa98Sdjl 		(me, "input desc == %p, dest == %p\n", desc, dest);
1820*cb5caa98Sdjl 		return (NSCD_INVALID_ARGUMENT);
1821*cb5caa98Sdjl 	}
1822*cb5caa98Sdjl 
1823*cb5caa98Sdjl 	/* fixed length data */
1824*cb5caa98Sdjl 	if (_nscd_cfg_flag_is_not_set(desc->pflag,
1825*cb5caa98Sdjl 			NSCD_CFG_PFLAG_VLEN_DATA)) {
1826*cb5caa98Sdjl 		(void) memcpy(dest, pdata, desc->p_size);
1827*cb5caa98Sdjl 		goto done;
1828*cb5caa98Sdjl 	}
1829*cb5caa98Sdjl 
1830*cb5caa98Sdjl 
1831*cb5caa98Sdjl 	/* variable length data from this point on */
1832*cb5caa98Sdjl 
1833*cb5caa98Sdjl 	/* make a copy of the variable length data */
1834*cb5caa98Sdjl 	rc = _nscd_cfg_copy_vlen_data(pdata, &tmp, desc, &dlen, in);
1835*cb5caa98Sdjl 	if (rc != NSCD_SUCCESS)
1836*cb5caa98Sdjl 		goto done;
1837*cb5caa98Sdjl 
1838*cb5caa98Sdjl 	if (in == nscd_true) { /* data to internal */
1839*cb5caa98Sdjl 
1840*cb5caa98Sdjl 		/* free the variable length data in the config store */
1841*cb5caa98Sdjl 		if (*(char **)dest != NULL)
1842*cb5caa98Sdjl 			_nscd_cfg_free_vlen_data_int(*(char **)dest);
1843*cb5caa98Sdjl 	}
1844*cb5caa98Sdjl 
1845*cb5caa98Sdjl 	if (set_addr == nscd_true) {
1846*cb5caa98Sdjl 		/*
1847*cb5caa98Sdjl 		 * set the addr of the vlen data
1848*cb5caa98Sdjl 		 */
1849*cb5caa98Sdjl 		*(char **)dest = tmp;
1850*cb5caa98Sdjl 	} else {
1851*cb5caa98Sdjl 		/*
1852*cb5caa98Sdjl 		 * copy the data content (not address)
1853*cb5caa98Sdjl 		 */
1854*cb5caa98Sdjl 		(void) memcpy(dest, tmp, dlen);
1855*cb5caa98Sdjl 	}
1856*cb5caa98Sdjl 
1857*cb5caa98Sdjl 	done:
1858*cb5caa98Sdjl 
1859*cb5caa98Sdjl 	return (rc);
1860*cb5caa98Sdjl }
1861*cb5caa98Sdjl 
1862*cb5caa98Sdjl static nscd_rc_t
1863*cb5caa98Sdjl _nscd_cfg_copy_group_data_in(
1864*cb5caa98Sdjl 	nscd_cfg_param_desc_t	*gdesc,
1865*cb5caa98Sdjl 	nscd_cfg_group_info_t	*gi,
1866*cb5caa98Sdjl 	void			*group_dest,
1867*cb5caa98Sdjl 	void			*group_src)
1868*cb5caa98Sdjl {
1869*cb5caa98Sdjl 	int			i, num;
1870*cb5caa98Sdjl 	nscd_cfg_param_desc_t	*desc;
1871*cb5caa98Sdjl 	void			*src, *dest;
1872*cb5caa98Sdjl 
1873*cb5caa98Sdjl 	i = 0;
1874*cb5caa98Sdjl 	num = gi->num_param;
1875*cb5caa98Sdjl 	desc = gdesc;
1876*cb5caa98Sdjl 
1877*cb5caa98Sdjl 	while (num-- > 0) {
1878*cb5caa98Sdjl 
1879*cb5caa98Sdjl 		desc++;
1880*cb5caa98Sdjl 
1881*cb5caa98Sdjl 		/* if member not selected by bitmap, skip */
1882*cb5caa98Sdjl 		if (_nscd_cfg_bitmap_is_not_set(gi->bitmap, i++))
1883*cb5caa98Sdjl 			continue;
1884*cb5caa98Sdjl 
1885*cb5caa98Sdjl 		src = (char *)group_src + desc->p_offset;
1886*cb5caa98Sdjl 		dest = (char *)group_dest + desc->p_offset;
1887*cb5caa98Sdjl 
1888*cb5caa98Sdjl 		/*
1889*cb5caa98Sdjl 		 * if variable length data, free and replace the old
1890*cb5caa98Sdjl 		 * with the new
1891*cb5caa98Sdjl 		 */
1892*cb5caa98Sdjl 		if (_nscd_cfg_flag_is_set(desc->pflag,
1893*cb5caa98Sdjl 				NSCD_CFG_PFLAG_VLEN_DATA)) {
1894*cb5caa98Sdjl 			_nscd_cfg_free_vlen_data_int(*(char **)dest);
1895*cb5caa98Sdjl 			*(char **)dest = *(char **)src;
1896*cb5caa98Sdjl 			*(char **)src = NULL;
1897*cb5caa98Sdjl 		} else {
1898*cb5caa98Sdjl 			/*
1899*cb5caa98Sdjl 			 * fixed length data, just copy it
1900*cb5caa98Sdjl 			 */
1901*cb5caa98Sdjl 			(void) memcpy(dest, src, desc->p_size);
1902*cb5caa98Sdjl 		}
1903*cb5caa98Sdjl 	}
1904*cb5caa98Sdjl 
1905*cb5caa98Sdjl 	return (NSCD_SUCCESS);
1906*cb5caa98Sdjl }
1907*cb5caa98Sdjl 
1908*cb5caa98Sdjl static nscd_rc_t
1909*cb5caa98Sdjl _nscd_cfg_copy_group_data_out(
1910*cb5caa98Sdjl 	nscd_cfg_param_desc_t	*gdesc,
1911*cb5caa98Sdjl 	void			*group_dest,
1912*cb5caa98Sdjl 	void			*group_src)
1913*cb5caa98Sdjl {
1914*cb5caa98Sdjl 
1915*cb5caa98Sdjl 	char			*me = "_nscd_cfg_copy_group_data_out";
1916*cb5caa98Sdjl 	void			*src, *dest;
1917*cb5caa98Sdjl 	int			dlen;
1918*cb5caa98Sdjl 	int			num;
1919*cb5caa98Sdjl 	nscd_cfg_group_info_t	*gi;
1920*cb5caa98Sdjl 	nscd_rc_t		rc = NSCD_SUCCESS;
1921*cb5caa98Sdjl 	nscd_cfg_param_desc_t	*desc;
1922*cb5caa98Sdjl 
1923*cb5caa98Sdjl 	if (group_dest == NULL) {
1924*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
1925*cb5caa98Sdjl 		(me, "input group_dest = NULL\n");
1926*cb5caa98Sdjl 		return (NSCD_INVALID_ARGUMENT);
1927*cb5caa98Sdjl 	}
1928*cb5caa98Sdjl 
1929*cb5caa98Sdjl 	gi = _nscd_cfg_get_gi(group_src);
1930*cb5caa98Sdjl 	num = gi->num_param;
1931*cb5caa98Sdjl 	desc = gdesc;
1932*cb5caa98Sdjl 
1933*cb5caa98Sdjl 	while (num-- > 0) {
1934*cb5caa98Sdjl 
1935*cb5caa98Sdjl 		desc++;
1936*cb5caa98Sdjl 
1937*cb5caa98Sdjl 		dest = (char *)group_dest + desc->p_offset;
1938*cb5caa98Sdjl 		src = (char *)group_src + desc->p_offset;
1939*cb5caa98Sdjl 
1940*cb5caa98Sdjl 		/*
1941*cb5caa98Sdjl 		 * if variable length data, get the real
1942*cb5caa98Sdjl 		 * address and length of the data
1943*cb5caa98Sdjl 		 */
1944*cb5caa98Sdjl 		if (_nscd_cfg_flag_is_set(desc->pflag,
1945*cb5caa98Sdjl 				NSCD_CFG_PFLAG_VLEN_DATA)) {
1946*cb5caa98Sdjl 			src = _nscd_cfg_locate_vlen_data(src, &dlen);
1947*cb5caa98Sdjl 			if (dlen == NULL)
1948*cb5caa98Sdjl 				continue;
1949*cb5caa98Sdjl 		}
1950*cb5caa98Sdjl 
1951*cb5caa98Sdjl 		/*
1952*cb5caa98Sdjl 		 * The nscd_true asks _nscd_cfg_copy_param_data
1953*cb5caa98Sdjl 		 * to set addr of the vlen data in 'dest' rather
1954*cb5caa98Sdjl 		 * than copying the data content
1955*cb5caa98Sdjl 		 */
1956*cb5caa98Sdjl 		rc = _nscd_cfg_copy_param_data(desc, dest, src,
1957*cb5caa98Sdjl 			nscd_false, nscd_true);
1958*cb5caa98Sdjl 		if (rc != NSCD_SUCCESS) {
1959*cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
1960*cb5caa98Sdjl 			(me, "unable to copy param data for %s\n",
1961*cb5caa98Sdjl 				desc->id.name);
1962*cb5caa98Sdjl 
1963*cb5caa98Sdjl 			_nscd_cfg_free_vlen_data_group(gdesc,
1964*cb5caa98Sdjl 				group_dest, nscd_false);
1965*cb5caa98Sdjl 
1966*cb5caa98Sdjl 			free(group_dest);
1967*cb5caa98Sdjl 
1968*cb5caa98Sdjl 			return (rc);
1969*cb5caa98Sdjl 		}
1970*cb5caa98Sdjl 	}
1971*cb5caa98Sdjl 
1972*cb5caa98Sdjl 	/*
1973*cb5caa98Sdjl 	 * set group bitmap
1974*cb5caa98Sdjl 	 */
1975*cb5caa98Sdjl 	(void) memcpy(group_dest, group_src,
1976*cb5caa98Sdjl 		sizeof (nscd_cfg_group_info_t));
1977*cb5caa98Sdjl 
1978*cb5caa98Sdjl 	return (rc);
1979*cb5caa98Sdjl }
1980*cb5caa98Sdjl 
1981*cb5caa98Sdjl 
1982*cb5caa98Sdjl /*
1983*cb5caa98Sdjl  * group_cfg is needed always; group_src may be NULL if
1984*cb5caa98Sdjl  * param_index not zero and pdata not NULL; group_cfg and
1985*cb5caa98Sdjl  * pdata should not be both non-NULL
1986*cb5caa98Sdjl  */
1987*cb5caa98Sdjl static nscd_rc_t
1988*cb5caa98Sdjl _nscd_cfg_copy_group_data_merge(
1989*cb5caa98Sdjl 	nscd_cfg_param_desc_t	*gdesc,
1990*cb5caa98Sdjl 	void			**group_dest,
1991*cb5caa98Sdjl 	void			*group_src,
1992*cb5caa98Sdjl 	void			*group_cfg,
1993*cb5caa98Sdjl 	int			param_index,
1994*cb5caa98Sdjl 	void			*pdata)
1995*cb5caa98Sdjl {
1996*cb5caa98Sdjl 
1997*cb5caa98Sdjl 	char			*me = "_nscd_cfg_copy_group_data_merge";
1998*cb5caa98Sdjl 	void			*src, *dest, *tmp_dest = NULL;
1999*cb5caa98Sdjl 	int			num, i = 0;
2000*cb5caa98Sdjl 	nscd_cfg_group_info_t	*gi;
2001*cb5caa98Sdjl 	nscd_rc_t		rc = NSCD_SUCCESS;
2002*cb5caa98Sdjl 	nscd_cfg_param_desc_t	*desc;
2003*cb5caa98Sdjl 	nscd_cfg_bitmap_t	bitmap;
2004*cb5caa98Sdjl 
2005*cb5caa98Sdjl 	if (group_dest == NULL) {
2006*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2007*cb5caa98Sdjl 		(me, "input **group_dest == NULL\n");
2008*cb5caa98Sdjl 		return (NSCD_INVALID_ARGUMENT);
2009*cb5caa98Sdjl 	}
2010*cb5caa98Sdjl 
2011*cb5caa98Sdjl 	if (group_cfg == NULL) {
2012*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2013*cb5caa98Sdjl 		(me, "input **group_cfg == NULL\n");
2014*cb5caa98Sdjl 		return (NSCD_INVALID_ARGUMENT);
2015*cb5caa98Sdjl 	}
2016*cb5caa98Sdjl 
2017*cb5caa98Sdjl 	if (param_index != NULL && pdata == NULL) {
2018*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2019*cb5caa98Sdjl 		(me, "param_index != NULL but pdata == %p\n", pdata);
2020*cb5caa98Sdjl 		return (NSCD_INVALID_ARGUMENT);
2021*cb5caa98Sdjl 	}
2022*cb5caa98Sdjl 
2023*cb5caa98Sdjl 	tmp_dest = calloc(1, gdesc->g_size);
2024*cb5caa98Sdjl 	if (tmp_dest == NULL)
2025*cb5caa98Sdjl 		return (NSCD_NO_MEMORY);
2026*cb5caa98Sdjl 
2027*cb5caa98Sdjl 	if (group_src != NULL)
2028*cb5caa98Sdjl 		gi = _nscd_cfg_get_gi(group_src);
2029*cb5caa98Sdjl 	else {
2030*cb5caa98Sdjl 		gi = _nscd_cfg_get_gi(group_cfg);
2031*cb5caa98Sdjl 		bitmap = NSCD_CFG_BITMAP_ZERO;
2032*cb5caa98Sdjl 	}
2033*cb5caa98Sdjl 
2034*cb5caa98Sdjl 	num = gi->num_param;
2035*cb5caa98Sdjl 	desc = gdesc;
2036*cb5caa98Sdjl 
2037*cb5caa98Sdjl 	while (num-- > 0) {
2038*cb5caa98Sdjl 
2039*cb5caa98Sdjl 		desc++;
2040*cb5caa98Sdjl 
2041*cb5caa98Sdjl 		dest = (char *)tmp_dest + desc->p_offset;
2042*cb5caa98Sdjl 
2043*cb5caa98Sdjl 		/*
2044*cb5caa98Sdjl 		 * if member not selected by bitmap in group_src,
2045*cb5caa98Sdjl 		 * get the member data in group_cfg
2046*cb5caa98Sdjl 		 */
2047*cb5caa98Sdjl 		if (_nscd_cfg_bitmap_is_not_set(gi->bitmap, i++) ||
2048*cb5caa98Sdjl 				group_src == NULL) {
2049*cb5caa98Sdjl 			src = (char *)group_cfg + desc->p_offset;
2050*cb5caa98Sdjl 		} else
2051*cb5caa98Sdjl 			src = (char *)group_src + desc->p_offset;
2052*cb5caa98Sdjl 
2053*cb5caa98Sdjl 		if (desc->id.index == param_index) {
2054*cb5caa98Sdjl 
2055*cb5caa98Sdjl 			/* use the param data in pdata if provided */
2056*cb5caa98Sdjl 			src = pdata;
2057*cb5caa98Sdjl 			_nscd_cfg_bitmap_set_nth(bitmap, i);
2058*cb5caa98Sdjl 		}
2059*cb5caa98Sdjl 
2060*cb5caa98Sdjl 		/*
2061*cb5caa98Sdjl 		 * if variable length data, get to the data
2062*cb5caa98Sdjl 		 * instead of pointer to the data
2063*cb5caa98Sdjl 		 */
2064*cb5caa98Sdjl 		if (_nscd_cfg_flag_is_set(desc->pflag,
2065*cb5caa98Sdjl 			NSCD_CFG_PFLAG_VLEN_DATA))
2066*cb5caa98Sdjl 				src = *(char **)src;
2067*cb5caa98Sdjl 
2068*cb5caa98Sdjl 		/*
2069*cb5caa98Sdjl 		 * nscd_true asks _nscd_cfg_copy_param_data to
2070*cb5caa98Sdjl 		 * set addr of the vlen data in 'dest' rather
2071*cb5caa98Sdjl 		 * than copying the data content
2072*cb5caa98Sdjl 		 */
2073*cb5caa98Sdjl 		rc = _nscd_cfg_copy_param_data(desc, dest, src,
2074*cb5caa98Sdjl 			nscd_true, nscd_true);
2075*cb5caa98Sdjl 		if (rc != NSCD_SUCCESS) {
2076*cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2077*cb5caa98Sdjl 			(me, "unable to copy param data for %s\n",
2078*cb5caa98Sdjl 				desc->id.name);
2079*cb5caa98Sdjl 
2080*cb5caa98Sdjl 			_nscd_cfg_free_vlen_data_group(gdesc,
2081*cb5caa98Sdjl 				tmp_dest, nscd_true);
2082*cb5caa98Sdjl 
2083*cb5caa98Sdjl 			free(tmp_dest);
2084*cb5caa98Sdjl 
2085*cb5caa98Sdjl 			return (rc);
2086*cb5caa98Sdjl 		}
2087*cb5caa98Sdjl 	}
2088*cb5caa98Sdjl 
2089*cb5caa98Sdjl 	*group_dest = tmp_dest;
2090*cb5caa98Sdjl 
2091*cb5caa98Sdjl 	/*
2092*cb5caa98Sdjl 	 * set bitmap: if input is group data, use the one
2093*cb5caa98Sdjl 	 * given; if input is param data, use the one computed
2094*cb5caa98Sdjl 	 * above
2095*cb5caa98Sdjl 	 */
2096*cb5caa98Sdjl 	if (group_src != NULL)
2097*cb5caa98Sdjl 		(void) memcpy(*group_dest, group_src,
2098*cb5caa98Sdjl 			sizeof (nscd_cfg_group_info_t));
2099*cb5caa98Sdjl 	else {
2100*cb5caa98Sdjl 		gi = _nscd_cfg_get_gi(*group_dest);
2101*cb5caa98Sdjl 		_nscd_cfg_bitmap_set(&gi->bitmap, bitmap);
2102*cb5caa98Sdjl 	}
2103*cb5caa98Sdjl 
2104*cb5caa98Sdjl 	return (rc);
2105*cb5caa98Sdjl }
2106*cb5caa98Sdjl 
2107*cb5caa98Sdjl /* ARGSUSED */
2108*cb5caa98Sdjl nscd_rc_t
2109*cb5caa98Sdjl _nscd_cfg_get(
2110*cb5caa98Sdjl 	nscd_cfg_handle_t	*handle,
2111*cb5caa98Sdjl 	void			**data,
2112*cb5caa98Sdjl 	int			*data_len,
2113*cb5caa98Sdjl 	nscd_cfg_error_t	**errorp)
2114*cb5caa98Sdjl {
2115*cb5caa98Sdjl 	char			*me = "_nscd_cfg_get";
2116*cb5caa98Sdjl 	int			dlen;
2117*cb5caa98Sdjl 	nscd_rc_t		rc = NSCD_SUCCESS;
2118*cb5caa98Sdjl 	nscd_cfg_id_t		*nswdb;
2119*cb5caa98Sdjl 	nscd_cfg_param_desc_t	*desc;
2120*cb5caa98Sdjl 	void			*cfg_data, *ptr = NULL;
2121*cb5caa98Sdjl 	nscd_bool_t		get_group = nscd_false;
2122*cb5caa98Sdjl 	nscd_bool_t		out = nscd_false;
2123*cb5caa98Sdjl 	nscd_cfg_lock_t		*lock = NULL;
2124*cb5caa98Sdjl 
2125*cb5caa98Sdjl 	if (data_len != NULL)
2126*cb5caa98Sdjl 		*data_len = 0;
2127*cb5caa98Sdjl 
2128*cb5caa98Sdjl 	if (data == NULL) {
2129*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2130*cb5caa98Sdjl 		(me, "input data = %p\n", data);
2131*cb5caa98Sdjl 		return (NSCD_INVALID_ARGUMENT);
2132*cb5caa98Sdjl 	}
2133*cb5caa98Sdjl 
2134*cb5caa98Sdjl 	*data = NULL;
2135*cb5caa98Sdjl 
2136*cb5caa98Sdjl 	if (handle == NULL) {
2137*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2138*cb5caa98Sdjl 		(me, "handle is NULL\n");
2139*cb5caa98Sdjl 		return (NSCD_INVALID_ARGUMENT);
2140*cb5caa98Sdjl 	}
2141*cb5caa98Sdjl 
2142*cb5caa98Sdjl 	nswdb = handle->nswdb;
2143*cb5caa98Sdjl 	desc = (nscd_cfg_param_desc_t *)handle->desc;
2144*cb5caa98Sdjl 
2145*cb5caa98Sdjl 	if (_nscd_cfg_flag_is_set(desc->pflag, NSCD_CFG_PFLAG_GROUP))
2146*cb5caa98Sdjl 		get_group = nscd_true;
2147*cb5caa98Sdjl 
2148*cb5caa98Sdjl 	/*
2149*cb5caa98Sdjl 	 * locate the current value of the param or group
2150*cb5caa98Sdjl 	 * and lock the config data for reading
2151*cb5caa98Sdjl 	 */
2152*cb5caa98Sdjl 	rc = _nscd_cfg_locate_cfg_data(&cfg_data, nscd_true, desc,
2153*cb5caa98Sdjl 		nswdb, get_group, NULL, &dlen, &lock);
2154*cb5caa98Sdjl 	if (rc != NSCD_SUCCESS) {
2155*cb5caa98Sdjl 
2156*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2157*cb5caa98Sdjl 		(me, "unable to locate config data\n");
2158*cb5caa98Sdjl 		return (rc);
2159*cb5caa98Sdjl 
2160*cb5caa98Sdjl 	} else if (cfg_data == NULL) /* NULL vlen data */
2161*cb5caa98Sdjl 		goto done;
2162*cb5caa98Sdjl 
2163*cb5caa98Sdjl 	ptr = calloc(1, dlen);
2164*cb5caa98Sdjl 	if (ptr == NULL) {
2165*cb5caa98Sdjl 		rc = NSCD_NO_MEMORY;
2166*cb5caa98Sdjl 		goto error_exit;
2167*cb5caa98Sdjl 	}
2168*cb5caa98Sdjl 
2169*cb5caa98Sdjl 	if (get_group == nscd_true) {
2170*cb5caa98Sdjl 
2171*cb5caa98Sdjl 		rc = _nscd_cfg_copy_group_data_out(desc, ptr, cfg_data);
2172*cb5caa98Sdjl 		if (rc != NSCD_SUCCESS) {
2173*cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2174*cb5caa98Sdjl 			(me, "unable to copy group data %p: "
2175*cb5caa98Sdjl 			"error = %d\n", cfg_data, rc);
2176*cb5caa98Sdjl 
2177*cb5caa98Sdjl 			goto error_exit;
2178*cb5caa98Sdjl 		}
2179*cb5caa98Sdjl 	} else {
2180*cb5caa98Sdjl 		/*
2181*cb5caa98Sdjl 		 * nscd_false asks _nscd_cfg_copy_param_data to
2182*cb5caa98Sdjl 		 * copy the data content rather than just setting
2183*cb5caa98Sdjl 		 * the addr of the vlen data in 'ptr'
2184*cb5caa98Sdjl 		 */
2185*cb5caa98Sdjl 		rc = _nscd_cfg_copy_param_data(desc, ptr, cfg_data,
2186*cb5caa98Sdjl 			out, nscd_false);
2187*cb5caa98Sdjl 
2188*cb5caa98Sdjl 		if (rc != NSCD_SUCCESS) {
2189*cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2190*cb5caa98Sdjl 			(me, "unable to copy param data %p: "
2191*cb5caa98Sdjl 			"error = %d\n", cfg_data, rc);
2192*cb5caa98Sdjl 
2193*cb5caa98Sdjl 			goto error_exit;
2194*cb5caa98Sdjl 		}
2195*cb5caa98Sdjl 	}
2196*cb5caa98Sdjl 
2197*cb5caa98Sdjl 	*data = ptr;
2198*cb5caa98Sdjl 
2199*cb5caa98Sdjl 	done:
2200*cb5caa98Sdjl 
2201*cb5caa98Sdjl 	if (data_len != NULL)
2202*cb5caa98Sdjl 		*data_len = dlen;
2203*cb5caa98Sdjl 
2204*cb5caa98Sdjl 	_nscd_cfg_unlock(lock);
2205*cb5caa98Sdjl 
2206*cb5caa98Sdjl 	return (NSCD_SUCCESS);
2207*cb5caa98Sdjl 
2208*cb5caa98Sdjl 	error_exit:
2209*cb5caa98Sdjl 
2210*cb5caa98Sdjl 	_nscd_cfg_unlock(lock);
2211*cb5caa98Sdjl 	if (ptr != NULL)
2212*cb5caa98Sdjl 		free(ptr);
2213*cb5caa98Sdjl 
2214*cb5caa98Sdjl 	return (rc);
2215*cb5caa98Sdjl }
2216*cb5caa98Sdjl 
2217*cb5caa98Sdjl /*
2218*cb5caa98Sdjl  * three type of data:
2219*cb5caa98Sdjl  * 1 - single param
2220*cb5caa98Sdjl  * 	desc is that of the param
2221*cb5caa98Sdjl  * 2 - single param to be sent in a group
2222*cb5caa98Sdjl  *	a single bit is set in the bitmap,
2223*cb5caa98Sdjl  * 	desc is that of the group
2224*cb5caa98Sdjl  * 3 - group data
2225*cb5caa98Sdjl  *	one of more bits are set in the bitmap,
2226*cb5caa98Sdjl  * 	desc is that of the group
2227*cb5caa98Sdjl  */
2228*cb5caa98Sdjl static nscd_rc_t
2229*cb5caa98Sdjl _nscd_cfg_notify_s(
2230*cb5caa98Sdjl 	nscd_cfg_param_desc_t	*desc,
2231*cb5caa98Sdjl 	nscd_cfg_id_t		*nswdb,
2232*cb5caa98Sdjl 	void			*data,
2233*cb5caa98Sdjl 	nscd_cfg_error_t	**errorp)
2234*cb5caa98Sdjl {
2235*cb5caa98Sdjl 	int			i, num, is_group = 0;
2236*cb5caa98Sdjl 	void			*cookie = NULL;
2237*cb5caa98Sdjl 	void			*cdata;
2238*cb5caa98Sdjl 	nscd_rc_t		rc;
2239*cb5caa98Sdjl 	nscd_cfg_flag_t		dflag, dflag1;
2240*cb5caa98Sdjl 	nscd_cfg_bitmap_t	bitmap_s, bitmap_in, *bitmap_addr = NULL;
2241*cb5caa98Sdjl 	nscd_cfg_group_info_t	*gi;
2242*cb5caa98Sdjl 
2243*cb5caa98Sdjl 	if (errorp != NULL)
2244*cb5caa98Sdjl 		*errorp = NULL;
2245*cb5caa98Sdjl 
2246*cb5caa98Sdjl 	/*
2247*cb5caa98Sdjl 	 * Set data flag going with data to be sent to the
2248*cb5caa98Sdjl 	 * verify/notify routines. To allow the config flag
2249*cb5caa98Sdjl 	 * be exipandable, set the bits one by one.
2250*cb5caa98Sdjl 	 */
2251*cb5caa98Sdjl 	dflag = NSCD_CFG_FLAG_ZERO;
2252*cb5caa98Sdjl 	dflag = _nscd_cfg_flag_set(dflag, NSCD_CFG_DFLAG_STATIC_DATA);
2253*cb5caa98Sdjl 	if (_nscd_cfg_flag_is_set(desc->pflag, NSCD_CFG_PFLAG_GROUP)) {
2254*cb5caa98Sdjl 		dflag = _nscd_cfg_flag_set(dflag, NSCD_CFG_DFLAG_GROUP);
2255*cb5caa98Sdjl 		is_group = 1;
2256*cb5caa98Sdjl 	}
2257*cb5caa98Sdjl 	if (nswdb != NULL &&
2258*cb5caa98Sdjl 		strcmp(NSCD_CFG_NSW_ALLDB, nswdb->name) == 0)
2259*cb5caa98Sdjl 		dflag = _nscd_cfg_flag_set(dflag,
2260*cb5caa98Sdjl 				NSCD_CFG_DFLAG_SET_ALL_DB);
2261*cb5caa98Sdjl 
2262*cb5caa98Sdjl 	/*
2263*cb5caa98Sdjl 	 * the bitmap in the input data may be replaced before
2264*cb5caa98Sdjl 	 * sending to the components, so save the bitmap for
2265*cb5caa98Sdjl 	 * later use
2266*cb5caa98Sdjl 	 */
2267*cb5caa98Sdjl 	if (is_group == 1) {
2268*cb5caa98Sdjl 		gi = _nscd_cfg_get_gi(data);
2269*cb5caa98Sdjl 		bitmap_in = gi->bitmap;
2270*cb5caa98Sdjl 		bitmap_addr = &(gi->bitmap);
2271*cb5caa98Sdjl 
2272*cb5caa98Sdjl 		if (_nscd_cfg_flag_is_set(desc->pflag,
2273*cb5caa98Sdjl 			NSCD_CFG_PFLAG_INIT_SEND_WHOLE_GROUP))
2274*cb5caa98Sdjl 			/* send the entire group just once */
2275*cb5caa98Sdjl 			num = 1;
2276*cb5caa98Sdjl 
2277*cb5caa98Sdjl 		else { /* send individual members one by one */
2278*cb5caa98Sdjl 
2279*cb5caa98Sdjl 			num = desc->p_fn;
2280*cb5caa98Sdjl 
2281*cb5caa98Sdjl 			/*
2282*cb5caa98Sdjl 			 * skip the first desc which is for the group
2283*cb5caa98Sdjl 			 * and get to the desc for the first member
2284*cb5caa98Sdjl 			 */
2285*cb5caa98Sdjl 			desc++;
2286*cb5caa98Sdjl 
2287*cb5caa98Sdjl 			dflag = _nscd_cfg_flag_unset(dflag,
2288*cb5caa98Sdjl 				NSCD_CFG_DFLAG_GROUP);
2289*cb5caa98Sdjl 		}
2290*cb5caa98Sdjl 	} else {
2291*cb5caa98Sdjl 		/* not group data, send the member once */
2292*cb5caa98Sdjl 			num = 1;
2293*cb5caa98Sdjl 	}
2294*cb5caa98Sdjl 
2295*cb5caa98Sdjl 	dflag1 = dflag;
2296*cb5caa98Sdjl 	for (i = 0; i < num; i++, desc++) {
2297*cb5caa98Sdjl 
2298*cb5caa98Sdjl 		dflag = dflag1;
2299*cb5caa98Sdjl 
2300*cb5caa98Sdjl 		if (is_group == 0) {
2301*cb5caa98Sdjl 			cdata = data;
2302*cb5caa98Sdjl 			goto verify_data;
2303*cb5caa98Sdjl 		}
2304*cb5caa98Sdjl 
2305*cb5caa98Sdjl 		if (_nscd_cfg_flag_is_set(desc->pflag,
2306*cb5caa98Sdjl 				NSCD_CFG_PFLAG_SEND_BIT_SELECTED)) {
2307*cb5caa98Sdjl 
2308*cb5caa98Sdjl 			/* set the bitmap to select just this member */
2309*cb5caa98Sdjl 			bitmap_s = NSCD_CFG_BITMAP_ZERO;
2310*cb5caa98Sdjl 			_nscd_cfg_bitmap_set_nth(bitmap_s, i);
2311*cb5caa98Sdjl 			/* replace the bitmap in the input data */
2312*cb5caa98Sdjl 			_nscd_cfg_bitmap_set(bitmap_addr, bitmap_s);
2313*cb5caa98Sdjl 
2314*cb5caa98Sdjl 			/*
2315*cb5caa98Sdjl 			 * send the whole group but with only one
2316*cb5caa98Sdjl 			 * member selected
2317*cb5caa98Sdjl 			 */
2318*cb5caa98Sdjl 			cdata = data;
2319*cb5caa98Sdjl 
2320*cb5caa98Sdjl 			dflag = _nscd_cfg_flag_set(dflag,
2321*cb5caa98Sdjl 				NSCD_CFG_DFLAG_GROUP);
2322*cb5caa98Sdjl 			dflag = _nscd_cfg_flag_set(dflag,
2323*cb5caa98Sdjl 				NSCD_CFG_DFLAG_BIT_SELECTED);
2324*cb5caa98Sdjl 		} else {
2325*cb5caa98Sdjl 			/*
2326*cb5caa98Sdjl 			 * send param data or group data:
2327*cb5caa98Sdjl 			 * param data - non-xero desc->p_offset
2328*cb5caa98Sdjl 			 * group data - zero desc->p_offset
2329*cb5caa98Sdjl 			 */
2330*cb5caa98Sdjl 			cdata = (char *)data + desc->p_offset;
2331*cb5caa98Sdjl 
2332*cb5caa98Sdjl 			/*
2333*cb5caa98Sdjl 			 * if variable length data, need to send pointer
2334*cb5caa98Sdjl 			 * to the data (not the address of the pointer)
2335*cb5caa98Sdjl 			 */
2336*cb5caa98Sdjl 			if (_nscd_cfg_flag_is_set(desc->pflag,
2337*cb5caa98Sdjl 				NSCD_CFG_PFLAG_VLEN_DATA))
2338*cb5caa98Sdjl 				cdata = *(char **)cdata;
2339*cb5caa98Sdjl 		}
2340*cb5caa98Sdjl 
2341*cb5caa98Sdjl 		verify_data:
2342*cb5caa98Sdjl 
2343*cb5caa98Sdjl 		if (desc->verify != NULL) {
2344*cb5caa98Sdjl 			dflag = _nscd_cfg_flag_set(dflag,
2345*cb5caa98Sdjl 				NSCD_CFG_DFLAG_VERIFY);
2346*cb5caa98Sdjl 			rc = desc->verify(cdata, desc, nswdb,
2347*cb5caa98Sdjl 				dflag, errorp, &cookie);
2348*cb5caa98Sdjl 			if (rc != NSCD_SUCCESS)
2349*cb5caa98Sdjl 				goto error_exit;
2350*cb5caa98Sdjl 		}
2351*cb5caa98Sdjl 
2352*cb5caa98Sdjl 		if (desc->notify != NULL) {
2353*cb5caa98Sdjl 			dflag = _nscd_cfg_flag_set(dflag,
2354*cb5caa98Sdjl 				NSCD_CFG_DFLAG_NOTIFY);
2355*cb5caa98Sdjl 
2356*cb5caa98Sdjl 			rc = desc->notify(data, desc, nswdb,
2357*cb5caa98Sdjl 				dflag, errorp, cookie);
2358*cb5caa98Sdjl 			if (rc != NSCD_SUCCESS)
2359*cb5caa98Sdjl 				goto error_exit;
2360*cb5caa98Sdjl 		}
2361*cb5caa98Sdjl 	}
2362*cb5caa98Sdjl 
2363*cb5caa98Sdjl 	rc = NSCD_SUCCESS;
2364*cb5caa98Sdjl 
2365*cb5caa98Sdjl 	error_exit:
2366*cb5caa98Sdjl 
2367*cb5caa98Sdjl 	/* restore the bitmap in the input data */
2368*cb5caa98Sdjl 	if (bitmap_addr != NULL)
2369*cb5caa98Sdjl 		_nscd_cfg_bitmap_set(bitmap_addr, bitmap_in);
2370*cb5caa98Sdjl 
2371*cb5caa98Sdjl 	return (rc);
2372*cb5caa98Sdjl }
2373*cb5caa98Sdjl 
2374*cb5caa98Sdjl /*
2375*cb5caa98Sdjl  * Convert string 'str' to data based on the data type in 'desc'.
2376*cb5caa98Sdjl  * 'data' points to the buffer in which the converted data
2377*cb5caa98Sdjl  * is placed. '*data_p' points to the buffer, or in the case
2378*cb5caa98Sdjl  * of a string data type, points to the untoched string (i.e.,
2379*cb5caa98Sdjl  * 'str').
2380*cb5caa98Sdjl  */
2381*cb5caa98Sdjl nscd_rc_t
2382*cb5caa98Sdjl _nscd_cfg_str_to_data(
2383*cb5caa98Sdjl 	nscd_cfg_param_desc_t	*desc,
2384*cb5caa98Sdjl 	char			*str,
2385*cb5caa98Sdjl 	void			*data,
2386*cb5caa98Sdjl 	void			**data_p,
2387*cb5caa98Sdjl 	nscd_cfg_error_t	**errorp)
2388*cb5caa98Sdjl {
2389*cb5caa98Sdjl 
2390*cb5caa98Sdjl 	char			*me = "_nscd_cfg_str_to_data";
2391*cb5caa98Sdjl 	char			*c;
2392*cb5caa98Sdjl 	nscd_cfg_bitmap_t	bitmap;
2393*cb5caa98Sdjl 	char			msg[NSCD_CFG_MAX_ERR_MSG_LEN];
2394*cb5caa98Sdjl 	nscd_rc_t		rc = NSCD_CFG_DATA_CONVERSION_FAILED;
2395*cb5caa98Sdjl 
2396*cb5caa98Sdjl 	if (desc == NULL || str == NULL || data == NULL) {
2397*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2398*cb5caa98Sdjl 		(me, "ERROR: one of the following is NULL "
2399*cb5caa98Sdjl 		"desc = %p, str = %p, data = %p, data_p = %p\n",
2400*cb5caa98Sdjl 		desc, str, data, data_p);
2401*cb5caa98Sdjl 
2402*cb5caa98Sdjl 		return (NSCD_INVALID_ARGUMENT);
2403*cb5caa98Sdjl 	}
2404*cb5caa98Sdjl 	*data_p = data;
2405*cb5caa98Sdjl 
2406*cb5caa98Sdjl 	/* if description is that of a group, return error */
2407*cb5caa98Sdjl 	if (_nscd_cfg_flag_is_set(desc->pflag, NSCD_CFG_PFLAG_GROUP)) {
2408*cb5caa98Sdjl 
2409*cb5caa98Sdjl 		(void) snprintf(msg, sizeof (msg),
2410*cb5caa98Sdjl 		gettext("single data specified for group %s"), desc->id.name);
2411*cb5caa98Sdjl 
2412*cb5caa98Sdjl 		if (errorp != NULL)
2413*cb5caa98Sdjl 			*errorp = _nscd_cfg_make_error(NSCD_INVALID_ARGUMENT,
2414*cb5caa98Sdjl 				msg);
2415*cb5caa98Sdjl 
2416*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2417*cb5caa98Sdjl 		(me, "ERROR: %s)\n", msg);
2418*cb5caa98Sdjl 
2419*cb5caa98Sdjl 		return (NSCD_INVALID_ARGUMENT);
2420*cb5caa98Sdjl 
2421*cb5caa98Sdjl 	}
2422*cb5caa98Sdjl 
2423*cb5caa98Sdjl 	if (desc->type == NSCD_CFG_DATA_STRING) {
2424*cb5caa98Sdjl 		if (strcmp(str, NSCD_NULL) == 0)
2425*cb5caa98Sdjl 			*(char **)data_p = NULL;
2426*cb5caa98Sdjl 		else {
2427*cb5caa98Sdjl 			/* remove the " char if quoted string */
2428*cb5caa98Sdjl 			if (str[0] == '"') {
2429*cb5caa98Sdjl 				c = str + strlen(str) - 1;
2430*cb5caa98Sdjl 				if (*c == '"')
2431*cb5caa98Sdjl 					*c = '\0';
2432*cb5caa98Sdjl 				*(char **)data_p = str + 1;
2433*cb5caa98Sdjl 			} else
2434*cb5caa98Sdjl 				*(char **)data_p = str;
2435*cb5caa98Sdjl 
2436*cb5caa98Sdjl 		}
2437*cb5caa98Sdjl 		return (NSCD_SUCCESS);
2438*cb5caa98Sdjl 	}
2439*cb5caa98Sdjl 
2440*cb5caa98Sdjl 	if (str == NULL) {
2441*cb5caa98Sdjl 
2442*cb5caa98Sdjl 		(void) snprintf(msg, sizeof (msg),
2443*cb5caa98Sdjl 		gettext("data must be specified for %s"), desc->id.name);
2444*cb5caa98Sdjl 
2445*cb5caa98Sdjl 		if (errorp != NULL)
2446*cb5caa98Sdjl 			*errorp = _nscd_cfg_make_error(NSCD_INVALID_ARGUMENT,
2447*cb5caa98Sdjl 				msg);
2448*cb5caa98Sdjl 
2449*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2450*cb5caa98Sdjl 		(me, "ERROR: %s\n", msg);
2451*cb5caa98Sdjl 
2452*cb5caa98Sdjl 		return (NSCD_INVALID_ARGUMENT);
2453*cb5caa98Sdjl 
2454*cb5caa98Sdjl 	}
2455*cb5caa98Sdjl 
2456*cb5caa98Sdjl 	switch (desc->type) {
2457*cb5caa98Sdjl 
2458*cb5caa98Sdjl 	case NSCD_CFG_DATA_BOOLEAN:
2459*cb5caa98Sdjl 
2460*cb5caa98Sdjl 		if (strcasecmp(str, "yes") == 0)
2461*cb5caa98Sdjl 			*(nscd_bool_t *)data = nscd_true;
2462*cb5caa98Sdjl 		else if (strcasecmp(str, "no") == 0)
2463*cb5caa98Sdjl 			*(nscd_bool_t *)data = nscd_false;
2464*cb5caa98Sdjl 		else {
2465*cb5caa98Sdjl 
2466*cb5caa98Sdjl 		(void) snprintf(msg, sizeof (msg),
2467*cb5caa98Sdjl 		gettext("data (%s) must be 'yes' or 'no' for %s"),
2468*cb5caa98Sdjl 				str, desc->id.name);
2469*cb5caa98Sdjl 
2470*cb5caa98Sdjl 		if (errorp != NULL)
2471*cb5caa98Sdjl 			*errorp = _nscd_cfg_make_error(NSCD_INVALID_ARGUMENT,
2472*cb5caa98Sdjl 				msg);
2473*cb5caa98Sdjl 
2474*cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2475*cb5caa98Sdjl 			(me, "ERROR: %s\n", msg);
2476*cb5caa98Sdjl 
2477*cb5caa98Sdjl 			return (NSCD_INVALID_ARGUMENT);
2478*cb5caa98Sdjl 		}
2479*cb5caa98Sdjl 
2480*cb5caa98Sdjl 		break;
2481*cb5caa98Sdjl 
2482*cb5caa98Sdjl 	case NSCD_CFG_DATA_INTEGER:
2483*cb5caa98Sdjl 
2484*cb5caa98Sdjl 		errno = 0;
2485*cb5caa98Sdjl 		*(int *)data = (int)strtol(str, (char **)NULL, 10);
2486*cb5caa98Sdjl 		if (errno != NULL) {
2487*cb5caa98Sdjl 
2488*cb5caa98Sdjl 			(void) snprintf(msg, sizeof (msg),
2489*cb5caa98Sdjl 			gettext("unable to convert data (%s) for %s"),
2490*cb5caa98Sdjl 				str, desc->id.name);
2491*cb5caa98Sdjl 
2492*cb5caa98Sdjl 			if (errorp != NULL)
2493*cb5caa98Sdjl 				*errorp = _nscd_cfg_make_error(rc, msg);
2494*cb5caa98Sdjl 
2495*cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2496*cb5caa98Sdjl 			(me, "ERROR: %s\n", msg);
2497*cb5caa98Sdjl 
2498*cb5caa98Sdjl 			return (rc);
2499*cb5caa98Sdjl 		}
2500*cb5caa98Sdjl 
2501*cb5caa98Sdjl 		break;
2502*cb5caa98Sdjl 
2503*cb5caa98Sdjl 	case NSCD_CFG_DATA_BITMAP:
2504*cb5caa98Sdjl 
2505*cb5caa98Sdjl 		errno = 0;
2506*cb5caa98Sdjl 		bitmap = (nscd_cfg_bitmap_t)strtol(str, (char **)NULL, 10);
2507*cb5caa98Sdjl 		if (errno != NULL) {
2508*cb5caa98Sdjl 
2509*cb5caa98Sdjl 			(void) snprintf(msg, sizeof (msg),
2510*cb5caa98Sdjl 			gettext("unable to convert data (%s) for %s"),
2511*cb5caa98Sdjl 				str, desc->id.name);
2512*cb5caa98Sdjl 
2513*cb5caa98Sdjl 			if (errorp != NULL)
2514*cb5caa98Sdjl 				*errorp = _nscd_cfg_make_error(rc, msg);
2515*cb5caa98Sdjl 
2516*cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2517*cb5caa98Sdjl 			(me, "ERROR: %s\n", msg);
2518*cb5caa98Sdjl 
2519*cb5caa98Sdjl 			return (rc);
2520*cb5caa98Sdjl 		}
2521*cb5caa98Sdjl 
2522*cb5caa98Sdjl 		_nscd_cfg_bitmap_set(data, bitmap);
2523*cb5caa98Sdjl 
2524*cb5caa98Sdjl 		break;
2525*cb5caa98Sdjl 
2526*cb5caa98Sdjl 	}
2527*cb5caa98Sdjl 
2528*cb5caa98Sdjl 	return (NSCD_SUCCESS);
2529*cb5caa98Sdjl }
2530*cb5caa98Sdjl 
2531*cb5caa98Sdjl 
2532*cb5caa98Sdjl nscd_rc_t
2533*cb5caa98Sdjl _nscd_cfg_set(
2534*cb5caa98Sdjl 	nscd_cfg_handle_t	*handle,
2535*cb5caa98Sdjl 	void			*data,
2536*cb5caa98Sdjl 	nscd_cfg_error_t	**errorp)
2537*cb5caa98Sdjl {
2538*cb5caa98Sdjl 	char			*me = "_nscd_cfg_set";
2539*cb5caa98Sdjl 	int			dlen;
2540*cb5caa98Sdjl 	nscd_cfg_id_t		*nswdb;
2541*cb5caa98Sdjl 	nscd_cfg_param_desc_t	*desc, *gdesc;
2542*cb5caa98Sdjl 	nscd_cfg_group_info_t	*gi;
2543*cb5caa98Sdjl 	char			*nswdb_name, *param_name;
2544*cb5caa98Sdjl 	void			*pdata = NULL;
2545*cb5caa98Sdjl 	void			*cfg_data, *vdata_addr = NULL;
2546*cb5caa98Sdjl 	nscd_bool_t		get_group = 0;
2547*cb5caa98Sdjl 	nscd_bool_t		in = nscd_true;
2548*cb5caa98Sdjl 	nscd_cfg_lock_t		*lock = NULL;
2549*cb5caa98Sdjl 	nscd_rc_t		rc = NSCD_SUCCESS;
2550*cb5caa98Sdjl 
2551*cb5caa98Sdjl 	if (handle == NULL) {
2552*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2553*cb5caa98Sdjl 		(me, "handle is NULL\n");
2554*cb5caa98Sdjl 		return (NSCD_INVALID_ARGUMENT);
2555*cb5caa98Sdjl 	}
2556*cb5caa98Sdjl 
2557*cb5caa98Sdjl 	nswdb = handle->nswdb;
2558*cb5caa98Sdjl 	desc = (nscd_cfg_param_desc_t *)handle->desc;
2559*cb5caa98Sdjl 	if (nswdb == NULL)
2560*cb5caa98Sdjl 		nswdb_name = "global";
2561*cb5caa98Sdjl 	else
2562*cb5caa98Sdjl 		nswdb_name = nswdb->name;
2563*cb5caa98Sdjl 	param_name = desc->id.name;
2564*cb5caa98Sdjl 
2565*cb5caa98Sdjl 	if (data == NULL && _nscd_cfg_flag_is_not_set(desc->pflag,
2566*cb5caa98Sdjl 			NSCD_CFG_PFLAG_VLEN_DATA)) {
2567*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2568*cb5caa98Sdjl 		(me, "data == NULL\n");
2569*cb5caa98Sdjl 		return (NSCD_INVALID_ARGUMENT);
2570*cb5caa98Sdjl 	}
2571*cb5caa98Sdjl 
2572*cb5caa98Sdjl 	if (_nscd_cfg_flag_is_set(desc->pflag,
2573*cb5caa98Sdjl 			NSCD_CFG_PFLAG_UPDATE_SEND_WHOLE_GROUP) ||
2574*cb5caa98Sdjl 		_nscd_cfg_flag_is_set(desc->pflag, NSCD_CFG_PFLAG_GROUP))
2575*cb5caa98Sdjl 		get_group = nscd_true;
2576*cb5caa98Sdjl 
2577*cb5caa98Sdjl 	/*
2578*cb5caa98Sdjl 	 * locate the current value of the param or group
2579*cb5caa98Sdjl 	 * and lock the config data for writing
2580*cb5caa98Sdjl 	 */
2581*cb5caa98Sdjl 	rc = _nscd_cfg_locate_cfg_data(&cfg_data, nscd_false, desc,
2582*cb5caa98Sdjl 		nswdb, get_group, &vdata_addr, &dlen, &lock);
2583*cb5caa98Sdjl 	if (rc != NSCD_SUCCESS) {
2584*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2585*cb5caa98Sdjl 		(me, "unable to locate config data (rc = %d)\n", rc);
2586*cb5caa98Sdjl 		return (rc);
2587*cb5caa98Sdjl 	}
2588*cb5caa98Sdjl 
2589*cb5caa98Sdjl 	if (_nscd_cfg_flag_is_set(desc->pflag, NSCD_CFG_PFLAG_GROUP) &&
2590*cb5caa98Sdjl 		((nscd_cfg_group_info_t *)cfg_data)->num_param !=
2591*cb5caa98Sdjl 		((nscd_cfg_group_info_t *)data)->num_param) {
2592*cb5caa98Sdjl 
2593*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2594*cb5caa98Sdjl 		(me, "number of parameters in group <%s : %s> not equal: "
2595*cb5caa98Sdjl 		"%d in input data, should be %d\n",
2596*cb5caa98Sdjl 		NSCD_STR_OR_GLOBAL(nswdb_name),
2597*cb5caa98Sdjl 		NSCD_STR_OR_NULL(param_name),
2598*cb5caa98Sdjl 		((nscd_cfg_group_info_t *)data)->num_param,
2599*cb5caa98Sdjl 		((nscd_cfg_group_info_t *)cfg_data)->num_param);
2600*cb5caa98Sdjl 
2601*cb5caa98Sdjl 		rc = NSCD_INVALID_ARGUMENT;
2602*cb5caa98Sdjl 		goto error_exit;
2603*cb5caa98Sdjl 	}
2604*cb5caa98Sdjl 
2605*cb5caa98Sdjl 	/*
2606*cb5caa98Sdjl 	 * if variable length data, we want the address
2607*cb5caa98Sdjl 	 * of the pointer pointing to the data
2608*cb5caa98Sdjl 	 */
2609*cb5caa98Sdjl 	if (vdata_addr != NULL)
2610*cb5caa98Sdjl 		cfg_data = vdata_addr;
2611*cb5caa98Sdjl 
2612*cb5caa98Sdjl 	/*
2613*cb5caa98Sdjl 	 * just copy in the specified data, if no need
2614*cb5caa98Sdjl 	 * to verify the data or notify the associated
2615*cb5caa98Sdjl 	 * component
2616*cb5caa98Sdjl 	 */
2617*cb5caa98Sdjl 		if (get_group == nscd_true) {
2618*cb5caa98Sdjl 
2619*cb5caa98Sdjl 			gdesc = &_nscd_cfg_param_desc[desc->g_index];
2620*cb5caa98Sdjl 
2621*cb5caa98Sdjl 			rc = _nscd_cfg_copy_group_data_merge(
2622*cb5caa98Sdjl 				gdesc, &pdata, data, cfg_data,
2623*cb5caa98Sdjl 				desc->id.index, data);
2624*cb5caa98Sdjl 
2625*cb5caa98Sdjl 			if (rc != NSCD_SUCCESS) {
2626*cb5caa98Sdjl 				_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2627*cb5caa98Sdjl 				(me, "unable to copy group data <%s : %s>\n",
2628*cb5caa98Sdjl 				NSCD_STR_OR_GLOBAL(nswdb_name),
2629*cb5caa98Sdjl 				NSCD_STR_OR_NULL(param_name));
2630*cb5caa98Sdjl 
2631*cb5caa98Sdjl 				goto error_exit;
2632*cb5caa98Sdjl 			}
2633*cb5caa98Sdjl 
2634*cb5caa98Sdjl 			rc = _nscd_cfg_notify_s(gdesc, nswdb,
2635*cb5caa98Sdjl 				pdata, errorp);
2636*cb5caa98Sdjl 
2637*cb5caa98Sdjl 		} else
2638*cb5caa98Sdjl 			rc = _nscd_cfg_notify_s(desc, nswdb, data,
2639*cb5caa98Sdjl 				errorp);
2640*cb5caa98Sdjl 
2641*cb5caa98Sdjl 		if (rc != NSCD_SUCCESS) {
2642*cb5caa98Sdjl 
2643*cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2644*cb5caa98Sdjl 			(me, "verifying/notifying  of new configuration "
2645*cb5caa98Sdjl 			"parameter <%s : %s> failed. %s\n",
2646*cb5caa98Sdjl 			NSCD_STR_OR_GLOBAL(nswdb_name),
2647*cb5caa98Sdjl 			param_name, (*errorp && (*errorp)->msg) ?
2648*cb5caa98Sdjl 			(*errorp)->msg : "");
2649*cb5caa98Sdjl 
2650*cb5caa98Sdjl 			goto error_exit;
2651*cb5caa98Sdjl 		}
2652*cb5caa98Sdjl 
2653*cb5caa98Sdjl 	/*
2654*cb5caa98Sdjl 	 * Move the new config into the config store
2655*cb5caa98Sdjl 	 */
2656*cb5caa98Sdjl 	rc = NSCD_CFG_SET_PARAM_FAILED;
2657*cb5caa98Sdjl 	if (_nscd_cfg_flag_is_set(desc->pflag,
2658*cb5caa98Sdjl 			NSCD_CFG_PFLAG_GROUP)) {
2659*cb5caa98Sdjl 		gi = _nscd_cfg_get_gi(pdata);
2660*cb5caa98Sdjl 		rc = _nscd_cfg_copy_group_data_in(gdesc, gi,
2661*cb5caa98Sdjl 			cfg_data, pdata);
2662*cb5caa98Sdjl 	} else {
2663*cb5caa98Sdjl 		/*
2664*cb5caa98Sdjl 		 * nscd_true asks _nscd_cfg_copy_param_data to
2665*cb5caa98Sdjl 		 * set addr of the vlen data in 'cfg_data' rather
2666*cb5caa98Sdjl 		 * than copying the data content
2667*cb5caa98Sdjl 		 */
2668*cb5caa98Sdjl 		if (pdata != NULL)
2669*cb5caa98Sdjl 			_nscd_cfg_free_vlen_data_group(gdesc,
2670*cb5caa98Sdjl 				pdata, in);
2671*cb5caa98Sdjl 
2672*cb5caa98Sdjl 		rc = _nscd_cfg_copy_param_data(desc,
2673*cb5caa98Sdjl 			cfg_data, data, in, nscd_true);
2674*cb5caa98Sdjl 	}
2675*cb5caa98Sdjl 
2676*cb5caa98Sdjl 	if (rc != NSCD_SUCCESS) {
2677*cb5caa98Sdjl 
2678*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2679*cb5caa98Sdjl 		(me, "unable to make new param data <%s : %s> current\n",
2680*cb5caa98Sdjl 		NSCD_STR_OR_GLOBAL(nswdb_name),
2681*cb5caa98Sdjl 		NSCD_STR_OR_NULL(param_name));
2682*cb5caa98Sdjl 	}
2683*cb5caa98Sdjl 
2684*cb5caa98Sdjl 	error_exit:
2685*cb5caa98Sdjl 
2686*cb5caa98Sdjl 	_nscd_cfg_unlock(lock);
2687*cb5caa98Sdjl 
2688*cb5caa98Sdjl 	return (rc);
2689*cb5caa98Sdjl }
2690*cb5caa98Sdjl 
2691*cb5caa98Sdjl nscd_rc_t
2692*cb5caa98Sdjl _nscd_cfg_set_linked(
2693*cb5caa98Sdjl 	nscd_cfg_handle_t		*handle,
2694*cb5caa98Sdjl 	void				*data,
2695*cb5caa98Sdjl 	nscd_cfg_error_t		**errorp)
2696*cb5caa98Sdjl {
2697*cb5caa98Sdjl 	char				*me = "_nscd_cfg_set_linked";
2698*cb5caa98Sdjl 	nscd_cfg_id_t			*nswdb;
2699*cb5caa98Sdjl 	nscd_cfg_handle_t		*hl;
2700*cb5caa98Sdjl 	nscd_cfg_param_desc_t		*desc;
2701*cb5caa98Sdjl 	char				*nswdb_name, *param_name, *dbl;
2702*cb5caa98Sdjl 	nscd_rc_t			rc = NSCD_SUCCESS;
2703*cb5caa98Sdjl 	nscd_cfg_nsw_spc_default_t	*spc;
2704*cb5caa98Sdjl 	int				i;
2705*cb5caa98Sdjl 	char				msg[NSCD_CFG_MAX_ERR_MSG_LEN];
2706*cb5caa98Sdjl 
2707*cb5caa98Sdjl 	if (handle == NULL) {
2708*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2709*cb5caa98Sdjl 		(me, "handle is NULL\n");
2710*cb5caa98Sdjl 		return (NSCD_INVALID_ARGUMENT);
2711*cb5caa98Sdjl 	}
2712*cb5caa98Sdjl 
2713*cb5caa98Sdjl 	nswdb = handle->nswdb;
2714*cb5caa98Sdjl 	desc = (nscd_cfg_param_desc_t *)handle->desc;
2715*cb5caa98Sdjl 
2716*cb5caa98Sdjl 	/*
2717*cb5caa98Sdjl 	 * no need to do the special linking thing,
2718*cb5caa98Sdjl 	 * if a global param, or a group, or not a linked param
2719*cb5caa98Sdjl 	 */
2720*cb5caa98Sdjl 	if (nswdb == NULL || _nscd_cfg_flag_is_set(desc->pflag,
2721*cb5caa98Sdjl 			NSCD_CFG_PFLAG_GROUP) ||
2722*cb5caa98Sdjl 			_nscd_cfg_flag_is_not_set(desc->pflag,
2723*cb5caa98Sdjl 			NSCD_CFG_PFLAG_LINKED))
2724*cb5caa98Sdjl 		return (_nscd_cfg_set(handle, data, errorp));
2725*cb5caa98Sdjl 	else
2726*cb5caa98Sdjl 		nswdb_name = nswdb->name;
2727*cb5caa98Sdjl 	param_name = desc->id.name;
2728*cb5caa98Sdjl 
2729*cb5caa98Sdjl 	/*
2730*cb5caa98Sdjl 	 * if a param is linked to another, it can not be
2731*cb5caa98Sdjl 	 * changed directly
2732*cb5caa98Sdjl 	 */
2733*cb5caa98Sdjl 	for (i = 0; i < _nscd_cfg_num_link_default; i++) {
2734*cb5caa98Sdjl 
2735*cb5caa98Sdjl 		if (_nscd_cfg_nsw_link_default[i].data == NULL)
2736*cb5caa98Sdjl 			continue;
2737*cb5caa98Sdjl 
2738*cb5caa98Sdjl 		if (strcmp(_nscd_cfg_nsw_link_default[i].db,
2739*cb5caa98Sdjl 				nswdb_name) == 0 &&
2740*cb5caa98Sdjl 			_nscd_cfg_nsw_link_default[i].group_off ==
2741*cb5caa98Sdjl 				desc->g_offset &&
2742*cb5caa98Sdjl 			_nscd_cfg_nsw_link_default[i].param_off ==
2743*cb5caa98Sdjl 				desc->p_offset) {
2744*cb5caa98Sdjl 
2745*cb5caa98Sdjl 			rc = NSCD_CFG_READ_ONLY;
2746*cb5caa98Sdjl 
2747*cb5caa98Sdjl 			(void) snprintf(msg, sizeof (msg),
2748*cb5caa98Sdjl gettext("vaule of \'%s\' not changeable, change that of \'%s\' instead"),
2749*cb5caa98Sdjl 				nswdb->name, "passwd");
2750*cb5caa98Sdjl 
2751*cb5caa98Sdjl 			if (errorp != NULL)
2752*cb5caa98Sdjl 				*errorp = _nscd_cfg_make_error(rc, msg);
2753*cb5caa98Sdjl 
2754*cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2755*cb5caa98Sdjl 			(me, "ERROR: %s\n", msg);
2756*cb5caa98Sdjl 
2757*cb5caa98Sdjl 			return (rc);
2758*cb5caa98Sdjl 		}
2759*cb5caa98Sdjl 	}
2760*cb5caa98Sdjl 
2761*cb5caa98Sdjl 	/*
2762*cb5caa98Sdjl 	 * if a param is linked from another, it should be verify
2763*cb5caa98Sdjl 	 * and changed first
2764*cb5caa98Sdjl 	 */
2765*cb5caa98Sdjl 	for (i = 0; i < _nscd_cfg_num_link_default; i++) {
2766*cb5caa98Sdjl 
2767*cb5caa98Sdjl 		if (_nscd_cfg_nsw_link_default[i].data == NULL)
2768*cb5caa98Sdjl 			continue;
2769*cb5caa98Sdjl 
2770*cb5caa98Sdjl 		spc = _nscd_cfg_nsw_link_default[i].data;
2771*cb5caa98Sdjl 
2772*cb5caa98Sdjl 		if (strcmp(spc->db, nswdb_name) == 0 &&
2773*cb5caa98Sdjl 			spc->group_off == desc->g_offset &&
2774*cb5caa98Sdjl 			spc->param_off == desc->p_offset) {
2775*cb5caa98Sdjl 
2776*cb5caa98Sdjl 			rc = _nscd_cfg_set(handle, data, errorp);
2777*cb5caa98Sdjl 			if (rc != NSCD_SUCCESS)
2778*cb5caa98Sdjl 				return (rc);
2779*cb5caa98Sdjl 			break;
2780*cb5caa98Sdjl 		}
2781*cb5caa98Sdjl 	}
2782*cb5caa98Sdjl 
2783*cb5caa98Sdjl 	/*
2784*cb5caa98Sdjl 	 * then change all those linked to the one that has been changed
2785*cb5caa98Sdjl 	 */
2786*cb5caa98Sdjl 	for (i = 0; i < _nscd_cfg_num_link_default; i++) {
2787*cb5caa98Sdjl 
2788*cb5caa98Sdjl 		if (_nscd_cfg_nsw_link_default[i].data == NULL)
2789*cb5caa98Sdjl 			continue;
2790*cb5caa98Sdjl 
2791*cb5caa98Sdjl 		spc = _nscd_cfg_nsw_link_default[i].data;
2792*cb5caa98Sdjl 
2793*cb5caa98Sdjl 		if (strcmp(spc->db, nswdb_name) == 0 &&
2794*cb5caa98Sdjl 			spc->group_off == desc->g_offset &&
2795*cb5caa98Sdjl 			spc->param_off == desc->p_offset &&
2796*cb5caa98Sdjl 			_nscd_cfg_nsw_link_default[i].group_off ==
2797*cb5caa98Sdjl 				desc->g_offset &&
2798*cb5caa98Sdjl 			_nscd_cfg_nsw_link_default[i].param_off ==
2799*cb5caa98Sdjl 				desc->p_offset) {
2800*cb5caa98Sdjl 
2801*cb5caa98Sdjl 			dbl = _nscd_cfg_nsw_link_default[i].db;
2802*cb5caa98Sdjl 
2803*cb5caa98Sdjl 			rc = _nscd_cfg_get_handle(param_name, dbl,
2804*cb5caa98Sdjl 				&hl, errorp);
2805*cb5caa98Sdjl 			rc = _nscd_cfg_set(hl, data, errorp);
2806*cb5caa98Sdjl 			_nscd_cfg_free_handle(hl);
2807*cb5caa98Sdjl 			if (rc != NSCD_SUCCESS)
2808*cb5caa98Sdjl 				return (rc);
2809*cb5caa98Sdjl 		}
2810*cb5caa98Sdjl 	}
2811*cb5caa98Sdjl 
2812*cb5caa98Sdjl 	return (_nscd_cfg_set(handle, data, errorp));
2813*cb5caa98Sdjl }
2814*cb5caa98Sdjl 
2815*cb5caa98Sdjl /*
2816*cb5caa98Sdjl  * Return a list of space-separated database names that
2817*cb5caa98Sdjl  * have at least one of the input sources appeared in the
2818*cb5caa98Sdjl  * configured nsswitch policy string of the databases.
2819*cb5caa98Sdjl  * The return string should be freed by the caller.
2820*cb5caa98Sdjl  *
2821*cb5caa98Sdjl  * For compat sources (compat_group and compat_passwd),
2822*cb5caa98Sdjl  * "group" will be returned, if the policy string for
2823*cb5caa98Sdjl  * compat_group contains one of the input sources. Same
2824*cb5caa98Sdjl  * for compat_passwd and passwd.
2825*cb5caa98Sdjl  */
2826*cb5caa98Sdjl char *
2827*cb5caa98Sdjl _nscd_srcs_in_db_nsw_policy(
2828*cb5caa98Sdjl 	int			num_src,
2829*cb5caa98Sdjl 	char			**srcs)
2830*cb5caa98Sdjl {
2831*cb5caa98Sdjl 	uint8_t			i, j, n = 0, nc = 0;
2832*cb5caa98Sdjl 	uint8_t			compat_grp = 0, compat_pwd = 0;
2833*cb5caa98Sdjl 	uint8_t			*db;
2834*cb5caa98Sdjl 	uint8_t			*db_compat;
2835*cb5caa98Sdjl 	int			dlen = 0;
2836*cb5caa98Sdjl 	nscd_cfg_nsw_db_data_t	*dbcfg;
2837*cb5caa98Sdjl 	nscd_cfg_switch_t	*sw;
2838*cb5caa98Sdjl 	char			*outstr = NULL;
2839*cb5caa98Sdjl 	char			*dbname;
2840*cb5caa98Sdjl 
2841*cb5caa98Sdjl 	db = (uint8_t *)calloc(_nscd_cfg_num_nsw_db, sizeof (uint8_t));
2842*cb5caa98Sdjl 	if (db == NULL)
2843*cb5caa98Sdjl 		return (NULL);
2844*cb5caa98Sdjl 
2845*cb5caa98Sdjl 	db_compat = (uint8_t *)calloc(_nscd_cfg_num_nsw_db,
2846*cb5caa98Sdjl 		sizeof (uint8_t));
2847*cb5caa98Sdjl 	if (db_compat == NULL) {
2848*cb5caa98Sdjl 		free(db);
2849*cb5caa98Sdjl 		return (NULL);
2850*cb5caa98Sdjl 	}
2851*cb5caa98Sdjl 
2852*cb5caa98Sdjl 	for (i = 0; i < _nscd_cfg_num_nsw_db; i++) {
2853*cb5caa98Sdjl 
2854*cb5caa98Sdjl 		(void) rw_rdlock(&nscd_cfg_nsw_db_data_rwlock[i]);
2855*cb5caa98Sdjl 
2856*cb5caa98Sdjl 		dbcfg = &nscd_cfg_nsw_db_data_current[i];
2857*cb5caa98Sdjl 		sw = &dbcfg->sw;
2858*cb5caa98Sdjl 		if (sw->nsw_config_string == NULL)
2859*cb5caa98Sdjl 			continue;
2860*cb5caa98Sdjl 
2861*cb5caa98Sdjl 		dbname = _nscd_cfg_nsw_db[i].name;
2862*cb5caa98Sdjl 		for (j = 0; j < num_src; j++) {
2863*cb5caa98Sdjl 			if (strstr(sw->nsw_config_string, srcs[j]) !=
2864*cb5caa98Sdjl 				NULL) {
2865*cb5caa98Sdjl 				db[n++] = i;
2866*cb5caa98Sdjl 				dlen += strlen(dbname) + 1;
2867*cb5caa98Sdjl 			} else if (strcmp(sw->nsw_config_string,
2868*cb5caa98Sdjl 					"compat") == 0) {
2869*cb5caa98Sdjl 				if (strcmp(dbname, "passwd") == 0) {
2870*cb5caa98Sdjl 					compat_pwd = 1;
2871*cb5caa98Sdjl 					dlen += 7;
2872*cb5caa98Sdjl 				} else if (strcmp(dbname, "group") == 0) {
2873*cb5caa98Sdjl 					compat_grp = 1;
2874*cb5caa98Sdjl 					dlen += 6;
2875*cb5caa98Sdjl 				} else {
2876*cb5caa98Sdjl 					db_compat[nc++] = i;
2877*cb5caa98Sdjl 				dlen += strlen(dbname) + 1;
2878*cb5caa98Sdjl 
2879*cb5caa98Sdjl 				}
2880*cb5caa98Sdjl 			}
2881*cb5caa98Sdjl 		}
2882*cb5caa98Sdjl 		(void) rw_unlock(&nscd_cfg_nsw_db_data_rwlock[i]);
2883*cb5caa98Sdjl 	}
2884*cb5caa98Sdjl 
2885*cb5caa98Sdjl 	if (dlen != NULL)
2886*cb5caa98Sdjl 		outstr = (char *)calloc(1, dlen);
2887*cb5caa98Sdjl 	if (outstr == NULL) {
2888*cb5caa98Sdjl 		free(db_compat);
2889*cb5caa98Sdjl 		free(db);
2890*cb5caa98Sdjl 		return (NULL);
2891*cb5caa98Sdjl 	}
2892*cb5caa98Sdjl 
2893*cb5caa98Sdjl 	for (j = 0; j < n; j++) {
2894*cb5caa98Sdjl 		dbname = _nscd_cfg_nsw_db[db[j]].name;
2895*cb5caa98Sdjl 		if (strstr(dbname, "group_compat") != NULL) {
2896*cb5caa98Sdjl 			if (compat_grp == 1)
2897*cb5caa98Sdjl 				dbname = "group";
2898*cb5caa98Sdjl 			else
2899*cb5caa98Sdjl 				continue;
2900*cb5caa98Sdjl 		} else if (strstr(dbname, "passwd_compat") != NULL) {
2901*cb5caa98Sdjl 			if (compat_pwd == 1)
2902*cb5caa98Sdjl 				dbname = "passwd";
2903*cb5caa98Sdjl 			else
2904*cb5caa98Sdjl 				continue;
2905*cb5caa98Sdjl 		}
2906*cb5caa98Sdjl 
2907*cb5caa98Sdjl 		(void) strlcat(outstr, dbname, dlen);
2908*cb5caa98Sdjl 		(void) strlcat(outstr, ",", dlen);
2909*cb5caa98Sdjl 	}
2910*cb5caa98Sdjl 
2911*cb5caa98Sdjl 	for (j = 0; j < nc; j++) {
2912*cb5caa98Sdjl 		dbname = _nscd_cfg_nsw_db[db_compat[j]].name;
2913*cb5caa98Sdjl 		if (compat_pwd == 1) {
2914*cb5caa98Sdjl 			(void) strlcat(outstr, dbname, dlen);
2915*cb5caa98Sdjl 			(void) strlcat(outstr, " ", dlen);
2916*cb5caa98Sdjl 		}
2917*cb5caa98Sdjl 	}
2918*cb5caa98Sdjl 
2919*cb5caa98Sdjl 	free(db);
2920*cb5caa98Sdjl 	free(db_compat);
2921*cb5caa98Sdjl 	return (outstr);
2922*cb5caa98Sdjl 
2923*cb5caa98Sdjl }
2924