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 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 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 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 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 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