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