1cb5caa9djl/*
2cb5caa9djl * CDDL HEADER START
3cb5caa9djl *
4cb5caa9djl * The contents of this file are subject to the terms of the
5cb5caa9djl * Common Development and Distribution License (the "License").
6cb5caa9djl * You may not use this file except in compliance with the License.
7cb5caa9djl *
8cb5caa9djl * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9cb5caa9djl * or http://www.opensolaris.org/os/licensing.
10cb5caa9djl * See the License for the specific language governing permissions
11cb5caa9djl * and limitations under the License.
12cb5caa9djl *
13cb5caa9djl * When distributing Covered Code, include this CDDL HEADER in each
14cb5caa9djl * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15cb5caa9djl * If applicable, add the following below this CDDL HEADER, with the
16cb5caa9djl * fields enclosed by brackets "[]" replaced with your own identifying
17cb5caa9djl * information: Portions Copyright [yyyy] [name of copyright owner]
18cb5caa9djl *
19cb5caa9djl * CDDL HEADER END
20cb5caa9djl */
21cb5caa9djl/*
22cb5caa9djl * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23cb5caa9djl * Use is subject to license terms.
24cb5caa9djl */
25cb5caa9djl
26cb5caa9djl#pragma ident	"%Z%%M%	%I%	%E% SMI"
27cb5caa9djl
28cb5caa9djl#include <stdlib.h>
29cb5caa9djl#include <locale.h>
30cb5caa9djl#include <string.h>
31cb5caa9djl#include "nscd_config.h"
32cb5caa9djl#include "nscd_log.h"
33cb5caa9djl#include "nscd_switch.h"
34cb5caa9djl
35cb5caa9djl/*
36cb5caa9djl * Configuration data for the nscd switch functions.
37cb5caa9djl */
38cb5caa9djlnscd_cfg_global_switch_t	nscd_switch_cfg_g;
39cb5caa9djlnscd_cfg_switch_t		*nscd_switch_cfg;
40cb5caa9djl
41cb5caa9djl/*
42cb5caa9djl * statistics of the nscd switch functions.
43cb5caa9djl */
44cb5caa9djlnscd_cfg_stat_global_switch_t	nscd_switch_stats_g;
45cb5caa9djlnscd_cfg_stat_switch_t		*nscd_switch_stats;
46cb5caa9djl
47cb5caa9djl/*
48cb5caa9djl * cookie is set up by the verify function for passing to
49cb5caa9djl * the notify function
50cb5caa9djl */
51cb5caa9djltypedef struct {
52cb5caa9djl	struct __nsw_switchconfig_v1	*cfg;
53cb5caa9djl	char				*cfgstr;
54cb5caa9djl} nsw_cfg_cookie_t;
55cb5caa9djl
56cb5caa9djlnscd_rc_t
57cb5caa9djl_nscd_alloc_switch_cfg()
58cb5caa9djl{
59cb5caa9djl	nscd_switch_cfg  = calloc(NSCD_NUM_DB, sizeof (nscd_cfg_switch_t));
60cb5caa9djl	if (nscd_switch_cfg == NULL)
61cb5caa9djl		return (NSCD_NO_MEMORY);
62cb5caa9djl
63cb5caa9djl	return (NSCD_SUCCESS);
64cb5caa9djl}
65cb5caa9djl
66cb5caa9djlnscd_rc_t
67cb5caa9djl_nscd_alloc_switch_stats()
68cb5caa9djl{
69cb5caa9djl
70cb5caa9djl	nscd_switch_stats = calloc(NSCD_NUM_DB,
71cb5caa9djl		sizeof (nscd_cfg_stat_switch_t));
72cb5caa9djl	if (nscd_switch_stats == NULL)
73cb5caa9djl		return (NSCD_NO_MEMORY);
74cb5caa9djl
75cb5caa9djl	return (NSCD_SUCCESS);
76cb5caa9djl}
77cb5caa9djl
78cb5caa9djl/* ARGSUSED */
79cb5caa9djlnscd_rc_t
80cb5caa9djl_nscd_cfg_switch_notify(
81cb5caa9djl	void				*data,
82cb5caa9djl	struct nscd_cfg_param_desc	*pdesc,
83cb5caa9djl	nscd_cfg_id_t			*nswdb,
84cb5caa9djl	nscd_cfg_flag_t			dflag,
85cb5caa9djl	nscd_cfg_error_t		**errorp,
86cb5caa9djl	void				*cookie)
87cb5caa9djl{
88cb5caa9djl
89cb5caa9djl	void				*dp;
90cb5caa9djl	nscd_rc_t			rc;
91cb5caa9djl	nsw_cfg_cookie_t		*ck = (nsw_cfg_cookie_t *)cookie;
92cb5caa9djl
93cb5caa9djl	if (_nscd_cfg_flag_is_set(dflag, NSCD_CFG_DFLAG_INIT) ||
94cb5caa9djl		_nscd_cfg_flag_is_set(dflag, NSCD_CFG_DFLAG_GROUP)) {
95cb5caa9djl		/*
96cb5caa9djl		 * group data is received, copy in the
97cb5caa9djl		 * entire strcture
98cb5caa9djl		 */
99cb5caa9djl		if (_nscd_cfg_flag_is_set(pdesc->pflag,
100cb5caa9djl			NSCD_CFG_PFLAG_GLOBAL)) {
101cb5caa9djl			nscd_switch_cfg_g = *(nscd_cfg_global_switch_t *)data;
102cb5caa9djl		} else {
103cb5caa9djl			nscd_switch_cfg[nswdb->index] =
104cb5caa9djl				*(nscd_cfg_switch_t *)data;
105cb5caa9djl
106cb5caa9djl		}
107cb5caa9djl	} else {
108cb5caa9djl		/*
109cb5caa9djl		 * individual paramater is received: copy in the
110cb5caa9djl		 * parameter value except for nsw-config-string.
111cb5caa9djl		 */
112cb5caa9djl		if (_nscd_cfg_flag_is_set(pdesc->pflag,
113cb5caa9djl			NSCD_CFG_PFLAG_GLOBAL)) {
114cb5caa9djl			dp = (char *)&nscd_switch_cfg_g + pdesc->p_offset;
115cb5caa9djl			(void) memcpy(dp, data, pdesc->p_size);
116cb5caa9djl		} else {
117cb5caa9djl			dp = (char *)&nscd_switch_cfg[nswdb->index] +
118cb5caa9djl				pdesc->p_offset;
119cb5caa9djl			if (pdesc->p_offset !=
120cb5caa9djl				offsetof(nscd_cfg_switch_t, nsw_config_string))
121cb5caa9djl				(void) memcpy(dp, data, pdesc->p_size);
122cb5caa9djl		}
123cb5caa9djl	}
124cb5caa9djl
125cb5caa9djl	/*
126cb5caa9djl	 * cookie contains data for the switch policy config
127cb5caa9djl	 */
128cb5caa9djl	if (cookie != NULL) {
129ad0e80fmichen		rc = _nscd_create_sw_struct(nswdb->index, -1, nswdb->name,
130cb5caa9djl			ck->cfgstr, ck->cfg, NULL);
131cb5caa9djl		if (rc != NSCD_SUCCESS) {
132cb5caa9djl			(void) __nsw_freeconfig_v1(ck->cfg);
133cb5caa9djl			free(ck);
134cb5caa9djl			return (rc);
135cb5caa9djl		}
136cb5caa9djl		free(ck);
137cb5caa9djl	}
138cb5caa9djl
139cb5caa9djl	if (_nscd_cfg_flag_is_not_set(dflag, NSCD_CFG_DFLAG_STATIC_DATA))
140cb5caa9djl		free(data);
141cb5caa9djl
142cb5caa9djl	return (NSCD_SUCCESS);
143cb5caa9djl}
144cb5caa9djl
145cb5caa9djl/* ARGSUSED */
146cb5caa9djlnscd_rc_t
147cb5caa9djl_nscd_cfg_switch_verify(
148cb5caa9djl	void				*data,
149cb5caa9djl	struct	nscd_cfg_param_desc	*pdesc,
150cb5caa9djl	nscd_cfg_id_t			*nswdb,
151cb5caa9djl	nscd_cfg_flag_t			dflag,
152cb5caa9djl	nscd_cfg_error_t		**errorp,
153cb5caa9djl	void				**cookie)
154cb5caa9djl{
155cb5caa9djl	char				*me = "_nscd_cfg_switch_verify";
156cb5caa9djl	nscd_cfg_switch_t		*cfg;
157cb5caa9djl	char				*nswcfgstr;
158cb5caa9djl	int				size;
159cb5caa9djl	struct __nsw_switchconfig_v1	*switchcfg = NULL;
160cb5caa9djl	enum __nsw_parse_err		err;
161cb5caa9djl	nsw_cfg_cookie_t		*ck;
162cb5caa9djl	char				buf[MAX_NSSWITCH_CONFIG_STRING_SZ];
163cb5caa9djl	char				msg[NSCD_CFG_MAX_ERR_MSG_LEN];
164cb5caa9djl
165cb5caa9djl	/*
166cb5caa9djl	 * global config data has nothing special to verify
167cb5caa9djl	 */
168cb5caa9djl	if (_nscd_cfg_flag_is_set(pdesc->pflag, NSCD_CFG_PFLAG_GLOBAL))
169cb5caa9djl		return (NSCD_SUCCESS);
170cb5caa9djl
171cb5caa9djl	*cookie = NULL;
172cb5caa9djl
173cb5caa9djl	/*
174cb5caa9djl	 * switch policy string is the one to parse and verify
175cb5caa9djl	 */
176cb5caa9djl
177cb5caa9djl	if (_nscd_cfg_flag_is_set(dflag, NSCD_CFG_DFLAG_INIT) ||
178cb5caa9djl		_nscd_cfg_flag_is_set(dflag, NSCD_CFG_DFLAG_GROUP)) {
179cb5caa9djl
180cb5caa9djl		/* get it from the group data */
181cb5caa9djl		cfg = (nscd_cfg_switch_t *)data;
182cb5caa9djl		nswcfgstr = cfg->nsw_config_string;
183cb5caa9djl	} else {
184cb5caa9djl		/* not group, and not the switch policy string, return */
185cb5caa9djl		if (pdesc->p_offset != offsetof(nscd_cfg_switch_t,
186cb5caa9djl			nsw_config_string))
187cb5caa9djl		return (NSCD_SUCCESS);
188cb5caa9djl
189cb5caa9djl		/* the data itself is the string */
190cb5caa9djl		nswcfgstr = (char *)data;
191cb5caa9djl	}
192cb5caa9djl
193cb5caa9djl	/*
194cb5caa9djl	 * convert the string into struct __nsw_switchconfig_v1
195cb5caa9djl	 */
196cb5caa9djl	size = MAX_NSSWITCH_CONFIG_STRING_SZ;
197cb5caa9djl	if (strlcpy(buf, nswcfgstr, size) >= size) {
198cb5caa9djl
199cb5caa9djl		(void) snprintf(msg, sizeof (msg),
200cb5caa9djl	gettext("switch policy string too long (\"%s : %s\" > %d)"),
201cb5caa9djl			nswdb->name, nswcfgstr, size);
202cb5caa9djl
203cb5caa9djl		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
204cb5caa9djl		(me, "%s\n", msg);
205cb5caa9djl
206cb5caa9djl		if (*errorp)
207cb5caa9djl			*errorp = _nscd_cfg_make_error(
208cb5caa9djl				NSCD_CFG_SYNTAX_ERROR, msg);
209cb5caa9djl
210cb5caa9djl		return (NSCD_CFG_SYNTAX_ERROR);
211cb5caa9djl	}
212cb5caa9djl	switchcfg = _nsw_getoneconfig_v1(nswdb->name, buf, &err);
213cb5caa9djl	if (switchcfg == NULL) {
214cb5caa9djl
215cb5caa9djl		(void) snprintf(msg, sizeof (msg),
216cb5caa9djl		gettext("syntax error: switch policy string (%s : %s) rc = %d"),
217cb5caa9djl		nswdb->name, nswcfgstr, err);
218cb5caa9djl
219cb5caa9djl		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
220cb5caa9djl		(me, "%s\n", msg);
221cb5caa9djl
222cb5caa9djl		if (*errorp)
223cb5caa9djl			*errorp = _nscd_cfg_make_error(
224cb5caa9djl				NSCD_CFG_SYNTAX_ERROR, msg);
225cb5caa9djl
226cb5caa9djl		return (NSCD_CFG_SYNTAX_ERROR);
227cb5caa9djl	}
228cb5caa9djl
229cb5caa9djl	/* save the __nsw_switchconfig_v1 for the notify function */
230cb5caa9djl	ck = calloc(1, sizeof (nsw_cfg_cookie_t));
231cb5caa9djl	if (ck == NULL) {
232cb5caa9djl		(void) __nsw_freeconfig_v1(switchcfg);
233cb5caa9djl		return (NSCD_CFG_SYNTAX_ERROR);
234cb5caa9djl	}
235cb5caa9djl	ck->cfg = switchcfg;
236cb5caa9djl	ck->cfgstr = nswcfgstr;
237cb5caa9djl	*cookie = ck;
238cb5caa9djl
239cb5caa9djl	return (NSCD_SUCCESS);
240cb5caa9djl}
241cb5caa9djl
242cb5caa9djl/* ARGSUSED */
243cb5caa9djlnscd_rc_t
244cb5caa9djl_nscd_cfg_switch_get_stat(
245cb5caa9djl	void				**stat,
246cb5caa9djl	struct nscd_cfg_stat_desc	*sdesc,
247cb5caa9djl	nscd_cfg_id_t			*nswdb,
248cb5caa9djl	nscd_cfg_flag_t			*dflag,
249cb5caa9djl	void				(**free_stat)(void *stat),
250cb5caa9djl	nscd_cfg_error_t		**errorp)
251cb5caa9djl{
252cb5caa9djl
253cb5caa9djl	if (_nscd_cfg_flag_is_set(sdesc->sflag, NSCD_CFG_SFLAG_GLOBAL)) {
254cb5caa9djl		*stat = &NSCD_SW_STATS_G;
255cb5caa9djl	} else
256cb5caa9djl		*stat = &NSCD_SW_STATS(nswdb->index);
257cb5caa9djl
258cb5caa9djl	/* indicate the statistics are static, i.e., do not free */
259cb5caa9djl	*dflag = _nscd_cfg_flag_set(*dflag, NSCD_CFG_DFLAG_STATIC_DATA);
260cb5caa9djl
261cb5caa9djl	return (NSCD_SUCCESS);
262cb5caa9djl}
263