24 #define CONFMGT_PRIVATE
40 #include "ext/siphash.h"
72 #define managed_var_free(mv) \
73 FREE_AND_NULL(managed_var_t, managed_var_free_, (mv))
100 smartlist_free(suite->
configs);
104 #define config_suite_free(suite) \
105 FREE_AND_NULL(config_suite_t, config_suite_free_, (suite))
140 #define IDX_TOPLEVEL (-1)
168 "Tried to add a format to a configuration manager after "
169 "it had been frozen.");
171 if (object_idx != IDX_TOPLEVEL) {
172 tor_assertf(! fmt->has_config_suite,
173 "Tried to register a toplevel format in a non-toplevel position");
175 if (fmt->config_suite_offset) {
176 tor_assertf(fmt->has_config_suite,
177 "config_suite_offset was set, but has_config_suite was not.");
182 "Tried to register an already-registered format.");
185 for (i = 0; fmt->vars[i].member.name; ++i) {
187 mv->
cvar = &fmt->vars[i];
194 for (i = 0; fmt->abbrevs[i].abbreviated; ++i) {
200 if (fmt->deprecations) {
202 for (d = fmt->deprecations; d->
name; ++d) {
250 if (idx == IDX_TOPLEVEL)
253 tor_assertf(idx >= 0 && idx < smartlist_len(mgr->
subconfigs),
254 "Index %d is out of range.", idx);
258 smartlist_len((*suite)->configs));
260 return smartlist_get((*suite)->configs, idx);
287 static uint64_t mgr_count = 0;
293 (uint64_t) (uintptr_t) mgr,
296 (uint32_t)siphash24g(magic_input,
sizeof(magic_input));
311 memset(mgr, 0,
sizeof(*mgr));
365 if (suitep == NULL) {
370 tor_assert(smartlist_len((*suitep)->configs) ==
373 void *obj = smartlist_get((*suitep)->configs, fmt_sl_idx);
376 } SMARTLIST_FOREACH_END(fmt);
381 #define CONFIG_CHECK(mgr, cfg) STMT_BEGIN \
382 config_mgr_assert_magic_ok((mgr), (cfg)); \
396 void *obj = tor_malloc_zero(fmt->size);
399 } SMARTLIST_FOREACH_END(fmt);
416 int command_line,
int warn_obsolete)
420 if (!strcasecmp(option, abbrev->abbreviated) &&
421 (command_line || !abbrev->commandline_only)) {
422 if (warn_obsolete && abbrev->warn) {
424 "The configuration option '%s' is deprecated; "
432 option = abbrev->full;
434 } SMARTLIST_FOREACH_END(abbrev);
444 if (BUG(mgr == NULL) || BUG(key == NULL))
449 if (!strcasecmp(d->name, key)) {
450 return d->why_deprecated ? d->why_deprecated :
"";
452 } SMARTLIST_FOREACH_END(d);
470 bool allow_truncated,
int *idx_out)
472 const size_t keylen = strlen(key);
481 if (!strcasecmp(mv->cvar->member.name, key)) {
483 *idx_out = mv_sl_idx;
486 } SMARTLIST_FOREACH_END(mv);
488 if (!allow_truncated)
493 if (!strncasecmp(key, mv->cvar->member.name, keylen)) {
494 log_warn(
LD_CONFIG,
"The abbreviation '%s' is deprecated. "
495 "Please use '%s' instead",
496 key, mv->cvar->member.name);
498 *idx_out = mv_sl_idx;
501 } SMARTLIST_FOREACH_END(mv);
527 return smartlist_len(mgr->
all_vars);
539 return (have_flags & flag) != 0;
661 log_warn(
LD_GENERAL,
"Skipping obsolete configuration option \"%s\".",
664 log_warn(
LD_GENERAL,
"This copy of Tor was built without support for "
665 "the option \"%s\". Skipping.", var->
cvar->member.
name);
682 } SMARTLIST_FOREACH_END(mv);
694 const char *space = (why && strlen(why)) ?
" " :
"";
695 log_warn(
LD_CONFIG,
"The %s option is deprecated, and will most likely "
696 "be removed in a future version of Tor.%s%s (If you think this is "
697 "a mistake, please let us know!)",
727 void *lvalue =
STRUCT_VAR_P(options, fmt->extra->offset);
729 "Found unrecognized option '%s'; saving it.", c->key);
734 "Unknown option '%s'. Failing.", c->key);
743 if (strcmp(cvar->member.
name, c->key)) {
745 c->key = tor_strdup(cvar->member.
name);
748 const char *deprecation_msg;
749 if (warn_deprecations &&
754 if (!strlen(c->value)) {
758 c->
command != CONFIG_LINE_CLEAR) {
762 "Linelist option '%s' has no value. Skipping.", c->key);
768 }
else if (c->
command == CONFIG_LINE_CLEAR && !clear_first) {
784 log_warn(
LD_CONFIG,
"Option '%s' used more than once; all but the last "
785 "value will be ignored.", cvar->member.
name);
799 const char *key,
int use_defaults)
830 if (!TOR_ISPRINT(*value))
844 const char *key,
int escape_val)
855 log_warn(
LD_CONFIG,
"Unknown option '%s'. Failing.", key);
859 log_warn(
LD_CONFIG,
"Option '%s' is obsolete or unfetchable. Failing.",
869 for (line = result; line; line = line->next) {
873 line->value = newval;
938 unsigned config_assign_flags,
char **msg)
949 for (p = list; p; p = p->next) {
951 if (strcmp(full,p->key)) {
953 p->key = tor_strdup(full);
960 for (p = list; p; p = p->next)
969 options_seen, msg))) {
970 bitarray_free(options_seen);
975 bitarray_free(options_seen);
1011 c->key = tor_strdup(var->
cvar->member.
name);
1015 log_warn(
LD_BUG,
"Failed to assign default: %s", msg);
1019 config_free_lines(c);
1037 tor_assert(smartlist_len((*suitep)->configs) ==
1040 void *obj = smartlist_get((*suitep)->configs, fmt_sl_idx);
1041 if (fmt->clear_fn) {
1042 fmt->clear_fn(mgr, obj);
1044 } SMARTLIST_FOREACH_END(fmt);
1049 } SMARTLIST_FOREACH_END(mv);
1054 config_free_lines(*linep);
1060 config_suite_free(*suitep);
1071 const void *o1,
const void *o2,
1097 const void *options1,
const void *options2)
1113 const char *varname = mv->cvar->member.name;
1121 (*next)->key = tor_strdup(varname);
1124 next = &(*next)->next;
1125 } SMARTLIST_FOREACH_END(mv);
1146 log_err(
LD_BUG,
"Unable to copy value for %s.",
1147 mv->cvar->member.name);
1148 tor_assert_unreached();
1151 } SMARTLIST_FOREACH_END(mv);
1163 if (!mv->cvar->initvalue)
1166 } SMARTLIST_FOREACH_END(mv);
1178 const void *old_options,
1179 const void *new_options,
1184 if (BUG(! old_options))
1188 for (i = 0; fmt->vars[i].member.name; ++i) {
1193 if (!
struct_var_eq(old_options, new_options, &v->member)) {
1195 "While Tor is running, changing %s is not allowed",
1216 const void *old_options,
void *options,
1222 if (fmt->pre_normalize_fn) {
1223 if (fmt->pre_normalize_fn(options, msg_out) < 0) {
1224 return VSTAT_PRE_NORMALIZE_ERR;
1228 if (fmt->legacy_validate_fn) {
1229 if (fmt->legacy_validate_fn(old_options, options, msg_out) < 0) {
1230 return VSTAT_LEGACY_ERR;
1234 if (fmt->validate_fn) {
1235 if (fmt->validate_fn(options, msg_out) < 0) {
1236 return VSTAT_VALIDATE_ERR;
1242 return VSTAT_TRANSITION_ERR;
1245 if (fmt->check_transition_fn) {
1246 if (fmt->check_transition_fn(old_options, options, msg_out) < 0) {
1247 return VSTAT_TRANSITION_ERR;
1252 if (fmt->post_normalize_fn) {
1253 if (fmt->post_normalize_fn(options, msg_out) < 0) {
1254 return VSTAT_POST_NORMALIZE_ERR;
1273 const void *old_options,
void *options,
1290 void *obj = smartlist_get((*suitep_new)->configs, fmt_sl_idx);
1291 const void *obj_old=NULL;
1293 obj_old = smartlist_get((*suitep_old)->configs, fmt_sl_idx);
1298 } SMARTLIST_FOREACH_END(fmt);
1315 const void *options,
int minimal,
1316 int comment_defaults)
1320 const void *defaults = default_options;
1321 void *defaults_tmp = NULL;
1326 if (defaults == NULL) {
1332 if (default_options == NULL) {
1335 log_err(
LD_BUG,
"Failed to validate default config: %s", msg);
1344 int comment_option = 0;
1348 const char *
name = mv->cvar->member.name;
1351 else if (comment_defaults &&
1358 for (; line; line = line->next) {
1364 int value_exists = line->value && *(line->value);
1366 comment_option ?
"# " :
"",
1367 line->key, value_exists ?
" " :
"", line->value);
1369 config_free_lines(assigned);
1370 } SMARTLIST_FOREACH_END(mv);
1374 for (; line; line = line->next) {
1375 int value_exists = line->value && *(line->value);
1377 line->key, value_exists ?
" " :
"", line->value);
1383 smartlist_free(elements);
1384 config_free(mgr, defaults_tmp);
1400 mv->cvar->member.name);
1403 } SMARTLIST_FOREACH_END(mv);