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