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);
Implements a variable-sized (but non-resizeable) bit-array.
static void bitarray_set(bitarray_t *b, int bit)
static unsigned int bitarray_is_set(bitarray_t *b, int bit)
static bitarray_t * bitarray_init_zero(unsigned int n_bits)
#define STRUCT_VAR_P(st, off)
Locale-independent character-type inspection (header)
void config_line_append(config_line_t **lst, const char *key, const char *val)
static void config_clear(const config_mgr_t *mgr, void *options, const managed_var_t *var)
static config_suite_t ** config_mgr_get_suite_ptr(const config_mgr_t *mgr, void *toplevel)
const char * config_find_deprecation(const config_mgr_t *mgr, const char *key)
static void config_mgr_register_fmt(config_mgr_t *mgr, const config_format_t *fmt, int object_idx)
void config_init(const config_mgr_t *mgr, void *options)
static bool config_var_needs_copy(const config_var_t *var)
static bool config_var_has_flag(const config_var_t *var, uint32_t flag)
static int config_count_options(const config_mgr_t *mgr)
static int config_check_immutable_flags(const config_format_t *fmt, const void *old_options, const void *new_options, char **msg_out)
void config_mgr_freeze(config_mgr_t *mgr)
void warn_deprecated_option(const char *what, const char *why)
char * config_dump(const config_mgr_t *mgr, const void *default_options, const void *options, int minimal, int comment_defaults)
bool config_var_is_listable(const config_var_t *var)
static int managed_var_cmp(const void **a, const void **b)
static int config_assign_line(const config_mgr_t *mgr, void *options, config_line_t *c, unsigned flags, bitarray_t *options_seen, char **msg)
bool config_check_ok(const config_mgr_t *mgr, const void *options, int severity)
void config_free_(const config_mgr_t *mgr, void *options)
void * config_mgr_get_obj_mutable(const config_mgr_t *mgr, void *toplevel, int idx)
static int config_assign_value(const config_mgr_t *mgr, void *options, config_line_t *c, char **msg)
int config_is_same(const config_mgr_t *mgr, const void *o1, const void *o2, const char *name)
void config_check_toplevel_magic(const config_mgr_t *mgr, const void *object)
config_line_t * config_get_assigned_option(const config_mgr_t *mgr, const void *options, const char *key, int escape_val)
static bool config_var_is_replaced_on_set(const config_var_t *var)
static void config_reset(const config_mgr_t *fmt, void *options, const managed_var_t *var, int use_defaults)
const void * config_mgr_get_obj(const config_mgr_t *mgr, const void *toplevel, int idx)
config_line_t * config_get_changes(const config_mgr_t *mgr, const void *options1, const void *options2)
bool config_var_is_settable(const config_var_t *var)
static void managed_var_free_(managed_var_t *mv)
static void config_mgr_assert_magic_ok(const config_mgr_t *mgr, const void *options)
static bool config_var_should_list_changes(const config_var_t *var)
static void config_mark_lists_fragile(const config_mgr_t *mgr, void *options)
static void config_suite_free_(config_suite_t *suite)
void * config_new(const config_mgr_t *mgr)
static int config_value_needs_escape(const char *value)
config_mgr_t * config_mgr_new(const config_format_t *toplevel_fmt)
const char * config_expand_abbrev(const config_mgr_t *mgr, const char *option, int command_line, int warn_obsolete)
static config_suite_t * config_suite_new(void)
const char * config_find_option_name(const config_mgr_t *mgr, const char *key)
validation_status_t config_validate(const config_mgr_t *mgr, const void *old_options, void *options, char **msg_out)
int config_assign(const config_mgr_t *mgr, void *options, config_line_t *list, unsigned config_assign_flags, char **msg)
static bool config_var_is_dumpable(const config_var_t *var)
static bool config_var_is_gettable(const config_var_t *var)
static const managed_var_t * config_mgr_find_var(const config_mgr_t *mgr, const char *key, bool allow_truncated, int *idx_out)
static validation_status_t config_validate_single(const config_format_t *fmt, const void *old_options, void *options, char **msg_out)
STATIC void config_reset_line(const config_mgr_t *mgr, void *options, const char *key, int use_defaults)
void * config_dup(const config_mgr_t *mgr, const void *old)
#define CONFIG_CHECK(mgr, cfg)
smartlist_t * config_mgr_list_deprecated_vars(const config_mgr_t *mgr)
smartlist_t * config_mgr_list_vars(const config_mgr_t *mgr)
void config_mgr_free_(config_mgr_t *mgr)
int config_mgr_add_format(config_mgr_t *mgr, const config_format_t *fmt)
#define CAL_WARN_DEPRECATIONS
#define CFLG_WARN_DISABLED
#define CFLG_WARN_OBSOLETE
char * esc_for_log(const char *s)
#define log_fn(severity, domain, args,...)
int tor_asprintf(char **strp, const char *fmt,...)
void smartlist_add_asprintf(struct smartlist_t *sl, const char *pattern,...)
char * smartlist_join_strings(smartlist_t *sl, const char *join, int terminate, size_t *len_out)
void smartlist_sort(smartlist_t *sl, int(*compare)(const void **a, const void **b))
smartlist_t * smartlist_new(void)
int smartlist_contains(const smartlist_t *sl, const void *element)
void smartlist_add(smartlist_t *sl, void *element)
#define SMARTLIST_FOREACH_BEGIN(sl, type, var)
#define SMARTLIST_FOREACH(sl, type, var, cmd)
smartlist_t * all_deprecations
smartlist_t * all_abbrevs
const config_format_t * toplevel
struct_magic_decl_t toplevel_magic
const config_var_t * cvar
void struct_set_magic(void *object, const struct_magic_decl_t *decl)
void struct_check_magic(const void *object, const struct_magic_decl_t *decl)
bool struct_var_eq(const void *a, const void *b, const struct_member_t *member)
int struct_var_kvassign(void *object, const struct config_line_t *line, char **errmsg, const struct_member_t *member)
int struct_var_copy(void *dest, const void *src, const struct_member_t *member)
void struct_var_free(void *object, const struct_member_t *member)
void struct_var_mark_fragile(void *object, const struct_member_t *member)
bool struct_var_ok(const void *object, const struct_member_t *member)
struct config_line_t * struct_var_kvencode(const void *object, const struct_member_t *member)
uint32_t struct_var_get_flags(const struct_member_t *member)
Header for lib/confmgt/structvar.c.
Header for lib/confmgt/unitparse.c.
Macros to manage assertions, fatal and non-fatal.
#define tor_assert_nonfatal_unreached()
int strcmpstart(const char *s1, const char *s2)
Header for util_string.c.