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